tryton-4.6.5/0000755000175000017500000000000013260723567012410 5ustar cedced00000000000000tryton-4.6.5/darwin/0000755000175000017500000000000013260723567013674 5ustar cedced00000000000000tryton-4.6.5/darwin/gtk-2.0/0000755000175000017500000000000013260723567014756 5ustar cedced00000000000000tryton-4.6.5/darwin/gtk-2.0/gdk-pixbuf.loaders0000644000175000017500000000626713251060075020370 0ustar cedced00000000000000# GdkPixbuf Image Loader Modules file # Automatically generated file, do not edit # Created by gdk-pixbuf-query-loaders from gdk-pixbuf-2.34.0 # # LoaderDir = @executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders # "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ani.so" "ani" 4 "gdk-pixbuf" "Windows animated cursor" "LGPL" "application/x-navi-animation" "" "ani" "" "RIFF ACON" " xxxx " 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-bmp.so" "bmp" 5 "gdk-pixbuf" "BMP" "LGPL" "image/bmp" "image/x-bmp" "image/x-MS-bmp" "" "bmp" "" "BM" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-gif.so" "gif" 4 "gdk-pixbuf" "GIF" "LGPL" "image/gif" "" "gif" "" "GIF8" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-icns.so" "icns" 4 "gdk-pixbuf" "MacOS X icon" "GPL" "image/x-icns" "" "icns" "" "icns" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-ico.so" "ico" 5 "gdk-pixbuf" "Windows icon" "LGPL" "image/x-icon" "image/x-ico" "image/x-win-bitmap" "image/vnd.microsoft.icon" "application/ico" "image/ico" "image/icon" "text/ico" "" "ico" "cur" "" " \001 " "zz znz" 100 " \002 " "zz znz" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-jpeg.so" "jpeg" 5 "gdk-pixbuf" "JPEG" "LGPL" "image/jpeg" "" "jpeg" "jpe" "jpg" "" "\377\330" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-png.so" "png" 5 "gdk-pixbuf" "PNG" "LGPL" "image/png" "" "png" "" "\211PNG\r\n\032\n" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-pnm.so" "pnm" 4 "gdk-pixbuf" "PNM/PBM/PGM/PPM" "LGPL" "image/x-portable-anymap" "image/x-portable-bitmap" "image/x-portable-graymap" "image/x-portable-pixmap" "" "pnm" "pbm" "pgm" "ppm" "" "P1" "" 100 "P2" "" 100 "P3" "" 100 "P4" "" 100 "P5" "" 100 "P6" "" 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-qtif.so" "qtif" 4 "gdk-pixbuf" "QuickTime" "LGPL" "image/x-quicktime" "image/qtif" "" "qtif" "qif" "" "abcdidsc" "xxxx " 100 "abcdidat" "xxxx " 100 "@executable_path/lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.so" "svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL" "image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" "" "svg" "svgz" "svg.gz" "" " '" !endif ;General Name "Tryton ${VERSION}" OutFile "tryton-${VERSION}.exe" SetCompressor lzma SetCompress auto SilentInstall silent Icon "tryton\data\pixmaps\tryton\tryton.ico" Section InitPluginsDir ;Set output path to the installation directory SetOutPath '$PLUGINSDIR' ;Put file File /r "dist\*" File "COPYRIGHT" File "INSTALL" File "LICENSE" File "README" File "CHANGELOG" SetOutPath "$PLUGINSDIR\doc" File /r "doc\*" ;Run the exe SetOutPath '$EXEDIR' nsExec::Exec $PLUGINSDIR\tryton.exe SectionEnd tryton-4.6.5/make-darwin-installer.sh0000644000175000017500000000061613251060075017125 0ustar cedced00000000000000#!/bin/sh set -e version=`python setup.py --version` python setup.py compile_catalog python setup-freeze.py bdist_mac rm -rf dist mkdir dist mv build/Tryton.app dist/ for f in CHANGELOG COPYRIGHT LICENSE README; do cp ${f} dist/${f}.txt done cp -r doc dist/ rm -f "tryton-${version}.dmg" hdiutil create "tryton-${version}.dmg" -volname "Tryton Client ${version}" \ -fs HFS+ -srcfolder dist tryton-4.6.5/doc/0000755000175000017500000000000013260723567013155 5ustar cedced00000000000000tryton-4.6.5/doc/usage.rst0000644000175000017500000005543513255571102015015 0ustar cedced00000000000000 :tocdepth: 2 Client Usage ############ This document is the reference about the concepts of the graphical user interface (also known as *Tryton client* ) of the Tryton application framework. Name **** tryton - Graphical user client of the Tryton application framework Synopsis ******** :: tryton [options] [url] After startup the `login dialog`__ is displayed. __ Menu-Connection_ Options ******* --version Show program version number and exit -h, --help Show help message and exit -c FILE, --config=FILE Specify alternate `configuration file`_ -d, --dev Enable development mode, which deactivates client side caching -v, --verbose Enable basic debugging -l LOG_LEVEL, --log-level=LOG_LEVEL Specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL -u LOGIN, --user=LOGIN Specify the login user -s SERVER, --server=SERVER Specify the server hostname:port Environment *********** `GTKOSXAPPLICATION` Activate with native Mac desktop URL *** When an url is passed, the client will try to find already running client that could handle it and send to this one to open the url. If it doesn't find one then it will start the GUI and open the url itself. The url schemes are: `tryton://[:]//model/[/][;parameters]` `tryton://[:]//wizard/[;parameters]` `tryton://[:]//report/[;parameters]` where `parameters` are the corresponding fields of actions encoded in `JSON`_. .. _JSON: http://en.wikipedia.org/wiki/Json .. Note:: `model` is for `act_window` .. Note:: `report` must have at least a data parameter with `ids`, `id` and `model name` Overview ******** The following schematic illustration of the Tryton client shows the names of all important visual parts. Figure: Tryton client application:: Client Window ________________________________________________________________ | Tryton _ o x| |----------------------------------------------------------------| Menu bar | Connection User Options Favorites Help | |________________________________________________________________| | | ______ | Tabs | Menu | [Tab1] |[Tab2]| [Tab3]... | |-------------| +-------+ +--------------------------------+| | + | | Menu Tab2 || | |-+ | |-----------------------------------------------|| Tool bar | | |- | | New Save Switch Reload | Prev Next | Attach v || | | |- | |-----------------------------------------------|| | + | | _______________________ || Search widget | |-+ | | Filter | *| Bookmark <- -> || | | |- | |-----------------------------------------------|| | | |- | | || | + | | || View | |-+ | | || | |- | | || | |- | | || | | | || | | | || | | | || | | | || |_____________| |_______________________________________________|| |________________________________________________________________| Menu Bar ^^^^^^^^ The menu bar is the main control unit. It provides most of the functionalities of the client application. The menu bar is grouped into categories. It is controlled with mouse or keyboard. The `menu bar items`_ are explained later. Mouse and Keyboard Use ++++++++++++++++++++++ Most functions of the Tryton client can be accessed with mouse or keyboard. `Key bindings`__ for all menu items are preset. Furthermore all key bindings are manually configurable. To change the binding of a menu item the user needs to put the cursor onto it and simply press the user defined key combination. For this purpose it is needed to activate the configuration of the key bindings with Options > Menubar > Change Accelerators. After the configuration it is preferable to disable Change Accelerators, to avoid accidental changes of key bindings while navigating the Menu bar with the keyboard. To remove a key binding simply press the delete button while pointing the cursor on the menu item to change. .. Note:: Usually key bindings are composed with modifier keys. __ Menu-Help-Keyboard_Shortcuts_ Additionally the menu bar items are accessible with the *Alt* or *Option* key. The user needs to hold the *Alt* or *Option* key followed by the underlined character of the menu bar item to choose. To dive into deeper menu levels, he needs to release the *Alt* or *Option* key and to simply press the underlined letter of the sub menu item. If there exist several menu items with the same shortcut, repeated activation of the shortcut key will jump to the next one. The second mouse button (usually right mouse button) provides an additional contextual menu for some views and fields. In this context menu the user finds :term:`actions` to copy and paste contents or selections for several fields. Tabbed Main Frame ^^^^^^^^^^^^^^^^^ This part of the client contains all the related contents and functions provided by the :term:`Tryton server` :term:`modules`. All aspects inside the *main frame* depend at least on the individual set of installed modules. The main frame provides a `tabbed document interface`__ to arrange different views side by side. New :term:`tabs` are opened by special :term:`actions`, like choosing a menu item or clicking some action buttons. All tabs include titles which show the name of the provided view. :term:`Tabs` can be arranged by Drag and Drop. __ TDI_ .. _TDI: http://en.wikipedia.org/wiki/Tabbed_document_interface .. Note:: Inside :term:`views` there can be tabs, too. Menu ++++ The *menu* does not contain fixed menu items. All of them are dynamically provided by the actual set of the installed :term:`modules` depending on the access rules of the current user. If a menu item is clicked, the appropriate action will open in a new tab. A search field allows to quickly filter the menu items by name and to search in models for which the global search is enabled. Menu Bar Items ************** The following section describes the function of each menu bar entry in detail. A rule of thumb: All items of the menu bar that are suffixed by three dots (...) will open an intermediate :term:`dialog` for setting up the provided menu action. Most dialogs provide a *Cancel* button, used to stop the complete dialog process. Connection ^^^^^^^^^^ The connection menu level provides functions about Tryton server login, logout and closing the client application. .. _Menu-Connection: Connect... By choosing this menu entry the client will be connected to an available Tryton server. A :term:`dialog` opens to request credentials: * `Server`__ * Database: Database to connect server side * User name: Tryton user name to login * Password: Tryton password to login * Actions: - Connect: Connects to the server with the given credentials. - Cancel .. note:: Depending on server configuration for session timeout, the actual user may be logged out of the current session, and need to login again. Default timeout for inactivity logout is six minutes. .. _Menu-Connection-Disconnect: Disconnect... Disconnects the client from an active server connection. In case of unsaved changes in an open tab, the Tryton client will request for saving the changes. __ Connection-Server-Connection_ .. _Connection-Server-Connection: Server (connection) dialog: This :term:`dialog` is widely used to setup a Tryton server connection. This dialog shows the actual state of the client/server communication. It also shows when there is no connection to a Tryton server at all. The *Change* button opens a dialog for connection details: * Server: Network address or IP number of the Tryton server (protocols are not supported) * Port: Port where the Tryton server listens. .. note:: If there is no connection to a Tryton server, many items in menu bar and tool bar are deactivated. User ^^^^ This menu bar item controls the preferences of the actual user. .. _Menu-User-Preferences: Preferences... A preference dialog opens, where the actual user can show and edit his personal settings. All user preferences are stored server side. I.e. logging in with the same credentials from different computers always restores the same preferences. * Name: Real name of the Tryton user. * Password: Password of the Tryton user. * Email: Email address of the Tryton user. * Signature: Signature block for the Tryton user. * Menu Action: Defines the action which is called as the `Menu`_. * Language: Language of the client interface. * Timezone: The local timezone where the user/client resides. * Groups: Displays the users membership to access groups. * Applications: A list of applications along with their access key and the authorization state. .. _Menu-User-Menu-Reload: Menu Reload: Reload the menu. .. _Menu-User-Menu-Toggle: Menu Toggle: Toggle the menu visibility Options ^^^^^^^ The Options menu sets up several visual and context depending preferences. Toolbar +++++++ .. _Menu-Options-Toolbar-Default: Default: Shows labels and icons as defaulted in the GTK configuration. .. _Menu-Options-Toolbar-Text_and_Icons: Text and Icons: Shows labels and icons in the tool bar. .. _Menu-Options-Toolbar-Icons: Icons: Shows icons only in the tool bar. .. _Menu-Options-Toolbar-Text: Text: Shows labels only in the tool bar. Menubar +++++++ .. _Menu-Options-Menubar-Accelerators: Change Accelerators: If checked, keyboard shortcuts can be defined. S. a. `mouse and keyboard use`_ Mode ++++ .. _Menu-Options-Mode-Normal: Normal: Shows the client in full feature mode. .. _Menu-Options-Mode_PDA: PDA: Shows the client in a condensed mode. Form ++++ .. _Menu-Options-Form-Toolbar: Toolbar: Checkbox to disable/enable the tool bar. .. _Menu-Options-Form-Save_Columns_Width: Save Width/Height: Check box to enable saving of manually adjusted widths of columns in lists and trees. Additionally saving of manually adjusted widths and heights of dialog and popup windows. .. _Menu-Options-Form-Save_Tree_State: Save Tree Expanded State: Check box to enable saving of expanded and selected nodes in trees/lists. .. _Menu-Options-Form-Fast_Tabbing: Fast Tabbing: Check box to enable fast tabbing navigation by skipping readonly entries. .. _Menu-Options-Form-Spell_Checking: Spell Checking: Check box to enable spell checking in fields. .. _Menu-Options-Email: Email...: Open a dialog to set up an email reader. * Command Line: The command line calling the email reader. * Placeholders: - ``${to}``: the destination email address - ``${cc}``: the carbon copy email address - ``${subject}``: the subject of the email - ``${body}``: the body of the email - ``${attachment}``: the attachment of the email * Examples: - Thunderbird 2 on Linux: ``thunderbird -compose "to='${to}',cc='${cc}',subject='${subject}',body='${body}',attachment='file://${attachment}'"`` - Thunderbird 2 on Windows XP SP3: ``"C:\\Program Files\\Mozilla Thunderbird\\thunderbird.exe" -compose to="${to}",cc="${cc}",subject="${subject}",body="${body}",attachment="${attachment}"`` .. note:: The path of *Program Files* may vary dependent on the localization of your Windows version. .. _Menu-Options-Save_Options: Save Options: Saves all the options. Favorites ^^^^^^^^^ A collection of user defined menu favorites. Help ^^^^ .. _Menu-Help-Keyboard_Shortcuts: Keyboard Shortcuts...: Shows the information dialog of the predefined keyboard shortcut map. * Edition Widgets: Shows shortcuts working on text entries, relation entries and date/time entries. .. _Menu-Help-About: About...: License, Contributors, Authors of Tryton Tool Bar ******** The tool bar contains the functionalities linked to the current tab. Some operations are working with one record or with a selection of :term:`records`. In :term:`form view` the actual record is selected for operations. In :term:`tree view` all selected records are used for operations. .. _Toolbar-New: New: Creates a new record. .. _Toolbar-Save: Save: Saves the actual record. .. _Toolbar-Switch_View: Switch View: Switches the actual view aspect to: * :term:`Form view` * :term:`Tree view` * :term:`Graph view` Not all views provide all aspects. .. _Toolbar-Reload_Undo: Reload/Undo: Reloads the content of the actual tab. Undoes changes, if save request for the current record is denied. .. _Toolbar-Duplicate: Duplicate: Duplicates the content of the actual record in a newly created record. .. _Toolbar-Delete: Delete: Deletes the selected or actual record. .. _Toolbar-Previous: Previous: Goes to the last record in a list (sequence). .. _Toolbar-Next: Next: Goes to the next record in a list (sequence). .. _Toolbar-Search: Search: Goes to the search widget. .. _Toolbar-View_Logs: View Logs...: Shows generic information of the current record. .. _Toolbar-Show revisions: Show revisions...: Reload the current view/record at a specific revision. .. _Toolbar-Close: Close Tab: Closes the current tab. A Request :term:`Dialog` opens in case of unsaved changes. .. _Toolbar-Attachment: Attachment: The attachment item handles the document management system of Tryton which is able to attach files to any arbitrary :term:`model`. On click it opens the attachments :term:`dialog`. The default dialog shows a list view of the attached files and links. .. _Toolbar-Actions: Actions...: Shows all actions for the actual view, model and record. .. _Toolbar-Relate: Relate...: Shows all relate view for the actual view, model and record. .. _Toolbar-Report: Report...: Shows all reports for the actual view, model and record. .. _Toolbar-Email: E-Mail...: Shows all email reports for the actual view, model and record. .. _Toolbar-Print: Print...: Shows all print actions for the actual view, model and record. .. _Toolbar-Copy-URL: Copy URL: Copy the URL of the form into the clipboard. .. _Toolbar-Export_Data: Export Data...: Export of current/selected records into :term:`CSV`-file or open it in Excel. * Predefined exports - Choose preferences of already saved exports. * All Fields: Fields available from the model. * Fields to export: Defines the specific fields to export. * Options: - Save: Save export as a CSV file. - Open: Open export in spread sheet application. * Add field names: Add a header row with field names to the export data. * Actions: - Add: Adds selected fields to *Fields to export*. - Remove: Removes selected fields from *Fields to export*. - Clear: Removes all fields from *Fields to export*. - Save Export: Saves field mapping to a *Predefined export* with a name. - Delete Export: Deletes a selected *Predefined export*. - OK: Exports the data (action depending on *Options*). - Cancel .. _Toolbar-Import_Data: Import Data...: Import records from :term:`CSV`-file. * All Fields: Fields available in the model (required fields are marked up). * Fields to Import: Exact sequence of all columns in the CSV file. * File to Import: File :term:`dialog` for choosing a CSV file to import. * CSV Parameters: Setup specific parameters for chosen CSV file. - Field Separator: Character which separates CSV fields. - Text Delimiter: Character which encloses text in CSV. - Encoding: :term:`Character encoding` of CSV file. - Lines to Skip: Count of lines to skip a headline or another offset. * Actions: - Add: Adds fields to *Fields to Import*. - Remove: Deletes fields from *Fields to Import*. - Clear: Removes all fields from *Fields to Import*. - Auto-Detect: Tries to auto detect fields in the CSV *File to Import*. - OK: Proceeds the data import. - Cancel Widgets ******* There are a several widgets used on Tryton in client side. The follow sections will explains some of them. Date/DateTime/Time Widgets ^^^^^^^^^^^^^^^^^^^^^^^^^^ These widgets have several key shortcuts to quickly modify the value. Each key increases if lower case or decreases if upper case: - `y`: by one year - `m`: by one month - `w`: by one week - `d`: by one day - `h`: by one hour - `i`: by one minute - `s`: by one second Search Widget ^^^^^^^^^^^^^ The search widget adds the ability to easily search for records on the current tab. This widget is visible only on :term:`tree view`. The Syntax ++++++++++ A query is composed of search clauses. A clause is composed of a field name (with `:` at the end), an operator and a value. The field name is optional and defaults to the record name. The operator is also optional and defaults to `like` or `equal` depending on the type of the field. The default operator is `=` except for fields of type `char`, `text` and `many2one` which is `ilike`. Field Names +++++++++++ All field names shown in the :term:`tree view` can be searched. Field names must be followed by a `:` For example: ``Name:`` If the field name contains spaces, it is possible to escape it using double quotes. For example: ``"Receivable Today":`` Operators +++++++++ The following operators can be used: * `=`: equal to * `<`: less then * `<=`: less then or equal to * `>`: greater then * `>=`: greater then or equal to * `!=`: not equal * `!`: not equal or not like (depending of the type of field) For example: ``Name: != Dwight`` .. note:: The `ilike` operator is never explicit and `%` is appended to the value to make it behaves like `starts with` Values ++++++ The format of the value depends on the type of the field. A list of values can be set using `;` as separator. For example: ``Name: Michael; Pam`` It will find all records having the `Name` starting with `Michael` or `Pam`. A range of number values can be set using `..`. For example: ``Amount: 100..500`` It will find all records with `Amount` between `100` and `500` included. There are two wildcards: * `%`: matches any string of zero or more characters. * `_`: matches any single character. It is possible to escape special characters in values by using double quotes. For example: ``Name: "Michael:Scott"`` Here it will search with the value `Michael:Scott`. Clause composition ++++++++++++++++++ The clauses can be composed using the two boolean operators `and` and `or`. By default, there is an implicit `and` between each clause if no operator is specified. For example: ``Name: Michael Amount: 100`` is the same as ``Name: Michael and Amount: 100`` The `and` operator has a highest precedence than `or` but you can change it by using parenthesis. For example: ``(Name: Michael or Name: Pam) and Amount: 100`` is different than ``Name: Michael or Name: Pam and Amount: 100`` which is evaluated as ``Name: Michael or (Name: Pam and Amount: 100)`` RichText Editor ^^^^^^^^^^^^^^^ This feature create a rich text editor with various features that allow for text formatting. The features are: * Bold: On/off style of bold text * Italic: On/off style of italic text * Underline: On/off style of underline text * Choose font family: Choice from a combo box the desired font family * Choose font size: Choice from a combo box the desired size font * Text justify: Choice between four options for alignment of the line (left, right, center, fill) * Background color: Choose the background color of text from a color palette * Foreground color: Choose the foreground color of text from a color palette Besides these features, it can change and edit text markup. The text markup feature has a similar HTML tags and is used to describe the format specified by the user and is a way of storing this format for future opening of a correct formatted text. The tags are explain follows: * Bold: Tag `b` is used, i.e. text * Italic: Tag `i` is used, i.e. text * Underline: Tag `u` is used, i.e. text * Font family: It is a attribute `font-family` for `span` tag, i.e. text * Font size: It is a attribute `size` for `span` tag, i.e. text * Text Justify: For justification text is used paragraph tag `p`. The paragraph tag is used to create new lines and the alignment is applied across the board. Example:

some text

* Background color: It is a attribute `background` for `span` tag, i.e. text * Foreground color: It is a attribute `foreground` for `span` tag, i.e. text CSS *** The client can be styled using the file `theme.css`. Here are the list of custom selectors: * `.readonly`: readonly widget or label * `.required`: widget or label of required field * `.invalid`: widget for which the field value is not valid * `window.profile-`: the name of the connection profile is set on the main window For more information about style option see `GTK+ CSS`_ .. GTK+ CSS:: https://developer.gnome.org/gtk3/stable/chap-css-overview.html Appendix ******** Configuration File ^^^^^^^^^^^^^^^^^^ :: ~/.config/tryton/x.y/tryton.conf # General configuration ~/.config/tryton/x.y/accel.map # Accelerators configuration ~/.config/tryton/x.y/known_hosts # Fingerprints ~/.config/tryton/x.y/ca_certs # Certification Authority (http://docs.python.org/library/ssl.html#ssl-certificates) ~/.config/tryton/x.y/profiles.cfg # Profile configuration ~/.config/tryton/x.y/plugins # Local user plugins directory ~/.config.tryton/x.y/theme.css # Custom CSS theme .. note:: `~` means the home directory of the user. But on Windows system it is the `APPDATA` directory. tryton-4.6.5/doc/introduction.rst0000644000175000017500000000024613175640533016426 0ustar cedced00000000000000Introduction ############ Tryton is a Graphical User Interface to the Tryton Framework based on GTK__ and Python__. __ http://www.gtk.org __ http://www.python.org tryton-4.6.5/doc/index.rst0000755000175000017500000000043113175640533015013 0ustar cedced00000000000000.. Tryton documentation master file. You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. Tryton Client ############# Contents: .. toctree:: :maxdepth: 2 introduction installation usage glossary tryton-4.6.5/doc/glossary.rst0000644000175000017500000001354713175640533015560 0ustar cedced00000000000000Glossary ######## .. glossary:: :sorted: Actions An *action* is a function which is triggered by a user intervention. *Actions* are called from activating menu items or pushing buttons. Actions often provide :term:`wizards`. Board The *board* is a type of :term:`views` able to handle other views. This view type is not documented or not used for now. Character Encoding See [WP-ENCOD]_ CSV File format for Comma Separated Values. See [WP-CSV]_ Data *Data* means information content produced by users. Dialog A *dialog* is a :term:`popup` window, which overlays other windows and request user interaction. *Dialogs* are used to set up special :term:`actions`. Fields *Fields* are attributes of a *data object*. *Fields* are represented as table fields in relational databases. Form View The *form* is a mode of :term:`views`, which displays single :term:`records` of data. Form The *form* is the general type of :term:`views` used in Tryton. The *form* provides several modes for presenting :term:`data`: * :term:`Form View` * :term:`Tree View` * :term:`Graph View` Graph View *Graph view* is a mode of :term:`views` to show sets of data in a diagram. *Graph views* can be pie-charts or bar-charts. Main Frame The *main frame* is a huge part arranged in the center of the :term:`Tryton client`. *Using the Tryton client* means mainly using the *main frame* part. It contains :term:`tabs` to organize and to show different :term:`views`. Model A *model* describes how data is represented and accessed. Models formally define records and relationships for a certain domain of interest. Modules *Modules* are enclosed file packages for the :term:`Tryton server`. A *Module* defines the :term:`Model`, the presentation of the information (:term:`views`), functions, :term:`actions` and default presets. Additionally *modules* may provide standardized data like ISO names for countries. *Modules* in Tryton are build up generically. That is, they are constructed as simple as possible to provide the desired functionality. Plugins A *plugin* is an add-on module for the :term:`Tryton client`. Popup A small window which pops up the main window. Records A *record* is a singular dataset in a :term:`Model`. *Records* are represented as lines or *records* in a relational database table. Tabs *Tabs* are :term:`widgets` to arrange different contents side by side. They are used to switch quickly between different domains of interest. Tryton uses *tabs* in two layer: * A tabbed :term:`Main Frame`. * Tabs inside :term:`Views`. The main frame consists of *tabs* that embed the main menu and all views to an appropriate :term:`model`. The other type of *tabs* is used inside of :term:`views` to split them into visual domains of the same model. These *tabs* are used for structuring contents of one model to different sub headings. Three-Tiers A *three-tiers* application framework like Tryton, is build up of three different software components: 1. The storage or data tier. 2. The logic or application tier. 3. The presentation tier. The storage tier in the Tryton framework is provided by the PostgreSQL database engine. The application logic tier is provided by :term:`Tryton server` and its :term:`modules`. The presentation tier is mainly provided by the :term:`Tryton client`. In a *three tiers* framework, the presentation tier (client) never connects directly to the storage tier. All communication is controlled by the application tier. Tree View *Tree view* is a mode of :term:`views` showing sets of :term:`data`. *Tree views* can be flat lists or tables as well as tree-like nested lists. Tryton Server The *Tryton server* is the application or logic tier in the :term:`three-tiers` application platform *Tryton*. The *Tryton server* connects the underlying application logic of the different :term:`modules` with corresponding database records. The *Tryton server* provides different interfaces to present the generated information: * :term:`Tryton client`: (graphical user interface GUI) * XMLRPC see [WP-XMLRPC]_ * WebDAV see [WP-WebDAV]_ * OpenOffice Tryton Client The *Tryton client* application is the graphical user interface (GUI) of the :term:`Tryton server`. Views A *view* is the visual presentation of :term:`data`. *Views* resides inside :term:`tabs` in the :term:`main frame` of the :term:`Tryton client`. There are two general types of *views* in Tryton: 1. :term:`Form` 2. :term:`Board` Each of the view types has different modes to show data. *Views* are built of several :term:`widgets` and provide often additional :term:`actions`. It is also possible to present the same data in different view modes alternately. Widgets A *Widget* is a visual element of a graphical user interface (GUI). Some *Widgets* solely show informations, others allow manipulation from user side. Example *Widgets* are buttons, check-boxes, entry-boxes, selection lists, tables, lists, trees, ... Wizards *Wizards* define stateful sequences of interaction to proceed complex :term:`actions`. A *wizard* divides the complexity of some actions into several user guided steps. References ********** .. [WP-XMLRPC] http://en.wikipedia.org/wiki/Xmlrpc .. [WP-WebDAV] http://en.wikipedia.org/wiki/Webdav .. [WP-CSV] http://en.wikipedia.org/wiki/Comma-separated_values .. [WP-ENCOD] http://en.wikipedia.org/wiki/Character_encoding tryton-4.6.5/doc/installation.rst0000644000175000017500000000223513251060075016376 0ustar cedced00000000000000Installing tryton ================= Prerequisites ------------- * Python 2.7.9 or later (http://www.python.org/) * gtk+ 2.6 or later and pygtk 2.22 or later (http://www.pygtk.org/) * gtk+ 3.20 or later and py-gobject3 (http://www.gtk.org/) * librsvg (http://librsvg.sourceforge.net/) * python-dateutil (http://labix.org/python-dateutil) * chardet (http://pypi.python.org/pypi/chardet) * Optional: cdecimal (http://www.bytereef.org/mpdecimal/index.html) * Optional: GooCalendar (http://code.google.com/p/goocalendar/) Installation ------------ Once you've downloaded and unpacked a tryton source release, enter the directory where the archive was unpacked, and run: ``python setup.py install`` Note that you may need administrator/root privileges for this step, as this command will by default attempt to install tryton to the Python site-packages directory on your system. For advanced options, please refer to the easy_install__ and/or the distutils__ documentation: __ http://setuptools.readthedocs.io/en/latest/easy_install.html __ http://docs.python.org/inst/inst.html To use without installation, run ``bin/tryton`` from where the archive was unpacked. tryton-4.6.5/doc/make.bat0000644000175000017500000000577713175640533014576 0ustar cedced00000000000000@ECHO OFF REM Command file for Sphinx documentation set SPHINXBUILD=sphinx-build set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . if NOT "%PAPER%" == "" ( set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% ) if "%1" == "" goto help if "%1" == "help" ( :help echo.Please use `make ^` where ^ is one of echo. html to make standalone HTML files echo. dirhtml to make HTML files named index.html in directories echo. pickle to make pickle files echo. json to make JSON files echo. htmlhelp to make HTML files and a HTML help project echo. qthelp to make HTML files and a qthelp project echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter echo. changes to make an overview over all changed/added/deprecated items echo. linkcheck to check all external links for integrity echo. doctest to run all doctests embedded in the documentation if enabled goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) if "%1" == "html" ( %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html echo. echo.Build finished. The HTML pages are in %BUILDDIR%/html. goto end ) if "%1" == "dirhtml" ( %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml echo. echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. goto end ) if "%1" == "pickle" ( %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle echo. echo.Build finished; now you can process the pickle files. goto end ) if "%1" == "json" ( %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json echo. echo.Build finished; now you can process the JSON files. goto end ) if "%1" == "htmlhelp" ( %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp echo. echo.Build finished; now you can run HTML Help Workshop with the ^ .hhp project file in %BUILDDIR%/htmlhelp. goto end ) if "%1" == "qthelp" ( %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp echo. echo.Build finished; now you can run "qcollectiongenerator" with the ^ .qhcp project file in %BUILDDIR%/qthelp, like this: echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Tryton.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Tryton.ghc goto end ) if "%1" == "latex" ( %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex echo. echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. goto end ) if "%1" == "changes" ( %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes echo. echo.The overview file is in %BUILDDIR%/changes. goto end ) if "%1" == "linkcheck" ( %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck echo. echo.Link check complete; look for any errors in the above output ^ or in %BUILDDIR%/linkcheck/output.txt. goto end ) if "%1" == "doctest" ( %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest echo. echo.Testing of doctests in the sources finished, look at the ^ results in %BUILDDIR%/doctest/output.txt. goto end ) :end tryton-4.6.5/doc/Makefile0000644000175000017500000000606613175640533014621 0ustar cedced00000000000000# Makefile for Sphinx documentation # # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build PAPER = BUILDDIR = _build # Internal variables. PAPEROPT_a4 = -D latex_paper_size=a4 PAPEROPT_letter = -D latex_paper_size=letter ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest help: @echo "Please use \`make ' where is one of" @echo " html to make standalone HTML files" @echo " dirhtml to make HTML files named index.html in directories" @echo " pickle to make pickle files" @echo " json to make JSON files" @echo " htmlhelp to make HTML files and a HTML help project" @echo " qthelp to make HTML files and a qthelp project" @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" @echo " changes to make an overview of all changed/added/deprecated items" @echo " linkcheck to check all external links for integrity" @echo " doctest to run all doctests embedded in the documentation (if enabled)" clean: -rm -rf $(BUILDDIR)/* html: $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." dirhtml: $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." pickle: $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." json: $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." htmlhelp: $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ ".hhp project file in $(BUILDDIR)/htmlhelp." qthelp: $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp @echo @echo "Build finished; now you can run "qcollectiongenerator" with the" \ ".qhcp project file in $(BUILDDIR)/qthelp, like this:" @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Tryton.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Tryton.qhc" latex: $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ "run these through (pdf)latex." changes: $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." linkcheck: $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." doctest: $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." tryton-4.6.5/doc/build.py0000644000175000017500000000146513175640533014630 0ustar cedced00000000000000# -*- coding: utf-8 -*- # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import sys import os from os import path from sphinx.util.console import nocolor from sphinx.application import Sphinx srcdir = confdir = path.abspath(path.normpath(path.dirname(__file__))) outdir = os.path.join(srcdir, 'html') static_dir = os.path.join(srcdir, 'static') doctreedir = path.join(outdir, '.doctrees') status = sys.stdout confoverrides = {} freshenv = True buildername = 'html' if not path.isdir(outdir): os.mkdir(outdir) if not path.isdir(static_dir): os.mkdir(static_dir) nocolor() app = Sphinx(srcdir, confdir, outdir, doctreedir, buildername, confoverrides, status, sys.stderr, freshenv) app.builder.build_all() tryton-4.6.5/doc/conf.py0000644000175000017500000001476213255571102014454 0ustar cedced00000000000000# -*- coding: utf-8 -*- # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # # Tryton documentation build configuration file, created by # sphinx-quickstart on Tue Mar 23 13:25:32 2010. # # This file is execfile()d with the current directory set to its containing dir # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.append(os.path.abspath('.')) # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = ['sphinx.ext.todo'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8' # The master toctree document. master_doc = 'index' # General information about the project. project = 'tryton' copyright = u'2008-2011, Anne Krings, Bertrand Chenal, Cédric Krier, \ Mathias Behrle, Tobias Paepke, Udo Spallek' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. version = '4.6' # The full version, including alpha/beta/rc tags. release = '4.6' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of documents that shouldn't be included in the build. # unused_docs = [] # List of directories, relative to source directory, that shouldn't be searched # for source files. exclude_trees = ['_build'] # The reST default role (used for this markup: `text`) to use for all documents # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. html_theme = 'default' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_use_modindex = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = '' # Output file base name for HTML help builder. htmlhelp_basename = 'trytonddoc' # -- Options for LaTeX output ------------------------------------------------- # The paper size ('letter' or 'a4'). # latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). # latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]) latex_documents = [ ('index', 'tryton.tex', 'tryton Documentation', u'Anne Krings, Bertrand Chenal, Cédric Krier, Mathias Behrle, ' 'Tobias Paepke, Udo Spallek', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # Additional stuff for the LaTeX preamble. # latex_preamble = '' # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_use_modindex = True tryton-4.6.5/setup.py0000644000175000017500000000636713251060075014122 0ustar cedced00000000000000#!/usr/bin/env python # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from setuptools import setup, find_packages import os import re def read(fname): return open(os.path.join(os.path.dirname(__file__), fname)).read() args = {} try: from babel.messages import frontend as babel args['cmdclass'] = { 'compile_catalog': babel.compile_catalog, 'extract_messages': babel.extract_messages, 'init_catalog': babel.init_catalog, 'update_catalog': babel.update_catalog, } args['message_extractors'] = { 'tryton': [ ('**.py', 'python', None), ], } except ImportError: pass package_data = { 'tryton': ['data/pixmaps/tryton/*.png', 'data/pixmaps/tryton/*.svg', 'data/locale/*/LC_MESSAGES/*.mo', 'data/locale/*/LC_MESSAGES/*.po', ] } data_files = [] def get_version(): init = read(os.path.join('tryton', '__init__.py')) return re.search('__version__ = "([0-9.]*)"', init).group(1) version = get_version() major_version, minor_version, _ = version.split('.', 2) major_version = int(major_version) minor_version = int(minor_version) name = 'tryton' download_url = 'http://downloads.tryton.org/%s.%s/' % ( major_version, minor_version) if minor_version % 2: version = '%s.%s.dev0' % (major_version, minor_version) download_url = 'hg+http://hg.tryton.org/%s#egg=%s-%s' % ( name, name, version) dist = setup(name=name, version=version, description='Tryton client', long_description=read('README'), author='Tryton', author_email='issue_tracker@tryton.org', url='http://www.tryton.org/', download_url=download_url, keywords='business application ERP', packages=find_packages(), package_data=package_data, data_files=data_files, scripts=['bin/tryton'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: X11 Applications :: GTK', 'Framework :: Tryton', 'Intended Audience :: End Users/Desktop', 'License :: OSI Approved :: GNU General Public License (GPL)', 'Natural Language :: Bulgarian', 'Natural Language :: Catalan', 'Natural Language :: Chinese (Simplified)', 'Natural Language :: Czech', 'Natural Language :: Dutch', 'Natural Language :: English', 'Natural Language :: French', 'Natural Language :: German', 'Natural Language :: Hungarian', 'Natural Language :: Italian', 'Natural Language :: Polish', 'Natural Language :: Portuguese (Brazilian)', 'Natural Language :: Russian', 'Natural Language :: Slovenian', 'Natural Language :: Spanish', 'Natural Language :: Japanese', 'Operating System :: OS Independent', 'Programming Language :: Python :: 2.7', 'Topic :: Office/Business', ], platforms='any', license='GPL-3', install_requires=[ # "pygtk >= 2.6", "python-dateutil", "chardet", ], extras_require={ 'cdecimal': ['cdecimal'], 'calendar': ['GooCalendar'], }, zip_safe=False, **args ) tryton-4.6.5/MANIFEST.in0000644000175000017500000000054413251060075014135 0ustar cedced00000000000000include LICENSE include COPYRIGHT include README include INSTALL include CHANGELOG include setup.nsi include setup-single.nsi include setup-bundle.sh include tryton.desktop include *.nsh include setup-freeze.py include make-*-installer.sh include */gtk-2.0/* include doc/* recursive-include doc *.rst recursive-include doc *.po recursive-include doc *.pot tryton-4.6.5/slovenian.nsh0000644000175000017500000000166213175640533015121 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_SLOVENIAN} LangString LicenseText ${CURLANG} "Tryton je izdan pod licenco GNU General Public License, kot jo je objavila Free Software Foundation, bodisi pod razliico 3 ali (po vai izbiri) katerokoli poznejo razliico. Licenco pozorno preberite. Kliknite Naprej za nadaljevanje." LangString LicenseNext ${CURLANG} "&Naprej" LangString PreviousInstall ${CURLANG} "Prosimo, da odstranite prejnjo namestitev Trytona" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "Namestitev tryton.exe in ostalih potrebnih datotek" LangString SecStartMenuName ${CURLANG} "Blinjici v zaetnem meniju in na namizju" LangString SecStartMenuDesc ${CURLANG} "Ustvari blinjici v zaetnem meniju in na namizju" tryton-4.6.5/catalan.nsh0000644000175000017500000000174713175640533014532 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_CATALAN} LangString LicenseText ${CURLANG} "Tryton est alliberat sota la llicncia GNU General Public License publicada per la Free Software Foundation, o b la versi 3 de la llicncia, o (sota la vostra elecci) qualsevol versi posterior. Llegiu detingudament la llicncia. Premeu Segent per continuar." LangString LicenseNext ${CURLANG} "&Segent" LangString PreviousInstall ${CURLANG} "Desinstalleu la versi anterior de Tryton" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "Installa tryton.exe i altres fitxers necessaris" LangString SecStartMenuName ${CURLANG} "Accessos directes al men d'inici i a l'escriptori" LangString SecStartMenuDesc ${CURLANG} "Crea accessos directes al men d'inici i a l'escriptori" tryton-4.6.5/english.nsh0000644000175000017500000000163213175640533014551 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_ENGLISH} LangString LicenseText ${CURLANG} "Tryton is released under the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Please carefully read the license. Click Next to continue." LangString LicenseNext ${CURLANG} "&Next" LangString PreviousInstall ${CURLANG} "Please uninstall the previous Tryton installation" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "Install tryton.exe and other required files" LangString SecStartMenuName ${CURLANG} "Start Menu and Desktop Shortcuts" LangString SecStartMenuDesc ${CURLANG} "Create shortcuts in the start menu and on desktop" tryton-4.6.5/PKG-INFO0000644000175000017500000000531613260723567013512 0ustar cedced00000000000000Metadata-Version: 1.1 Name: tryton Version: 4.6.5 Summary: Tryton client Home-page: http://www.tryton.org/ Author: Tryton Author-email: issue_tracker@tryton.org License: GPL-3 Download-URL: http://downloads.tryton.org/4.6/ Description-Content-Type: UNKNOWN Description: tryton ====== The client of the Tryton application platform. A three-tiers high-level general purpose application platform written in Python and use Postgresql as database engine. It is the core base of an Open Source ERP. It provides modularity, scalability and security. Installing ---------- See INSTALL Package Contents ---------------- bin/ Script for startup. doc/ sphinx documentation in reStructuredText. To generate the HTML: python doc/build.py tryton/ tryton sources. Support ------- If you encounter any problems with Tryton, please don't hesitate to ask questions on the Tryton bug tracker, mailing list, wiki or IRC channel: http://bugs.tryton.org/ http://groups.tryton.org/ http://wiki.tryton.org/ irc://irc.freenode.net/tryton License ------- See LICENSE Copyright --------- See COPYRIGHT For more information please visit the Tryton web site: http://www.tryton.org/ Keywords: business application ERP Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: X11 Applications :: GTK Classifier: Framework :: Tryton Classifier: Intended Audience :: End Users/Desktop Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Natural Language :: Bulgarian Classifier: Natural Language :: Catalan Classifier: Natural Language :: Chinese (Simplified) Classifier: Natural Language :: Czech Classifier: Natural Language :: Dutch Classifier: Natural Language :: English Classifier: Natural Language :: French Classifier: Natural Language :: German Classifier: Natural Language :: Hungarian Classifier: Natural Language :: Italian Classifier: Natural Language :: Polish Classifier: Natural Language :: Portuguese (Brazilian) Classifier: Natural Language :: Russian Classifier: Natural Language :: Slovenian Classifier: Natural Language :: Spanish Classifier: Natural Language :: Japanese Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.7 Classifier: Topic :: Office/Business tryton-4.6.5/tryton.egg-info/0000755000175000017500000000000013260723567015441 5ustar cedced00000000000000tryton-4.6.5/tryton.egg-info/top_level.txt0000644000175000017500000000000713260723567020170 0ustar cedced00000000000000tryton tryton-4.6.5/tryton.egg-info/not-zip-safe0000644000175000017500000000000113211351742017653 0ustar cedced00000000000000 tryton-4.6.5/tryton.egg-info/PKG-INFO0000644000175000017500000000531613260723567016543 0ustar cedced00000000000000Metadata-Version: 1.1 Name: tryton Version: 4.6.5 Summary: Tryton client Home-page: http://www.tryton.org/ Author: Tryton Author-email: issue_tracker@tryton.org License: GPL-3 Download-URL: http://downloads.tryton.org/4.6/ Description-Content-Type: UNKNOWN Description: tryton ====== The client of the Tryton application platform. A three-tiers high-level general purpose application platform written in Python and use Postgresql as database engine. It is the core base of an Open Source ERP. It provides modularity, scalability and security. Installing ---------- See INSTALL Package Contents ---------------- bin/ Script for startup. doc/ sphinx documentation in reStructuredText. To generate the HTML: python doc/build.py tryton/ tryton sources. Support ------- If you encounter any problems with Tryton, please don't hesitate to ask questions on the Tryton bug tracker, mailing list, wiki or IRC channel: http://bugs.tryton.org/ http://groups.tryton.org/ http://wiki.tryton.org/ irc://irc.freenode.net/tryton License ------- See LICENSE Copyright --------- See COPYRIGHT For more information please visit the Tryton web site: http://www.tryton.org/ Keywords: business application ERP Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: X11 Applications :: GTK Classifier: Framework :: Tryton Classifier: Intended Audience :: End Users/Desktop Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Natural Language :: Bulgarian Classifier: Natural Language :: Catalan Classifier: Natural Language :: Chinese (Simplified) Classifier: Natural Language :: Czech Classifier: Natural Language :: Dutch Classifier: Natural Language :: English Classifier: Natural Language :: French Classifier: Natural Language :: German Classifier: Natural Language :: Hungarian Classifier: Natural Language :: Italian Classifier: Natural Language :: Polish Classifier: Natural Language :: Portuguese (Brazilian) Classifier: Natural Language :: Russian Classifier: Natural Language :: Slovenian Classifier: Natural Language :: Spanish Classifier: Natural Language :: Japanese Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python :: 2.7 Classifier: Topic :: Office/Business tryton-4.6.5/tryton.egg-info/SOURCES.txt0000644000175000017500000002266613260723567017341 0ustar cedced00000000000000.hgtags CHANGELOG COPYRIGHT INSTALL LICENSE MANIFEST.in README catalan.nsh english.nsh french.nsh german.nsh make-darwin-installer.sh make-win32-installer.sh portuguese.nsh russian.nsh setup-freeze.py setup-single.nsi setup.cfg setup.nsi setup.py slovenian.nsh spanish.nsh tryton.desktop bin/tryton darwin/gtk-2.0/gdk-pixbuf.loaders darwin/gtk-2.0/gtk.immodules darwin/gtk-2.0/gtkrc doc/Makefile doc/build.py doc/conf.py doc/glossary.rst doc/index.rst doc/installation.rst doc/introduction.rst doc/make.bat doc/usage.rst tryton/__init__.py tryton/client.py tryton/config.py tryton/exceptions.py tryton/fingerprints.py tryton/ipc.py tryton/jsonrpc.py tryton/pyson.py tryton/rpc.py tryton/signal_event.py tryton/translate.py tryton.egg-info/PKG-INFO tryton.egg-info/SOURCES.txt tryton.egg-info/dependency_links.txt tryton.egg-info/not-zip-safe tryton.egg-info/requires.txt tryton.egg-info/top_level.txt tryton/action/__init__.py tryton/action/main.py tryton/common/__init__.py tryton/common/button.py tryton/common/cellrendererbinary.py tryton/common/cellrendererbutton.py tryton/common/cellrendererclickablepixbuf.py tryton/common/cellrenderercombo.py tryton/common/cellrendererfloat.py tryton/common/cellrendererinteger.py tryton/common/cellrenderertext.py tryton/common/cellrenderertoggle.py tryton/common/common.py tryton/common/completion.py tryton/common/datetime_.py tryton/common/datetime_strftime.py tryton/common/domain_inversion.py tryton/common/domain_parser.py tryton/common/entry_position.py tryton/common/environment.py tryton/common/focus.py tryton/common/htmltextbuffer.py tryton/common/placeholder_entry.py tryton/common/popup_menu.py tryton/common/selection.py tryton/common/timedelta.py tryton/common/treeviewcontrol.py tryton/common/widget_style.py tryton/data/locale/tryton.pot tryton/data/locale/bg/LC_MESSAGES/tryton.mo tryton/data/locale/bg/LC_MESSAGES/tryton.po tryton/data/locale/ca/LC_MESSAGES/tryton.mo tryton/data/locale/ca/LC_MESSAGES/tryton.po tryton/data/locale/cs/LC_MESSAGES/tryton.mo tryton/data/locale/cs/LC_MESSAGES/tryton.po tryton/data/locale/de/LC_MESSAGES/tryton.mo tryton/data/locale/de/LC_MESSAGES/tryton.po tryton/data/locale/es/LC_MESSAGES/tryton.mo tryton/data/locale/es/LC_MESSAGES/tryton.po tryton/data/locale/es_419/LC_MESSAGES/tryton.mo tryton/data/locale/es_419/LC_MESSAGES/tryton.po tryton/data/locale/fr/LC_MESSAGES/tryton.mo tryton/data/locale/fr/LC_MESSAGES/tryton.po tryton/data/locale/hu_HU/LC_MESSAGES/tryton.mo tryton/data/locale/hu_HU/LC_MESSAGES/tryton.po tryton/data/locale/it_IT/LC_MESSAGES/tryton.mo tryton/data/locale/it_IT/LC_MESSAGES/tryton.po tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo tryton/data/locale/ja_JP/LC_MESSAGES/tryton.po tryton/data/locale/lo/LC_MESSAGES/tryton.mo tryton/data/locale/lo/LC_MESSAGES/tryton.po tryton/data/locale/lt/LC_MESSAGES/tryton.mo tryton/data/locale/lt/LC_MESSAGES/tryton.po tryton/data/locale/nl/LC_MESSAGES/tryton.mo tryton/data/locale/nl/LC_MESSAGES/tryton.po tryton/data/locale/pl/LC_MESSAGES/tryton.mo tryton/data/locale/pl/LC_MESSAGES/tryton.po tryton/data/locale/pt_BR/LC_MESSAGES/tryton.mo tryton/data/locale/pt_BR/LC_MESSAGES/tryton.po tryton/data/locale/ru/LC_MESSAGES/tryton.mo tryton/data/locale/ru/LC_MESSAGES/tryton.po tryton/data/locale/sl/LC_MESSAGES/tryton.mo tryton/data/locale/sl/LC_MESSAGES/tryton.po tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo tryton/data/locale/zh_CN/LC_MESSAGES/tryton.po tryton/data/pixmaps/tryton/tryton-attachment-hi.svg tryton/data/pixmaps/tryton/tryton-attachment.svg tryton/data/pixmaps/tryton/tryton-bookmark.svg tryton/data/pixmaps/tryton/tryton-clear.svg tryton/data/pixmaps/tryton/tryton-close.svg tryton/data/pixmaps/tryton/tryton-connect.svg tryton/data/pixmaps/tryton/tryton-copy.svg tryton/data/pixmaps/tryton/tryton-delete.svg tryton/data/pixmaps/tryton/tryton-dialog-error.svg tryton/data/pixmaps/tryton/tryton-dialog-information.svg tryton/data/pixmaps/tryton/tryton-dialog-warning.svg tryton/data/pixmaps/tryton/tryton-disconnect.svg tryton/data/pixmaps/tryton/tryton-executable.svg tryton/data/pixmaps/tryton/tryton-find-replace.svg tryton/data/pixmaps/tryton/tryton-find.svg tryton/data/pixmaps/tryton/tryton-folder-new.svg tryton/data/pixmaps/tryton/tryton-fullscreen.svg tryton/data/pixmaps/tryton/tryton-go-home.svg tryton/data/pixmaps/tryton/tryton-go-jump.svg tryton/data/pixmaps/tryton/tryton-go-next.svg tryton/data/pixmaps/tryton/tryton-go-previous.svg tryton/data/pixmaps/tryton/tryton-help.svg tryton/data/pixmaps/tryton/tryton-icon.png tryton/data/pixmaps/tryton/tryton-icon.svg tryton/data/pixmaps/tryton/tryton-list-add.svg tryton/data/pixmaps/tryton/tryton-list-remove.svg tryton/data/pixmaps/tryton/tryton-locale.svg tryton/data/pixmaps/tryton/tryton-lock.svg tryton/data/pixmaps/tryton/tryton-log-out.svg tryton/data/pixmaps/tryton/tryton-mail-message-new.svg tryton/data/pixmaps/tryton/tryton-mail-message.svg tryton/data/pixmaps/tryton/tryton-new.svg tryton/data/pixmaps/tryton/tryton-noimage.png tryton/data/pixmaps/tryton/tryton-note-hi.svg tryton/data/pixmaps/tryton/tryton-note.svg tryton/data/pixmaps/tryton/tryton-open.svg tryton/data/pixmaps/tryton/tryton-preferences-system-session.svg tryton/data/pixmaps/tryton/tryton-preferences-system.svg tryton/data/pixmaps/tryton/tryton-preferences.svg tryton/data/pixmaps/tryton/tryton-print-email.svg tryton/data/pixmaps/tryton/tryton-print-open.svg tryton/data/pixmaps/tryton/tryton-print.svg tryton/data/pixmaps/tryton/tryton-refresh.svg tryton/data/pixmaps/tryton/tryton-save-as.svg tryton/data/pixmaps/tryton/tryton-save.svg tryton/data/pixmaps/tryton/tryton-star.svg tryton/data/pixmaps/tryton/tryton-start-here.svg tryton/data/pixmaps/tryton/tryton-system-file-manager.svg tryton/data/pixmaps/tryton/tryton-system.svg tryton/data/pixmaps/tryton/tryton-text-background.svg tryton/data/pixmaps/tryton/tryton-text-foreground.svg tryton/data/pixmaps/tryton/tryton-text-markup.svg tryton/data/pixmaps/tryton/tryton-undo.svg tryton/data/pixmaps/tryton/tryton-unstar.svg tryton/data/pixmaps/tryton/tryton-web-browser.svg tryton/data/pixmaps/tryton/tryton.icns tryton/data/pixmaps/tryton/tryton.ico tryton/data/pixmaps/tryton/tryton.png tryton/gui/__init__.py tryton/gui/main.py tryton/gui/window/__init__.py tryton/gui/window/about.py tryton/gui/window/attachment.py tryton/gui/window/board.py tryton/gui/window/dblogin.py tryton/gui/window/email.py tryton/gui/window/form.py tryton/gui/window/infobar.py tryton/gui/window/limit.py tryton/gui/window/nomodal.py tryton/gui/window/note.py tryton/gui/window/preference.py tryton/gui/window/revision.py tryton/gui/window/shortcuts.py tryton/gui/window/tabcontent.py tryton/gui/window/win_csv.py tryton/gui/window/win_export.py tryton/gui/window/win_form.py tryton/gui/window/win_import.py tryton/gui/window/win_search.py tryton/gui/window/window.py tryton/gui/window/wizard.py tryton/gui/window/view_board/__init__.py tryton/gui/window/view_board/action.py tryton/gui/window/view_board/view_board.py tryton/gui/window/view_form/__init__.py tryton/gui/window/view_form/model/__init__.py tryton/gui/window/view_form/model/field.py tryton/gui/window/view_form/model/group.py tryton/gui/window/view_form/model/record.py tryton/gui/window/view_form/screen/__init__.py tryton/gui/window/view_form/screen/screen.py tryton/gui/window/view_form/view/__init__.py tryton/gui/window/view_form/view/calendar_.py tryton/gui/window/view_form/view/form.py tryton/gui/window/view_form/view/graph.py tryton/gui/window/view_form/view/list.py tryton/gui/window/view_form/view/screen_container.py tryton/gui/window/view_form/view/calendar_gtk/__init__.py tryton/gui/window/view_form/view/calendar_gtk/calendar_.py tryton/gui/window/view_form/view/calendar_gtk/dates_period.py tryton/gui/window/view_form/view/calendar_gtk/toolbar.py tryton/gui/window/view_form/view/form_gtk/__init__.py tryton/gui/window/view_form/view/form_gtk/binary.py tryton/gui/window/view_form/view/form_gtk/calendar.py tryton/gui/window/view_form/view/form_gtk/char.py tryton/gui/window/view_form/view/form_gtk/checkbox.py tryton/gui/window/view_form/view/form_gtk/dictionary.py tryton/gui/window/view_form/view/form_gtk/float.py tryton/gui/window/view_form/view/form_gtk/image.py tryton/gui/window/view_form/view/form_gtk/integer.py tryton/gui/window/view_form/view/form_gtk/many2many.py tryton/gui/window/view_form/view/form_gtk/many2one.py tryton/gui/window/view_form/view/form_gtk/multiselection.py tryton/gui/window/view_form/view/form_gtk/one2many.py tryton/gui/window/view_form/view/form_gtk/one2one.py tryton/gui/window/view_form/view/form_gtk/progressbar.py tryton/gui/window/view_form/view/form_gtk/pyson.py tryton/gui/window/view_form/view/form_gtk/reference.py tryton/gui/window/view_form/view/form_gtk/richtextbox.py tryton/gui/window/view_form/view/form_gtk/selection.py tryton/gui/window/view_form/view/form_gtk/state_widget.py tryton/gui/window/view_form/view/form_gtk/textbox.py tryton/gui/window/view_form/view/form_gtk/timedelta.py tryton/gui/window/view_form/view/form_gtk/url.py tryton/gui/window/view_form/view/form_gtk/widget.py tryton/gui/window/view_form/view/graph_gtk/__init__.py tryton/gui/window/view_form/view/graph_gtk/bar.py tryton/gui/window/view_form/view/graph_gtk/graph.py tryton/gui/window/view_form/view/graph_gtk/line.py tryton/gui/window/view_form/view/graph_gtk/pie.py tryton/gui/window/view_form/view/list_gtk/__init__.py tryton/gui/window/view_form/view/list_gtk/editabletree.py tryton/gui/window/view_form/view/list_gtk/widget.py tryton/plugins/__init__.py tryton/plugins/translation/__init__.py win32/gtk-2.0/gdk-pixbuf.loaders win32/gtk-2.0/gtk.immodules win32/gtk-2.0/gtkrctryton-4.6.5/tryton.egg-info/dependency_links.txt0000644000175000017500000000000113260723567021507 0ustar cedced00000000000000 tryton-4.6.5/tryton.egg-info/requires.txt0000644000175000017500000000010513260723567020035 0ustar cedced00000000000000python-dateutil chardet [calendar] GooCalendar [cdecimal] cdecimal tryton-4.6.5/tryton/0000755000175000017500000000000013260723567013747 5ustar cedced00000000000000tryton-4.6.5/tryton/plugins/0000755000175000017500000000000013260723567015430 5ustar cedced00000000000000tryton-4.6.5/tryton/plugins/__init__.py0000644000175000017500000000175613175640533017546 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os import imp import gettext from tryton.config import get_config_dir, CURRENT_DIR __all__ = ['MODULES', 'register'] _ = gettext.gettext MODULES = [] def register(): global MODULES paths = [ os.path.join(get_config_dir(), 'plugins'), os.path.join(CURRENT_DIR, 'plugins'), ] paths = filter(os.path.isdir, paths) imported = set() for path in paths: for plugin in os.listdir(path): module = os.path.splitext(plugin)[0] if module == '__init__' or module in imported: continue try: module = imp.load_module(module, *imp.find_module(module, [path])) MODULES.append(module) except ImportError: continue else: imported.add(module.__name__) tryton-4.6.5/tryton/plugins/translation/0000755000175000017500000000000013260723567017766 5ustar cedced00000000000000tryton-4.6.5/tryton/plugins/translation/__init__.py0000644000175000017500000000122713251060075022065 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext from tryton.gui.window import Window from tryton.common import MODELACCESS _ = gettext.gettext def translate_view(datas): model = datas['model'] Window.create('ir.translation', res_id=False, domain=[('model', '=', model)], mode=['tree', 'form']) def get_plugins(model): access = MODELACCESS['ir.translation'] if access['read'] and access['write']: return [ (_('Translate view'), translate_view), ] else: return [] tryton-4.6.5/tryton/gui/0000755000175000017500000000000013260723567014533 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/0000755000175000017500000000000013260723567016042 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/board.py0000644000175000017500000000356613255571102017503 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Board" import gettext from tryton.signal_event import SignalEvent from tryton.gui import Main from tryton.gui.window.view_board import ViewBoard from tryton.common import RPCExecute, RPCException from tabcontent import TabContent _ = gettext.gettext class Board(SignalEvent, TabContent): 'Board' def __init__(self, model, name='', **attributes): super(Board, self).__init__() context = attributes.get('context') self.view_ids = attributes.get('view_ids') try: view, = RPCExecute('model', 'ir.ui.view', 'read', self.view_ids, ['arch'], context=context) except RPCException: raise self.board = ViewBoard(view['arch'], context=context) self.model = model self.dialogs = [] if not name: self.name = self.board.name else: self.name = name self.create_tabcontent() def get_toolbars(self): return {} def widget_get(self): return self.board.widget_get() def sig_reload(self, test_modified=True): self.board.reload() return True def sig_close(self): return True def __eq__(self, value): if not value: return False if not isinstance(value, Board): return False return (self.model == value.model and self.view_ids == value.view_ids and self.board.context == value.board.context and self.name == value.name) def sig_win_close(self, widget): Main.get_main().sig_win_close(widget) def set_cursor(self): if not self.board.actions: return first_action = self.board.actions[0] first_action.screen.set_cursor() tryton-4.6.5/tryton/gui/window/nomodal.py0000644000175000017500000000236613175640533020050 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import tryton.common as common class NoModal(object): def __init__(self): self.parent = common.get_toplevel_window() self.sensible_widget = common.get_sensible_widget(self.parent) self.page = None self.parent_focus = [] focus = self.parent.get_focus() while focus: self.parent_focus.append(focus) focus = focus.get_parent() def register(self): from tryton.gui.main import Main main = Main.get_main() self.page = main.get_page() if not self.page: self.page = main self.page.dialogs.append(self) self.sensible_widget.props.sensitive = False def destroy(self): self.page.dialogs.remove(self) # Test if the parent is not already destroyed if self.parent not in gtk.window_list_toplevels(): return self.parent.present() self.sensible_widget.props.sensitive = True for focus in self.parent_focus: if focus and focus.is_ancestor(self.parent): focus.grab_focus() break tryton-4.6.5/tryton/gui/window/email.py0000644000175000017500000000712713251060075017476 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from tryton.config import TRYTON_ICON, CONFIG from tryton.common import get_toplevel_window _ = gettext.gettext class Email(object): def __init__(self): self.parent = get_toplevel_window() self.win = gtk.Dialog(_('Email'), self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) self.win.set_default_response(gtk.RESPONSE_OK) self.win.set_icon(TRYTON_ICON) self.win.vbox.set_spacing(3) self.win.vbox.pack_start(gtk.Label( _('Email Program Settings')), expand=False, fill=True) self.win.vbox.pack_start(gtk.HSeparator()) hbox = gtk.HBox(spacing=3) label = gtk.Label(_('Command Line:')) hbox.pack_start(label, expand=True, fill=True) self.entry = gtk.Entry() self.entry.set_property('activates_default', True) self.entry.set_width_chars(50) self.entry.set_text(CONFIG['client.email']) label.set_mnemonic_widget(label) hbox.pack_start(self.entry, expand=True, fill=True) self.win.vbox.pack_start(hbox, expand=True, fill=True) label = gtk.Label(_('Legend of Available Placeholders:')) label.set_alignment(0.0, 0.5) label.set_padding(0, 10) self.win.vbox.pack_start(label, expand=False, fill=True) hbox = gtk.HBox(spacing=3) vboxl = gtk.VBox(homogeneous=True, spacing=3) label = gtk.Label(_('To:')) label.set_alignment(0, 0) label.set_padding(10, 0) vboxl.pack_start(label, expand=False, fill=False) label = gtk.Label(_('CC:')) label.set_alignment(0, 0) label.set_padding(10, 0) vboxl.pack_start(label, expand=False, fill=False) label = gtk.Label(_('Subject:')) label.set_alignment(0, 0) label.set_padding(10, 0) vboxl.pack_start(label, expand=False, fill=False) label = gtk.Label(_('Body:')) label.set_alignment(0, 0) label.set_padding(10, 0) vboxl.pack_start(label, expand=False, fill=False) label = gtk.Label(_('Attachment:')) label.set_alignment(0, 0) label.set_padding(10, 0) vboxl.pack_start(label, expand=False, fill=False) vboxr = gtk.VBox(homogeneous=True, spacing=3) label = gtk.Label(' ${to}') label.set_alignment(0, 0) vboxr.pack_start(label, expand=False, fill=False) label = gtk.Label(' ${cc}') label.set_alignment(0, 0) vboxr.pack_start(label, expand=False, fill=False) label = gtk.Label(' ${subject}') label.set_alignment(0, 0) vboxr.pack_start(label, expand=False, fill=False) label = gtk.Label(' ${body}') label.set_alignment(0, 0) vboxr.pack_start(label, expand=False, fill=False) label = gtk.Label(' ${attachment}') label.set_alignment(0, 0) vboxr.pack_start(label, expand=False, fill=False) hbox.pack_start(vboxl, expand=False, fill=False) hbox.pack_start(vboxr, expand=False, fill=False) self.win.vbox.pack_start(hbox, expand=True, fill=True) self.win.show_all() def run(self): "Run the window" res = self.win.run() if res == gtk.RESPONSE_OK: CONFIG['client.email'] = self.entry.get_text() CONFIG.save() self.parent.present() self.win.destroy() return res tryton-4.6.5/tryton/gui/window/view_board/0000755000175000017500000000000013260723567020163 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_board/action.py0000644000175000017500000001225413251060075022002 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. 'Action' import gtk from tryton.gui.window.view_form.screen import Screen import tryton.rpc as rpc import tryton.common as common from tryton.pyson import PYSONDecoder import gettext from tryton.signal_event import SignalEvent from tryton.gui.window.win_form import WinForm from tryton.common import RPCExecute, RPCException from tryton.action import Action as GenericAction _ = gettext.gettext class Action(SignalEvent): def __init__(self, attrs=None, context=None): if context is None: context = {} super(Action, self).__init__() self.name = attrs['name'] self.context = context.copy() try: self.action = RPCExecute('model', 'ir.action.act_window', 'get', self.name) except RPCException: raise view_ids = [] self.action['view_mode'] = None if self.action.get('views', []): view_ids = [x[0] for x in self.action['views']] self.action['view_mode'] = [x[1] for x in self.action['views']] elif self.action.get('view_id', False): view_ids = [self.action['view_id'][0]] if 'view_mode' in attrs: self.action['view_mode'] = attrs['view_mode'] self.action.setdefault('pyson_domain', '[]') self.context.update(rpc.CONTEXT) self.context['_user'] = rpc._USER self.context.update(PYSONDecoder(self.context).decode( self.action.get('pyson_context', '{}'))) eval_ctx = self.context.copy() self.context.update(PYSONDecoder(eval_ctx).decode( self.action.get('pyson_context', '{}'))) self.domain = [] self.update_domain([]) search_context = self.context.copy() search_context['context'] = self.context search_context['_user'] = rpc._USER search_value = PYSONDecoder(search_context).decode( self.action['pyson_search_value'] or '{}') self.widget = gtk.Frame() self.widget.set_border_width(0) vbox = gtk.VBox(homogeneous=False, spacing=3) self.widget.add(vbox) self.title = gtk.Label() self.widget.set_label_widget(self.title) self.widget.set_label_align(0.0, 0.5) self.widget.show_all() self.screen = Screen(self.action['res_model'], mode=self.action['view_mode'], context=self.context, view_ids=view_ids, domain=self.domain, search_value=search_value, row_activate=self.row_activate) vbox.pack_start(self.screen.widget, expand=True, fill=True) self.screen.signal_connect(self, 'record-message', self._active_changed) if attrs.get('string'): self.title.set_text(attrs['string']) else: self.title.set_text(self.action['name']) self.widget.set_size_request(int(attrs.get('width', -1)), int(attrs.get('height', -1))) self.screen.search_filter() def row_activate(self): if not self.screen.current_record: return if (self.screen.current_view.view_type == 'tree' and int(self.screen.current_view.attributes.get( 'keyword_open', 0))): GenericAction.exec_keyword('tree_open', { 'model': self.screen.model_name, 'id': (self.screen.current_record.id if self.screen.current_record else None), 'ids': [r.id for r in self.screen.selected_records], }, context=self.screen.context.copy(), warning=False) else: def callback(result): if result: self.screen.current_record.save() else: self.screen.current_record.cancel() WinForm(self.screen, callback) def set_value(self, mode, model_field): self.screen.current_view.set_value() return True def display(self): self.screen.search_filter(self.screen.screen_container.get_text()) def _active_changed(self, *args): self.signal('active-changed') def _get_active(self): if self.screen and self.screen.current_record: return common.EvalEnvironment(self.screen.current_record) active = property(_get_active) def update_domain(self, actions): domain_ctx = self.context.copy() domain_ctx['context'] = domain_ctx domain_ctx['_user'] = rpc._USER for action in actions: if action.active: domain_ctx[action.name] = action.active new_domain = PYSONDecoder(domain_ctx).decode( self.action['pyson_domain']) if self.domain == new_domain: return del self.domain[:] self.domain.extend(new_domain) if hasattr(self, 'screen'): # Catch early update # Using idle_add to prevent corruption of the event who triggered # the update. def display(): if self.screen.widget.props.window: self.display() gtk.idle_add(display) tryton-4.6.5/tryton/gui/window/view_board/__init__.py0000644000175000017500000000025113175640533022266 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from view_board import * tryton-4.6.5/tryton/gui/window/view_board/view_board.py0000644000175000017500000001404413251060075022645 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import xml.dom.minidom from tryton.gui.window.view_form.view.form import Container from tryton.common import node_attributes, ICONFACTORY from .action import Action _ = gettext.gettext class ViewBoard(object): 'View board' def __init__(self, arch, context=None): self.context = context self.actions = [] xml_dom = xml.dom.minidom.parseString(arch) for node in xml_dom.childNodes: if node.nodeType == node.ELEMENT_NODE: break self.attributes = node_attributes(node) self.widget = self.parse(node).table self.widget.show_all() self._active_changed(None) def parse(self, node, container=None): if not container: node_attrs = node_attributes(node) container = Container(int(node_attrs.get('col', 4))) for node in node.childNodes: if node.nodeType != node.ELEMENT_NODE: continue node_attrs = node_attributes(node) for i_field in ('yexpand', 'yfill', 'xexpand', 'xfill', 'colspan', 'position'): if i_field in node_attrs: node_attrs[i_field] = int(node_attrs[i_field]) parser = getattr(self, '_parse_%s' % node.tagName) parser(node, container, node_attrs) return container def _parse_image(self, node, container, attributes): ICONFACTORY.register_icon(attributes['name']) image = gtk.Image() image.set_from_stock(attributes['name'], gtk.ICON_SIZE_DIALOG) container.add(image, attributes) def _parse_separator(self, node, container, attributes): vbox = gtk.VBox() if attributes.get('string'): label = gtk.Label(attributes['string']) label.set_alignment(float(attributes.get('xalign', 0.0)), float(attributes.get('yalign', 0.5))) vbox.pack_start(label) vbox.pack_start(gtk.HSeparator()) container.add(vbox, attributes) def _parse_label(self, node, container, attributes): if not attributes.get('string'): container.add(None, attributes) return label = gtk.Label(attributes['string']) label.set_alignment(float(attributes.get('xalign', 0.0)), float(attributes.get('yalign', 0.5))) label.set_angle(int(attributes.get('angle', 0))) attributes.setdefault('xexpand', 0) container.add(label, attributes) def _parse_newline(self, node, container, attributes): container.add_row() def _parse_notebook(self, node, container, attributes): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) notebook = gtk.Notebook() notebook.set_scrollable(True) container.add(notebook, attributes) self.parse(node, notebook) def _parse_page(self, node, notebook, attributes): tab_box = gtk.HBox(spacing=3) if '_' not in attributes['string']: attributes['string'] = '_' + attributes['string'] label = gtk.Label(attributes['string']) label.set_use_underline(True) tab_box.pack_start(label) if 'icon' in attributes: ICONFACTORY.register_icon(attributes['icon']) pixbuf = tab_box.render_icon(attributes['icon'], gtk.ICON_SIZE_SMALL_TOOLBAR) icon = gtk.Image() icon.set_from_pixbuf(pixbuf) tab_box.pack_start(icon) tab_box.show_all() viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolledwindow.add(viewport) scrolledwindow.show_all() notebook.append_page(scrolledwindow, tab_box) container = self.parse(node) viewport.add(container.table) def _parse_group(self, node, container, attributes): group = self.parse(node) group.table.set_homogeneous(attributes.get('homogeneous', False)) frame = gtk.Frame() frame.set_label(attributes.get('string')) if not attributes.get('string'): frame.set_shadow_type(gtk.SHADOW_NONE) frame.set_border_width(0) frame.add(group.table) container.add(frame, attributes) def _parse_paned(self, node, container, attributes, Paned): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) paned = Paned() if 'position' in attributes: paned.set_position(attributes['position']) container.add(paned, attributes) self.parse(node, paned) def _parse_hpaned(self, node, container, attributes): self._parse_paned(node, container, attributes, gtk.HPaned) def _parse_vpaned(self, node, container, attributes): self._parse_paned(node, container, attributes, gtk.VPaned) def _parse_child(self, node, paned, attributes): container = self.parse(node) if not paned.get_child1(): pack = paned.pack1 else: pack = paned.pack2 pack(container.table, resize=True, shrink=True) def _parse_action(self, node, container, attributes): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) action = Action(attributes, self.context) action.signal_connect(self, 'active-changed', self._active_changed) self.actions.append(action) container.add(action.widget, attributes) def widget_get(self): return self.widget def reload(self): for action in self.actions: action.display() def _active_changed(self, event_action, *args): for action in self.actions: if action == event_action: continue action.update_domain(self.actions) tryton-4.6.5/tryton/gui/window/note.py0000644000175000017500000000270313251060075017347 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext from tryton.gui.window.view_form.screen import Screen from tryton.gui.window.win_form import WinForm _ = gettext.gettext class Note(WinForm): "Note window" def __init__(self, record, callback=None): self.resource = '%s,%s' % (record.model_name, record.id) self.note_callback = callback title = _('Notes (%s)') % (record.rec_name()) screen = Screen('ir.note', domain=[ ('resource', '=', self.resource), ], mode=['tree', 'form'], exclude_field='resource') super(Note, self).__init__(screen, self.callback, view_type='tree', title=title) screen.search_filter() def destroy(self): self.prev_view.save_width_height() super(Note, self).destroy() def callback(self, result): if result: resource = self.screen.group.fields['resource'] unread = self.screen.group.fields['unread'] for record in self.screen.group: if record.loaded or record.id < 0: resource.set_client(record, self.resource) if 'unread' not in record.modified_fields: unread.set_client(record, False) self.screen.save_current() if self.note_callback: self.note_callback() tryton-4.6.5/tryton/gui/window/wizard.py0000644000175000017500000003176513255571102017716 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import logging import gettext import gtk import pango from tryton.signal_event import SignalEvent import tryton.common as common from tryton.gui.window.view_form.screen import Screen from tryton.gui import Main from tryton.exceptions import TrytonServerError from tryton.gui.window.nomodal import NoModal from tryton.common.button import Button from tryton.common import RPCExecute, RPCException from tryton.common import TRYTON_ICON from .infobar import InfoBar _ = gettext.gettext logger = logging.getLogger(__name__) class Wizard(InfoBar): def __init__(self, name=''): super(Wizard, self).__init__() self.widget = gtk.VBox(spacing=3) self.toolbar_box = None self.widget.show() self.name = name or '' self.id = None self.ids = None self.action = None self.action_id = None self.direct_print = False self.email_print = False self.email = False self.context = None self.states = {} self.response2state = {} self.__processing = False self.__waiting_response = False self.session_id = None self.start_state = None self.end_state = None self.screen = None self.screen_state = None self.state = None def run(self, action, data, direct_print=False, email_print=False, email=None, context=None): self.action = action self.action_id = data.get('action_id') self.id = data.get('id') self.ids = data.get('ids') self.model = data.get('model') self.direct_print = direct_print self.email_print = email_print self.email = email self.context = context def callback(result): try: result = result() except RPCException: self.destroy() return self.session_id, self.start_state, self.end_state = result self.state = self.start_state self.process() RPCExecute('wizard', action, 'create', callback=callback) def process(self): from tryton.action import Action if self.__processing or self.__waiting_response: return self.__processing = True ctx = self.context.copy() ctx['active_id'] = self.id ctx['active_ids'] = self.ids ctx['active_model'] = self.model ctx['action_id'] = self.action_id if self.screen: data = { self.screen_state: self.screen.get_on_change_value(), } else: data = {} def callback(result): try: result = result() except RPCException, rpc_exception: if (not isinstance(rpc_exception.exception, TrytonServerError) or not self.screen): self.state = self.end_state self.end() self.__processing = False return if 'view' in result: self.clean() view = result['view'] self.update(view['fields_view'], view['defaults'], view['buttons']) self.screen_state = view['state'] self.__waiting_response = True else: self.state = self.end_state def execute_actions(): for action in result.get('actions', []): for k, v in [ ('direct_print', self.direct_print), ('email_print', self.email_print), ('email', self.email), ]: action[0].setdefault(k, v) Action._exec_action(*action, context=self.context.copy()) if self.state == self.end_state: self.end(lambda *a: execute_actions()) else: execute_actions() self.__processing = False RPCExecute('wizard', self.action, 'execute', self.session_id, data, self.state, context=ctx, callback=callback) def destroy(self): if self.screen: self.screen.destroy() def end(self, callback=None): try: RPCExecute('wizard', self.action, 'delete', self.session_id, process_exception=False, callback=callback) except Exception: logger.warn( _("Unable to delete wizard %s") % self.session_id, exc_info=True) def clean(self): for widget in self.widget.get_children(): self.widget.remove(widget) self.states = {} def response(self, widget, response): self.__waiting_response = False state = self.response2state.get(response, self.end_state) self.screen.current_view.set_value() if (not self.screen.current_record.validate() and state != self.end_state): self.screen.display(set_cursor=True) self.message_info(self.screen.invalid_message(), gtk.MESSAGE_ERROR) return self.message_info() self.state = state self.process() def _get_button(self, definition): button = Button(definition) self.states[definition['state']] = button response = len(self.states) self.response2state[response] = definition['state'] button.show() return button def _record_changed(self, screen, record): self.update_buttons(record) def update_buttons(self, record): for button in self.states.itervalues(): button.state_set(record) def update(self, view, defaults, buttons): for button in buttons: self._get_button(button) self.screen = Screen(view['model'], mode=[], context=self.context) self.screen.add_view(view) self.screen.switch_view() self.screen.widget.show() self.screen.signal_connect(self, 'group-changed', self._record_changed) title = gtk.Label() title.modify_font(pango.FontDescription("bold 14")) title.set_label(self.name) title.set_padding(20, 4) title.set_alignment(0.0, 0.5) title.set_size_request(0, -1) # Allow overflow title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() hbox = gtk.HBox() hbox.pack_start(title, expand=True, fill=True) hbox.show() frame = gtk.Frame() frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) frame.add(hbox) frame.show() eb = gtk.EventBox() eb.add(frame) eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) eb.show() self.widget.pack_start(eb, expand=False, fill=True, padding=3) if self.toolbar_box: self.widget.pack_start(self.toolbar_box, False, True) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) viewport.add(self.screen.widget) viewport.show() self.scrolledwindow = gtk.ScrolledWindow() self.scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolledwindow.add(viewport) self.scrolledwindow.show() self.widget.pack_start(self.scrolledwindow, expand=True, fill=True) self.create_info_bar() self.widget.pack_start(self.info_bar, False, True) self.screen.new(default=False) self.screen.current_record.set_default(defaults) self.update_buttons(self.screen.current_record) self.screen.set_cursor() class WizardForm(Wizard, SignalEvent): "Wizard" def __init__(self, name=''): super(WizardForm, self).__init__(name=name) self.toolbar_box = gtk.HBox() self.hbuttonbox = gtk.HButtonBox() self.hbuttonbox.set_spacing(5) self.hbuttonbox.set_layout(gtk.BUTTONBOX_END) self.hbuttonbox.show() self.widget.pack_start(self.toolbar_box, False, True) self.dialogs = [] self.handlers = { 'but_close': self.sig_close } def clean(self): super(WizardForm, self).clean() for button in self.hbuttonbox.get_children(): self.hbuttonbox.remove(button) def _get_button(self, state): button = super(WizardForm, self)._get_button(state) response = len(self.states) button.connect('clicked', self.response, response) self.hbuttonbox.pack_start(button) return button def update(self, view, defaults, buttons): super(WizardForm, self).update(view, defaults, buttons) self.widget.pack_start(self.hbuttonbox, expand=False, fill=True) def sig_close(self): if self.end_state in self.states: self.states[self.end_state].clicked() return self.state == self.end_state def destroy(self): if self.toolbar_box.get_children(): toolbar = self.toolbar_box.get_children()[0] self.toolbar_box.remove(toolbar) super(WizardForm, self).destroy() def end(self, callback=None): super(WizardForm, self).end(callback=callback) Main.get_main()._win_del(self.widget) def set_cursor(self): if self.screen: self.screen.set_cursor() class WizardDialog(Wizard, NoModal): def __init__(self, name=''): if not name: name = _('Wizard') Wizard.__init__(self, name=name) NoModal.__init__(self) self.dia = gtk.Dialog(self.name, self.parent, gtk.DIALOG_DESTROY_WITH_PARENT) self.dia.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.dia.set_icon(TRYTON_ICON) self.dia.set_deletable(False) self.dia.connect('delete-event', lambda *a: True) self.dia.connect('close', self.close) self.dia.connect('response', self.response) self.accel_group = gtk.AccelGroup() self.dia.add_accel_group(self.accel_group) self.dia.vbox.pack_start(self.widget, expand=True, fill=True) self.register() def clean(self): super(WizardDialog, self).clean() hbuttonbox = self.dia.get_action_area() for button in hbuttonbox.get_children(): hbuttonbox.remove(button) def _get_button(self, definition): button = super(WizardDialog, self)._get_button(definition) response = len(self.states) self.dia.add_action_widget(button, response) if definition['default']: button.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) button.set_can_default(True) button.grab_default() self.dia.set_default_response(response) return button def update(self, view, defaults, buttons): # Dialog must be shown before the screen is displayed # to get the treeview realized when displayed sensible_allocation = self.sensible_widget.get_allocation() self.dia.set_default_size(int(sensible_allocation.width * 0.9), int(sensible_allocation.height * 0.9)) self.dia.show() common.center_window(self.dia, self.parent, self.sensible_widget) super(WizardDialog, self).update(view, defaults, buttons) def destroy(self, action=None): super(WizardDialog, self).destroy() self.dia.destroy() NoModal.destroy(self) main = Main.get_main() if self.parent == main.window: current_form = main.get_page() if current_form: for dialog in current_form.dialogs: dialog.show() if self.page.dialogs: dialog = self.page.dialogs[-1] else: dialog = self.page screen = getattr(dialog, 'screen', None) if self.sensible_widget == main.window: screen = main.menu_screen if screen: if (screen.current_record and self.sensible_widget != main.window): if screen.model_name == self.model: ids = self.ids else: # Wizard run from a children record so reload parent record ids = [screen.current_record.id] screen.reload(ids, written=True) if action: screen.client_action(action) def end(self, callback=None): def end_callback(action): self.destroy(action=action()) if callback: callback() super(WizardDialog, self).end(callback=end_callback) def close(self, widget, event=None): widget.emit_stop_by_name('close') if self.end_state in self.states: self.states[self.end_state].clicked() return True def show(self): self.dia.show() def hide(self): self.dia.hide() tryton-4.6.5/tryton/gui/window/infobar.py0000644000175000017500000000142613175640533020033 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk class InfoBar(object): def create_info_bar(self): self.info_label = gtk.Label() self.info_bar = gtk.InfoBar() self.info_bar.get_content_area().pack_start( self.info_label, False, False) self.info_bar.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE) self.info_bar.connect('response', lambda i, r: i.hide()) def message_info(self, message=None, type_=gtk.MESSAGE_ERROR): if message: self.info_label.set_label(message) self.info_bar.set_message_type(type_) self.info_bar.show_all() else: self.info_bar.hide() tryton-4.6.5/tryton/gui/window/tabcontent.py0000644000175000017500000002470513255571102020553 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext import gtk import pango import tryton.common as common from tryton.config import CONFIG from tryton.gui import Main from .infobar import InfoBar _ = gettext.gettext class ToolbarItem(object): def __init__(self, id, label, tooltip=None, stock_id=None, accel_path=None): self.id = id self.label = label self.tooltip = tooltip self.stock_id = stock_id self.accel_path = accel_path @property def menu(self): return True @property def toolbar(self): return bool(self.tooltip) class TabContent(InfoBar): @property def menu_def(self): return [ ToolbarItem( id='switch', label=_("_Switch View"), tooltip=_("Switch View"), stock_id='tryton-fullscreen', accel_path='/Form/Switch View'), ToolbarItem( id='previous', label=_("_Previous"), tooltip=_("Previous Record"), stock_id='tryton-go-previous', accel_path='/Form/Previous'), ToolbarItem( id='next', label=_("_Next"), tooltip=_("Next Record"), stock_id='tryton-go-next', accel_path='/Form/Next'), ToolbarItem( id='search', label=_("_Search"), stock_id='tryton-find', accel_path='/Form/Search'), None, ToolbarItem( id='new', label=_("_New"), tooltip=_("Create a new record"), stock_id='tryton-new', accel_path='/Form/New'), ToolbarItem( id='save', label=_("_Save"), tooltip=_("Save this record"), stock_id='tryton-save', accel_path='/Form/Save'), ToolbarItem( id='reload', label=_("_Reload/Undo"), tooltip=_("Reload/Undo"), stock_id='tryton-refresh', accel_path='/Form/Reload'), ToolbarItem( id='copy', label=_("_Duplicate"), stock_id='tryton-copy', accel_path='/Form/Duplicate'), ToolbarItem( id='remove', label=_("_Delete..."), stock_id='tryton-delete', accel_path='/Form/Delete'), None, ToolbarItem( id='logs', label=_("View _Logs...")), ToolbarItem( id='revision' if self.model in common.MODELHISTORY else None, label=_("Show revisions..."), stock_id='tryton-clock'), None, ToolbarItem( id='attach', label=_("A_ttachments..."), tooltip=_("Add an attachment to the record"), stock_id='tryton-attachment', accel_path='/Form/Attachments'), ToolbarItem( id='note', label=_("_Notes..."), tooltip=_("Add a note to the record"), stock_id='tryton-note', accel_path='/Form/Notes'), ToolbarItem( id='action', label=_("_Actions..."), stock_id='tryton-executable', accel_path='/Form/Actions'), ToolbarItem( id='relate', label=_("_Relate..."), stock_id='tryton-go-jump', accel_path='/Form/Relate'), None, ToolbarItem( id='print_open', label=_("_Report..."), stock_id='tryton-print-open', accel_path='/Form/Report'), ToolbarItem( id='print_email', label=_("_E-Mail..."), stock_id='tryton-print-email', accel_path='/Form/Email'), ToolbarItem( id='print', label=_("_Print..."), stock_id='tryton-print', accel_path='/Form/Print'), None, ToolbarItem( id='export', label=_("_Export Data..."), stock_id='tryton-save-as', accel_path='/Form/Export Data'), ToolbarItem( id='import', label=_("_Import Data..."), accel_path='/Form/Import Data'), ToolbarItem( id='copy_url', label=_("Copy _URL..."), stock_id='tryton-web-browser', accel_path='/Form/Copy URL'), None, ToolbarItem( id='win_close', label=_("_Close Tab"), stock_id='tryton-close', accel_path='/Form/Close'), ] def create_tabcontent(self): self.buttons = {} self.menu_buttons = {} self.tooltips = common.Tooltips() self.accel_group = Main.get_main().accel_group self.widget = gtk.VBox(spacing=3) self.widget.show() title_box = self.make_title_bar() self.widget.pack_start(title_box, expand=False, fill=True, padding=3) self.toolbar = self.create_toolbar(self.get_toolbars()) self.toolbar.show_all() self.widget.pack_start(self.toolbar, False, True) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) viewport.add(self.widget_get()) viewport.show() self.scrolledwindow = gtk.ScrolledWindow() self.scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolledwindow.add(viewport) self.scrolledwindow.show() self.widget.pack_start(self.scrolledwindow) self.create_info_bar() self.widget.pack_start(self.info_bar, False, True) def make_title_bar(self): self.title = title = gtk.Label() title.modify_font(pango.FontDescription("bold 14")) title.set_label(self.name) title.set_padding(10, 4) title.set_alignment(0.0, 0.5) title.set_size_request(0, -1) # Allow overflow title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() title_menu = gtk.MenuBar() title_item = gtk.MenuItem('') title_item.remove(title_item.get_children()[0]) menu_image = gtk.Image() menu_image.set_from_stock('tryton-preferences-system', gtk.ICON_SIZE_BUTTON) title_item.add(menu_image) title_item.set_submenu(self.set_menu_form()) title_menu.append(title_item) title_menu.show_all() self.status_label = gtk.Label() self.status_label.set_padding(5, 4) self.status_label.set_alignment(0.0, 0.5) self.status_label.show() hbox = gtk.HBox() hbox.pack_start(title, expand=True, fill=True) hbox.pack_start(self.status_label, expand=False, fill=True) hbox.show() frame = gtk.Frame() frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) frame.add(hbox) frame.show() eb = gtk.EventBox() eb.add(frame) eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) eb.show() frame_menu = gtk.Frame() frame_menu.set_shadow_type(gtk.SHADOW_ETCHED_IN) frame_menu.add(title_menu) frame_menu.show() title_box = gtk.HBox() title_box.pack_start(frame_menu, expand=False, fill=True) title_box.pack_start(eb, expand=True, fill=True) title_box.show() return title_box def create_base_toolbar(self, toolbar): previous = None for item in self.menu_def: if item and item.toolbar: callback = getattr(self, 'sig_%s' % item.id, None) if not callback: continue toolitem = gtk.ToolButton(item.stock_id) toolitem.set_label(item.label) toolitem.set_use_underline(True) toolitem.connect('clicked', callback) self.tooltips.set_tip(toolitem, item.tooltip) self.buttons[item.id] = toolitem elif not item and previous: toolitem = gtk.SeparatorToolItem() else: continue previous = item toolbar.insert(toolitem, -1) def set_menu_form(self): menu_form = gtk.Menu() menu_form.set_accel_group(self.accel_group) menu_form.set_accel_path('/Form') previous = None for item in self.menu_def: if item and item.menu: callback = getattr(self, 'sig_%s' % item.id, None) if not callback: continue menuitem = gtk.ImageMenuItem(item.label, self.accel_group) menuitem.set_use_underline(True) menuitem.connect('activate', callback) if item.stock_id: image = gtk.Image() image.set_from_stock(item.stock_id, gtk.ICON_SIZE_MENU) menuitem.set_image(image) if item.accel_path: menuitem.set_accel_path(item.accel_path) self.menu_buttons[item.id] = menuitem elif not item and previous: menuitem = gtk.SeparatorMenuItem() else: continue previous = item menu_form.add(menuitem) menu_form.show_all() return menu_form def create_toolbar(self, toolbars): gtktoolbar = gtk.Toolbar() option = CONFIG['client.toolbar'] if option == 'default': gtktoolbar.set_style(False) elif option == 'both': gtktoolbar.set_style(gtk.TOOLBAR_BOTH) elif option == 'text': gtktoolbar.set_style(gtk.TOOLBAR_TEXT) elif option == 'icons': gtktoolbar.set_style(gtk.TOOLBAR_ICONS) self.create_base_toolbar(gtktoolbar) return gtktoolbar tryton-4.6.5/tryton/gui/window/attachment.py0000644000175000017500000000357313251060075020540 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Attachment" import os import urllib import urlparse import sys import gettext from tryton.gui.window.view_form.screen import Screen from tryton.gui.window.win_form import WinForm _ = gettext.gettext class Attachment(WinForm): "Attachment window" def __init__(self, record, callback=None): self.resource = '%s,%s' % (record.model_name, record.id) self.attachment_callback = callback title = _('Attachments (%s)') % (record.rec_name()) screen = Screen('ir.attachment', domain=[ ('resource', '=', self.resource), ], mode=['tree', 'form'], exclude_field='resource') super(Attachment, self).__init__(screen, self.callback, view_type='tree', title=title) screen.search_filter() def destroy(self): self.prev_view.save_width_height() super(Attachment, self).destroy() def callback(self, result): if result: resource = self.screen.group.fields['resource'] for record in self.screen.group: resource.set_client(record, self.resource) self.screen.save_current() if self.attachment_callback: self.attachment_callback() def add_uri(self, uri): self.screen.switch_view('form') data_field = self.screen.group.fields['data'] name_field = self.screen.group.fields[data_field.attrs['filename']] new_record = self.screen.new() file_name = os.path.basename(urlparse.urlparse(uri).path) name_field.set_client(new_record, file_name) uri = urllib.unquote(uri) uri = uri.decode('utf-8').encode(sys.getfilesystemencoding()) data_field.set_client(new_record, urllib.urlopen(uri).read()) self.screen.display() tryton-4.6.5/tryton/gui/window/limit.py0000644000175000017500000000353113251060075017520 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import sys import gtk import gettext from tryton.config import TRYTON_ICON, CONFIG from tryton.common import get_toplevel_window _ = gettext.gettext class Limit(object): 'Set Search Limit' def __init__(self): self.parent = get_toplevel_window() self.win = gtk.Dialog(_('Limit'), self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) self.win.set_default_response(gtk.RESPONSE_OK) self.win.set_icon(TRYTON_ICON) self.win.vbox.set_spacing(3) self.win.vbox.pack_start(gtk.Label( _('Search Limit Settings')), expand=False, fill=True) self.win.vbox.pack_start(gtk.HSeparator()) hbox = gtk.HBox(spacing=3) label = gtk.Label(_('Limit:')) hbox.pack_start(label, expand=True, fill=True) adjustment = gtk.Adjustment(value=CONFIG['client.limit'], lower=1, upper=sys.maxint, step_incr=10, page_incr=100) self.spin_limit = gtk.SpinButton() self.spin_limit.configure(adjustment, climb_rate=1, digits=0) self.spin_limit.set_numeric(False) self.spin_limit.set_activates_default(True) label.set_mnemonic_widget(self.spin_limit) hbox.pack_start(self.spin_limit, expand=True, fill=True) self.win.vbox.pack_start(hbox, expand=True, fill=True) self.win.show_all() def run(self): 'Run the window' res = self.win.run() if res == gtk.RESPONSE_OK: CONFIG['client.limit'] = self.spin_limit.get_value_as_int() CONFIG.save() self.parent.present() self.win.destroy() return res tryton-4.6.5/tryton/gui/window/win_form.py0000644000175000017500000004265113251060075020230 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from tryton.common import TRYTON_ICON import tryton.common as common import gtk import pango import gettext from tryton.gui.window.nomodal import NoModal from tryton.common.domain_parser import quote from .infobar import InfoBar _ = gettext.gettext class WinForm(NoModal, InfoBar): "Form window" def __init__(self, screen, callback, view_type='form', new=False, many=0, domain=None, context=None, save_current=False, title='', rec_name=None): NoModal.__init__(self) self.screen = screen self.callback = callback self.many = many self.domain = domain self.context = context self.save_current = save_current self.title = title self.prev_view = self.screen.current_view self.screen.screen_container.alternate_view = True if view_type not in (x.view_type for x in self.screen.views) and \ view_type not in self.screen.view_to_load: self.screen.add_view_id(None, view_type) self.screen.switch_view(view_type=view_type) if new: self.screen.new(rec_name=rec_name) self.win = gtk.Dialog(_('Link'), self.parent, gtk.DIALOG_DESTROY_WITH_PARENT) self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) self.win.set_deletable(False) self.win.connect('delete-event', lambda *a: True) self.win.connect('close', self.close) self.win.connect('response', self.response) self.accel_group = gtk.AccelGroup() self.win.add_accel_group(self.accel_group) readonly = self.screen.readonly or self.screen.group.readonly self.but_ok = None self.but_new = None if view_type == 'form': if not new and self.screen.current_record.id < 0: stock_id = gtk.STOCK_DELETE else: stock_id = gtk.STOCK_CANCEL self.but_cancel = self.win.add_button(stock_id, gtk.RESPONSE_CANCEL) if new and self.many: self.but_new = self.win.add_button(gtk.STOCK_NEW, gtk.RESPONSE_ACCEPT) self.but_new.set_accel_path('/Form/New', self.accel_group) if self.save_current: self.but_ok = gtk.Button(_('_Save'), use_underline=True) img_save = gtk.Image() img_save.set_from_stock('tryton-save', gtk.ICON_SIZE_BUTTON) self.but_ok.set_image(img_save) self.but_ok.set_accel_path('/Form/Save', self.accel_group) self.but_ok.set_can_default(True) self.but_ok.show() self.win.add_action_widget(self.but_ok, gtk.RESPONSE_OK) if not new: self.but_ok.props.sensitive = False else: self.but_ok = self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) self.but_ok.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) self.win.set_default_response(gtk.RESPONSE_OK) self.win.set_title(self.title) title = gtk.Label() title.modify_font(pango.FontDescription("bold 12")) title.set_label(self.title) title.set_padding(20, 3) title.set_alignment(0.0, 0.5) title.set_size_request(0, -1) # Allow overflow title.modify_fg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#000000")) title.show() hbox = gtk.HBox() hbox.pack_start(title, expand=True, fill=True) hbox.show() frame = gtk.Frame() frame.set_shadow_type(gtk.SHADOW_ETCHED_IN) frame.add(hbox) frame.show() eb = gtk.EventBox() eb.add(frame) eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#ffffff")) eb.show() self.win.vbox.pack_start(eb, expand=False, fill=True, padding=3) if view_type == 'tree': hbox = gtk.HBox(homogeneous=False, spacing=0) tooltips = common.Tooltips() access = common.MODELACCESS[screen.model_name] if domain is not None: self.wid_text = gtk.Entry() self.wid_text.set_property('width_chars', 13) self.wid_text.connect('activate', self._sig_activate) self.wid_text.connect('focus-out-event', self._focus_out) hbox.pack_start(self.wid_text, expand=True, fill=True) self.but_add = gtk.Button() tooltips.set_tip(self.but_add, _('Add')) self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) if not access['read'] or readonly: self.but_add.set_sensitive(False) self.but_remove = gtk.Button() tooltips.set_tip(self.but_remove, _('Remove ')) self.but_remove.connect('clicked', self._sig_remove, True) img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) self.but_remove.add(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_remove, expand=False, fill=False) if not access['read'] or readonly: self.but_remove.set_sensitive(False) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) self.but_new = gtk.Button() tooltips.set_tip(self.but_new, _('Create a new record ')) self.but_new.connect('clicked', self._sig_new) img_new = gtk.Image() img_new.set_from_stock('tryton-new', gtk.ICON_SIZE_SMALL_TOOLBAR) img_new.set_alignment(0.5, 0.5) self.but_new.add(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_new, expand=False, fill=False) if not access['create'] or readonly: self.but_new.set_sensitive(False) self.but_del = gtk.Button() tooltips.set_tip(self.but_del, _('Delete selected record ')) self.but_del.connect('clicked', self._sig_remove, False) img_del = gtk.Image() img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR) img_del.set_alignment(0.5, 0.5) self.but_del.add(img_del) self.but_del.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_del, expand=False, fill=False) if not access['delete'] or readonly: self.but_del.set_sensitive(False) self.but_undel = gtk.Button() tooltips.set_tip(self.but_undel, _('Undelete selected record ')) self.but_undel.connect('clicked', self._sig_undelete) img_undel = gtk.Image() img_undel.set_from_stock('tryton-undo', gtk.ICON_SIZE_SMALL_TOOLBAR) img_undel.set_alignment(0.5, 0.5) self.but_undel.add(img_undel) self.but_undel.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_undel, expand=False, fill=False) if not access['delete'] or readonly: self.but_undel.set_sensitive(False) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) self.but_pre = gtk.Button() tooltips.set_tip(self.but_pre, _('Previous')) self.but_pre.connect('clicked', self._sig_previous) img_pre = gtk.Image() img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR) img_pre.set_alignment(0.5, 0.5) self.but_pre.add(img_pre) self.but_pre.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_pre, expand=False, fill=False) self.label = gtk.Label('(0,0)') hbox.pack_start(self.label, expand=False, fill=False) self.but_next = gtk.Button() tooltips.set_tip(self.but_next, _('Next')) self.but_next.connect('clicked', self._sig_next) img_next = gtk.Image() img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR) img_next.set_alignment(0.5, 0.5) self.but_next.add(img_next) self.but_next.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_next, expand=False, fill=False) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) but_switch = gtk.Button() tooltips.set_tip(but_switch, _('Switch')) but_switch.connect('clicked', self.switch_view) img_switch = gtk.Image() img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR) img_switch.set_alignment(0.5, 0.5) but_switch.add(img_switch) but_switch.set_relief(gtk.RELIEF_NONE) hbox.pack_start(but_switch, expand=False, fill=False) but_switch.props.sensitive = screen.number_of_views > 1 tooltips.enable() alignment = gtk.Alignment(1.0) alignment.add(hbox) alignment.show_all() self.win.vbox.pack_start(alignment, expand=False, fill=True) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_placement(gtk.CORNER_TOP_LEFT) scroll.set_shadow_type(gtk.SHADOW_NONE) scroll.show() self.win.vbox.pack_start(scroll, expand=True, fill=True) scroll.add(self.screen.screen_container.alternate_viewport) self.create_info_bar() self.win.vbox.pack_start(self.info_bar, False, True) sensible_allocation = self.sensible_widget.get_allocation() self.win.set_default_size(int(sensible_allocation.width * 0.9), int(sensible_allocation.height * 0.9)) if view_type == 'tree': self.screen.signal_connect(self, 'record-message', self._sig_label) self.screen.screen_container.alternate_viewport.connect( 'key-press-event', self.on_keypress) if self.save_current and not new: self.screen.signal_connect(self, 'record-message', self.activate_save) self.screen.signal_connect(self, 'record-modified', self.activate_save) self.register() self.win.show() common.center_window(self.win, self.parent, self.sensible_widget) self.screen.display() self.screen.current_view.set_cursor() def on_keypress(self, widget, event): if (event.keyval == gtk.keysyms.F3) \ and self.but_new.get_property('sensitive'): self._sig_new(widget) return False if event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) \ and widget == self.screen.screen_container.alternate_viewport: self._sig_remove(widget) return False def switch_view(self, widget): self.screen.switch_view() def _sig_new(self, widget): self.screen.new() self.screen.current_view.widget.set_sensitive(True) def _sig_next(self, widget): self.screen.display_next() def _sig_previous(self, widget): self.screen.display_prev() def _sig_remove(self, widget, remove=False): self.screen.remove(remove=remove) def _sig_undelete(self, button): self.screen.unremove() def _sig_activate(self, *args): self._sig_add() self.wid_text.grab_focus() def _focus_out(self, *args): if self.wid_text.get_text(): self._sig_add() def _sig_add(self, *args): from tryton.gui.window.win_search import WinSearch domain = self.domain[:] model_name = self.screen.model_name value = self.wid_text.get_text().decode('utf-8') def callback(result): if result: ids = [x[0] for x in result] self.screen.load(ids, modified=True) self.screen.display(res_id=ids[0]) self.screen.set_cursor() self.wid_text.set_text('') win = WinSearch(model_name, callback, sel_multi=True, context=self.context, domain=domain) win.screen.search_filter(quote(value)) win.show() def _sig_label(self, screen, signal_data): name = '_' access = common.MODELACCESS[screen.model_name] readonly = screen.group.readonly if signal_data[0] >= 1: name = str(signal_data[0]) if self.domain is not None: self.but_remove.set_sensitive(True) if signal_data[0] < signal_data[1]: self.but_next.set_sensitive(True) else: self.but_next.set_sensitive(False) if signal_data[0] > 1: self.but_pre.set_sensitive(True) else: self.but_pre.set_sensitive(False) if access['delete'] and not readonly: self.but_del.set_sensitive(True) self.but_undel.set_sensitive(True) else: self.but_del.set_sensitive(False) self.but_undel.set_sensitive(False) self.but_next.set_sensitive(False) self.but_pre.set_sensitive(False) if self.domain is not None: self.but_remove.set_sensitive(False) line = '(%s/%s)' % (name, signal_data[1]) self.label.set_text(line) def activate_save(self, *args): modified = self.screen.modified() # Keep sensible as change could have been trigger by a Many2One edition sensitive = modified or self.but_ok.props.sensitive self.but_ok.props.sensitive = sensitive self.win.set_default_response( gtk.RESPONSE_OK if sensitive else gtk.RESPONSE_CANCEL) def close(self, widget): widget.emit_stop_by_name('close') self.response(self.win, gtk.RESPONSE_CANCEL) return True def response(self, win, response_id): validate = False cancel_responses = (gtk.RESPONSE_CANCEL, gtk.RESPONSE_DELETE_EVENT) self.screen.current_view.set_value() readonly = self.screen.group.readonly if (response_id not in cancel_responses and not readonly and self.screen.current_record is not None): validate = self.screen.current_record.validate( self.screen.current_view.get_fields()) if validate and self.screen.pre_validate: validate = self.screen.current_record.pre_validate() if validate and self.save_current: if not self.screen.save_current(): validate = False elif validate and self.screen.current_view.view_type == 'form': view = self.screen.current_view for widgets in view.widgets.itervalues(): for widget in widgets: if (hasattr(widget, 'screen') and widget.screen.pre_validate): record = widget.screen.current_record if record: validate = record.pre_validate() if not validate: self.message_info(self.screen.invalid_message(), gtk.MESSAGE_ERROR) self.screen.set_cursor() self.screen.display() return self.message_info() if response_id == gtk.RESPONSE_ACCEPT: self.new() return if (self.screen.current_record and not readonly and response_id in cancel_responses): if (self.screen.current_record.id < 0 or self.save_current): self.screen.cancel_current() elif self.screen.current_record.modified: self.screen.current_record.cancel() self.screen.current_record.reload() self.screen.current_record.signal('record-changed') result = False else: result = response_id not in cancel_responses self.callback(result) self.destroy() def new(self): self.screen.new() self.screen.current_view.display() self.screen.set_cursor(new=True) self.many -= 1 if self.many == 0: self.but_new.set_sensitive(False) self.win.set_default_response(gtk.RESPONSE_OK) def destroy(self): self.screen.screen_container.alternate_view = False viewport = self.screen.screen_container.alternate_viewport viewport.get_parent().remove(viewport) self.screen.switch_view(view_type=self.prev_view.view_type) self.screen.signal_unconnect(self) self.win.destroy() NoModal.destroy(self) def show(self): self.win.show() common.center_window(self.win, self.parent, self.sensible_widget) def hide(self): self.win.hide() tryton-4.6.5/tryton/gui/window/win_import.py0000644000175000017500000001731213251060075020573 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import csv import gettext import gtk import tryton.common as common from tryton.common import RPCExecute, RPCException from tryton.gui.window.win_csv import WinCSV _ = gettext.gettext class WinImport(WinCSV): "Window import" def __init__(self, model, context): self.model = model self.context = context self.fields_data = {} self.fields = {} self.fields_invert = {} super(WinImport, self).__init__() self.dialog.set_title(_('Import from CSV')) def add_header(self, box): pass def add_buttons(self, box): button_autodetect = gtk.Button( _('_Auto-Detect'), stock=None, use_underline=True) button_autodetect.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-find', gtk.ICON_SIZE_BUTTON) button_autodetect.set_image(img_button) button_autodetect.connect_after('clicked', self.sig_autodetect) box.pack_start(button_autodetect, False, False, 0) def add_chooser(self, box): hbox_csv_import = gtk.HBox() box.pack_start(hbox_csv_import, False, True, 4) label_csv_import = gtk.Label(_("File to Import:")) hbox_csv_import.pack_start(label_csv_import, False, False, 0) self.import_csv_file = gtk.FileChooserButton(_("Open...")) label_csv_import.set_mnemonic_widget(self.import_csv_file) hbox_csv_import.pack_start(self.import_csv_file, True, True, 0) def add_csv_header_param(self, table): label_csv_skip = gtk.Label(_('Lines to Skip:')) label_csv_skip.set_alignment(1, 0.5) table.attach(label_csv_skip, 2, 3, 1, 2) self.csv_skip = gtk.SpinButton() self.csv_skip.configure(gtk.Adjustment(0, 0, 100, 1, 10), 1, 0) label_csv_skip.set_mnemonic_widget(self.csv_skip) table.attach(self.csv_skip, 3, 4, 1, 2) def model_populate(self, fields, parent_node=None, prefix_field='', prefix_name=''): fields_order = fields.keys() fields_order.sort(lambda x, y: -cmp(fields[x].get('string', ''), fields[y].get('string', ''))) for field in fields_order: if not fields[field].get('readonly', False): self.fields_data[prefix_field + field] = fields[field] name = fields[field]['string'] or field node = self.model1.insert( parent_node, 0, [name, prefix_field + field]) name = prefix_name + name # Only One2Many can be nested for import if fields[field]['type'] == 'one2many': relation = fields[field].get('relation') else: relation = None self.fields[prefix_field + field] = (name, relation) self.fields_invert[name] = prefix_field + field if relation: self.model1.insert(node, 0, [None, '']) def _get_fields(self, model): try: return RPCExecute('model', model, 'fields_get', None, context=self.context) except RPCException: return '' def on_row_expanded(self, treeview, iter, path): child = self.model1.iter_children(iter) # autodetect could call for node without children if child is None: return if self.model1.get_value(child, 0) is None: prefix_field = self.model1.get_value(iter, 1) name, model = self.fields[prefix_field] self.model_populate(self._get_fields(model), iter, prefix_field + '/', name + '/') self.model1.remove(child) def sig_autodetect(self, widget=None): fname = self.import_csv_file.get_filename() if not fname: common.message(_('You must select an import file first.')) return True self.csv_skip.set_value(1) try: data = csv.reader( open(fname, 'rb'), quotechar=self.get_quotechar(), delimiter=self.get_delimiter()) except IOError: common.warning(_('Error opening CSV file'), _('Error')) return True self.sig_unsel_all() encoding = self.get_encoding() word = '' for line in data: for word in line: word = word.decode(encoding) if word not in self.fields_invert and word not in self.fields: iter = self.model1.get_iter_first() prefix = '' for parent in word.split('/')[:-1]: while iter: if self.model1.get_value(iter, 0) == parent or \ self.model1.get_value(iter, 1) == \ (prefix + parent): self.on_row_expanded(self.view1, iter, self.model1.get_path(iter)) break iter = self.model1.iter_next(iter) prefix = parent + '/' if word in self.fields_invert: name = word field = self.fields_invert[word] elif word in self.fields: name = self.fields[word][0] field = word else: common.warning(_('Error processing the file at field %s.') % word, _('Error')) return True num = self.model2.append() self.model2.set(num, 0, name, 1, field) break return True def sig_sel(self, *args): sel = self.view1.get_selection() sel.selected_foreach(self._sig_sel_add) def _sig_sel_add(self, store, path, iter): num = self.model2.append() name = self.fields[store.get_value(iter, 1)][0] self.model2.set(num, 0, name, 1, store.get_value(iter, 1)) def sig_unsel(self, *args): store, paths = self.view2.get_selection().get_selected_rows() # Convert first into TreeIter before removing from the store iters = [store.get_iter(p) for p in paths] for i in iters: store.remove(i) def sig_unsel_all(self, *args): self.model2.clear() def response(self, dialog, response): if response == gtk.RESPONSE_OK: fields = [] iter = self.model2.get_iter_first() while iter: fields.append(self.model2.get_value(iter, 1)) iter = self.model2.iter_next(iter) fname = self.import_csv_file.get_filename() if fname: self.import_csv(fname, fields) self.destroy() def import_csv(self, fname, fields): # TODO: make it works with references skip = self.csv_skip.get_value_as_int() encoding = self.get_encoding() reader = csv.reader( open(fname, 'rb'), quotechar=self.get_quotechar(), delimiter=self.get_delimiter()) data = [] for i, line in enumerate(reader): if i < skip or not line: continue data.append([x.decode(encoding).encode('utf-8') for x in line]) try: count = RPCExecute( 'model', self.model, 'import_data', fields, data, context=self.context) except RPCException: return if count == 1: common.message(_('%d record imported.') % count) else: common.message(_('%d records imported.') % count) tryton-4.6.5/tryton/gui/window/__init__.py0000644000175000017500000000031513175640533020146 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from window import * from email import * from limit import * tryton-4.6.5/tryton/gui/window/preference.py0000644000175000017500000000710313255571102020521 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Preference" import gettext import gtk import copy from tryton.gui.window.view_form.screen import Screen from tryton.config import TRYTON_ICON from tryton.common import RPCExecute, RPCException, Login from tryton.gui.window.nomodal import NoModal from tryton.exceptions import TrytonError import tryton.rpc as rpc _ = gettext.gettext class Preference(NoModal): "Preference window" def __init__(self, user, callback): NoModal.__init__(self) self.callback = callback self.win = gtk.Dialog(_('Preferences'), self.parent, gtk.DIALOG_DESTROY_WITH_PARENT) self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) self.accel_group = gtk.AccelGroup() self.win.add_accel_group(self.accel_group) self.but_cancel = self.win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) self.but_ok = self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) self.but_ok.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) self.win.set_default_response(gtk.RESPONSE_OK) self.win.connect('response', self.response) try: view = RPCExecute('model', 'res.user', 'get_preferences_fields_view') except RPCException: self.win.destroy() self.win = None return title = gtk.Label(_('Edit User Preferences')) title.show() self.win.vbox.pack_start(title, expand=False, fill=True) self.screen = Screen('res.user', mode=[]) # Reset readonly set automaticly by MODELACCESS self.screen.readonly = False self.screen.group.readonly = False self.screen.group.skip_model_access = True self.screen.add_view(view) self.screen.switch_view() self.screen.new(default=False) try: preferences = RPCExecute('model', 'res.user', 'get_preferences', False) except RPCException: self.win.destroy() self.win = None return self.screen.current_record.cancel() self.screen.current_record.set(preferences) self.screen.current_record.id = rpc._USER self.screen.current_record.validate(softvalidation=True) self.screen.display(set_cursor=True) self.screen.widget.show() self.win.vbox.pack_start(self.screen.widget) self.win.set_title(_('Preference')) width, height = self.parent.get_size() self.win.set_default_size(int(width * 0.9), int(height * 0.9)) self.register() self.win.show() def response(self, win, response_id): if response_id == gtk.RESPONSE_OK: if self.screen.current_record.validate(): vals = copy.copy(self.screen.get()) context = rpc.CONTEXT.copy() func = lambda parameters: rpc.execute( 'model', 'res.user', 'set_preferences', vals, parameters, context) try: Login(func) except TrytonError, exception: if exception.faultCode == 'QueryCanceled': return raise self.parent.present() self.destroy() self.callback() def destroy(self): self.screen.destroy() self.win.destroy() NoModal.destroy(self) tryton-4.6.5/tryton/gui/window/win_export.py0000644000175000017500000003275713255571102020616 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import csv import os import tempfile import types import gtk import gobject import gettext import tryton.common as common from tryton.common import RPCExecute, RPCException from tryton.gui.window.win_csv import WinCSV _ = gettext.gettext class WinExport(WinCSV): "Window export" def __init__(self, model, ids, context=None): self.ids = ids self.model = model self.context = context self.fields = {} super(WinExport, self).__init__() self.dialog.set_title(_('Export to CSV')) def add_header(self, box): frame_predef_exports = gtk.Frame() frame_predef_exports.set_border_width(2) frame_predef_exports.set_shadow_type(gtk.SHADOW_NONE) box.pack_start(frame_predef_exports, True, True, 0) viewport_exports = gtk.Viewport() scrolledwindow_exports = gtk.ScrolledWindow() scrolledwindow_exports.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) label_predef_exports = gtk.Label(_("Predefined exports")) label_predef_exports.set_use_markup(True) frame_predef_exports.set_label_widget(label_predef_exports) viewport_exports.add(scrolledwindow_exports) frame_predef_exports.add(viewport_exports) self.pref_export = gtk.TreeView() self.pref_export.append_column(gtk.TreeViewColumn(_('Name'), gtk.CellRendererText(), text=2)) scrolledwindow_exports.add(self.pref_export) self.pref_export.connect("button-press-event", self.export_click) self.pref_export.connect("key-press-event", self.export_keypress) self.predef_model = gtk.ListStore( gobject.TYPE_INT, gobject.TYPE_PYOBJECT, gobject.TYPE_STRING) self.fill_predefwin() def add_buttons(self, box): button_save_export = gtk.Button( _('_Save Export'), stock=None, use_underline=True) button_save_export.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-save', gtk.ICON_SIZE_BUTTON) button_save_export.set_image(img_button) button_save_export.connect_after('clicked', self.addreplace_predef) box.pack_start(button_save_export, False, False, 0) button_del_export = gtk.Button( _('_Delete Export'), stock=None, use_underline=True) button_del_export.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-delete', gtk.ICON_SIZE_BUTTON) button_del_export.set_image(img_button) button_del_export.connect_after('clicked', self.remove_predef) box.pack_start(button_del_export, False, False, 0) def add_chooser(self, box): hbox_csv_export = gtk.HBox() box.pack_start(hbox_csv_export, False, True, 0) if hasattr(gtk, 'ComboBoxText'): self.saveas = gtk.ComboBoxText() else: self.saveas = gtk.combo_box_new_text() hbox_csv_export.pack_start(self.saveas, True, True, 0) self.saveas.append_text(_("Open")) self.saveas.append_text(_("Save")) self.saveas.set_active(0) def add_csv_header_param(self, table): self.add_field_names = gtk.CheckButton(_("Add _field names")) self.add_field_names.set_active(True) table.attach(self.add_field_names, 2, 4, 1, 2) def model_populate(self, fields, parent_node=None, prefix_field='', prefix_name=''): key = lambda (n, f): f.get('string') or n for name, field in sorted(fields.items(), key=key, reverse=True): string_ = field['string'] or name items = [(name, field, string_)] if field['type'] == 'selection': items.insert(0, ('%s.translated' % name, field, _('%s (string)') % string_)) elif field['type'] == 'reference': items.insert(0, ('%s.translated' % name, field, _('%s (model name)') % string_)) items.insert(0, ('%s/rec_name' % name, field, _("%s (record name)") % string_)) for name, field, string_ in items: path = prefix_field + name long_string = string_ if prefix_field: long_string = prefix_name + string_ node = self.model1.insert(parent_node, 0, [string_, path]) self.fields[path] = (string_, long_string, field.get('relation')) # Insert relation only to real field if '.' not in name: if field.get('relation'): self.model1.insert(node, 0, [None, '']) def _get_fields(self, model): try: return RPCExecute('model', model, 'fields_get', None, context=self.context) except RPCException: return '' def on_row_expanded(self, treeview, iter, path): child = self.model1.iter_children(iter) if self.model1.get_value(child, 0) is None: prefix_field = self.model1.get_value(iter, 1) string_, long_string, relation = self.fields[prefix_field] self.model_populate(self._get_fields(relation), iter, prefix_field + '/', string_ + '/') self.model1.remove(child) def sig_sel(self, *args): sel = self.view1.get_selection() sel.selected_foreach(self._sig_sel_add) def _sig_sel_add(self, store, path, iter): name = store.get_value(iter, 1) string_, long_string, relation = self.fields[name] if relation: return num = self.model2.append() self.model2.set(num, 0, long_string, 1, name) def sig_unsel(self, *args): store, paths = self.view2.get_selection().get_selected_rows() # Convert first into TreeIter before removing from the store iters = [store.get_iter(p) for p in paths] for i in iters: store.remove(i) def sig_unsel_all(self, *args): self.model2.clear() def fill_predefwin(self): try: export_ids = RPCExecute('model', 'ir.export', 'search', [('resource', '=', self.model)], 0, None, None, context=self.context) except RPCException: return try: exports = RPCExecute('model', 'ir.export', 'read', export_ids, None, context=self.context) except RPCException: return try: lines = RPCExecute('model', 'ir.export.line', 'read', sum((list(x['export_fields']) for x in exports), []), None, context=self.context) except RPCException: return id2lines = {} for line in lines: id2lines.setdefault(line['export'], []).append(line) for export in exports: self.predef_model.append(( export['id'], [x['name'] for x in id2lines.get(export['id'], [])], export['name'])) self.pref_export.set_model(self.predef_model) def addreplace_predef(self, widget): iter = self.model2.get_iter_first() fields = [] while iter: field_name = self.model2.get_value(iter, 1) fields.append(field_name) iter = self.model2.iter_next(iter) if not fields: return selection = self.pref_export.get_selection().get_selected() if selection is None: return model, iter_ = selection if iter_ is None: pref_id = None name = common.ask(_('What is the name of this export?')) if not name: return else: pref_id = model.get_value(iter_, 0) name = model.get_value(iter_, 2) override = common.sur(_("Override '%s' definition?") % name) if not override: return try: new_id, = RPCExecute('model', 'ir.export', 'create', [{ 'name': name, 'resource': self.model, 'export_fields': [('create', [{ 'name': x, } for x in fields])], }], context=self.context) if pref_id: RPCExecute('model', 'ir.export', 'delete', [pref_id], context=self.context) except RPCException: return if iter_ is None: self.predef_model.append((new_id, fields, name)) else: model.set_value(iter_, 0, new_id) model.set_value(iter_, 1, fields) def remove_predef(self, widget): sel = self.pref_export.get_selection().get_selected() if sel is None: return None (model, i) = sel if not i: return None export_id = model.get_value(i, 0) try: RPCExecute('model', 'ir.export', 'delete', [export_id], context=self.context) except RPCException: return for i in range(len(self.predef_model)): if self.predef_model[i][0] == export_id: del self.predef_model[i] break self.pref_export.set_model(self.predef_model) def sel_predef(self, path): self.model2.clear() for name in self.predef_model[path[0]][1]: if name not in self.fields: iter = self.model1.get_iter_first() prefix = '' for parent in name.split('/')[:-1]: while iter: if self.model1.get_value(iter, 1) == \ (prefix + parent): self.on_row_expanded(self.view1, iter, self.model1.get_path(iter)) iter = self.model1.iter_children(iter) prefix += parent + '/' break else: iter = self.model1.iter_next(iter) if name not in self.fields: continue self.sel_field(name) def sel_field(self, name): _, long_string, relation = self.fields[name] if relation: return self.model2.append((long_string, name)) def response(self, dialog, response): if response == gtk.RESPONSE_OK: fields = [] fields2 = [] iter = self.model2.get_iter_first() while iter: fields.append(self.model2.get_value(iter, 1)) fields2.append(self.model2.get_value(iter, 0)) iter = self.model2.iter_next(iter) action = self.saveas.get_active() try: data = RPCExecute('model', self.model, 'export_data', self.ids, fields, context=self.context) except RPCException: data = [] if action == 0: fileno, fname = tempfile.mkstemp('.csv', 'tryton_') self.export_csv(fname, fields2, data, popup=False) os.close(fileno) common.file_open(fname, 'csv') else: fname = common.file_selection(_('Save As...'), action=gtk.FILE_CHOOSER_ACTION_SAVE) if fname: self.export_csv(fname, fields2, data) self.destroy() def export_csv(self, fname, fields, data, popup=True): encoding = self.csv_enc.get_active_text() or 'UTF-8' try: writer = csv.writer( open(fname, 'wb+'), quotechar=self.get_quotechar(), delimiter=self.get_delimiter()) if self.add_field_names.get_active(): writer.writerow(fields) for line in data: row = [] for val in line: if isinstance(type(val), types.StringType): val = val.replace('\n', ' ').replace('\t', ' ') val = val.encode(encoding) row.append(val) writer.writerow(row) if popup: if len(data) == 1: common.message(_('%d record saved.') % len(data)) else: common.message(_('%d records saved.') % len(data)) return True except IOError, exception: common.warning(_("Operation failed.\nError message:\n%s") % exception, _('Error')) return False def export_click(self, treeview, event): path_at_pos = treeview.get_path_at_pos(int(event.x), int(event.y)) if not path_at_pos or event.button != 1: return path, col, x, y = path_at_pos selection = treeview.get_selection() if event.type == gtk.gdk._2BUTTON_PRESS: self.sel_predef(path) selection.select_path(path) return True elif selection.path_is_selected(path): selection.unselect_path(path) return True def export_keypress(self, treeview, event): if event.keyval not in (gtk.keysyms.Return, gtk.keysyms.space): return model, selected = treeview.get_selection().get_selected() if not selected: return self.sel_predef(model.get_path(selected)) tryton-4.6.5/tryton/gui/window/window.py0000644000175000017500000000304113251060075017705 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. class Window(object): hide_current = False allow_similar = False def __init__(self, hide_current=False, allow_similar=True): Window.hide_current = hide_current Window.allow_similar = allow_similar def __enter__(self): return self def __exit__(self, type, value, traceback): Window.hide_current = False Window.allow_similar = False @staticmethod def create(model, **attributes): from tryton.gui import Main if model: from form import Form win = Form(model, **attributes) else: from board import Board win = Board(model, **attributes) win.icon = attributes.get('icon') Main.get_main().win_add(win, hide_current=Window.hide_current, allow_similar=Window.allow_similar) @staticmethod def create_wizard(action, data, direct_print=False, email_print=False, email=None, name='', context=None, icon=None, window=False): from tryton.gui import Main from wizard import WizardForm, WizardDialog if window: win = WizardForm(name=name) win.icon = icon Main.get_main().win_add(win, Window.hide_current) else: win = WizardDialog(name=name) win.run(action, data, direct_print=direct_print, email_print=email_print, email=email, context=context) tryton-4.6.5/tryton/gui/window/win_search.py0000644000175000017500000001212713255571102020527 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import tryton.common as common from tryton.gui.window.view_form.screen import Screen from tryton.config import TRYTON_ICON from tryton.gui.window.win_form import WinForm from tryton.gui.window.nomodal import NoModal _ = gettext.gettext class WinSearch(NoModal): def __init__(self, model, callback, sel_multi=True, context=None, domain=None, view_ids=None, views_preload=None, new=True, title=''): NoModal.__init__(self) if view_ids is None: view_ids = [] if views_preload is None: views_preload = {} self.domain = domain or [] self.context = context or {} self.view_ids = view_ids self.views_preload = views_preload self.sel_multi = sel_multi self.callback = callback self.title = title self.win = gtk.Dialog(_('Search'), self.parent, gtk.DIALOG_DESTROY_WITH_PARENT) self.win.set_icon(TRYTON_ICON) self.win.set_default_response(gtk.RESPONSE_APPLY) self.win.connect('response', self.response) self.accel_group = gtk.AccelGroup() self.win.add_accel_group(self.accel_group) self.but_cancel = self.win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) self.but_find = self.win.add_button(gtk.STOCK_FIND, gtk.RESPONSE_APPLY) if new and common.MODELACCESS[model]['create']: self.but_new = self.win.add_button(gtk.STOCK_NEW, gtk.RESPONSE_ACCEPT) self.but_new.set_accel_path('/Form/New', self.accel_group) self.but_ok = self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) self.but_ok.add_accelerator('clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) hbox = gtk.HBox() hbox.show() self.win.vbox.pack_start(hbox, expand=False, fill=True) self.win.vbox.pack_start(gtk.HSeparator(), expand=False, fill=True) scrollwindow = gtk.ScrolledWindow() scrollwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.win.vbox.pack_start(scrollwindow, expand=True, fill=True) self.screen = Screen(model, domain=domain, mode=['tree'], context=context, view_ids=view_ids, views_preload=views_preload, row_activate=self.sig_activate, readonly=True) self.view = self.screen.current_view # Prevent to set tree_state self.screen.tree_states_done.add(id(self.view)) sel = self.view.treeview.get_selection() self.win.set_title(_('Search %s') % self.title) if not sel_multi: sel.set_mode(gtk.SELECTION_SINGLE) else: sel.set_mode(gtk.SELECTION_MULTIPLE) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) viewport.add(self.screen.widget) self.screen.widget.show() viewport.show() scrollwindow.add(viewport) scrollwindow.show() self.model_name = model self.win.set_default_size(700, 500) self.register() sensible_allocation = self.sensible_widget.get_allocation() self.win.set_default_size(int(sensible_allocation.width * 0.9), int(sensible_allocation.height * 0.9)) def sig_activate(self, *args): self.view.treeview.emit_stop_by_name('row_activated') self.win.response(gtk.RESPONSE_OK) return True def destroy(self): self.screen.destroy() self.win.destroy() NoModal.destroy(self) def show(self): self.win.show() common.center_window(self.win, self.parent, self.sensible_widget) def hide(self): self.win.hide() def response(self, win, response_id): res = None if response_id == gtk.RESPONSE_OK: res = [r.id for r in self.screen.selected_records] elif response_id == gtk.RESPONSE_APPLY: self.screen.search_filter(self.screen.screen_container.get_text()) return elif response_id == gtk.RESPONSE_ACCEPT: # Remove first tree view as mode if form only view_ids = self.view_ids[1:] screen = Screen(self.model_name, domain=self.domain, context=self.context, mode=['form'], view_ids=view_ids, views_preload=self.views_preload) def callback(result): if result: record = screen.current_record res = [(record.id, record.value.get('rec_name', ''))] self.callback(res) else: self.callback(None) self.destroy() WinForm( screen, callback, new=True, save_current=True, title=self.title) return if res: group = self.screen.group res = [(id_, group.get(id_).value.get('rec_name', '')) for id_ in res] self.callback(res) self.destroy() tryton-4.6.5/tryton/gui/window/revision.py0000644000175000017500000000706513251060075020246 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from tryton.config import TRYTON_ICON from tryton.common import get_toplevel_window from tryton.common.datetime_strftime import datetime_strftime from tryton.common.datetime_ import date_parse _ = gettext.gettext class Revision(object): 'Ask revision' def __init__(self, revisions, revision=None, format_='%x %H:%M:%S.%f'): self.parent = get_toplevel_window() self.win = gtk.Dialog(_('Revision'), self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) self.win.set_default_response(gtk.RESPONSE_OK) self.win.set_icon(TRYTON_ICON) self.win.vbox.set_spacing(3) self.win.vbox.pack_start(gtk.Label( _('Select a revision')), expand=False, fill=True) self.win.vbox.pack_start(gtk.HSeparator()) hbox = gtk.HBox(spacing=3) label = gtk.Label(_('Revision:')) hbox.pack_start(label, expand=True, fill=True) list_store = gtk.ListStore(str, str) # Set model on instantiation to get the default cellrenderer as text combobox = gtk.ComboBoxEntry(model=list_store) self.entry = combobox.get_child() self.entry.connect('focus-out-event', self.focus_out) self.entry.connect('activate', self.activate) label.set_mnemonic_widget(self.entry) combobox.connect('changed', self.changed) self.entry.set_property('activates_default', True) self._format = format_ if revision: self.entry.set_text(datetime_strftime(revision, self._format)) self._value = revision active = -1 else: self._value = None active = 0 list_store.append(('', '')) for i, (rev, id_, name) in enumerate(revisions, 1): list_store.append((datetime_strftime(rev, self._format), name)) if rev == revision: active = i combobox.set_active(active) cell = gtk.CellRendererText() combobox.pack_start(cell, True) combobox.add_attribute(cell, 'text', 1) hbox.pack_start(combobox, expand=True, fill=True) combobox.set_entry_text_column(0) self.win.vbox.pack_start(hbox, expand=True, fill=True) self.win.show_all() def focus_out(self, entry, event): self.parse() self.update() return False def activate(self, entry): self.parse() self.update() return False def changed(self, combobox): # "changed" signal is also triggered by text editing # so only parse when a row is active if combobox.get_active_iter(): self.parse() self.update() return False def parse(self): text = self.entry.get_text() value = None if text: try: value = date_parse(text, self._format) except ValueError: pass self._value = value def update(self): if not self._value: self.entry.set_text('') else: self.entry.set_text(datetime_strftime(self._value, self._format)) def run(self): response = self.win.run() revision = None if response == gtk.RESPONSE_OK: revision = self._value self.parent.present() self.win.destroy() return revision tryton-4.6.5/tryton/gui/window/win_csv.py0000644000175000017500000003154713251060075020062 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import locale import os import sys import gtk import gobject import gettext from tryton.common import center_window from tryton.config import TRYTON_ICON from tryton.gui.window.nomodal import NoModal _ = gettext.gettext encodings = ["ascii", "big5", "big5hkscs", "cp037", "cp424", "cp437", "cp500", "cp720", "cp737", "cp775", "cp850", "cp852", "cp855", "cp856", "cp857", "cp858", "cp860", "cp861", "cp862", "cp863", "cp864", "cp865", "cp866", "cp869", "cp874", "cp875", "cp932", "cp949", "cp950", "cp1006", "cp1026", "cp1140", "cp1250", "cp1251", "cp1252", "cp1253", "cp1254", "cp1255", "cp1256", "cp1257", "cp1258", "euc_jp", "euc_jis_2004", "euc_jisx0213", "euc_kr", "gb2312", "gbk", "gb18030", "hz", "iso2022_jp", "iso2022_jp_1", "iso2022_jp_2", "iso2022_jp_2004", "iso2022_jp_3", "iso2022_jp_ext", "iso2022_kr", "latin_1", "iso8859_2", "iso8859_3", "iso8859_4", "iso8859_5", "iso8859_6", "iso8859_7", "iso8859_8", "iso8859_9", "iso8859_10", "iso8859_13", "iso8859_14", "iso8859_15", "iso8859_16", "johab", "koi8_r", "koi8_u", "mac_cyrillic", "mac_greek", "mac_iceland", "mac_latin2", "mac_roman", "mac_turkish", "ptcp154", "shift_jis", "shift_jis_2004", "shift_jisx0213", "utf_32", "utf_32_be", "utf_32_le", "utf_16", "utf_16_be", "utf_16_le", "utf_7", "utf_8", "utf_8_sig"] class WinCSV(NoModal): def __init__(self, *args, **kwargs): super(WinCSV, self).__init__(*args, **kwargs) self.dialog = gtk.Dialog( parent=self.parent, flags=gtk.DIALOG_DESTROY_WITH_PARENT) self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.dialog.set_icon(TRYTON_ICON) self.dialog.connect('response', self.response) dialog_vbox = gtk.VBox() self.add_header(dialog_vbox) hbox_mapping = gtk.HBox(True) dialog_vbox.pack_start(hbox_mapping, True, True, 0) frame_fields = gtk.Frame() frame_fields.set_shadow_type(gtk.SHADOW_NONE) viewport_fields = gtk.Viewport() scrolledwindow_fields = gtk.ScrolledWindow() scrolledwindow_fields.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) viewport_fields.add(scrolledwindow_fields) frame_fields.add(viewport_fields) label_all_fields = gtk.Label(_('All fields')) label_all_fields.set_use_markup(True) frame_fields.set_label_widget(label_all_fields) hbox_mapping.pack_start(frame_fields, True, True, 0) vbox_buttons = gtk.VBox(False, 10) vbox_buttons.set_border_width(5) hbox_mapping.pack_start(vbox_buttons, False, True, 0) button_add = gtk.Button(_('_Add'), stock=None, use_underline=True) button_add.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-list-add', gtk.ICON_SIZE_BUTTON) button_add.set_image(img_button) button_add.connect_after('clicked', self.sig_sel) vbox_buttons.pack_start(button_add, False, False, 0) button_remove = gtk.Button( _('_Remove'), stock=None, use_underline=True) button_remove.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_BUTTON) button_remove.set_image(img_button) button_remove.connect_after('clicked', self.sig_unsel) vbox_buttons.pack_start(button_remove, False, False, 0) button_remove_all = gtk.Button( _('_Clear'), stock=None, use_underline=True) button_remove_all.set_alignment(0.0, 0.0) img_button = gtk.Image() img_button.set_from_stock('tryton-clear', gtk.ICON_SIZE_BUTTON) button_remove_all.set_image(img_button) button_remove_all.connect_after('clicked', self.sig_unsel_all) vbox_buttons.pack_start(button_remove_all, False, False, 0) hseparator_buttons = gtk.HSeparator() vbox_buttons.pack_start(hseparator_buttons, False, False, 3) self.add_buttons(vbox_buttons) frame_fields_selected = gtk.Frame() frame_fields_selected.set_shadow_type(gtk.SHADOW_NONE) viewport_fields_selected = gtk.Viewport() scrolledwindow_fields_selected = gtk.ScrolledWindow() scrolledwindow_fields_selected.set_policy( gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) viewport_fields_selected.add(scrolledwindow_fields_selected) frame_fields_selected.add(viewport_fields_selected) label_fields_selected = gtk.Label(_('Fields selected')) label_fields_selected .set_use_markup(True) frame_fields_selected.set_label_widget(label_fields_selected) hbox_mapping.pack_start(frame_fields_selected, True, True, 0) frame_csv_param = gtk.Frame() frame_csv_param.set_shadow_type(gtk.SHADOW_ETCHED_OUT) dialog_vbox.pack_start(frame_csv_param, False, True, 0) alignment_csv_param = gtk.Alignment(0.5, 0.5, 1, 1) alignment_csv_param.set_padding(7, 7, 7, 7) frame_csv_param.add(alignment_csv_param) vbox_csv_param = gtk.VBox() alignment_csv_param.add(vbox_csv_param) self.add_chooser(vbox_csv_param) expander_csv = gtk.Expander() vbox_csv_param.pack_start(expander_csv, False, True, 0) label_csv_param = gtk.Label(_('CSV Parameters')) expander_csv.set_label_widget(label_csv_param) table = gtk.Table(2, 4, False) table.set_border_width(8) table.set_row_spacings(9) table.set_col_spacings(8) expander_csv.add(table) label_csv_delimiter = gtk.Label(_('Delimiter:')) label_csv_delimiter.set_alignment(1, 0.5) table.attach(label_csv_delimiter, 0, 1, 0, 1) self.csv_delimiter = gtk.Entry() self.csv_delimiter.set_max_length(1) if os.name == 'nt' and ',' == locale.localeconv()['decimal_point']: delimiter = ';' else: delimiter = ',' self.csv_delimiter.set_text(delimiter) self.csv_delimiter.set_width_chars(1) label_csv_delimiter.set_mnemonic_widget(self.csv_delimiter) table.attach(self.csv_delimiter, 1, 2, 0, 1) label_csv_quotechar = gtk.Label(_("Quote char:")) label_csv_quotechar.set_alignment(1, 0.5) table.attach(label_csv_quotechar, 2, 3, 0, 1) self.csv_quotechar = gtk.Entry() self.csv_quotechar.set_text("\"") self.csv_quotechar.set_width_chars(1) label_csv_quotechar.set_mnemonic_widget(self.csv_quotechar) table.attach(self.csv_quotechar, 3, 4, 0, 1) label_csv_enc = gtk.Label(_("Encoding:")) label_csv_enc.set_alignment(1, 0.5) table.attach(label_csv_enc, 0, 1, 1, 2) if hasattr(gtk, 'ComboBoxText'): self.csv_enc = gtk.ComboBoxText() else: self.csv_enc = gtk.combo_box_new_text() for i, encoding in enumerate(encodings): self.csv_enc.append_text(encoding) if ((os.name == 'nt' and encoding == 'cp1252') or (os.name != 'nt' and encoding == 'utf_8')): self.csv_enc.set_active(i) label_csv_enc.set_mnemonic_widget(self.csv_enc) table.attach(self.csv_enc, 1, 2, 1, 2) self.add_csv_header_param(table) button_cancel = gtk.Button("gtk-cancel", stock="gtk-cancel") self.dialog.add_action_widget(button_cancel, gtk.RESPONSE_CANCEL) button_ok = gtk.Button("gtk-ok", stock="gtk-ok") self.dialog.add_action_widget(button_ok, gtk.RESPONSE_OK) self.dialog.vbox.pack_start(dialog_vbox) self.view1 = gtk.TreeView() self.view1.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.view1.connect('row-expanded', self.on_row_expanded) scrolledwindow_fields.add(self.view1) self.view2 = gtk.TreeView() self.view2.get_selection().set_mode(gtk.SELECTION_MULTIPLE) scrolledwindow_fields_selected.add(self.view2) self.view1.set_headers_visible(False) self.view2.set_headers_visible(False) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_('Field name'), cell, text=0) self.view1.append_column(column) cell = gtk.CellRendererText() column = gtk.TreeViewColumn(_('Field name'), cell, text=0) self.view2.append_column(column) self.model1 = gtk.TreeStore(gobject.TYPE_STRING, gobject.TYPE_STRING) self.model2 = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) self.model_populate(self._get_fields(self.model)) self.view1.set_model(self.model1) self.view1.connect('row-activated', self.sig_sel) self.view2.set_model(self.model2) self.view2.connect('row-activated', self.sig_unsel) sensible_allocation = self.sensible_widget.get_allocation() self.dialog.set_default_size( int(sensible_allocation.width * 0.9), int(sensible_allocation.height * 0.9)) self.dialog.show_all() center_window(self.dialog, self.parent, self.sensible_widget) self.register() if sys.platform != 'darwin': self.view2.drag_source_set( gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, [gtk.TargetEntry.new( 'EXPORT_TREE', gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) self.view2.drag_dest_set(gtk.DEST_DEFAULT_ALL, [gtk.TargetEntry.new( 'EXPORT_TREE', gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) self.view2.connect('drag-begin', self.drag_begin) self.view2.connect('drag-motion', self.drag_motion) self.view2.connect('drag-drop', self.drag_drop) self.view2.connect("drag-data-get", self.drag_data_get) self.view2.connect('drag-data-received', self.drag_data_received) self.view2.connect('drag-data-delete', self.drag_data_delete) def drag_begin(self, treeview, context): return True def drag_motion(self, treeview, context, x, y, time): try: treeview.set_drag_dest_row(*treeview.get_dest_row_at_pos(x, y)) except TypeError: treeview.set_drag_dest_row(len(treeview.get_model()) - 1, gtk.TREE_VIEW_DROP_AFTER) if hasattr(gtk.gdk, 'drag_status'): gtk.gdk.drag_status(context, gtk.gdk.ACTION_MOVE, time) else: context.drag_status(gtk.gdk.ACTION_MOVE, time) return True def drag_drop(self, treeview, context, x, y, time): treeview.emit_stop_by_name('drag-drop') return True def drag_data_get(self, treeview, context, selection, target_id, etime): treeview.emit_stop_by_name('drag-data-get') def _func_sel_get(store, path, iter_, data): data.append(path[0]) data = [] treeselection = treeview.get_selection() treeselection.selected_foreach(_func_sel_get, data) if not data: return data = ','.join(str(x) for x in data) selection.set(selection.get_target(), 8, data) return True def drag_data_received(self, treeview, context, x, y, selection, info, etime): treeview.emit_stop_by_name('drag-data-received') try: selection_data = selection.data except AttributeError: selection_data = selection.get_data() if not selection_data: return store = treeview.get_model() data_iters = [store.get_iter((int(i),)) for i in selection_data.split(',')] drop_info = treeview.get_dest_row_at_pos(x, y) if drop_info: path, position = drop_info pos = store.get_iter(path) else: pos = store.get_iter((len(store) - 1,)) position = gtk.TREE_VIEW_DROP_AFTER if position == gtk.TREE_VIEW_DROP_AFTER: data_iters = reversed(data_iters) for item in data_iters: if position == gtk.TREE_VIEW_DROP_BEFORE: store.move_before(item, pos) else: store.move_after(item, pos) if hasattr(gtk.gdk, 'drop_finish'): gtk.gdk.drop_finish(context, False, etime) else: context.drop_finish(False, etime) return True def drag_data_delete(self, treeview, context): treeview.emit_stop_by_name('drag-data-delete') def get_delimiter(self): return self.csv_delimiter.get_text() or ',' def get_quotechar(self): return self.csv_quotechar.get_text() or '"' def get_encoding(self): return self.csv_enc.get_active_text() or 'utf_8' def destroy(self): super(WinCSV, self).destroy() self.dialog.destroy() def show(self): self.dialog.show() def hide(self): self.dialog.hide() tryton-4.6.5/tryton/gui/window/dblogin.py0000644000175000017500000006333313255571102020030 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import ConfigParser import gtk import gobject import os import gettext import threading from tryton import __version__ import tryton.common as common from tryton.config import CONFIG, TRYTON_ICON, PIXMAPS_DIR, get_config_dir import tryton.rpc as rpc from tryton.exceptions import TrytonError _ = gettext.gettext class DBListEditor(object): def __init__(self, parent, profile_store, profiles, callback): self.profiles = profiles self.current_database = None self.old_profile, self.current_profile = None, None self.db_cache = None self.updating_db = False # GTK Stuffs self.parent = parent self.dialog = gtk.Dialog(title=_(u'Profile Editor'), parent=parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) self.ok_button = self.dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.dialog.set_icon(TRYTON_ICON) hpaned = gtk.HPaned() vbox_profiles = gtk.VBox(homogeneous=False, spacing=6) self.cell = gtk.CellRendererText() self.cell.set_property('editable', True) self.cell.connect('editing-started', self.edit_started) self.profile_tree = gtk.TreeView() self.profile_tree.set_model(profile_store) self.profile_tree.insert_column_with_attributes(-1, _(u'Profile'), self.cell, text=0) self.profile_tree.connect('cursor-changed', self.profile_selected) scroll = gtk.ScrolledWindow() scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.add(self.profile_tree) self.add_button = gtk.Button(_(u'_Add'), use_underline=True) self.add_button.connect('clicked', self.profile_create) add_image = gtk.Image() add_image.set_from_stock('gtk-add', gtk.ICON_SIZE_BUTTON) self.add_button.set_image(add_image) self.remove_button = gtk.Button(_(u'_Remove'), use_underline=True) self.remove_button.connect('clicked', self.profile_delete) remove_image = gtk.Image() remove_image.set_from_stock('gtk-remove', gtk.ICON_SIZE_BUTTON) self.remove_button.set_image(remove_image) vbox_profiles.pack_start(scroll, expand=True, fill=True) vbox_profiles.pack_start(self.add_button, expand=False, fill=True) vbox_profiles.pack_start(self.remove_button, expand=False, fill=True) hpaned.add1(vbox_profiles) table = gtk.Table(4, 2, homogeneous=False) table.set_row_spacings(3) table.set_col_spacings(3) host = gtk.Label(_(u'Host:')) host.set_alignment(1, 0.5) host.set_padding(3, 3) self.host_entry = gtk.Entry() self.host_entry.connect('focus-out-event', self.display_dbwidget) self.host_entry.connect('changed', self.update_profiles, 'host') self.host_entry.set_activates_default(True) host.set_mnemonic_widget(self.host_entry) table.attach(host, 0, 1, 1, 2, yoptions=False, xoptions=gtk.FILL) table.attach(self.host_entry, 1, 2, 1, 2, yoptions=False) database = gtk.Label(_(u'Database:')) database.set_alignment(1, 0.5) database.set_padding(3, 3) self.database_entry = gtk.Entry() self.database_entry.connect('changed', self.dbentry_changed) self.database_entry.connect('changed', self.update_profiles, 'database') self.database_entry.set_activates_default(True) self.database_label = gtk.Label() self.database_label.set_use_markup(True) self.database_label.set_alignment(0, 0.5) self.database_combo = gtk.ComboBox() dbstore = gtk.ListStore(gobject.TYPE_STRING) cell = gtk.CellRendererText() self.database_combo.pack_start(cell, True) self.database_combo.add_attribute(cell, 'text', 0) self.database_combo.set_model(dbstore) self.database_combo.connect('changed', self.dbcombo_changed) self.database_progressbar = gtk.ProgressBar() self.database_progressbar.set_text(_(u'Fetching databases list')) image = gtk.Image() image.set_from_stock('tryton-new', gtk.ICON_SIZE_BUTTON) db_box = gtk.VBox(homogeneous=True) db_box.pack_start(self.database_entry) db_box.pack_start(self.database_combo) db_box.pack_start(self.database_label) db_box.pack_start(self.database_progressbar) # Compute size_request of box in order to prevent "form jumping" width, height = 0, 0 for child in db_box.get_children(): cwidth, cheight = child.size_request() width, height = max(width, cwidth), max(height, cheight) db_box.set_size_request(width, height) table.attach(database, 0, 1, 2, 3, yoptions=False, xoptions=gtk.FILL) table.attach(db_box, 1, 2, 2, 3, yoptions=False) username = gtk.Label(_(u'Username:')) username.set_alignment(1, 0.5) username.set_padding(3, 3) self.username_entry = gtk.Entry() self.username_entry.connect('changed', self.update_profiles, 'username') username.set_mnemonic_widget(self.username_entry) self.username_entry.set_activates_default(True) table.attach(username, 0, 1, 3, 4, yoptions=False, xoptions=gtk.FILL) table.attach(self.username_entry, 1, 2, 3, 4, yoptions=False) hpaned.add2(table) hpaned.set_position(250) self.dialog.vbox.pack_start(hpaned) self.dialog.set_default_size(640, 350) self.dialog.set_default_response(gtk.RESPONSE_ACCEPT) self.dialog.connect('close', lambda *a: False) self.dialog.connect('response', self.response) self.callback = callback def response(self, widget, response): if self.callback: self.callback(self.current_profile['name']) self.parent.present() self.dialog.destroy() def run(self, profile_name): self.clear_entries() # must be done before show_all for windows self.dialog.show_all() model = self.profile_tree.get_model() if model: for i, row in enumerate(model): if row[0] == profile_name: break else: i = 0 self.profile_tree.get_selection().select_path((i,)) self.profile_selected(self.profile_tree) def _current_profile(self): model, selection = self.profile_tree.get_selection().get_selected() if not selection: return {'name': None, 'iter': None} return {'name': model[selection][0], 'iter': selection} def clear_entries(self): for entryname in ('host', 'database', 'username'): entry = getattr(self, '%s_entry' % entryname) entry.handler_block_by_func(self.update_profiles) entry.set_text('') entry.handler_unblock_by_func(self.update_profiles) self.current_database = None self.database_combo.set_active(-1) self.database_combo.get_model().clear() self.hide_database_info() def hide_database_info(self): self.database_entry.hide() self.database_combo.hide() self.database_label.hide() self.database_progressbar.hide() def profile_create(self, button): self.clear_entries() model = self.profile_tree.get_model() model.append(['', False]) column = self.profile_tree.get_column(0) self.profile_tree.set_cursor(len(model) - 1, column, start_editing=True) def profile_delete(self, button): self.clear_entries() model, selection = self.profile_tree.get_selection().get_selected() if not selection: return profile_name = model[selection][0] self.profiles.remove_section(profile_name) del model[selection] def profile_selected(self, treeview): self.old_profile = self.current_profile self.current_profile = self._current_profile() if not self.current_profile['name']: return if self.updating_db: self.current_profile = self.old_profile selection = treeview.get_selection() selection.select_iter(self.old_profile['iter']) return fields = ('host', 'database', 'username') for field in fields: entry = getattr(self, '%s_entry' % field) try: entry_value = self.profiles.get(self.current_profile['name'], field) except ConfigParser.NoOptionError: entry_value = '' entry.set_text(entry_value) if field == 'database': self.current_database = entry_value self.display_dbwidget(None, None) def edit_started(self, renderer, editable, path): if isinstance(editable, gtk.Entry): editable.connect('focus-out-event', self.edit_profilename, renderer, path) def edit_profilename(self, editable, event, renderer, path): newtext = editable.get_text() model = self.profile_tree.get_model() oldname = model[path][0] if oldname == newtext == '': del model[path] return elif oldname == newtext or newtext == '': return if newtext in self.profiles.sections(): del model[path] return elif oldname in self.profiles.sections(): self.profiles.add_section(newtext) for itemname, value in self.profiles.items(oldname): self.profiles.set(newtext, itemname, value) self.profiles.remove_section(oldname) model[path][0] = newtext else: model[path][0] = newtext self.profiles.add_section(newtext) self.current_profile = self._current_profile() self.host_entry.grab_focus() def update_profiles(self, editable, entryname): new_value = editable.get_text() if not new_value: return section = self._current_profile()['name'] self.profiles.set(section, entryname, new_value) self.validate_profile(section) def validate_profile(self, profile_name): model, selection = self.profile_tree.get_selection().get_selected() if not selection: return active = all(self.profiles.has_option(profile_name, option) for option in ('host', 'database')) model[selection][1] = active @classmethod def test_server_version(cls, host, port): ''' Tests if the server version is compatible with the client version It returns None if no information on server version is available. ''' version = rpc.server_version(host, port) if not version: return None return version.split('.')[:2] == __version__.split('.')[:2] def refresh_databases(self, host, port): self.dbs_updated = threading.Event() threading.Thread(target=self.refresh_databases_start, args=(host, port)).start() gobject.timeout_add(100, self.refresh_databases_end, host, port) def refresh_databases_start(self, host, port): dbs = None try: dbs = rpc.db_list(host, port) except Exception: pass finally: self.dbs = dbs self.dbs_updated.set() def refresh_databases_end(self, host, port): if not self.dbs_updated.isSet(): self.database_progressbar.show() self.database_progressbar.pulse() return True self.database_progressbar.hide() dbs = self.dbs label = None if self.test_server_version(host, port) is False: label = _(u'Incompatible version of the server') elif dbs is None: label = _(u'Could not connect to the server') if label: self.database_label.set_label('%s' % label) self.database_label.show() else: liststore = self.database_combo.get_model() liststore.clear() index = -1 for db_num, db_name in enumerate(dbs): liststore.append([db_name]) if self.current_database and db_name == self.current_database: index = db_num if index == -1: index = 0 self.database_combo.set_active(index) self.database_entry.set_text(self.current_database if self.current_database else '') if dbs: self.database_combo.show() else: self.database_entry.show() self.db_cache = (host, port, self.current_profile['name']) self.add_button.set_sensitive(True) self.remove_button.set_sensitive(True) self.ok_button.set_sensitive(True) self.cell.set_property('editable', True) self.host_entry.set_sensitive(True) self.updating_db = False return False def display_dbwidget(self, entry, event): netloc = self.host_entry.get_text() host = common.get_hostname(netloc) if not host: return port = common.get_port(netloc) if (host, port, self.current_profile['name']) == self.db_cache: return if self.updating_db: return self.hide_database_info() self.add_button.set_sensitive(False) self.remove_button.set_sensitive(False) self.ok_button.set_sensitive(False) self.cell.set_property('editable', False) self.host_entry.set_sensitive(False) self.updating_db = True self.refresh_databases(host, port) def dbcombo_changed(self, combobox): dbname = combobox.get_active_text() if dbname: self.current_database = dbname self.profiles.set(self.current_profile['name'], 'database', dbname) self.validate_profile(self.current_profile['name']) def dbentry_changed(self, entry): dbname = entry.get_text() if dbname: self.current_database = dbname self.profiles.set(self.current_profile['name'], 'database', dbname) self.validate_profile(self.current_profile['name']) def insert_text_port(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] try: int(new_value) except ValueError: entry.stop_emission('insert-text') class DBLogin(object): def __init__(self): # GTK Stuffs self.parent = common.get_toplevel_window() self.dialog = gtk.Dialog(title=_('Login'), parent=self.parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) self.dialog.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.dialog.set_icon(TRYTON_ICON) tooltips = common.Tooltips() button_cancel = gtk.Button(_('_Cancel'), use_underline=True) img_cancel = gtk.Image() img_cancel.set_from_stock('gtk-cancel', gtk.ICON_SIZE_BUTTON) button_cancel.set_image(img_cancel) tooltips.set_tip(button_cancel, _('Cancel connection to the Tryton server')) self.dialog.add_action_widget(button_cancel, gtk.RESPONSE_CANCEL) self.button_connect = gtk.Button(_('C_onnect'), use_underline=True) img_connect = gtk.Image() img_connect.set_from_stock('tryton-connect', gtk.ICON_SIZE_BUTTON) self.button_connect.set_image(img_connect) self.button_connect.set_can_default(True) tooltips.set_tip(self.button_connect, _('Connect the Tryton server')) self.dialog.add_action_widget(self.button_connect, gtk.RESPONSE_OK) self.dialog.set_default_response(gtk.RESPONSE_OK) alignment = gtk.Alignment(yalign=0, yscale=0, xscale=1) self.table_main = gtk.Table(3, 3, False) self.table_main.set_border_width(0) self.table_main.set_row_spacings(3) self.table_main.set_col_spacings(3) alignment.add(self.table_main) self.dialog.vbox.pack_start(alignment, True, True, 0) image = gtk.Image() image.set_from_file(os.path.join(PIXMAPS_DIR, 'tryton.png')) image.set_alignment(0.5, 1) ebox = gtk.EventBox() ebox.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("#1b2019")) ebox.add(image) self.table_main.attach(ebox, 0, 3, 0, 1, ypadding=2) self.profile_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) self.combo_profile = gtk.ComboBox() cell = gtk.CellRendererText() self.combo_profile.pack_start(cell, True) self.combo_profile.add_attribute(cell, 'text', 0) self.combo_profile.add_attribute(cell, 'sensitive', 1) self.combo_profile.set_model(self.profile_store) self.combo_profile.connect('changed', self.profile_changed) self.profile_label = gtk.Label(_(u'Profile:')) self.profile_label.set_justify(gtk.JUSTIFY_RIGHT) self.profile_label.set_alignment(1, 0.5) self.profile_label.set_padding(3, 3) self.profile_button = gtk.Button(_('_Manage profiles'), use_underline=True) self.profile_button.connect('clicked', self.profile_manage) self.table_main.attach(self.profile_label, 0, 1, 1, 2, xoptions=gtk.FILL) self.table_main.attach(self.combo_profile, 1, 2, 1, 2) self.table_main.attach(self.profile_button, 2, 3, 1, 2, xoptions=gtk.FILL) image = gtk.Image() image.set_from_stock('gtk-edit', gtk.ICON_SIZE_BUTTON) self.profile_button.set_image(image) self.expander = gtk.Expander() self.expander.set_label(_('Host / Database information')) self.expander.connect('notify::expanded', self.expand_hostspec) self.table_main.attach(self.expander, 0, 3, 3, 4) self.label_host = gtk.Label(_('Host:')) self.label_host.set_justify(gtk.JUSTIFY_RIGHT) self.label_host.set_alignment(1, 0.5) self.label_host.set_padding(3, 3) self.entry_host = gtk.Entry() self.entry_host.connect_after('focus-out-event', self.clear_profile_combo) self.entry_host.set_activates_default(True) self.label_host.set_mnemonic_widget(self.entry_host) self.table_main.attach(self.label_host, 0, 1, 4, 5, xoptions=gtk.FILL) self.table_main.attach(self.entry_host, 1, 3, 4, 5) self.label_database = gtk.Label(_('Database:')) self.label_database.set_justify(gtk.JUSTIFY_RIGHT) self.label_database.set_alignment(1, 0.5) self.label_database.set_padding(3, 3) self.entry_database = gtk.Entry() self.entry_database.connect_after('focus-out-event', self.clear_profile_combo) self.entry_database.set_activates_default(True) self.label_database.set_mnemonic_widget(self.entry_database) self.table_main.attach(self.label_database, 0, 1, 5, 6, xoptions=gtk.FILL) self.table_main.attach(self.entry_database, 1, 3, 5, 6) self.entry_login = gtk.Entry() self.entry_login.set_activates_default(True) self.table_main.attach(self.entry_login, 1, 3, 6, 7) label_username = gtk.Label(_("User name:")) label_username.set_alignment(1, 0.5) label_username.set_padding(3, 3) label_username.set_mnemonic_widget(self.entry_login) self.table_main.attach(label_username, 0, 1, 6, 7, xoptions=gtk.FILL) # Profile informations self.profile_cfg = os.path.join(get_config_dir(), 'profiles.cfg') self.profiles = ConfigParser.SafeConfigParser() if not os.path.exists(self.profile_cfg): short_version = '.'.join(__version__.split('.', 2)[:2]) name = 'demo%s.tryton.org' % short_version self.profiles.add_section(name) self.profiles.set(name, 'host', name) self.profiles.set(name, 'database', 'demo%s' % short_version) self.profiles.set(name, 'username', 'demo') else: self.profiles.read(self.profile_cfg) for section in self.profiles.sections(): active = all(self.profiles.has_option(section, option) for option in ('host', 'database')) self.profile_store.append([section, active]) def profile_manage(self, widget): def callback(profile_name): with open(self.profile_cfg, 'wb') as configfile: self.profiles.write(configfile) for idx, row in enumerate(self.profile_store): if row[0] == profile_name and row[1]: self.combo_profile.set_active(idx) self.profile_changed(self.combo_profile) break dia = DBListEditor(self.dialog, self.profile_store, self.profiles, callback) active_profile = self.combo_profile.get_active() profile_name = None if active_profile != -1: profile_name = self.profile_store[active_profile][0] dia.run(profile_name) def profile_changed(self, combobox): position = combobox.get_active() if position == -1: return profile = self.profile_store[position][0] try: username = self.profiles.get(profile, 'username') except ConfigParser.NoOptionError: username = '' host = self.profiles.get(profile, 'host') self.entry_host.set_text('%s' % host) self.entry_database.set_text(self.profiles.get(profile, 'database')) if username: self.entry_login.set_text(username) else: self.entry_login.set_text('') def clear_profile_combo(self, *args): netloc = self.entry_host.get_text() host = common.get_hostname(netloc) port = common.get_port(netloc) database = self.entry_database.get_text().strip() for idx, profile_info in enumerate(self.profile_store): if not profile_info[1]: continue profile = profile_info[0] profile_host = self.profiles.get(profile, 'host') profile_db = self.profiles.get(profile, 'database') if (host == common.get_hostname(profile_host) and port == common.get_port(profile_host) and database == profile_db): break else: idx = -1 self.combo_profile.set_active(idx) return False def expand_hostspec(self, expander, *args): visibility = expander.props.expanded self.entry_host.props.visible = visibility self.label_host.props.visible = visibility self.entry_database.props.visible = visibility self.label_database.props.visible = visibility def run(self): profile_name = CONFIG['login.profile'] can_use_profile = self.profiles.has_section(profile_name) if can_use_profile: for (configname, sectionname) in [ ('login.host', 'host'), ('login.db', 'database'), ]: if (self.profiles.get(profile_name, sectionname) != CONFIG[configname]): can_use_profile = False break if can_use_profile: for idx, row in enumerate(self.profile_store): if row[0] == profile_name: self.combo_profile.set_active(idx) break else: self.combo_profile.set_active(-1) host = CONFIG['login.host'] if CONFIG['login.host'] else '' self.entry_host.set_text(host) db = CONFIG['login.db'] if CONFIG['login.db'] else '' self.entry_database.set_text(db) self.entry_login.set_text(CONFIG['login.login']) self.clear_profile_combo() self.dialog.show_all() self.entry_login.grab_focus() # Reshow dialog for gtk-quarks self.dialog.reshow_with_initial_size() self.expander.set_expanded(CONFIG['login.expanded']) # The previous action did not called expand_hostspec self.expand_hostspec(self.expander) response, result = None, ('', '', '', '') while not all(result): response = self.dialog.run() if response != gtk.RESPONSE_OK: break self.clear_profile_combo() active_profile = self.combo_profile.get_active() if active_profile != -1: profile = self.profile_store[active_profile][0] else: profile = '' host = self.entry_host.get_text() hostname = common.get_hostname(host) port = common.get_port(host) test = DBListEditor.test_server_version(hostname, port) if not test: if test is False: common.warning('', _(u'Incompatible version of the server')) else: common.warning('', _(u'Could not connect to the server')) continue database = self.entry_database.get_text() login = self.entry_login.get_text() CONFIG['login.profile'] = profile CONFIG['login.host'] = host CONFIG['login.db'] = database CONFIG['login.expanded'] = self.expander.props.expanded CONFIG['login.login'] = login result = ( hostname, port, database, self.entry_login.get_text()) self.parent.present() self.dialog.destroy() if response != gtk.RESPONSE_OK: rpc.logout() raise TrytonError('QueryCanceled') return result tryton-4.6.5/tryton/gui/window/form.py0000644000175000017500000006016013255571102017350 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Form" import gettext import gtk import gobject from tryton.gui.window.view_form.screen import Screen from tryton.action import Action from tryton.gui import Main from tryton.gui.window import Window from tryton.gui.window.win_export import WinExport from tryton.gui.window.win_import import WinImport from tryton.gui.window.attachment import Attachment from tryton.gui.window.note import Note from tryton.gui.window.revision import Revision from tryton.signal_event import SignalEvent from tryton.common import message, sur, sur_3b, timezoned_date import tryton.common as common from tryton.common import RPCExecute, RPCException from tryton.common.datetime_strftime import datetime_strftime from tryton import plugins from tabcontent import TabContent _ = gettext.gettext class Form(SignalEvent, TabContent): "Form" def __init__(self, model, res_id=None, name='', **attributes): super(Form, self).__init__() self.model = model self.res_id = res_id self.mode = attributes.get('mode') self.view_ids = attributes.get('view_ids') self.dialogs = [] self.screen = Screen(self.model, **attributes) self.screen.widget.show() self.name = name self.create_tabcontent() self.set_buttons_sensitive() self.screen.signal_connect(self, 'record-message', self._record_message) self.screen.signal_connect(self, 'record-modified', lambda *a: gobject.idle_add(self._record_modified, *a)) self.screen.signal_connect(self, 'record-saved', self._record_saved) self.screen.signal_connect(self, 'attachment-count', self._attachment_count) self.screen.signal_connect(self, 'unread-note', self._unread_note) if res_id not in (None, False): if isinstance(res_id, (int, long)): res_id = [res_id] self.screen.load(res_id) else: if self.screen.current_view.view_type == 'form': self.sig_new(None, autosave=False) if self.screen.current_view.view_type \ in ('tree', 'graph', 'calendar'): self.screen.search_filter() self.update_revision() def get_toolbars(self): try: return RPCExecute('model', self.model, 'view_toolbar_get', context=self.screen.context) except RPCException: return {} def widget_get(self): return self.screen.widget def __eq__(self, value): if not value: return False if not isinstance(value, Form): return False return (self.model == value.model and self.res_id == value.res_id and self.screen.domain == value.screen.domain and self.mode == value.mode and self.view_ids == value.view_ids and self.screen.context == value.screen.context and self.name == value.name and self.screen.limit == value.screen.limit and self.screen.search_value == value.screen.search_value) def destroy(self): super(Form, self).destroy() self.screen.signal_unconnect(self) self.screen.destroy() def sig_attach(self, widget=None): record = self.screen.current_record if not record or record.id < 0: return Attachment(record, lambda: self.update_attachment_count(reload=True)) def update_attachment_count(self, reload=False): record = self.screen.current_record if record: attachment_count = record.get_attachment_count(reload=reload) else: attachment_count = 0 self._attachment_count(None, attachment_count) def _attachment_count(self, widget, signal_data): label = _('Attachment(%d)') % signal_data self.buttons['attach'].set_label(label) if signal_data: self.buttons['attach'].set_stock_id('tryton-attachment-hi') else: self.buttons['attach'].set_stock_id('tryton-attachment') record = self.screen.current_record self.buttons['attach'].props.sensitive = bool( record.id >= 0 if record else False) def sig_note(self, widget=None): record = self.screen.current_record if not record or record.id < 0: return Note(record, lambda: self.update_unread_note(reload=True)) def update_unread_note(self, reload=False): record = self.screen.current_record if record: unread = record.get_unread_note(reload=reload) else: unread = 0 self._unread_note(None, unread) def _unread_note(self, widget, signal_data): label = _('Note(%d)') % signal_data self.buttons['note'].set_label(label) if signal_data: self.buttons['note'].set_stock_id('tryton-note-hi') else: self.buttons['note'].set_stock_id('tryton-note') record = self.screen.current_record if not record or record.id < 0: sensitive = False else: sensitive = True self.buttons['note'].props.sensitive = sensitive def sig_switch(self, widget=None): if not self.modified_save(): return self.screen.switch_view() def sig_logs(self, widget=None): current_record = self.screen.current_record if not current_record or current_record.id < 0: self.message_info( _('You have to select one record.'), gtk.MESSAGE_INFO) return False fields = [ ('id', _('ID:')), ('create_uid.rec_name', _('Creation User:')), ('create_date', _('Creation Date:')), ('write_uid.rec_name', _('Latest Modification by:')), ('write_date', _('Latest Modification Date:')), ] try: res = RPCExecute('model', self.model, 'read', [current_record.id], [x[0] for x in fields], context=self.screen.context) except RPCException: return date_format = self.screen.context.get('date_format', '%x') datetime_format = date_format + ' %H:%M:%S.%f' message_str = '' for line in res: for (key, val) in fields: value = str(line.get(key, False) or '/') if line.get(key, False) \ and key in ('create_date', 'write_date'): date = timezoned_date(line[key]) value = common.datetime_strftime(date, datetime_format) message_str += val + ' ' + value + '\n' message_str += _('Model:') + ' ' + self.model message(message_str) return True def sig_revision(self, widget=None): if not self.modified_save(): return current_id = (self.screen.current_record.id if self.screen.current_record else None) try: revisions = RPCExecute('model', self.model, 'history_revisions', [r.id for r in self.screen.selected_records]) except RPCException: return revision = self.screen.context.get('_datetime') format_ = self.screen.context.get('date_format', '%x') format_ += ' %H:%M:%S.%f' revision = Revision(revisions, revision, format_).run() # Prevent too old revision in form view if (self.screen.current_view.view_type == 'form' and revision and revision < revisions[-1][0]): revision = revisions[-1][0] if revision != self.screen.context.get('_datetime'): self.screen.clear() # Update root group context that will be propagated self.screen.group._context['_datetime'] = revision if self.screen.current_view.view_type != 'form': self.screen.search_filter( self.screen.screen_container.get_text()) else: # Test if record exist in revisions self.screen.load([current_id]) self.screen.display(set_cursor=True) self.update_revision() def update_revision(self): revision = self.screen.context.get('_datetime') if revision: format_ = self.screen.context.get('date_format', '%x') format_ += ' %H:%M:%S.%f' revision = datetime_strftime(revision, format_) self.title.set_label('%s @ %s' % (self.name, revision)) else: self.title.set_label(self.name) self.set_buttons_sensitive(revision) def set_buttons_sensitive(self, revision=None): if not revision: access = common.MODELACCESS[self.model] for name, sensitive in [ ('new', access['create']), ('save', access['create'] or access['write']), ('remove', access['delete']), ('copy', access['create']), ('import', access['create']), ]: if name in self.buttons: self.buttons[name].props.sensitive = sensitive if name in self.menu_buttons: self.menu_buttons[name].props.sensitive = sensitive else: for name in ['new', 'save', 'remove', 'copy', 'import']: if name in self.buttons: self.buttons[name].props.sensitive = False if name in self.menu_buttons: self.menu_buttons[name].props.sensitive = False def sig_remove(self, widget=None): if not common.MODELACCESS[self.model]['delete']: return if self.screen.current_view.view_type == 'form': msg = _('Are you sure to remove this record?') else: msg = _('Are you sure to remove those records?') if sur(msg): if not self.screen.remove(delete=True, force_remove=True): self.message_info(_('Records not removed.'), gtk.MESSAGE_ERROR) else: self.message_info(_('Records removed.'), gtk.MESSAGE_INFO) self.screen.count_tab_domain() def sig_import(self, widget=None): WinImport(self.model, self.screen.context) def sig_export(self, widget=None): export = WinExport(self.model, [r.id for r in self.screen.selected_records], context=self.screen.context) for name in self.screen.current_view.get_fields(): export.sel_field(name) def sig_new(self, widget=None, autosave=True): if not common.MODELACCESS[self.model]['create']: return if autosave: if not self.modified_save(): return self.screen.new() self.message_info() self.activate_save() def sig_copy(self, widget=None): if not common.MODELACCESS[self.model]['create']: return if not self.modified_save(): return if self.screen.copy(): self.message_info(_('Working now on the duplicated record(s).'), gtk.MESSAGE_INFO) self.screen.count_tab_domain() def sig_save(self, widget=None): if widget: # Called from button so we must save the tree state self.screen.save_tree_state() if not (common.MODELACCESS[self.model]['write'] or common.MODELACCESS[self.model]['create']): return if self.screen.save_current(): self.message_info(_('Record saved.'), gtk.MESSAGE_INFO) self.screen.count_tab_domain() return True else: self.message_info(self.screen.invalid_message(), gtk.MESSAGE_ERROR) return False def sig_previous(self, widget=None): if not self.modified_save(): return self.screen.display_prev() self.message_info() self.activate_save() def sig_next(self, widget=None): if not self.modified_save(): return self.screen.display_next() self.message_info() self.activate_save() def sig_reload(self, test_modified=True): if test_modified: if not self.modified_save(): return False else: self.screen.save_tree_state(store=False) self.screen.cancel_current() set_cursor = False record_id = (self.screen.current_record.id if self.screen.current_record else None) if self.screen.current_view.view_type != 'form': self.screen.search_filter(self.screen.screen_container.get_text()) for record in self.screen.group: if record.id == record_id: self.screen.current_record = record set_cursor = True break self.screen.display(set_cursor=set_cursor) self.message_info() self.activate_save() self.screen.count_tab_domain() return True def sig_action(self, widget): if self.buttons['action'].props.sensitive: self.buttons['action'].props.active = True def sig_print(self, widget): if self.buttons['print'].props.sensitive: self.buttons['print'].props.active = True def sig_print_open(self, widget): if self.buttons['open'].props.sensitive: self.buttons['open'].props.active = True def sig_print_email(self, widget): if self.buttons['email'].props.sensitive: self.buttons['email'].props.active = True def sig_relate(self, widget): if self.buttons['relate'].props.sensitive: self.buttons['relate'].props.active = True def sig_copy_url(self, widget): if self.buttons['copy_url'].props.sensitive: self.buttons['copy_url'].props.active = True def sig_search(self, widget): search_container = self.screen.screen_container if hasattr(search_container, 'search_entry'): search_container.search_entry.grab_focus() def action_popup(self, widget): button, = widget.get_children() button.grab_focus() menu = widget._menu if not widget.props.active: menu.popdown() return def menu_position(menu, data): widget_allocation = widget.get_allocation() if hasattr(widget.window, 'get_root_coords'): x, y = widget.window.get_root_coords( widget_allocation.x, widget_allocation.y) else: x, y = widget.window.get_origin() x += widget_allocation.x y += widget_allocation.y return (x, y + widget_allocation.height, False) menu.show_all() menu.popup(None, None, menu_position, 0, gtk.get_current_event_time(), None) def _record_message(self, screen, signal_data): name = '_' if signal_data[0]: name = str(signal_data[0]) for button_id in ('print', 'relate', 'email', 'open', 'save', 'attach'): button = self.buttons[button_id] can_be_sensitive = getattr(button, '_can_be_sensitive', True) button.props.sensitive = (bool(signal_data[0]) and can_be_sensitive) button_switch = self.buttons['switch'] button_switch.props.sensitive = self.screen.number_of_views > 1 msg = name + ' / ' + str(signal_data[1]) if signal_data[1] < signal_data[2]: msg += _(' of ') + str(signal_data[2]) self.status_label.set_text(msg) self.message_info() self.activate_save() def _record_modified(self, screen, signal_data): # As it is called via idle_add, the form could have been destroyed in # the meantime. if self.widget_get().props.window: self.activate_save() def _record_saved(self, screen, signal_data): self.activate_save() self.update_attachment_count() def modified_save(self): self.screen.save_tree_state() self.screen.current_view.set_value() if self.screen.modified(): value = sur_3b( _('This record has been modified\n' 'do you want to save it?')) if value == 'ok': return self.sig_save(None) if value == 'ko': return self.sig_reload(test_modified=False) return False return True def sig_close(self, widget=None): for dialog in self.dialogs[:]: dialog.destroy() return self.modified_save() def _action(self, action, atype): action = action.copy() if not self.screen.save_current(): return record_id = (self.screen.current_record.id if self.screen.current_record else None) record_ids = [r.id for r in self.screen.selected_records] action = Action.evaluate(action, atype, self.screen.current_record) data = { 'model': self.screen.model_name, 'id': record_id, 'ids': record_ids, } Action._exec_action(action, data, self.screen.context) def activate_save(self): self.buttons['save'].props.sensitive = self.screen.modified() def sig_win_close(self, widget): Main.get_main().sig_win_close(widget) def create_toolbar(self, toolbars): gtktoolbar = super(Form, self).create_toolbar(toolbars) attach_btn = self.buttons['attach'] target_entry = gtk.TargetEntry.new('text/uri-list', 0, 0) attach_btn.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ target_entry, ], gtk.gdk.ACTION_MOVE | gtk.gdk.ACTION_COPY) attach_btn.connect('drag_data_received', self.attach_drag_data_received) iconstock = { 'print': 'tryton-print', 'action': 'tryton-executable', 'relate': 'tryton-go-jump', 'email': 'tryton-print-email', 'open': 'tryton-print-open', } for action_type, special_action, action_name, tooltip in ( ('action', 'action', _('Action'), _('Launch action')), ('relate', 'relate', _('Relate'), _('Open related records')), (None,) * 4, ('print', 'open', _('Report'), _('Open report')), ('print', 'email', _('E-Mail'), _('E-Mail report')), ('print', 'print', _('Print'), _('Print report')), ): if action_type is not None: tbutton = gtk.ToggleToolButton(iconstock.get(special_action)) tbutton.set_label(action_name) tbutton._menu = self._create_popup_menu(tbutton, action_type, toolbars[action_type], special_action) tbutton.connect('toggled', self.action_popup) self.tooltips.set_tip(tbutton, tooltip) self.buttons[special_action] = tbutton if action_type != 'action': tbutton._can_be_sensitive = bool( tbutton._menu.get_children()) else: tbutton = gtk.SeparatorToolItem() gtktoolbar.insert(tbutton, -1) gtktoolbar.insert(gtk.SeparatorToolItem(), -1) url_button = gtk.ToggleToolButton('tryton-web-browser') url_button.set_label(_('_Copy URL')) url_button.set_use_underline(True) self.tooltips.set_tip( url_button, _('Copy URL into clipboard')) url_button._menu = url_menu = gtk.Menu() url_menuitem = gtk.MenuItem() url_menuitem.connect('activate', self.url_copy) url_menu.add(url_menuitem) url_menu.show_all() url_menu.connect('deactivate', self._popup_menu_hide, url_button) url_button.connect('toggled', self.url_set, url_menuitem) url_button.connect('toggled', self.action_popup) self.buttons['copy_url'] = url_button gtktoolbar.insert(url_button, -1) return gtktoolbar def _create_popup_menu(self, widget, keyword, actions, special_action): menu = gtk.Menu() menu.connect('deactivate', self._popup_menu_hide, widget) if keyword == 'action': widget.connect('toggled', self._update_action_popup, menu) for action in actions: new_action = action.copy() if special_action == 'print': new_action['direct_print'] = True elif special_action == 'email': new_action['email_print'] = True action_name = action['name'] if '_' not in action_name: action_name = '_' + action_name menuitem = gtk.MenuItem(action_name) menuitem.set_use_underline(True) menuitem.connect('activate', self._popup_menu_selected, widget, new_action, keyword) menu.add(menuitem) return menu def _popup_menu_selected(self, menuitem, togglebutton, action, keyword): event = gtk.get_current_event() allow_similar = False if (event.state & gtk.gdk.CONTROL_MASK or event.state & gtk.gdk.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): self._action(action, keyword) togglebutton.props.active = False def _popup_menu_hide(self, menuitem, togglebutton): togglebutton.props.active = False def _update_action_popup(self, tbutton, menu): for item in menu.get_children(): if (getattr(item, '_update_action', False) or isinstance(item, gtk.SeparatorMenuItem)): menu.remove(item) buttons = self.screen.get_buttons() if buttons: menu.add(gtk.SeparatorMenuItem()) for button in buttons: menuitem = gtk.ImageMenuItem() menuitem.set_label('_' + button.attrs.get('string', _('Unknown'))) menuitem.set_use_underline(True) if button.attrs.get('icon'): icon = gtk.Image() icon.set_from_stock(button.attrs['icon'], gtk.ICON_SIZE_MENU) menuitem.set_image(icon) menuitem.connect('activate', lambda m, attrs: self.screen.button(attrs), button.attrs) menuitem._update_action = True menu.add(menuitem) menu.add(gtk.SeparatorMenuItem()) for plugin in plugins.MODULES: for name, func in plugin.get_plugins(self.model): menuitem = gtk.MenuItem('_' + name) menuitem.set_use_underline(True) menuitem.connect('activate', lambda m, func: func({ 'model': self.model, 'ids': [r.id for r in self.screen.selected_records], 'id': (self.screen.current_record.id if self.screen.current_record else None), }), func) menuitem._update_action = True menu.add(menuitem) def url_copy(self, menuitem): url = self.screen.get_url(self.name) for selection in [gtk.CLIPBOARD_PRIMARY, gtk.CLIPBOARD_CLIPBOARD]: clipboard = gtk.clipboard_get(selection) clipboard.set_text(url, -1) def url_set(self, button, menuitem): url = self.screen.get_url(self.name) size = 80 if len(url) > size: url = url[:size // 2] + '...' + url[-size // 2:] menuitem.set_label(url) def set_cursor(self): if self.screen: self.screen.set_cursor(reset_view=False) def attach_drag_data_received(self, widget, context, x, y, selection, info, timestamp): record = self.screen.current_record if not record or record.id < 0: return win_attach = Attachment(record, lambda: self.update_attachment_count(reload=True)) if info == 0: for uri in selection.data.splitlines(): # Win32 cut&paste terminates the list with a NULL character if not uri or uri == '\0': continue win_attach.add_uri(uri) tryton-4.6.5/tryton/gui/window/view_form/0000755000175000017500000000000013260723567020037 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/screen/0000755000175000017500000000000013260723567021316 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/screen/__init__.py0000644000175000017500000000024513175640533023424 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from screen import * tryton-4.6.5/tryton/gui/window/view_form/screen/screen.py0000644000175000017500000013315213255571102023142 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Screen" import copy import functools import gobject import datetime import calendar import json import collections import urllib import urlparse import xml.dom.minidom import gettext import logging import gtk from tryton.gui.window.view_form.model.group import Group from tryton.gui.window.view_form.view.screen_container import ScreenContainer from tryton.gui.window.view_form.view import View from tryton.signal_event import SignalEvent from tryton.config import CONFIG from tryton.jsonrpc import JSONEncoder from tryton.common.domain_parser import DomainParser from tryton.common import RPCExecute, RPCException, MODELACCESS, \ node_attributes, sur, RPCContextReload, warning from tryton.action import Action from tryton.pyson import PYSONDecoder import tryton.rpc as rpc _ = gettext.gettext logger = logging.getLogger(__name__) class Screen(SignalEvent): "Screen" # Width of tree columns per model # It is shared with all connection but it is the price for speed. tree_column_width = collections.defaultdict(lambda: {}) def __init__(self, model_name, **attributes): context = attributes.get('context', {}) self.limit = attributes.get('limit', CONFIG['client.limit']) self.offset = 0 super(Screen, self).__init__() self.readonly = attributes.get('readonly', False) if not (MODELACCESS[model_name]['write'] or MODELACCESS[model_name]['create']): self.readonly = True self.search_count = 0 if not attributes.get('row_activate'): self.row_activate = self.default_row_activate else: self.row_activate = attributes['row_activate'] self.domain = attributes.get('domain', []) self.context_domain = attributes.get('context_domain') self.size_limit = None self.views_preload = attributes.get('views_preload', {}) self.model_name = model_name self.views = [] self.view_ids = attributes.get('view_ids', [])[:] self.parent = None self.parent_name = None self.exclude_field = attributes.get('exclude_field') self.filter_widget = None self.tree_states = collections.defaultdict( lambda: collections.defaultdict(lambda: None)) self.tree_states_done = set() self.__group = None self.new_group(context or {}) self.__current_record = None self.current_record = None self.screen_container = ScreenContainer(attributes.get('tab_domain')) self.screen_container.alternate_view = attributes.get( 'alternate_view', False) self.widget = self.screen_container.widget_get() self.context_screen = None if attributes.get('context_model'): self.context_screen = Screen( attributes['context_model'], mode=['form'], context=context) self.context_screen.new() context_widget = self.context_screen.widget def walk_descendants(widget): yield widget if not hasattr(widget, 'get_children'): return for child in widget.get_children(): for widget in walk_descendants(child): yield widget for widget in reversed(list(walk_descendants(context_widget))): if isinstance(widget, gtk.Entry): widget.connect_after( 'activate', self.screen_container.activate) elif isinstance(widget, gtk.CheckButton): widget.connect_after( 'toggled', self.screen_container.activate) def remove_bin(widget): assert isinstance(widget, (gtk.ScrolledWindow, gtk.Viewport)) parent = widget.get_parent() parent.remove(widget) child = widget.get_child() while isinstance(child, (gtk.ScrolledWindow, gtk.Viewport)): child = child.get_child() child.get_parent().remove(child) parent.add(child) return child # Remove first level Viewport and ScrolledWindow to fill the Vbox for widget in [ self.context_screen.screen_container.viewport, self.context_screen.current_view.widget.get_children()[0], ]: remove_bin(widget) self.screen_container.filter_vbox.pack_start( context_widget, expand=False, fill=True) self.screen_container.filter_vbox.reorder_child( context_widget, 0) self.context_screen.widget.show() self.__current_view = 0 self.search_value = attributes.get('search_value') self.fields_view_tree = {} self.order = self.default_order = attributes.get('order') self.__date_format = self.context.get( 'date_format', rpc.CONTEXT.get('locale', {}).get('date', '%x')) self.view_to_load = [] self._domain_parser = {} self.pre_validate = False mode = attributes.get('mode') if mode is None: mode = ['tree', 'form'] self.view_to_load = mode[:] if self.view_ids or self.view_to_load: self.switch_view() self.count_tab_domain() def __repr__(self): return '' % (self.model_name, id(self)) def search_active(self, active=True): if active and not self.parent: self.screen_container.set_screen(self) self.screen_container.show_filter() else: self.screen_container.hide_filter() @property def domain_parser(self): view_id = self.current_view.view_id if self.current_view else None if view_id in self._domain_parser: return self._domain_parser[view_id] if view_id not in self.fields_view_tree: try: self.fields_view_tree[view_id] = view_tree = RPCExecute( 'model', self.model_name, 'fields_view_get', False, 'tree', context=self.context) except RPCException: view_tree = { 'fields': {}, } else: view_tree = self.fields_view_tree[view_id] fields = copy.deepcopy(view_tree['fields']) for name, props in fields.iteritems(): if props['type'] not in ('selection', 'reference'): continue if isinstance(props['selection'], (tuple, list)): continue props['selection'] = self.get_selection(props) if 'arch' in view_tree: # Filter only fields in XML view xml_dom = xml.dom.minidom.parseString(view_tree['arch']) root_node, = xml_dom.childNodes xml_fields = [node_attributes(node).get('name') for node in root_node.childNodes if node.nodeName == 'field'] fields = collections.OrderedDict( (name, fields[name]) for name in xml_fields) # Add common fields for name, string, type_ in ( ('id', _('ID'), 'integer'), ('create_uid', _('Creation User'), 'many2one'), ('create_date', _('Creation Date'), 'datetime'), ('write_uid', _('Modification User'), 'many2one'), ('write_date', _('Modification Date'), 'datetime'), ): if name not in fields: fields[name] = { 'string': string.decode('utf-8'), 'name': name, 'type': type_, } if type_ == 'datetime': fields[name]['format'] = '"%H:%M:%S"' context = rpc.CONTEXT.copy() context.update(self.context) domain_parser = DomainParser(fields, context) self._domain_parser[view_id] = domain_parser return domain_parser def get_selection(self, props): try: change_with = props.get('selection_change_with') if change_with: selection = RPCExecute('model', self.model_name, props['selection'], dict((p, None) for p in change_with)) else: selection = RPCExecute('model', self.model_name, props['selection']) except RPCException: selection = [] selection.sort(lambda x, y: cmp(x[1], y[1])) return selection def search_prev(self, search_string): if self.limit: self.offset -= self.limit self.search_filter(search_string=search_string) def search_next(self, search_string): if self.limit: self.offset += self.limit self.search_filter(search_string=search_string) def search_complete(self, search_string): return list(self.domain_parser.completion(search_string)) def search_filter(self, search_string=None, only_ids=False): if self.context_screen: context_record = self.context_screen.current_record if not context_record.validate(): self.clear() self.context_screen.display(set_cursor=True) return False context = self.context context.update(self.context_screen.get_on_change_value()) self.new_group(context) domain = self.search_domain(search_string, True) if self.context_domain: decoder = PYSONDecoder(self.context) domain = ['AND', domain, decoder.decode(self.context_domain)] tab_domain = self.screen_container.get_tab_domain() if tab_domain: domain = ['AND', domain, tab_domain] try: ids = RPCExecute('model', self.model_name, 'search', domain, self.offset, self.limit, self.order, context=self.context) except RPCException: ids = [] if not only_ids: if self.limit is not None and len(ids) == self.limit: try: self.search_count = RPCExecute('model', self.model_name, 'search_count', domain, context=self.context) except RPCException: self.search_count = 0 else: self.search_count = len(ids) self.screen_container.but_prev.set_sensitive(bool(self.offset)) if (self.limit is not None and len(ids) == self.limit and self.search_count > self.limit + self.offset): self.screen_container.but_next.set_sensitive(True) else: self.screen_container.but_next.set_sensitive(False) if only_ids: return ids self.clear() self.load(ids) self.count_tab_domain() return bool(ids) def search_domain(self, search_string=None, set_text=False): domain = [] # Test first parent to avoid calling unnecessary domain_parser if not self.parent and self.domain_parser: if search_string is not None: domain = self.domain_parser.parse(search_string) else: domain = self.search_value if set_text: self.screen_container.set_text( self.domain_parser.string(domain)) else: domain = [('id', 'in', [x.id for x in self.group])] if domain: if self.domain: domain = ['AND', domain, self.domain] else: domain = self.domain if self.current_view and self.current_view.view_type == 'calendar': if domain: domain = ['AND', domain, self.current_view.current_domain()] else: domain = self.current_view.current_domain() return domain def count_tab_domain(self): def set_tab_counter(count, idx): try: count = count() except RPCException: count = None self.screen_container.set_tab_counter(count, idx) screen_domain = self.search_domain(self.screen_container.get_text()) for idx, (name, domain, count) in enumerate( self.screen_container.tab_domain): if not count: continue domain = ['AND', domain, screen_domain] set_tab_counter(lambda: None, idx) RPCExecute('model', self.model_name, 'search_count', domain, context=self.context, callback=functools.partial(set_tab_counter, idx=idx)) @property def context(self): return self.group.context @property def date_format(self): return self.__date_format def __get_group(self): return self.__group def __set_group(self, group): fields = {} if self.group is not None: self.group.signal_unconnect(self) for name, field in self.group.fields.iteritems(): fields[name] = field.attrs self.tree_states_done.clear() self.__group = group self.parent = group.parent self.parent_name = group.parent_name if self.parent: self.filter_widget = None if len(group): self.current_record = group[0] else: self.current_record = None self.__group.signal_connect(self, 'group-cleared', self._group_cleared) self.__group.signal_connect(self, 'group-list-changed', self._group_list_changed) self.__group.signal_connect(self, 'record-modified', self._record_modified) self.__group.signal_connect(self, 'group-changed', self._group_changed) self.__group.add_fields(fields) self.__group.exclude_field = self.exclude_field group = property(__get_group, __set_group) def new_group(self, context=None): context = context if context is not None else self.context self.group = Group(self.model_name, {}, domain=self.domain, context=context, readonly=self.readonly) def _group_cleared(self, group, signal): for view in self.views: if hasattr(view, 'reload'): view.reload = True def _group_list_changed(self, group, signal): for view in self.views: if hasattr(view, 'group_list_changed'): view.group_list_changed(group, signal) def _record_modified(self, group, signal): self.signal('record-modified', signal) def _group_changed(self, group, record): if not self.parent: self.display() self.signal('group-changed', record) def __get_current_record(self): if (self.__current_record is not None and self.__current_record.group is None): self.__current_record = None return self.__current_record def __set_current_record(self, record): self.__current_record = record if record: try: pos = self.group.index(record) + self.offset + 1 except ValueError: # XXX offset? pos = record.get_index_path() else: pos = None self.signal('record-message', (pos or 0, len(self.group) + self.offset, self.search_count, record and record.id)) attachment_count = 0 if record and record.attachment_count > 0: attachment_count = record.attachment_count self.signal('attachment-count', attachment_count) unread_note = 0 if record and record.unread_note > 0: unread_note = record.unread_note self.signal('unread-note', unread_note) # update attachment-count after 1 second gobject.timeout_add(1000, self.update_attachment, record) gobject.timeout_add(1000, self.update_note, record) return True current_record = property(__get_current_record, __set_current_record) def update_attachment(self, record): if record != self.current_record: return False if record and self.signal_connected('attachment-count'): attachment_count = record.get_attachment_count() self.signal('attachment-count', attachment_count) return False def update_note(self, record): if record != self.current_record: return False if record and self.signal_connected('unread-note'): unread_note = record.get_unread_note() self.signal('unread-note', unread_note) return False def destroy(self): self.screen_container.destroy() for view in self.views: view.destroy() del self.views[:] super(Screen, self).destroy() self.group.signal_unconnect(self) self.group.destroy() def default_row_activate(self): if (self.current_view.view_type == 'tree' and int(self.current_view.attributes.get('keyword_open', 0))): return Action.exec_keyword('tree_open', { 'model': self.model_name, 'id': self.current_record.id if self.current_record else None, 'ids': [r.id for r in self.selected_records], }, context=self.context.copy(), warning=False) else: if not self.modified(): self.switch_view(view_type='form') return True @property def number_of_views(self): return len(self.views) + len(self.view_to_load) def switch_view(self, view_type=None): if self.current_view: self.current_view.set_value() if (self.current_record and self.current_record not in self.current_record.group): self.current_record = None fields = self.current_view.get_fields() if (self.current_record and self.current_view.editable and not self.current_record.validate(fields)): self.screen_container.set(self.current_view.widget) self.set_cursor() self.current_view.display() return if not view_type or self.current_view.view_type != view_type: for i in xrange(self.number_of_views): if len(self.view_to_load): self.load_view_to_load() self.__current_view = len(self.views) - 1 else: self.__current_view = ((self.__current_view + 1) % len(self.views)) if not view_type: break elif self.current_view.view_type == view_type: break self.screen_container.set(self.current_view.widget) self.display() # Postpone set of the cursor to ensure widgets are allocated gobject.idle_add(self.set_cursor) def load_view_to_load(self): if len(self.view_to_load): if self.view_ids: view_id = self.view_ids.pop(0) else: view_id = None view_type = self.view_to_load.pop(0) self.add_view_id(view_id, view_type) def add_view_id(self, view_id, view_type): if view_id and str(view_id) in self.views_preload: view = self.views_preload[str(view_id)] elif not view_id and view_type in self.views_preload: view = self.views_preload[view_type] else: try: view = RPCExecute('model', self.model_name, 'fields_view_get', view_id, view_type, context=self.context) except RPCException: return return self.add_view(view) def add_view(self, view): arch = view['arch'] fields = view['fields'] view_id = view['view_id'] xml_dom = xml.dom.minidom.parseString(arch) root, = xml_dom.childNodes if root.tagName == 'tree': self.fields_view_tree[view_id] = view # Ensure that loading is always lazy for fields on form view # and always eager for fields on tree or graph view if root.tagName == 'form': loading = 'lazy' else: loading = 'eager' for field in fields: if field not in self.group.fields or loading == 'eager': fields[field]['loading'] = loading else: fields[field]['loading'] = \ self.group.fields[field].attrs['loading'] self.group.add_fields(fields) view = View.parse(self, xml_dom, view.get('field_childs')) view.view_id = view_id self.views.append(view) return view def new(self, default=True, rec_name=None): previous_view = self.current_view if self.current_view.view_type == 'calendar': selected_date = self.current_view.get_selected_date() if self.current_view and not self.current_view.editable: self.switch_view('form') if self.current_view.view_type != 'form': return None if self.current_record: group = self.current_record.group else: group = self.group record = group.new(default, rec_name=rec_name) group.add(record, self.new_model_position()) if previous_view.view_type == 'calendar': previous_view.set_default_date(record, selected_date) self.current_record = record self.display() # Postpone set of the cursor to ensure widgets are allocated gobject.idle_add(self.set_cursor, True) return self.current_record def new_model_position(self): position = -1 if (self.current_view and self.current_view.view_type == 'tree' and self.current_view.attributes.get('editable') == 'top'): position = 0 return position def set_on_write(self, func_name): if func_name: self.group.on_write.add(func_name) def cancel_current(self): if self.current_record: self.current_record.cancel() if self.current_record.id < 0: self.remove(records=[self.current_record]) def save_current(self): if not self.current_record: if self.current_view.view_type == 'tree' and len(self.group): self.current_record = self.group[0] else: return True self.current_view.set_value() saved = False record_id = None fields = self.current_view.get_fields() path = self.current_record.get_path(self.group) if self.current_view.view_type == 'tree': # False value must be not saved saved = all((x is 0 or x > 0 for x in self.group.save())) record_id = self.current_record.id if self.current_record else None elif self.current_record.validate(fields): record_id = self.current_record.save(force_reload=True) # False value must be not saved saved = record_id is 0 or record_id > 0 else: self.set_cursor() self.current_view.display() return False if path and record_id: path = path[:-1] + ((path[-1][0], record_id),) self.current_record = self.group.get_by_path(path) self.display() self.signal('record-saved') return saved def __get_current_view(self): if not len(self.views): return None return self.views[self.__current_view] current_view = property(__get_current_view) def set_cursor(self, new=False, reset_view=True): current_view = self.current_view if not current_view: return elif current_view.view_type in ('tree', 'form'): current_view.set_cursor(new=new, reset_view=reset_view) def get(self): if not self.current_record: return None self.current_view.set_value() return self.current_record.get() def get_on_change_value(self): if not self.current_record: return None self.current_view.set_value() return self.current_record.get_on_change_value() def modified(self): if self.current_view.view_type != 'tree': if self.current_record: if self.current_record.modified or self.current_record.id < 0: return True else: for record in self.group: if record.modified or record.id < 0: return True if self.current_view.modified: return True return False def reload(self, ids, written=False): self.group.reload(ids) if written: self.group.written(ids) if self.parent: self.parent.root_parent.reload() self.display() def unremove(self): records = self.selected_records for record in records: self.group.unremove(record) def remove(self, delete=False, remove=False, force_remove=False, records=None): records = records or self.selected_records if not records: return if delete: # Must delete children records before parent records.sort(key=lambda r: r.depth, reverse=True) if not self.group.delete(records): return False top_record = records[0] top_group = top_record.group idx = top_group.index(top_record) path = top_record.get_path(self.group) for record in records: # set current model to None to prevent __select_changed # to save the previous_model as it can be already deleted. self.current_record = None record.group.remove(record, remove=remove, signal=False, force_remove=force_remove) # send record-changed only once record.signal('record-changed') if delete: for record in records: if record in record.group.record_deleted: record.group.record_deleted.remove(record) if record in record.group.record_removed: record.group.record_removed.remove(record) if record.parent: # Save parent without deleted children record.parent.save(force_reload=False) record.destroy() if idx > 0: record = top_group[idx - 1] path = path[:-1] + ((path[-1][0], record.id,),) else: path = path[:-1] if path: self.current_record = self.group.get_by_path(path) elif len(self.group): self.current_record = self.group[0] self.set_cursor() self.display() return True def copy(self): ids = [r.id for r in self.selected_records] try: new_ids = RPCExecute('model', self.model_name, 'copy', ids, {}, context=self.context) except RPCException: return False self.load(new_ids) return True def set_tree_state(self): view = self.current_view if view.view_type not in ('tree', 'form'): return if id(view) in self.tree_states_done: return if view.view_type == 'form' and self.tree_states_done: return if (view.view_type == 'tree' and not view.attributes.get('tree_state', False)): # Mark as done to not set later when the view_type change self.tree_states_done.add(id(view)) return parent = self.parent.id if self.parent else None if parent is not None and parent < 0: return expanded_nodes, selected_nodes = [], [] timestamp = self.parent._timestamp if self.parent else None state = self.tree_states[parent][view.children_field] if state: state_timestamp, expanded_nodes, selected_nodes = state if (timestamp != state_timestamp and view.view_type != 'form'): state = None if state is None and CONFIG['client.save_tree_state']: json_domain = self.get_tree_domain(parent) try: expanded_nodes, selected_nodes = RPCExecute('model', 'ir.ui.view_tree_state', 'get', self.model_name, json_domain, view.children_field) expanded_nodes = json.loads(expanded_nodes) selected_nodes = json.loads(selected_nodes) except RPCException: logger.warn( _('Unable to get view tree state for %s') % self.model_name) self.tree_states[parent][view.children_field] = ( timestamp, expanded_nodes, selected_nodes) if view.view_type == 'tree': view.expand_nodes(expanded_nodes) view.select_nodes(selected_nodes) else: if selected_nodes: record = None for node in selected_nodes[0]: new_record = self.group.get(node) if node < 0 and -node < len(self.group): # Negative id is the index of the new record new_record = self.group[-node] if not new_record: break else: record = new_record if record and record != self.current_record: self.current_record = record # Force a display of the view to synchronize the # widgets with the new record view.display() self.tree_states_done.add(id(view)) def save_tree_state(self, store=True): if not CONFIG['client.save_tree_state']: return parent = self.parent.id if self.parent else None timestamp = self.parent._timestamp if self.parent else None for view in self.views: if view.view_type == 'form': for widgets in view.widgets.itervalues(): for widget in widgets: if hasattr(widget, 'screen'): widget.screen.save_tree_state(store) if len(self.views) == 1 and self.current_record: path = self.current_record.id if path < 0: path = -self.current_record.group.index( self.current_record) self.tree_states[parent][view.children_field] = ( timestamp, [], [[path]]) elif view.view_type == 'tree': paths = view.get_expanded_paths() selected_paths = view.get_selected_paths() self.tree_states[parent][view.children_field] = ( timestamp, paths, selected_paths) if store and view.attributes.get('tree_state', False): json_domain = self.get_tree_domain(parent) json_paths = json.dumps(paths, separators=(',', ':')) json_selected_path = json.dumps( selected_paths, separators=(',', ':')) try: RPCExecute('model', 'ir.ui.view_tree_state', 'set', self.model_name, json_domain, view.children_field, json_paths, json_selected_path, process_exception=False) except Exception: logger.warn( _('Unable to set view tree state'), exc_info=True) def get_tree_domain(self, parent): if parent: domain = (self.domain + [(self.exclude_field, '=', parent)]) else: domain = self.domain json_domain = json.dumps( domain, cls=JSONEncoder, separators=(',', ':')) return json_domain def load(self, ids, set_cursor=True, modified=False): self.tree_states.clear() self.tree_states_done.clear() self.group.load(ids, modified=modified) self.current_view.reset() if ids and self.current_view.view_type != 'calendar': self.display(ids[0]) else: self.current_record = None self.display() if set_cursor: self.set_cursor() def display(self, res_id=None, set_cursor=False): if res_id: self.current_record = self.group.get(res_id) else: if (self.current_record and self.current_record in self.current_record.group): pass elif self.group and self.current_view.view_type != 'calendar': self.current_record = self.group[0] else: self.current_record = None if self.views: self.search_active(self.current_view.view_type in ('tree', 'graph', 'calendar')) for view in self.views: view.display() self.current_view.widget.set_sensitive( bool(self.group or (self.current_view.view_type != 'form') or self.current_record)) if set_cursor: self.set_cursor(reset_view=False) self.set_tree_state() # Force record-message signal self.current_record = self.current_record def display_next(self): view = self.current_view view.set_value() self.set_cursor(reset_view=False) if view.view_type == 'tree' and len(self.group): start, end = view.treeview.get_visible_range() vadjustment = view.treeview.get_vadjustment() vadjustment.props.value = min( vadjustment.props.value + vadjustment.props.page_increment, vadjustment.props.upper) model = view.treeview.get_model() iter_ = model.get_iter(end) self.current_record = model.get_value(iter_, 0) elif (view.view_type == 'form' and self.current_record and self.current_record.group): group = self.current_record.group record = self.current_record while group: children = record.children_group(view.children_field) if children: record = children[0] break idx = group.index(record) + 1 if idx < len(group): record = group[idx] break parent = record.parent if not parent or record.model_name != parent.model_name: break next = parent.next.get(id(parent.group)) while not next: parent = parent.parent if not parent: break next = parent.next.get(id(parent.group)) if not next: break record = next break self.current_record = record elif view.view_type == 'calendar': record = self.current_record goocalendar = view.widgets['goocalendar'] date = goocalendar.selected_date year = date.year month = date.month start = datetime.datetime(year, month, 1) nb_days = calendar.monthrange(year, month)[1] delta = datetime.timedelta(days=nb_days) end = start + delta events = goocalendar.event_store.get_events(start, end) events.sort() if not record: self.current_record = len(events) and events[0].record else: for idx, event in enumerate(events): if event.record == record: next_id = idx + 1 if next_id < len(events): self.current_record = events[next_id].record break else: self.current_record = self.group[0] if len(self.group) else None self.set_cursor(reset_view=False) view.display() def display_prev(self): view = self.current_view view.set_value() self.set_cursor(reset_view=False) if view.view_type == 'tree' and len(self.group): start, end = view.treeview.get_visible_range() vadjustment = view.treeview.get_vadjustment() vadjustment.props.value = min( vadjustment.props.value - vadjustment.props.page_increment, vadjustment.props.lower) model = view.treeview.get_model() iter_ = model.get_iter(start) self.current_record = model.get_value(iter_, 0) elif (view.view_type == 'form' and self.current_record and self.current_record.group): group = self.current_record.group record = self.current_record idx = group.index(record) - 1 if idx >= 0: record = group[idx] children = True while children: children = record.children_group(view.children_field) if children: record = children[-1] else: parent = record.parent if parent and record.model_name == parent.model_name: record = parent self.current_record = record elif view.view_type == 'calendar': record = self.current_record goocalendar = view.widgets['goocalendar'] date = goocalendar.selected_date year = date.year month = date.month start = datetime.datetime(year, month, 1) nb_days = calendar.monthrange(year, month)[1] delta = datetime.timedelta(days=nb_days) end = start + delta events = goocalendar.event_store.get_events(start, end) events.sort() if not record: self.current_record = len(events) and events[0].record else: for idx, event in enumerate(events): if event.record == record: prev_id = idx - 1 if prev_id >= 0: self.current_record = events[prev_id].record break else: self.current_record = self.group[-1] if len(self.group) else None self.set_cursor(reset_view=False) view.display() def invalid_message(self, record=None): if record is None: record = self.current_record domain_string = _('"%s" is not valid according to its domain') domain_parser = DomainParser( {n: f.attrs for n, f in record.group.fields.iteritems()}) fields = [] for field, invalid in sorted(record.invalid_fields.items()): string = record.group.fields[field].attrs['string'] if invalid == 'required' or invalid == [[field, '!=', None]]: fields.append(_('"%s" is required') % string) elif invalid == 'domain': fields.append(domain_string % string) elif invalid == 'children': fields.append(_('The values of "%s" are not valid') % string) else: if domain_parser.stringable(invalid): fields.append(domain_parser.string(invalid)) else: fields.append(domain_string % string) if len(fields) > 5: fields = fields[:5] + ['...'] return '\n'.join(fields) @property def selected_records(self): return self.current_view.selected_records def clear(self): self.current_record = None self.group.clear() def on_change(self, fieldname, attr): self.current_record.on_change(fieldname, attr) self.display() def get_buttons(self): 'Return active buttons for the current view' def is_active(record, button): if button.attrs.get('type', 'class') == 'instance': return False states = record.expr_eval(button.attrs.get('states', {})) return not (states.get('invisible') or states.get('readonly')) if not self.selected_records: return [] buttons = self.current_view.get_buttons() for record in self.selected_records: buttons = [b for b in buttons if is_active(record, b)] if not buttons: break return buttons def button(self, button): 'Execute button on the selected records' self.current_view.set_value() fields = self.current_view.get_fields() for record in self.selected_records: domain = record.expr_eval( button.get('states', {})).get('pre_validate', []) if not record.validate(fields, pre_validate=domain): warning(self.invalid_message(record), _('Pre-validation')) self.display(set_cursor=True) if domain: # Reset valid state with normal domain record.validate(fields) return if button.get('confirm', False) and not sur(button['confirm']): return if button.get('type', 'class') == 'class': if not self.current_record.save(force_reload=False): return if button.get('type', 'class') == 'class': self._button_class(button) else: self._button_instance(button) def _button_instance(self, button): record = self.current_record args = record.expr_eval(button.get('change', [])) values = record._get_on_change_args(args) try: changes = RPCExecute('model', self.model_name, button['name'], values, context=self.context) except RPCException: return record.set_on_change(changes) record.signal('record-changed') def _button_class(self, button): ids = [r.id for r in self.selected_records] context = self.context.copy() context['_timestamp'] = {} for record in self.selected_records: context['_timestamp'].update(record.get_timestamp()) try: action = RPCExecute('model', self.model_name, button['name'], ids, context=context) except RPCException: action = None self.reload(ids, written=True) if isinstance(action, basestring): self.client_action(action) elif action: Action.execute(action, { 'model': self.model_name, 'id': self.current_record.id, 'ids': ids, }, context=self.context, keyword=True) def client_action(self, action): access = MODELACCESS[self.model_name] if action == 'new': if access['create']: self.new() elif action == 'delete': if access['delete']: self.remove(delete=not self.parent, force_remove=not self.parent) elif action == 'remove': if access['write'] and access['read'] and self.parent: self.remove(remove=True) elif action == 'copy': if access['create']: self.copy() elif action == 'next': self.display_next() elif action == 'previous': self.display_prev() elif action == 'close': from tryton.gui import Main Main.get_main().sig_win_close() elif action.startswith('switch'): _, view_type = action.split(None, 1) self.switch_view(view_type=view_type) elif action == 'reload': if (self.current_view.view_type in ['tree', 'graph', 'calendar'] and not self.parent): self.search_filter() elif action == 'reload menu': from tryton.gui import Main RPCContextReload(Main.get_main().sig_win_menu) elif action == 'reload context': RPCContextReload() def get_url(self, name=''): query_string = [] if self.domain: query_string.append(('domain', json.dumps( self.domain, cls=JSONEncoder, separators=(',', ':')))) if self.context: query_string.append(('context', json.dumps( self.context, cls=JSONEncoder, separators=(',', ':')))) if self.context_screen: query_string.append( ('context_model', self.context_screen.model_name)) if name: query_string.append( ('name', json.dumps(name, separators=(',', ':')))) path = [rpc._DATABASE, 'model', self.model_name] view_ids = [v.view_id for v in self.views] + self.view_ids if self.current_view.view_type != 'form': search_string = self.screen_container.get_text() search_value = self.domain_parser.parse(search_string) if search_value: query_string.append(('search_value', json.dumps( search_value, cls=JSONEncoder, separators=(',', ':')))) elif self.current_record and self.current_record.id > -1: path.append(str(self.current_record.id)) i = view_ids.index(self.current_view.view_id) view_ids = view_ids[i:] + view_ids[:i] if view_ids: query_string.append(('views', json.dumps( view_ids, separators=(',', ':')))) query_string = urllib.urlencode(query_string) return urlparse.urlunparse(('tryton', '%s:%s' % (rpc._HOST, rpc._PORT), '/'.join(path), query_string, '', '')) tryton-4.6.5/tryton/gui/window/view_form/model/0000755000175000017500000000000013260723567021137 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/model/group.py0000644000175000017500000004067313255571102022645 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from record import Record from field import Field, M2OField, ReferenceField from tryton.signal_event import SignalEvent from tryton.common.domain_inversion import is_leaf from tryton.common import RPCExecute, RPCException, MODELACCESS class Group(SignalEvent, list): def __init__(self, model_name, fields, ids=None, parent=None, parent_name='', child_name='', context=None, domain=None, readonly=False, parent_datetime_field=None): super(Group, self).__init__() if domain is None: domain = [] self.__domain = domain self.__domain4inversion = None self.lock_signal = False self.parent = parent self.parent_name = parent_name or '' self.children = [] self.child_name = child_name self.parent_datetime_field = parent_datetime_field self._context = context or {} self.model_name = model_name self.fields = {} self.load_fields(fields) self.current_idx = None self.load(ids) self.record_deleted, self.record_removed = [], [] self.on_write = set() self.__readonly = readonly self.__id2record = {} self.__field_childs = None self.exclude_field = None self.skip_model_access = False if self.parent and self.parent.model_name == model_name: self.parent.group.children.append(self) @property def readonly(self): # Must skip res.user for Preference windows if (self._context.get('_datetime') or (not (MODELACCESS[self.model_name]['write'] or MODELACCESS[self.model_name]['create']) and not self.skip_model_access)): return True return self.__readonly @readonly.setter def readonly(self, value): self.__readonly = value @property def domain(self): if self.parent and self.child_name: field = self.parent.group.fields[self.child_name] return [self.__domain, field.domain_get(self.parent)] return self.__domain def clean4inversion(self, domain): "This method will replace non relevant fields for domain inversion" if domain in ([], ()): return [] head, tail = domain[0], domain[1:] if head in ('AND', 'OR'): pass elif is_leaf(head): field = head[0] if (field in self.fields and self.fields[field].attrs.get('readonly')): head = [] else: head = self.clean4inversion(head) return [head] + self.clean4inversion(tail) def __get_domain4inversion(self): domain = self.domain if (self.__domain4inversion is None or self.__domain4inversion[0] != domain): self.__domain4inversion = ( domain, self.clean4inversion(domain)) domain, domain4inversion = self.__domain4inversion return domain4inversion domain4inversion = property(__get_domain4inversion) def insert(self, pos, record): assert record.group is self if pos >= 1: self.__getitem__(pos - 1).next[id(self)] = record if pos < self.__len__(): record.next[id(self)] = self.__getitem__(pos) else: record.next[id(self)] = None super(Group, self).insert(pos, record) self.__id2record[record.id] = record if not self.lock_signal: self.signal('group-list-changed', ('record-added', record)) def append(self, record): assert record.group is self if self.__len__() >= 1: self.__getitem__(self.__len__() - 1).next[id(self)] = record record.next[id(self)] = None super(Group, self).append(record) self.__id2record[record.id] = record if not self.lock_signal: self.signal('group-list-changed', ('record-added', record)) def _remove(self, record): idx = self.index(record) if idx >= 1: if idx + 1 < self.__len__(): self.__getitem__(idx - 1).next[id(self)] = \ self.__getitem__(idx + 1) else: self.__getitem__(idx - 1).next[id(self)] = None self.signal('group-list-changed', ('record-removed', record)) super(Group, self).remove(record) del self.__id2record[record.id] def clear(self): # Use reversed order to minimize the cursor reposition as the cursor # has more chances to be on top of the list. for record in reversed(self[:]): self.signal('group-list-changed', ('record-removed', record)) record.destroy() self.pop() self.__id2record = {} self.record_removed, self.record_deleted = [], [] def move(self, record, pos): if self.__len__() > pos >= 0: idx = self.index(record) self._remove(record) if pos > idx: pos -= 1 self.insert(pos, record) else: self._remove(record) self.append(record) def __setitem__(self, i, value): super(Group, self).__setitem__(i, value) if not self.lock_signal: self.signal('group-list-changed', ('record-changed', i)) def __repr__(self): return '' % (self.model_name, id(self)) def load_fields(self, fields): for name, attr in fields.iteritems(): field = Field.get_field(attr['type']) attr['name'] = name self.fields[name] = field(attr) def save(self): saved = [] for record in self: saved.append(record.save(force_reload=False)) if self.record_deleted: for record in self.record_deleted: self._remove(record) record.destroy() self.delete(self.record_deleted) del self.record_deleted[:] return saved def delete(self, records): return Record.delete(records) @property def root_group(self): root = self parent = self.parent while parent: root = parent.group parent = parent.parent return root def written(self, ids): if isinstance(ids, (int, long)): ids = [ids] ids = [x for x in self.on_write_ids(ids) or [] if x not in ids] if not ids: return self.root_group.reload(ids) return ids def reload(self, ids): for child in self.children: child.reload(ids) for id_ in ids: record = self.get(id_) if record and not record.modified: record.cancel() def on_write_ids(self, ids): if not self.on_write: return [] res = [] for fnct in self.on_write: try: res += RPCExecute('model', self.model_name, fnct, ids, context=self.context) except RPCException: return [] return list({}.fromkeys(res)) def load(self, ids, modified=False): if not ids: return True if len(ids) > 1: self.lock_signal = True new_records = [] for id in ids: new_record = self.get(id) if not new_record: new_record = Record(self.model_name, id, group=self) self.append(new_record) new_record.signal_connect(self, 'record-changed', self._record_changed) new_record.signal_connect(self, 'record-modified', self._record_modified) new_records.append(new_record) # Remove previously removed or deleted records for record in self.record_removed[:]: if record.id in ids: self.record_removed.remove(record) for record in self.record_deleted[:]: if record.id in ids: self.record_deleted.remove(record) if self.lock_signal: self.lock_signal = False self.signal('group-cleared') if new_records and modified: for record in new_records: record.modified_fields.setdefault('id') new_records[0].signal('record-modified') new_records[0].signal('record-changed') self.current_idx = 0 return True @property def context(self): ctx = self._context.copy() if self.parent: ctx.update(self.parent.get_context()) if self.child_name in self.parent.group.fields: field = self.parent.group.fields[self.child_name] ctx.update(field.get_context(self.parent)) ctx.update(self._context) if self.parent_datetime_field: ctx['_datetime'] = self.parent.get_eval( )[self.parent_datetime_field] return ctx @context.setter def context(self, value): self._context = value.copy() def add(self, record, position=-1, signal=True): if record.group is not self: record.signal_unconnect(record.group) record.group = self record.signal_connect(self, 'record-changed', self._record_changed) record.signal_connect(self, 'record-modified', self._record_modified) if position == -1: self.append(record) else: self.insert(position, record) for record_rm in self.record_removed: if record_rm.id == record.id: self.record_removed.remove(record) for record_del in self.record_deleted: if record_del.id == record.id: self.record_deleted.remove(record) self.current_idx = position record.modified_fields.setdefault('id') record.signal('record-modified') if signal: self.signal('group-changed', record) # Set parent field to trigger on_change if self.parent and self.parent_name in self.fields: field = self.fields[self.parent_name] if isinstance(field, (M2OField, ReferenceField)): value = self.parent.id, '' if isinstance(field, ReferenceField): value = self.parent.model_name, value field.set_client(record, value) return record def set_sequence(self, field='sequence'): changed = False prev = None for record in self: # Assume not loaded records are correctly ordered # as far as we do not change any previous records. if record.get_loaded([field]) or changed or record.id < 0: if prev: index = prev[field].get(prev) else: index = None update = False value = record[field].get(record) if value is None: if index: update = True elif prev and record.id >= 0: update = record.id < prev.id if value == index: if prev and record.id >= 0: update = record.id < prev.id elif value <= (index or 0): update = True if update: if index is None: index = 0 index += 1 record.signal_unconnect(self, 'record-changed') try: record[field].set_client(record, index) finally: record.signal_connect(self, 'record-changed', self._record_changed) changed = record prev = record if changed: self.signal('group-changed', changed) def new(self, default=True, obj_id=None, rec_name=None): record = Record(self.model_name, obj_id, group=self) if default: record.default_get(rec_name=rec_name) record.signal_connect(self, 'record-changed', self._record_changed) record.signal_connect(self, 'record-modified', self._record_modified) return record def unremove(self, record, signal=True): if record in self.record_removed: self.record_removed.remove(record) if record in self.record_deleted: self.record_deleted.remove(record) if signal: record.signal('record-changed', record.parent) def remove(self, record, remove=False, modified=True, signal=True, force_remove=False): idx = self.index(record) if self[idx].id >= 0: if remove: if self[idx] in self.record_deleted: self.record_deleted.remove(self[idx]) self.record_removed.append(self[idx]) else: if self[idx] in self.record_removed: self.record_removed.remove(self[idx]) self.record_deleted.append(self[idx]) if record.parent: record.parent.modified_fields.setdefault('id') record.parent.signal('record-modified') if modified: record.modified_fields.setdefault('id') record.signal('record-modified') if self[idx].id < 0 or force_remove: self._remove(self[idx]) if len(self): self.current_idx = min(idx, len(self) - 1) else: self.current_idx = None if signal: record.signal('record-changed', record.parent) def _record_changed(self, record, signal_data): self.signal('group-changed', record) def _record_modified(self, record, signal_data): self.signal('record-modified', record) def prev(self): if len(self) and self.current_idx is not None: self.current_idx = (self.current_idx - 1) % len(self) elif len(self): self.current_idx = 0 else: return None return self[self.current_idx] def next(self): if len(self) and self.current_idx is not None: self.current_idx = (self.current_idx + 1) % len(self) elif len(self): self.current_idx = 0 else: return None return self[self.current_idx] def add_fields(self, fields): to_add = {} for name, attr in fields.iteritems(): if name not in self.fields: to_add[name] = attr else: self.fields[name].attrs.update(attr) self.load_fields(to_add) if not len(self): return True new = [] for record in self: if record.id < 0: new.append(record) if len(new) and len(to_add): try: values = RPCExecute('model', self.model_name, 'default_get', to_add.keys(), context=self.context) except RPCException: return False for record in new: record.set_default(values, signal=False) # Trigger signal only once with the last record record.signal('record-changed') def get(self, id): 'Return record with the id' return self.__id2record.get(id) def id_changed(self, old_id): 'Update index for old id' record = self.__id2record[old_id] self.__id2record[record.id] = record del self.__id2record[old_id] def destroy(self): if self.parent: try: self.parent.group.children.remove(self) except ValueError: pass # One2Many connect the group to itself to send signals to the parent # but as we are destroying the group, we do not need to notify the # parent otherwise it will trigger unnecessary display. self.signal_unconnect(self) self.clear() super(Group, self).destroy() def get_by_path(self, path): 'return record by path' group = self record = None for child_name, id_ in path: record = group.get(id_) if not record: return None if not child_name: continue record[child_name] group = record.value.get(child_name) if not isinstance(group, Group): return None return record tryton-4.6.5/tryton/gui/window/view_form/model/record.py0000644000175000017500000006033213251060075022757 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import tryton.rpc as rpc from tryton.signal_event import SignalEvent import tryton.common as common from tryton.pyson import PYSONDecoder import field as fields from functools import reduce from tryton.common import RPCExecute, RPCException from tryton.config import CONFIG class Record(SignalEvent): id = -1 def __init__(self, model_name, obj_id, group=None): super(Record, self).__init__() self.model_name = model_name if obj_id is None: self.id = Record.id else: self.id = obj_id if self.id < 0: Record.id -= 1 self._loaded = set() self.group = group if group is not None: assert model_name == group.model_name self.state_attrs = {} self.modified_fields = {} self._timestamp = None self.attachment_count = -1 self.unread_note = -1 self.button_clicks = {} self.next = {} # Used in Group list self.value = {} self.autocompletion = {} self.exception = False self.destroyed = False def __getitem__(self, name): if name not in self._loaded and self.id >= 0: id2record = { self.id: self, } if name == '*': loading = reduce( lambda x, y: 'eager' if x == y == 'eager' else 'lazy', (field.attrs.get('loading', 'eager') for field in self.group.fields.itervalues()), 'eager') # Set a valid name for next loaded check for fname, field in self.group.fields.iteritems(): if field.attrs.get('loading', 'eager') == loading: name = fname break else: loading = self.group.fields[name].attrs.get('loading', 'eager') if loading == 'eager': fnames = [fname for fname, field in self.group.fields.iteritems() if field.attrs.get('loading', 'eager') == 'eager'] else: fnames = self.group.fields.keys() fnames = [fname for fname in fnames if fname not in self._loaded] fnames.extend(('%s.rec_name' % fname for fname in fnames[:] if self.group.fields[fname].attrs['type'] in ('many2one', 'one2one', 'reference'))) if 'rec_name' not in fnames: fnames.append('rec_name') fnames.append('_timestamp') record_context = self.get_context() if loading == 'eager': limit = int(CONFIG['client.limit'] / len(fnames)) def filter_group(record): return name not in record._loaded and record.id >= 0 def filter_parent_group(record): return (filter_group(record) and record.id not in id2record and ((record.group == self.group) # Don't compute context for same group or (record.get_context() == record_context))) if self.parent and self.parent.model_name == self.model_name: group = sum(self.parent.group.children, []) filter_ = filter_parent_group else: group = self.group filter_ = filter_group if self in group: idx = group.index(self) length = len(group) n = 1 while len(id2record) < limit and (idx - n >= 0 or idx + n < length) and n < 2 * limit: if idx - n >= 0: record = group[idx - n] if filter_(record): id2record[record.id] = record if idx + n < length: record = group[idx + n] if filter_(record): id2record[record.id] = record n += 1 ctx = record_context.copy() ctx.update(dict(('%s.%s' % (self.model_name, fname), 'size') for fname, field in self.group.fields.iteritems() if field.attrs['type'] == 'binary' and fname in fnames)) exception = None try: values = RPCExecute('model', self.model_name, 'read', id2record.keys(), fnames, context=ctx) except RPCException, exception: values = [{'id': x} for x in id2record] default_values = dict((f, None) for f in fnames) for value in values: value.update(default_values) self.exception = True id2value = dict((value['id'], value) for value in values) for id, record in id2record.iteritems(): if not record.exception: record.exception = bool(exception) value = id2value.get(id) if record and not record.destroyed and value: for key in record.modified_fields: value.pop(key, None) record.set(value, signal=False) return self.group.fields.get(name, False) def __repr__(self): return '' % (self.id, self.model_name, id(self)) @property def modified(self): return bool(self.modified_fields) @property def parent(self): return self.group.parent @property def parent_name(self): return self.group.parent_name @property def root_parent(self): parent = self while parent.parent: parent = parent.parent return parent @property def depth(self): parent = self.parent i = 0 while parent: i += 1 parent = parent.parent return i def set_modified(self, value): if value: self.signal('record-modified') def children_group(self, field_name): if not field_name: return [] self._check_load([field_name]) group = self.value.get(field_name) if group is None: return None if id(group.fields) != id(self.group.fields): self.group.fields.update(group.fields) group.fields = self.group.fields group.on_write = self.group.on_write group.readonly = self.group.readonly group._context.update(self.group._context) return group def get_path(self, group): path = [] i = self child_name = '' while i: path.append((child_name, i.id)) if i.group is group: break child_name = i.group.child_name i = i.parent path.reverse() return tuple(path) def get_index_path(self, group=None): path = [] record = self while record: path.append(record.group.index(record)) if record.group is group: break record = record.parent path.reverse() return tuple(path) def get_removed(self): if self.group is not None: return self in self.group.record_removed return False removed = property(get_removed) def get_deleted(self): if self.group is not None: return self in self.group.record_deleted return False deleted = property(get_deleted) def get_readonly(self): return self.deleted or self.removed or self.exception readonly = property(get_readonly) def fields_get(self): return self.group.fields def _check_load(self, fields=None): if fields is not None: if not self.get_loaded(fields): self.reload(fields) return True return False if not self.loaded: self.reload() return True return False def get_loaded(self, fields=None): if fields: return set(fields) <= (self._loaded | set(self.modified_fields)) return set(self.group.fields.keys()) == self._loaded loaded = property(get_loaded) def get(self): value = {} for name, field in self.group.fields.iteritems(): if (field.attrs.get('readonly') and not isinstance(field, fields.O2MField)): continue if field.name not in self.modified_fields and self.id >= 0: continue value[name] = field.get(self) # Sending an empty x2MField breaks ModelFieldAccess.check if isinstance(field, fields.O2MField) and not value[name]: del value[name] return value def get_eval(self): value = {} for name, field in self.group.fields.iteritems(): if name not in self._loaded and self.id >= 0: continue value[name] = field.get_eval(self) value['id'] = self.id return value def get_on_change_value(self, skip=None): value = {} for name, field in self.group.fields.iteritems(): if skip and name in skip: continue if (self.id >= 0 and (name not in self._loaded or name not in self.modified_fields)): continue value[name] = field.get_on_change_value(self) value['id'] = self.id return value def cancel(self): self._loaded.clear() self.modified_fields.clear() self._timestamp = None self.button_clicks.clear() def get_timestamp(self): result = {self.model_name + ',' + str(self.id): self._timestamp} for name, field in self.group.fields.iteritems(): if name in self._loaded: result.update(field.get_timestamp(self)) return result def pre_validate(self): if not self.modified_fields: return True values = self._get_on_change_args(self.modified_fields) try: RPCExecute('model', self.model_name, 'pre_validate', values, context=self.get_context()) except RPCException: return False return True def save(self, force_reload=True): if self.id < 0 or self.modified: if self.id < 0: value = self.get() try: res, = RPCExecute('model', self.model_name, 'create', [value], context=self.get_context()) except RPCException: return False old_id = self.id self.id = res self.group.id_changed(old_id) elif self.modified: value = self.get() if value: context = self.get_context() context = context.copy() context['_timestamp'] = self.get_timestamp() try: RPCExecute('model', self.model_name, 'write', [self.id], value, context=context) except RPCException: return False self.cancel() if force_reload: self.reload() if self.group: self.group.written(self.id) if self.parent: self.parent.modified_fields.pop(self.group.child_name, None) self.parent.save(force_reload=force_reload) return self.id @staticmethod def delete(records): if not records: return record = records[0] root_group = record.group.root_group assert all(r.model_name == record.model_name for r in records) assert all(r.group.root_group == root_group for r in records) records = [r for r in records if r.id >= 0] ctx = {} ctx['_timestamp'] = {} for rec in records: ctx['_timestamp'].update(rec.get_timestamp()) record_ids = set(r.id for r in records) reload_ids = set(root_group.on_write_ids(list(record_ids))) reload_ids -= record_ids reload_ids = list(reload_ids) try: RPCExecute('model', record.model_name, 'delete', list(record_ids), context=ctx) except RPCException: return False if reload_ids: root_group.reload(reload_ids) return True def default_get(self, rec_name=None): if len(self.group.fields): context = self.get_context() context.setdefault('default_rec_name', rec_name) try: vals = RPCExecute('model', self.model_name, 'default_get', self.group.fields.keys(), context=context) except RPCException: return if (self.parent and self.parent_name in self.group.fields): parent_field = self.group.fields[self.parent_name] if isinstance(parent_field, fields.ReferenceField): vals[self.parent_name] = ( self.parent.model_name, self.parent.id) elif (self.group.fields[self.parent_name].attrs['relation'] == self.group.parent.model_name): vals[self.parent_name] = self.parent.id self.set_default(vals) return vals def rec_name(self): try: return RPCExecute('model', self.model_name, 'read', [self.id], ['rec_name'], context=self.get_context())[0]['rec_name'] except RPCException: return '' def validate(self, fields=None, softvalidation=False, pre_validate=None): if isinstance(fields, list) and fields: self._check_load(fields) elif fields is None: self._check_load() res = True for field_name, field in self.group.fields.iteritems(): if fields is not None and field_name not in fields: continue if field.attrs.get('readonly'): continue if field_name == self.group.exclude_field: continue if not field.validate(self, softvalidation, pre_validate): res = False return res def _get_invalid_fields(self): fields = {} for fname, field in self.group.fields.iteritems(): invalid = field.get_state_attrs(self).get('invalid') if invalid: fields[fname] = invalid return fields invalid_fields = property(_get_invalid_fields) def get_context(self): return self.group.context def set_default(self, val, signal=True, validate=True): fieldnames = [] for fieldname, value in val.items(): if fieldname not in self.group.fields: continue if fieldname == self.group.exclude_field: continue if isinstance(self.group.fields[fieldname], (fields.M2OField, fields.ReferenceField)): field_rec_name = fieldname + '.rec_name' if field_rec_name in val: self.value[field_rec_name] = val[field_rec_name] elif field_rec_name in self.value: del self.value[field_rec_name] self.group.fields[fieldname].set_default(self, value) self._loaded.add(fieldname) fieldnames.append(fieldname) self.on_change(fieldnames) self.on_change_with(fieldnames) if validate: self.validate(softvalidation=True) if signal: self.signal('record-changed') def set(self, val, signal=True, validate=True): later = {} fieldnames = [] for fieldname, value in val.iteritems(): if fieldname == '_timestamp': # Always keep the older timestamp if not self._timestamp: self._timestamp = value continue if fieldname not in self.group.fields: if fieldname == 'rec_name': self.value['rec_name'] = value continue if isinstance(self.group.fields[fieldname], fields.O2MField): later[fieldname] = value continue if isinstance(self.group.fields[fieldname], (fields.M2OField, fields.ReferenceField)): field_rec_name = fieldname + '.rec_name' if field_rec_name in val: self.value[field_rec_name] = val[field_rec_name] elif field_rec_name in self.value: del self.value[field_rec_name] self.group.fields[fieldname].set(self, value) self._loaded.add(fieldname) fieldnames.append(fieldname) for fieldname, value in later.iteritems(): self.group.fields[fieldname].set(self, value) self._loaded.add(fieldname) if validate: self.validate(fieldnames, softvalidation=True) if signal: self.signal('record-changed') def set_on_change(self, values): for fieldname, value in values.items(): if fieldname not in self.group.fields: continue if isinstance(self.group.fields[fieldname], (fields.M2OField, fields.ReferenceField)): field_rec_name = fieldname + '.rec_name' if field_rec_name in values: self.value[field_rec_name] = values[field_rec_name] elif field_rec_name in self.value: del self.value[field_rec_name] self.group.fields[fieldname].set_on_change(self, value) def reload(self, fields=None): if self.id < 0: return if not fields: self['*'] else: for field in fields: self[field] self.validate(fields or []) def expr_eval(self, expr): if not isinstance(expr, basestring): return expr ctx = rpc.CONTEXT.copy() ctx['context'] = ctx.copy() ctx['context'].update(self.get_context()) ctx.update(self.get_eval()) ctx['active_model'] = self.model_name ctx['active_id'] = self.id ctx['_user'] = rpc._USER if self.parent and self.parent_name: ctx['_parent_' + self.parent_name] = \ common.EvalEnvironment(self.parent) val = PYSONDecoder(ctx).decode(expr) return val def _get_on_change_args(self, args): res = {} values = common.EvalEnvironment(self, 'on_change') for arg in args: scope = values for i in arg.split('.'): if i not in scope: break scope = scope[i] else: res[arg] = scope res['id'] = self.id return res def on_change(self, fieldnames): values = {} for fieldname in fieldnames: on_change = self.group.fields[fieldname].attrs.get('on_change') if not on_change: continue values.update(self._get_on_change_args(on_change)) if values: try: changes = RPCExecute('model', self.model_name, 'on_change', values, fieldnames, context=self.get_context()) except RPCException: return for change in changes: self.set_on_change(change) def on_change_with(self, field_names): field_names = set(field_names) fieldnames = set() values = {} later = set() for fieldname in self.group.fields: on_change_with = self.group.fields[fieldname].attrs.get( 'on_change_with') if not on_change_with: continue if not field_names & set(on_change_with): continue if fieldnames & set(on_change_with): later.add(fieldname) continue fieldnames.add(fieldname) values.update(self._get_on_change_args(on_change_with)) if isinstance(self.group.fields[fieldname], (fields.M2OField, fields.ReferenceField)): field_rec_name = fieldname + '.rec_name' if field_rec_name in self.value: del self.value[field_rec_name] if fieldnames: try: result = RPCExecute('model', self.model_name, 'on_change_with', values, list(fieldnames), context=self.get_context()) except RPCException: return self.set_on_change(result) for fieldname in later: on_change_with = self.group.fields[fieldname].attrs.get( 'on_change_with') values = self._get_on_change_args(on_change_with) try: result = RPCExecute('model', self.model_name, 'on_change_with_' + fieldname, values, context=self.get_context()) except RPCException: return self.group.fields[fieldname].set_on_change(self, result) def autocomplete_with(self, field_name): for fieldname, fieldinfo in self.group.fields.iteritems(): autocomplete = fieldinfo.attrs.get('autocomplete', []) if field_name not in autocomplete: continue self.do_autocomplete(fieldname) def do_autocomplete(self, fieldname): self.autocompletion[fieldname] = [] autocomplete = self.group.fields[fieldname].attrs['autocomplete'] args = self._get_on_change_args(autocomplete) try: res = RPCExecute('model', self.model_name, 'autocomplete_' + fieldname, args, context=self.get_context()) except RPCException: # ensure res is a list res = [] self.autocompletion[fieldname] = res def set_field_context(self): from .group import Group for name, field in self.group.fields.iteritems(): value = self.value.get(name) if not isinstance(value, Group): continue context = field.attrs.get('context') if context: value.context = self.expr_eval(context) def get_attachment_count(self, reload=False): if self.id < 0: return 0 if self.attachment_count < 0 or reload: try: self.attachment_count = RPCExecute('model', 'ir.attachment', 'search_count', [ ('resource', '=', '%s,%s' % (self.model_name, self.id)), ], context=self.get_context()) except RPCException: return 0 return self.attachment_count def get_unread_note(self, reload=False): if self.id < 0: return 0 if self.unread_note < 0 or reload: try: self.unread_note = RPCExecute('model', 'ir.note', 'search_count', [ ('resource', '=', '%s,%s' % (self.model_name, self.id)), ('unread', '=', True), ], context=self.get_context()) except RPCException: return 0 return self.unread_note def get_button_clicks(self, name): if self.id < 0: return clicks = self.button_clicks.get(name) if clicks is not None: return clicks try: clicks = RPCExecute('model', 'ir.model.button.click', 'get_click', self.model_name, name, self.id) self.button_clicks[name] = clicks except RPCException: return return clicks def destroy(self): for v in self.value.itervalues(): if hasattr(v, 'destroy'): v.destroy() super(Record, self).destroy() self.destroyed = True tryton-4.6.5/tryton/gui/window/view_form/model/__init__.py0000644000175000017500000000022013175640533023236 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. tryton-4.6.5/tryton/gui/window/view_form/model/field.py0000644000175000017500000010415513255571102022570 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os from itertools import chain import tempfile import locale from tryton.common import \ domain_inversion, eval_domain, localize_domain, \ merge, inverse_leaf, filter_leaf, concat, simplify, unique_value, \ EvalEnvironment import tryton.common as common import datetime import decimal from decimal import Decimal import math from tryton.common import RPCExecute, RPCException import tryton.rpc as rpc class Field(object): ''' get: return the values to write to the server get_client: return the value for the client widget (form_gtk) set: save the value from the server set_client: save the value from the widget ''' _default = None @staticmethod def get_field(ctype): return TYPES.get(ctype, CharField) def __init__(self, attrs): self.attrs = attrs self.name = attrs['name'] def sig_changed(self, record): record.on_change([self.name]) record.on_change_with([self.name]) record.autocomplete_with(self.name) record.set_field_context() def domains_get(self, record, pre_validate=None): screen_domain = domain_inversion( [record.group.domain4inversion, pre_validate or []], self.name, EvalEnvironment(record)) if isinstance(screen_domain, bool) and not screen_domain: screen_domain = [('id', '=', None)] elif isinstance(screen_domain, bool) and screen_domain: screen_domain = [] attr_domain = record.expr_eval(self.attrs.get('domain', [])) return screen_domain, attr_domain def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) return concat(localize_domain(screen_domain), attr_domain) def validation_domains(self, record, pre_validate=None): return concat(*self.domains_get(record, pre_validate)) def get_context(self, record): context = record.get_context().copy() if record.parent: context.update(record.parent.get_context()) context.update(record.expr_eval(self.attrs.get('context', {}))) return context def _is_empty(self, record): return not self.get_eval(record) def check_required(self, record): state_attrs = self.get_state_attrs(record) if bool(int(state_attrs.get('required') or 0)): if (self._is_empty(record) and not bool(int(state_attrs.get('readonly') or 0))): return False return True def validate(self, record, softvalidation=False, pre_validate=None): if self.attrs.get('readonly'): return True invalid = False self.get_state_attrs(record)['domain_readonly'] = False domain = simplify(self.validation_domains(record, pre_validate)) if not softvalidation: if not self.check_required(record): invalid = 'required' if isinstance(domain, bool): if not domain: invalid = 'domain' elif domain == [('id', '=', None)]: invalid = 'domain' else: unique, leftpart, value = unique_value(domain) if unique: # If the inverted domain is so constraint that only one value # is possible we should use it. But we must also pay attention # to the fact that the original domain might be a 'OR' domain # and thus not preventing the modification of fields. if value is False: # XXX to remove once server domains are fixed value = None setdefault = True if record.group.domain: original_domain = merge(record.group.domain) else: original_domain = merge(domain) domain_readonly = original_domain[0] == 'AND' if '.' in leftpart: recordpart, localpart = leftpart.split('.', 1) constraintfields = set() if domain_readonly: for leaf in localize_domain(original_domain[1:]): constraintfields.add(leaf[0]) if localpart != 'id' or recordpart not in constraintfields: setdefault = False if setdefault and not pre_validate: self.set_client(record, value) self.get_state_attrs(record)['domain_readonly'] = ( domain_readonly) if not eval_domain(domain, EvalEnvironment(record)): invalid = domain self.get_state_attrs(record)['invalid'] = invalid return not invalid def set(self, record, value): record.value[self.name] = value def get(self, record): return record.value.get(self.name, self._default) def get_eval(self, record): return self.get(record) def get_on_change_value(self, record): return self.get_eval(record) def set_client(self, record, value, force_change=False): previous_value = self.get(record) self.set(record, value) if previous_value != self.get(record): record.modified_fields.setdefault(self.name) record.signal('record-modified') self.sig_changed(record) record.validate(softvalidation=True) record.signal('record-changed') elif force_change: self.sig_changed(record) record.validate(softvalidation=True) record.signal('record-changed') def get_client(self, record): return self.get(record) def set_default(self, record, value): self.set(record, value) record.modified_fields.setdefault(self.name) def set_on_change(self, record, value): record.modified_fields.setdefault(self.name) self.set(record, value) def state_set(self, record, states=('readonly', 'required', 'invisible')): state_changes = record.expr_eval(self.attrs.get('states', {})) for key in states: if key == 'readonly' and self.attrs.get(key, False): continue if key in state_changes: self.get_state_attrs(record)[key] = state_changes[key] elif key in self.attrs: self.get_state_attrs(record)[key] = self.attrs[key] if (record.group.readonly or self.get_state_attrs(record).get('domain_readonly')): self.get_state_attrs(record)['readonly'] = True def get_state_attrs(self, record): if self.name not in record.state_attrs: record.state_attrs[self.name] = self.attrs.copy() if record.group.readonly or record.readonly: record.state_attrs[self.name]['readonly'] = True return record.state_attrs[self.name] def get_timestamp(self, record): return {} class CharField(Field): _default = '' def get(self, record): return super(CharField, self).get(record) or self._default class SelectionField(Field): _default = None def get_client(self, record): return record.value.get(self.name) class DateTimeField(Field): _default = None def set_client(self, record, value, force_change=False): if isinstance(value, datetime.time): current_value = self.get_client(record) if current_value: value = datetime.datetime.combine( current_value.date(), value) else: value = None elif value and not isinstance(value, datetime.datetime): current_value = self.get_client(record) if current_value: time = current_value.time() else: time = datetime.time() value = datetime.datetime.combine(value, time) if value: value = common.untimezoned_date(value) super(DateTimeField, self).set_client(record, value, force_change=force_change) def get_client(self, record): value = super(DateTimeField, self).get_client(record) if value: return common.timezoned_date(value) def date_format(self, record): context = self.get_context(record) return context.get('date_format', '%x') def time_format(self, record): return record.expr_eval(self.attrs['format']) class DateField(Field): _default = None def set_client(self, record, value, force_change=False): if isinstance(value, datetime.datetime): assert(value.time() == datetime.time()) value = value.date() super(DateField, self).set_client(record, value, force_change=force_change) def date_format(self, record): context = self.get_context(record) return context.get('date_format', '%x') class TimeField(Field): _default = None def _is_empty(self, record): return self.get(record) is None def set_client(self, record, value, force_change=False): if isinstance(value, datetime.datetime): value = value.time() super(TimeField, self).set_client(record, value, force_change=force_change) def time_format(self, record): return record.expr_eval(self.attrs['format']) class TimeDeltaField(Field): _default = None def _is_empty(self, record): return self.get(record) is None def converter(self, record): # TODO allow local context converter return rpc.CONTEXT.get(self.attrs.get('converter')) def set_client(self, record, value, force_change=False): if isinstance(value, basestring): value = common.timedelta.parse(value, self.converter(record)) super(TimeDeltaField, self).set_client( record, value, force_change=force_change) def get_client(self, record): value = super(TimeDeltaField, self).get_client(record) return common.timedelta.format(value, self.converter(record)) class FloatField(Field): _default = None def _is_empty(self, record): return self.get(record) is None def get(self, record): return record.value.get(self.name, self._default) def digits(self, record, factor=1): digits = record.expr_eval(self.attrs.get('digits')) if not digits or any(d is None for d in digits): return shift = int(round(math.log(abs(factor), 10))) return (digits[0] + shift, digits[1] - shift) def convert(self, value): try: return locale.atof(value) except ValueError: return self._default def set_client(self, record, value, force_change=False, factor=1): if isinstance(value, basestring): value = self.convert(value) if value is not None: value /= factor super(FloatField, self).set_client(record, value, force_change=force_change) def get_client(self, record, factor=1): value = record.value.get(self.name) if value is not None: digits = self.digits(record, factor=factor) if digits: p = digits[1] else: d = value * factor if not isinstance(d, Decimal): d = Decimal(repr(d)) p = -int(d.as_tuple().exponent) return locale.format('%.*f', (p, value * factor), True) else: return '' class NumericField(FloatField): def convert(self, value): try: return locale.atof(value, Decimal) except decimal.InvalidOperation: return self._default def set_client(self, record, value, force_change=False, factor=1): return super(NumericField, self).set_client(record, value, force_change=force_change, factor=Decimal(str(factor))) def get_client(self, record, factor=1): return super(NumericField, self).get_client(record, factor=Decimal(str(factor))) class IntegerField(FloatField): def convert(self, value): try: return locale.atoi(value) except ValueError: return self._default def set_client(self, record, value, force_change=False, factor=1): return super(IntegerField, self).set_client(record, value, force_change=force_change, factor=int(factor)) def get_client(self, record, factor=1): return super(IntegerField, self).get_client(record, factor=int(factor)) class BooleanField(Field): _default = False def set_client(self, record, value, force_change=False): value = bool(value) super(BooleanField, self).set_client(record, value, force_change=force_change) def get(self, record): return bool(record.value.get(self.name)) def get_client(self, record): return bool(record.value.get(self.name)) class M2OField(Field): ''' internal = (id, name) ''' _default = None def _is_empty(self, record): return self.get(record) is None def get_client(self, record): rec_name = record.value.get(self.name + '.rec_name') if rec_name is None: self.set(record, self.get(record)) rec_name = record.value.get(self.name + '.rec_name') or '' return rec_name def set_client(self, record, value, force_change=False): if isinstance(value, (tuple, list)): value, rec_name = value else: if value == self.get(record): rec_name = record.value.get(self.name + '.rec_name', '') else: rec_name = '' record.value[self.name + '.rec_name'] = rec_name super(M2OField, self).set_client(record, value, force_change=force_change) def set(self, record, value): rec_name = record.value.get(self.name + '.rec_name') or '' if not rec_name and value >= 0: try: result, = RPCExecute('model', self.attrs['relation'], 'read', [value], ['rec_name']) except RPCException: return rec_name = result['rec_name'] or '' record.value[self.name + '.rec_name'] = rec_name record.value[self.name] = value def get_context(self, record): context = super(M2OField, self).get_context(record) if self.attrs.get('datetime_field'): context['_datetime'] = record.get_eval( )[self.attrs.get('datetime_field')] return context def validation_domains(self, record, pre_validate=None): screen_domain, attr_domain = self.domains_get(record, pre_validate) return screen_domain def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) return concat(localize_domain(inverse_leaf(screen_domain), self.name), attr_domain) def get_on_change_value(self, record): if record.parent_name == self.name and record.parent: return record.parent.get_on_change_value( skip={record.group.child_name}) return super(M2OField, self).get_on_change_value(record) class O2OField(M2OField): pass class O2MField(Field): ''' internal = Group of the related objects ''' _default = None def __init__(self, attrs): super(O2MField, self).__init__(attrs) def _group_changed(self, group, record): if not record.parent: return # Store parent as it could be removed by validation parent = record.parent parent.modified_fields.setdefault(self.name) self.sig_changed(parent) parent.validate(softvalidation=True) parent.signal('record-changed') def _group_list_changed(self, group, signal): if group.model_name == group.parent.model_name: group.parent.group.signal('group-list-changed', signal) def _group_cleared(self, group, signal): if group.model_name == group.parent.model_name: group.parent.signal('group-cleared') def _record_modified(self, group, record): if not record.parent: return record.parent.signal('record-modified') def _set_default_value(self, record, fields=None): if record.value.get(self.name) is not None: return from group import Group parent_name = self.attrs.get('relation_field', '') fields = fields or {} context = record.expr_eval(self.attrs.get('context', {})) group = Group(self.attrs['relation'], fields, parent=record, parent_name=parent_name, child_name=self.name, context=context, parent_datetime_field=self.attrs.get('datetime_field')) if not fields and record.model_name == self.attrs['relation']: group.fields = record.group.fields record.value[self.name] = group self._connect_value(group) def _connect_value(self, group): group.signal_connect(group, 'group-changed', self._group_changed) group.signal_connect(group, 'group-list-changed', self._group_list_changed) group.signal_connect(group, 'group-cleared', self._group_cleared) group.signal_connect(group, 'record-modified', self._record_modified) def get_client(self, record): self._set_default_value(record) return record.value.get(self.name) def get(self, record): if record.value.get(self.name) is None: return [] record_removed = record.value[self.name].record_removed record_deleted = record.value[self.name].record_deleted result = [] parent_name = self.attrs.get('relation_field', '') to_add = [] to_create = [] to_write = [] for record2 in record.value[self.name]: if record2 in record_removed or record2 in record_deleted: continue if record2.id >= 0: if record2.modified: values = record2.get() values.pop(parent_name, None) if values: to_write.extend(([record2.id], values)) to_add.append(record2.id) else: values = record2.get() values.pop(parent_name, None) to_create.append(values) if to_add: result.append(('add', to_add)) if to_create: result.append(('create', to_create)) if to_write: result.append(('write',) + tuple(to_write)) if record_removed: result.append(('remove', [x.id for x in record_removed])) if record_deleted: result.append(('delete', [x.id for x in record_deleted])) return result def get_timestamp(self, record): if record.value.get(self.name) is None: return {} result = {} record_modified = (r for r in record.value[self.name] if r.modified) for record2 in chain(record_modified, record.value[self.name].record_removed, record.value[self.name].record_deleted): result.update(record2.get_timestamp()) return result def get_eval(self, record): if record.value.get(self.name) is None: return [] record_removed = record.value[self.name].record_removed record_deleted = record.value[self.name].record_deleted return [x.id for x in record.value[self.name] if x not in record_removed and x not in record_deleted] def get_on_change_value(self, record): result = [] if record.value.get(self.name) is None: return [] for record2 in record.value[self.name]: if not (record2.deleted or record2.removed): result.append( record2.get_on_change_value( skip={self.attrs.get('relation_field', '')})) return result def _set_value(self, record, value, default=False, modified=False): self._set_default_value(record) group = record.value[self.name] if value is None: value = [] if not value or isinstance(value[0], (int, long)): mode = 'list ids' else: mode = 'list values' if mode == 'list values': context = self.get_context(record) field_names = set(f for v in value for f in v if f not in group.fields and '.' not in f) if field_names: try: fields = RPCExecute('model', self.attrs['relation'], 'fields_get', list(field_names), context=context) except RPCException: return group.load_fields(fields) if mode == 'list ids': for old_record in group: if old_record.id not in value: group.remove(old_record, remove=True, signal=False) group.load(value, modified=modified) else: for vals in value: new_record = record.value[self.name].new(default=False) if default: # Don't validate as parent will validate new_record.set_default(vals, signal=False, validate=False) group.add(new_record, signal=False) else: new_record.set(vals, signal=False) group.append(new_record) # Trigger signal only once with the last record new_record.signal('record-changed') def set(self, record, value, _default=False): group = record.value.get(self.name) fields = {} if group is not None: fields = group.fields.copy() # Unconnect to prevent infinite loop group.signal_unconnect(group) group.destroy() elif record.model_name == self.attrs['relation']: fields = record.group.fields if fields: fields = dict((fname, field.attrs) for fname, field in fields.iteritems()) record.value[self.name] = None self._set_default_value(record, fields=fields) group = record.value[self.name] group.signal_unconnect(group) self._set_value(record, value, default=_default) self._connect_value(group) def set_client(self, record, value, force_change=False): # domain inversion could try to set None as value if value is None: value = [] # domain inversion could try to set id as value if isinstance(value, (int, long)): value = [value] previous_ids = self.get_eval(record) # The order of the ids is not significant modified = set(previous_ids) != set(value) self._set_value(record, value, modified=modified) if modified: record.modified_fields.setdefault(self.name) record.signal('record-modified') self.sig_changed(record) record.validate(softvalidation=True) record.signal('record-changed') elif force_change: self.sig_changed(record) record.validate(softvalidation=True) record.signal('record-changed') def set_default(self, record, value): self.set(record, value, _default=True) record.modified_fields.setdefault(self.name) def set_on_change(self, record, value): record.modified_fields.setdefault(self.name) self._set_default_value(record) if isinstance(value, (list, tuple)): self._set_value(record, value, modified=True) return if value and (value.get('add') or value.get('update')): context = self.get_context(record) fields = record.value[self.name].fields values = chain(value.get('update', []), (d for _, d in value.get('add', []))) field_names = set(f for v in values for f in v if f not in fields and f != 'id') if field_names: try: fields = RPCExecute('model', self.attrs['relation'], 'fields_get', list(field_names), context=context) except RPCException: return else: fields = {} to_remove = [] for record2 in record.value[self.name]: if not record2.id: to_remove.append(record2) if value and value.get('remove'): for record_id in value['remove']: record2 = record.value[self.name].get(record_id) if record2 is not None: to_remove.append(record2) for record2 in to_remove: record.value[self.name].remove(record2, signal=False, force_remove=False) if value and (value.get('add') or value.get('update', [])): record.value[self.name].add_fields(fields) for index, vals in value.get('add', []): new_record = record.value[self.name].new(default=False) record.value[self.name].add(new_record, index, signal=False) new_record.set_on_change(vals) for vals in value.get('update', []): if 'id' not in vals: continue record2 = record.value[self.name].get(vals['id']) if record2 is not None: record2.set_on_change(vals) def validation_domains(self, record, pre_validate=None): screen_domain, attr_domain = self.domains_get(record, pre_validate) return screen_domain def validate(self, record, softvalidation=False, pre_validate=None): invalid = False ldomain = localize_domain(domain_inversion( record.group.clean4inversion(pre_validate or []), self.name, EvalEnvironment(record)), self.name) if isinstance(ldomain, bool): if ldomain: ldomain = [] else: ldomain = [('id', '=', None)] for record2 in record.value.get(self.name, []): if not record2.loaded and record2.id >= 0 and not pre_validate: continue if not record2.validate(softvalidation=softvalidation, pre_validate=ldomain): invalid = 'children' test = super(O2MField, self).validate(record, softvalidation, pre_validate) if test and invalid: self.get_state_attrs(record)['invalid'] = invalid return False return test def state_set(self, record, states=('readonly', 'required', 'invisible')): self._set_default_value(record) super(O2MField, self).state_set(record, states=states) def get_removed_ids(self, record): return [x.id for x in record.value[self.name].record_removed] def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) # Forget screen_domain because it only means at least one record # and not all records return attr_domain class M2MField(O2MField): def get_on_change_value(self, record): return self.get_eval(record) class ReferenceField(Field): _default = None def _is_empty(self, record): result = super(ReferenceField, self)._is_empty(record) if not result and record.value[self.name][1] < 0: result = True return result def get_client(self, record): if record.value.get(self.name): model, _ = record.value[self.name] name = record.value.get(self.name + '.rec_name') or '' return model, name else: return None def get(self, record): if (record.value.get(self.name) and record.value[self.name][0] and record.value[self.name][1] >= -1): return ','.join(map(str, record.value[self.name])) return None def set_client(self, record, value, force_change=False): if value: if isinstance(value, basestring): value = value.split(',') ref_model, ref_id = value if isinstance(ref_id, (tuple, list)): ref_id, rec_name = ref_id else: if ref_id: try: ref_id = int(ref_id) except ValueError: pass if '%s,%s' % (ref_model, ref_id) == self.get(record): rec_name = record.value.get(self.name + '.rec_name', '') else: rec_name = '' record.value[self.name + '.rec_name'] = rec_name value = (ref_model, ref_id) super(ReferenceField, self).set_client(record, value, force_change=force_change) def set(self, record, value): if not value: record.value[self.name] = self._default return if isinstance(value, basestring): ref_model, ref_id = value.split(',') if not ref_id: ref_id = None else: try: ref_id = int(ref_id) except ValueError: pass else: ref_model, ref_id = value rec_name = record.value.get(self.name + '.rec_name') or '' if ref_model and ref_id >= 0: if not rec_name and ref_id >= 0: try: result, = RPCExecute('model', ref_model, 'read', [ref_id], ['rec_name']) except RPCException: return rec_name = result['rec_name'] elif ref_model: rec_name = '' else: rec_name = str(ref_id) record.value[self.name] = ref_model, ref_id record.value[self.name + '.rec_name'] = rec_name def get_context(self, record): context = super(ReferenceField, self).get_context(record) if self.attrs.get('datetime_field'): context['_datetime'] = record.get_eval( )[self.attrs.get('datetime_field')] return context def get_on_change_value(self, record): if record.parent_name == self.name and record.parent: return record.parent.model_name, record.parent.get_on_change_value( skip={record.group.child_name}) return super(ReferenceField, self).get_on_change_value(record) def validation_domains(self, record, pre_validate=None): screen_domain, attr_domain = self.domains_get(record, pre_validate) return screen_domain def domain_get(self, record): if record.value.get(self.name): model = record.value[self.name][0] else: model = None screen_domain, attr_domain = self.domains_get(record) return concat(localize_domain( filter_leaf(screen_domain, self.name, model), strip_target=True), attr_domain) class _FileCache(object): def __init__(self, path): self.path = path class BinaryField(Field): _default = None cast = bytearray if bytes == str else bytes def get(self, record): result = record.value.get(self.name, self._default) if isinstance(result, _FileCache): try: with open(result.path, 'rb') as fp: result = self.cast(fp.read()) except IOError: result = self.get_data(record) return result def get_client(self, record): return self.get(record) def set_client(self, record, value, force_change=False): _, filename = tempfile.mkstemp(prefix='tryton_') with open(filename, 'wb') as fp: fp.write(value or '') self.set(record, _FileCache(filename)) record.modified_fields.setdefault(self.name) record.signal('record-modified') self.sig_changed(record) record.validate(softvalidation=True) record.signal('record-changed') def get_size(self, record): result = record.value.get(self.name) or 0 if isinstance(result, _FileCache): result = os.stat(result.path).st_size elif isinstance(result, (basestring, bytes, bytearray)): result = len(result) return result def get_data(self, record): if not isinstance(record.value.get(self.name), (basestring, bytes, bytearray, _FileCache)): if record.id < 0: return '' context = record.get_context() try: values, = RPCExecute('model', record.model_name, 'read', [record.id], [self.name], context=context) except RPCException: return '' _, filename = tempfile.mkstemp(prefix='tryton_') with open(filename, 'wb') as fp: fp.write(values[self.name] or '') self.set(record, _FileCache(filename)) return self.get(record) class DictField(Field): _default = {} def get(self, record): return super(DictField, self).get(record) or self._default def get_client(self, record): return super(DictField, self).get_client(record) or self._default def validation_domains(self, record, pre_validate=None): screen_domain, attr_domain = self.domains_get(record, pre_validate) return screen_domain def domain_get(self, record): screen_domain, attr_domain = self.domains_get(record) return concat(localize_domain(inverse_leaf(screen_domain)), attr_domain) def date_format(self, record): context = self.get_context(record) return context.get('date_format', '%x') def time_format(self, record): return '%X' TYPES = { 'char': CharField, 'integer': IntegerField, 'biginteger': IntegerField, 'float': FloatField, 'numeric': NumericField, 'many2one': M2OField, 'many2many': M2MField, 'one2many': O2MField, 'reference': ReferenceField, 'selection': SelectionField, 'boolean': BooleanField, 'datetime': DateTimeField, 'date': DateField, 'time': TimeField, 'timedelta': TimeDeltaField, 'one2one': O2OField, 'binary': BinaryField, 'dict': DictField, } tryton-4.6.5/tryton/gui/window/view_form/view/0000755000175000017500000000000013260723567021011 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/view/list.py0000644000175000017500000013315313255571102022332 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gobject import gtk import sys import json import locale import gettext from functools import wraps from collections import defaultdict from tryton.config import CONFIG from tryton.common.cellrendererbutton import CellRendererButton from tryton.gui.window import Window from tryton.common.popup_menu import populate from tryton.common import RPCExecute, RPCException, node_attributes, Tooltips from tryton.common import domain_inversion, simplify, unique_value from tryton.common.widget_style import widget_class from tryton.pyson import PYSONDecoder import tryton.common as common from . import View from .list_gtk.editabletree import EditableTreeView, TreeView from .list_gtk.widget import (Affix, Char, Text, Int, Boolean, URL, Date, Time, Float, TimeDelta, Binary, M2O, O2O, O2M, M2M, Selection, Reference, ProgressBar, Button, Image) _ = gettext.gettext def delay(func): """Decorator for ViewTree method to delay execution when idle and if display counter did not change""" @wraps(func) def wrapper(self, *args, **kwargs): def wait(): if not self.treeview.props.window: return if self.treeview.display_counter == display_counter: func(self, *args, **kwargs) display_counter = self.treeview.display_counter gobject.idle_add(wait) return wrapper def path_convert_id2pos(model, id_path): "This function will transform a path of id into a path of position" group = model.group id_path = id_path[:] indexes = [] while id_path: current_id = id_path.pop(0) try: record = group.get(current_id) indexes.append(group.index(record)) group = record.children_group(model.children_field) except (KeyError, AttributeError, ValueError): return None return tuple(indexes) class AdaptModelGroup(gtk.GenericTreeModel): def __init__(self, group, children_field=None): super(AdaptModelGroup, self).__init__() self.group = group self.set_property('leak_references', False) self.children_field = children_field self.__removed = None # XXX dirty hack to allow update of has_child def added(self, group, record): if (group is self.group and (record.group is self.group or record.group.child_name == self.children_field)): path = record.get_index_path(self.group) iter_ = self.get_iter(path) self.row_inserted(path, iter_) if record.children_group(self.children_field): self.row_has_child_toggled(path, iter_) if (record.parent and record.group is not self.group): path = record.parent.get_index_path(self.group) iter_ = self.get_iter(path) self.row_has_child_toggled(path, iter_) def removed(self, group, record): if (group is self.group and (record.group is self.group or record.group.child_name == self.children_field)): path = record.get_index_path(self.group) self.row_deleted(path) def append(self, model): self.group.add(model) def prepend(self, model): self.group.add(model, 0) def remove(self, iter_): record = self.get_value(iter_, 0) record.group.remove(record) self.invalidate_iters() def __move(self, record, path, offset=0): iter_ = self.get_iter(path) record_pos = self.get_value(iter_, 0) group = record_pos.group pos = group.index(record_pos) + offset if group is not record.group: prev_group = record.group record.group.remove(record, remove=True, force_remove=True) # Don't remove record from previous group # as the new parent will change the parent # This prevents concurrency conflict record.group.record_removed.remove(record) group.add(record) if not record.parent_name: record.modified_fields.setdefault(prev_group.parent_name) record.value[prev_group.parent_name] = None else: record.modified_fields.setdefault(record.parent_name) group.move(record, pos) def move_before(self, record, path): self.__move(record, path) def move_after(self, record, path): self.__move(record, path, 1) def move_into(self, record, path): iter_ = self.get_iter(path) parent = self.get_value(iter_, 0) group = parent.children_group(self.children_field) if group is not record.group: record.group.remove(record, remove=True, force_remove=True) # Don't remove record from previous group # as the new parent will change the parent # This prevents concurrency conflict if record in record.group.record_removed: record.group.record_removed.remove(record) group.add(record) record.modified_fields.setdefault(record.parent_name or 'id') group.move(record, 0) def sort(self, ids): ids2pos = {} pos = 0 new_order = [] for record in self.group: ids2pos[record.id] = pos new_order.append(pos) pos += 1 pos = 0 for obj_id in ids: try: old_pos = ids2pos[obj_id] if old_pos != pos: new_order[old_pos] = pos pos += 1 except KeyError: continue self.group.sort(lambda x, y: cmp(new_order[ids2pos[x.id]], new_order[ids2pos[y.id]])) prev = None for record in self.group: if prev: prev.next[id(self.group)] = record prev = record if prev: prev.next[id(self.group)] = None path = gtk.TreePath() # XXX pygobject does not allow to create empty TreePath, # it is always a path of 0 # see: https://bugzilla.gnome.org/show_bug.cgi?id=770665 if hasattr(path, 'get_depth'): while path.get_depth(): path.up() self.rows_reordered(path, None, new_order) def __len__(self): return len(self.group) def on_get_flags(self): if not self.children_field: return gtk.TREE_MODEL_LIST_ONLY return 0 def on_get_n_columns(self): # XXX return 1 def on_get_column_type(self, index): # XXX return gobject.TYPE_PYOBJECT def on_get_path(self, record): return record.get_index_path(self.group) def on_get_iter(self, path): group = self.group record = None for i in path: if group is None or i >= len(group): return None record = group[i] if not self.children_field: break group = record.children_group(self.children_field) return record def on_get_value(self, record, column): return record def on_iter_next(self, record): if record is None: return None return record.next.get(id(record.group)) def on_iter_has_child(self, record): if record is None or not self.children_field: return False children = record.children_group(self.children_field) if children is None: return False length = len(children) if self.__removed and self.__removed in children: length -= 1 return bool(length) def on_iter_children(self, record): if record is None: if self.group: return self.group[0] else: return None if self.children_field: children = record.children_group(self.children_field) if children: return children[0] return None def on_iter_n_children(self, record): if record is None: return len(self.group) if not self.children_field: return 0 return len(record.children_group(self.children_field)) def on_iter_nth_child(self, record, nth): if record is None: if nth < len(self.group): return self.group[nth] return None if not self.children_field: return None if nth < len(record.children_group(self.children_field)): return record.children_group(self.children_field)[nth] return None def on_iter_parent(self, record): if record is None: return None return record.parent class ViewTree(View): def __init__(self, screen, xml, children_field): super(ViewTree, self).__init__(screen, xml) self.view_type = 'tree' self.widgets = defaultdict(list) self.state_widgets = [] self.children_field = children_field self.sum_widgets = [] self.sum_box = gtk.HBox() self.reload = False if self.attributes.get('editable') and not screen.readonly: self.treeview = EditableTreeView(self.attributes['editable'], self) grid_lines = gtk.TREE_VIEW_GRID_LINES_BOTH else: self.treeview = TreeView(self) grid_lines = gtk.TREE_VIEW_GRID_LINES_VERTICAL self.parse(xml) self.treeview.set_property('rules-hint', True) self.treeview.set_property('enable-grid-lines', grid_lines) self.treeview.set_fixed_height_mode( all(c.get_sizing() == gtk.TREE_VIEW_COLUMN_FIXED for c in self.treeview.get_columns())) self.treeview.connect('button-press-event', self.__button_press) self.treeview.connect('key-press-event', self.on_keypress) self.treeview.connect_after('row-activated', self.__sig_switch) if self.children_field: self.treeview.connect('test-expand-row', self.test_expand_row) self.treeview.set_expander_column(self.treeview.get_column(0)) self.treeview.set_rubber_banding(True) selection = self.treeview.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) selection.connect('changed', self.__select_changed) self.set_drag_and_drop() self.widget = gtk.VBox() scroll = gtk.ScrolledWindow() scroll.add(self.treeview) scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_placement(gtk.CORNER_TOP_LEFT) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN) viewport.add(scroll) self.widget.pack_start(viewport, expand=True, fill=True) self.sum_box.show() self.widget.pack_start(self.sum_box, expand=False, fill=False) self.display() def parse(self, xml): for node in xml.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.tagName == 'field': self._parse_field(node) elif node.tagName == 'button': self._parse_button(node) self.add_last_column() def _parse_field(self, node): group = self.screen.group node_attrs = node_attributes(node) name = node_attrs['name'] field = group.fields[name] for b_field in ('readonly', 'expand'): if b_field in node_attrs: node_attrs[b_field] = bool(int(node_attrs[b_field])) for i_field in ('width', 'height'): if i_field in node_attrs: node_attrs[i_field] = int(node_attrs[i_field]) if 'widget' not in node_attrs: node_attrs['widget'] = field.attrs['type'] for attr in ('relation', 'domain', 'selection', 'relation_field', 'string', 'views', 'invisible', 'add_remove', 'sort', 'context', 'size', 'filename', 'autocomplete', 'translate', 'create', 'delete', 'selection_change_with', 'schema_model'): if (attr in field.attrs and attr not in node_attrs): node_attrs[attr] = field.attrs[attr] Widget = self.get_widget(node_attrs['widget']) widget = Widget(self, node_attrs) self.widgets[name].append(widget) column = gtk.TreeViewColumn(field.attrs['string']) column._type = 'field' column.name = name prefixes = [] suffixes = [] if node_attrs['widget'] in ('url', 'email', 'callto', 'sip'): prefixes.append(Affix(self, node_attrs, protocol=node_attrs['widget'])) if 'icon' in node_attrs: prefixes.append(Affix(self, node_attrs)) for affix in node.childNodes: affix_attrs = node_attributes(affix) if 'name' not in affix_attrs: affix_attrs['name'] = name if affix.tagName == 'prefix': list_ = prefixes else: list_ = suffixes list_.append(Affix(self, affix_attrs)) for prefix in prefixes: column.pack_start(prefix.renderer, expand=False) column.set_cell_data_func(prefix.renderer, prefix.setter) column.pack_start(widget.renderer, expand=True) column.set_cell_data_func(widget.renderer, widget.setter) for suffix in suffixes: column.pack_start(suffix.renderer, expand=False) column.set_cell_data_func(suffix.renderer, suffix.setter) self.set_column_widget(column, field, node_attrs, align=widget.align) self.set_column_width(column, field, node_attrs) if (not self.attributes.get('sequence') and not self.children_field and field.attrs.get('sortable', True)): column.connect('clicked', self.sort_model) self.treeview.append_column(column) self.add_sum(node_attrs) def _parse_button(self, node): node_attrs = node_attributes(node) widget = Button(self, node_attrs) self.state_widgets.append(widget) column = gtk.TreeViewColumn(node_attrs.get('string', ''), widget.renderer) column._type = 'button' column.name = None column.set_cell_data_func(widget.renderer, widget.setter) self.set_column_widget(column, None, node_attrs, arrow=False) self.set_column_width(column, None, node_attrs) decoder = PYSONDecoder(self.screen.context) column.set_visible( not decoder.decode(node_attrs.get('tree_invisible', '0'))) self.treeview.append_column(column) WIDGETS = { 'char': Char, 'many2one': M2O, 'date': Date, 'one2many': O2M, 'many2many': M2M, 'selection': Selection, 'float': Float, 'numeric': Float, 'timedelta': TimeDelta, 'integer': Int, 'biginteger': Int, 'time': Time, 'boolean': Boolean, 'text': Text, 'url': URL, 'email': URL, 'callto': URL, 'sip': URL, 'progressbar': ProgressBar, 'reference': Reference, 'one2one': O2O, 'binary': Binary, 'image': Image, } @classmethod def get_widget(cls, name): return cls.WIDGETS[name] def set_column_widget(self, column, field, attributes, arrow=True, align=0.5): hbox = gtk.HBox(False, 2) label = gtk.Label(attributes['string']) if field and self.editable: required = field.attrs.get('required') readonly = field.attrs.get('readonly') attrlist = common.get_label_attributes(readonly, required) label.set_attributes(attrlist) widget_class(label, 'readonly', readonly) widget_class(label, 'required', required) label.show() help = None if field and field.attrs.get('help'): help = field.attrs['help'] elif attributes.get('help'): help = attributes['help'] if help: tooltips = Tooltips() tooltips.set_tip(label, help) tooltips.enable() if arrow: arrow_widget = gtk.Arrow(gtk.ARROW_NONE, gtk.SHADOW_NONE) arrow_widget.show() column.arrow = arrow_widget hbox.pack_start(label, True, True, 0) if arrow: hbox.pack_start(arrow_widget, False, False, 0) column.set_clickable(True) hbox.show() column.set_widget(hbox) column.set_alignment(align) def set_column_width(self, column, field, attributes): default_width = { 'integer': 60, 'biginteger': 60, 'float': 80, 'numeric': 80, 'timedelta': 100, 'date': 100, 'datetime': 100, 'time': 100, 'selection': 90, 'char': 100, 'one2many': 50, 'many2many': 50, 'boolean': 20, 'binary': 200, } width = self.screen.tree_column_width[self.screen.model_name].get( column.name) if not width: if 'width' in attributes: width = int(attributes['width']) elif field: width = default_width.get(field.attrs['type'], 100) else: width = 80 column.width = width if width > 0: column.set_fixed_width(width) column.set_min_width(1) expand = attributes.get('expand', False) column.set_expand(expand) column.set_resizable(True) if attributes.get('widget') != 'text': column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) def get_column_widget(self, column): 'Return the widget of the column' idx = [c for c in self.treeview.get_columns() if c.name == column.name].index(column) return self.widgets[column.name][idx] def add_sum(self, attributes): if 'sum' not in attributes: return if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + attributes['sum'] else: text = attributes['sum'] + _(':') label, sum_ = gtk.Label(text), gtk.Label() hbox = gtk.HBox() hbox.pack_start(label, expand=True, fill=False, padding=2) hbox.pack_start(sum_, expand=True, fill=False, padding=2) hbox.show_all() self.sum_box.pack_start(hbox, expand=False, fill=False) self.sum_widgets.append((attributes['name'], sum_)) def sort_model(self, column): for col in self.treeview.get_columns(): if col != column and getattr(col, 'arrow', None): col.arrow.set(gtk.ARROW_NONE, gtk.SHADOW_NONE) self.screen.order = self.screen.default_order if column.arrow.props.arrow_type == gtk.ARROW_NONE: column.arrow.set(gtk.ARROW_DOWN, gtk.SHADOW_IN) self.screen.order = [(column.name, 'ASC')] else: if column.arrow.props.arrow_type == gtk.ARROW_DOWN: column.arrow.set(gtk.ARROW_UP, gtk.SHADOW_IN) self.screen.order = [(column.name, 'DESC')] else: column.arrow.set(gtk.ARROW_NONE, gtk.SHADOW_NONE) model = self.treeview.get_model() unsaved_records = [x for x in model.group if x.id < 0] search_string = self.screen.screen_container.get_text() or u'' if (self.screen.search_count == len(model) or unsaved_records or self.screen.parent): ids = self.screen.search_filter( search_string=search_string, only_ids=True) model.sort(ids) else: self.screen.search_filter(search_string=search_string) def add_last_column(self): for column in self.treeview.get_columns(): if column.get_expand(): break else: column = gtk.TreeViewColumn() column._type = 'fill' column.name = None column.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED) self.treeview.append_column(column) def set_drag_and_drop(self): dnd = False if self.children_field: children = self.screen.group.fields.get(self.children_field) if children: parent_name = children.attrs.get('relation_field') dnd = parent_name in self.widgets elif self.attributes.get('sequence'): dnd = True # Disable DnD on mac until it is fully supported if sys.platform == 'darwin': dnd = False if self.screen.readonly: dnd = False if not dnd: return self.treeview.enable_model_drag_dest( [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) self.treeview.enable_model_drag_source( gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, [('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) # XXX have to set manually because enable_model_drag_source # does not set the mask # https://bugzilla.gnome.org/show_bug.cgi?id=756177 self.treeview.drag_source_set( gtk.gdk.BUTTON1_MASK | gtk.gdk.BUTTON3_MASK, [gtk.TargetEntry.new( 'MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0)], gtk.gdk.ACTION_MOVE) self.treeview.connect("drag-data-get", self.drag_data_get) self.treeview.connect('drag-data-received', self.drag_data_received) self.treeview.connect('drag-drop', self.drag_drop) self.treeview.connect('drag-data-delete', self.drag_data_delete) @property def modified(self): return False @property def editable(self): return (bool(getattr(self.treeview, 'editable', False)) and not self.screen.readonly) def get_fields(self): return [col.name for col in self.treeview.get_columns() if col.name] def get_buttons(self): return [b for b in self.state_widgets if isinstance(b.renderer, CellRendererButton)] def on_keypress(self, widget, event): control_mask = gtk.gdk.CONTROL_MASK if sys.platform == 'darwin': control_mask = gtk.gdk.MOD2_MASK if (event.keyval == gtk.keysyms.c and event.state & control_mask): self.on_copy() return False if (event.keyval == gtk.keysyms.v and event.state & control_mask): self.on_paste() return False def test_expand_row(self, widget, iter_, path): model = widget.get_model() iter_ = model.iter_children(iter_) if not iter_: return False fields = [col.name for col in self.treeview.get_columns() if col.name] while iter_: record = model.get_value(iter_, 0) if not record.get_loaded(fields): for field in fields: record[field] if record.exception: return True iter_ = model.iter_next(iter_) return False def on_copy(self): for clipboard_type in (gtk.gdk.SELECTION_CLIPBOARD, gtk.gdk.SELECTION_PRIMARY): clipboard = self.treeview.get_clipboard(clipboard_type) targets = [ ('STRING', 0, 0), ('TEXT', 0, 1), ('COMPOUND_TEXT', 0, 2), ('UTF8_STRING', 0, 3) ] selection = self.treeview.get_selection() # Set to clipboard directly if not too much selected rows # to speed up paste # Don't use set_with_data on mac see: # http://bugzilla.gnome.org/show_bug.cgi?id=508601 if selection.count_selected_rows() < 100 \ or sys.platform == 'darwin': data = [] selection.selected_foreach(self.copy_foreach, data) clipboard.set_text('\n'.join(data), -1) else: clipboard.set_with_data(targets, self.copy_get_func, self.copy_clear_func, selection) def copy_foreach(self, treemodel, path, iter, data): record = treemodel.get_value(iter, 0) values = [] for col in self.treeview.get_columns(): if not col.get_visible() or not col.name: continue widget = self.get_column_widget(col) values.append('"' + str(widget.get_textual_value(record)).replace('"', '""') + '"') data.append('\t'.join(values)) return def copy_get_func(self, clipboard, selectiondata, info, selection): data = [] selection.selected_foreach(self.copy_foreach, data) clipboard.set_text('\n'.join(data), -1) del data return def copy_clear_func(self, clipboard, selection): del selection return def on_paste(self): if not self.editable: return def unquote(value): if value[:1] == '"' and value[-1:] == '"': return value[1:-1] return value data = [] for clipboard_type in (gtk.gdk.SELECTION_CLIPBOARD, gtk.gdk.SELECTION_PRIMARY): clipboard = self.treeview.get_clipboard(clipboard_type) text = clipboard.wait_for_text() if not text: continue data = [[unquote(v) for v in l.split('\t')] for l in text.splitlines()] break col = self.treeview.get_cursor()[1] columns = [c for c in self.treeview.get_columns() if c.get_visible() and c.name] if col in columns: idx = columns.index(col) columns = columns[idx:] if self.screen.current_record: record = self.screen.current_record group = record.group idx = group.index(record) else: group = self.screen.group idx = len(group) default = None for line in data: if idx >= len(group): record = group.new(default=False) if default is None: default = record.default_get() record.set_default(default) group.add(record) record = group[idx] for col, value in zip(columns, line): widget = self.get_column_widget(col) if widget.get_textual_value(record) != value: widget.value_from_text(record, value) if value and not widget.get_textual_value(record): # Stop setting value if a value is correctly set idx = len(group) break if not record.validate(): break idx += 1 self.screen.current_record = record self.screen.display(set_cursor=True) def drag_data_get(self, treeview, context, selection, target_id, etime): treeview.emit_stop_by_name('drag-data-get') def _func_sel_get(model, path, iter_, data): value = model.get_value(iter_, 0) data.append(json.dumps( value.get_path(model.group), separators=(',', ':'))) data = [] treeselection = treeview.get_selection() treeselection.selected_foreach(_func_sel_get, data) if not data: return data = str(data[0]) selection.set(selection.get_target(), 8, data) return True def drag_data_received(self, treeview, context, x, y, selection, info, etime): treeview.emit_stop_by_name('drag-data-received') if self.attributes.get('sequence'): field = self.screen.group.fields[self.attributes['sequence']] for record in self.screen.group: if field.get_state_attrs( record).get('readonly', False): return try: selection_data = selection.data except AttributeError: selection_data = selection.get_data() if not selection_data: return # Don't received if the treeview was editing because it breaks the # internal state of the cursor. cursor, column = treeview.get_cursor() if column: for renderer in column.get_cell_renderers(): if renderer.props.editing: return model = treeview.get_model() try: data = json.loads(selection_data) except ValueError: return record = model.group.get_by_path(data) record_path = record.get_index_path(model.group) drop_info = treeview.get_dest_row_at_pos(x, y) def check_recursion(from_, to): if not from_ or not to: return True if from_ == to: return False length = min(len(from_), len(to)) if len(from_) < len(to) and from_[:length] == to[:length]: return False return True if drop_info: path, position = drop_info check_path = tuple(path) if position in (gtk.TREE_VIEW_DROP_BEFORE, gtk.TREE_VIEW_DROP_AFTER): check_path = path[:-1] if not check_recursion(record_path, check_path): return if position == gtk.TREE_VIEW_DROP_BEFORE: model.move_before(record, path) elif position == gtk.TREE_VIEW_DROP_AFTER: model.move_after(record, path) elif self.children_field: model.move_into(record, path) else: model.move_after(record, (len(model) - 1,)) if hasattr(gtk.gdk, 'drop_finish'): gtk.gdk.drop_finish(context, False, etime) else: context.drop_finish(False, etime) if self.attributes.get('sequence'): record.group.set_sequence(field=self.attributes['sequence']) return True def drag_drop(self, treeview, context, x, y, time): treeview.emit_stop_by_name('drag-drop') targets = treeview.drag_dest_get_target_list() target = treeview.drag_dest_find_target(context, targets) treeview.drag_get_data(context, target, time) return True def drag_data_delete(self, treeview, context): treeview.emit_stop_by_name('drag-data-delete') def __button_press(self, treeview, event): if event.button == 3: try: path, col, x, y = treeview.get_path_at_pos( int(event.x), int(event.y)) except TypeError: # Outside row return False menu = gtk.Menu() copy_item = gtk.ImageMenuItem('gtk-copy') copy_item.set_use_stock(True) copy_item.connect('activate', lambda x: self.on_copy()) menu.append(copy_item) if self.editable: paste_item = gtk.ImageMenuItem('gtk-paste') paste_item.set_use_stock(True) paste_item.connect('activate', lambda x: self.on_paste()) menu.append(paste_item) menu.show_all() menu.popup(None, None, None, event.button, event.time) def pop(menu, group, record): # Don't activate actions if parent is modified parent = record.parent if record else None while parent: if parent.modified: break parent = parent.parent else: populate(menu, group.model_name, record) for col in self.treeview.get_columns(): if not col.get_visible() or not col.name: continue field = group.fields[col.name] model = None if field.attrs['type'] == 'many2one': model = field.attrs['relation'] record_id = field.get(record) elif field.attrs['type'] == 'reference': value = field.get(record) if value: model, record_id = value.split(',') record_id = int(record_id) if not model: continue label = field.attrs['string'] context = field.get_context(record) populate( menu, model, record_id, title=label, field=field, context=context) menu.show_all() selection = treeview.get_selection() if selection.count_selected_rows() == 1: group = self.screen.group if selection.get_mode() == gtk.SELECTION_SINGLE: model = selection.get_selected()[0] elif selection.get_mode() == gtk.SELECTION_MULTIPLE: model = selection.get_selected_rows()[0] record = model.get_value(model.get_iter(path), 0) # Delay filling of popup as it can take time gobject.idle_add(pop, menu, group, record) return True # Don't change the selection elif event.button == 2: event.button = 1 event.state |= gtk.gdk.MOD1_MASK treeview.emit('button-press-event', event) return True return False def group_list_changed(self, group, signal): model = self.treeview.get_model() if model is not None: if signal[0] == 'record-added': model.added(group, signal[1]) elif signal[0] == 'record-removed': model.removed(group, signal[1]) self.display() def __str__(self): return 'ViewList (%d)' % id(self) def __getitem__(self, name): return None def save_width_height(self): if not CONFIG['client.save_width_height']: return fields = {} last_col = None for col in self.treeview.get_columns(): if col.get_visible(): last_col = col if not hasattr(col, 'name') or not hasattr(col, 'width'): continue if (col.get_width() != col.width and col.get_visible() and not col.get_expand()): fields[col.name] = col.get_width() # Don't set width for last visible columns # as it depends of the screen size if last_col and last_col.name in fields: del fields[last_col.name] if fields and any(fields.itervalues()): model_name = self.screen.model_name try: RPCExecute('model', 'ir.ui.view_tree_width', 'set_width', model_name, fields) except RPCException: pass self.screen.tree_column_width[model_name].update(fields) def destroy(self): self.save_width_height() self.treeview.destroy() def __sig_switch(self, treeview, path, column): if column._type == 'button': return allow_similar = False event = gtk.get_current_event() if (event.state & gtk.gdk.MOD1_MASK or event.state & gtk.gdk.SHIFT_MASK): allow_similar = True with Window(allow_similar=allow_similar): if not self.screen.row_activate() and self.children_field: if treeview.row_expanded(path): treeview.collapse_row(path) else: treeview.expand_row(path, False) def __select_changed(self, tree_sel): previous_record = self.screen.current_record if previous_record and previous_record not in previous_record.group: previous_record = None if tree_sel.get_mode() == gtk.SELECTION_SINGLE: model, iter_ = tree_sel.get_selected() if model and iter_: record = model.get_value(iter_, 0) self.screen.current_record = record else: self.screen.current_record = None elif tree_sel.get_mode() == gtk.SELECTION_MULTIPLE: model, paths = tree_sel.get_selected_rows() if model and paths: iter_ = model.get_iter(paths[0]) record = model.get_value(iter_, 0) self.screen.current_record = record else: self.screen.current_record = None if self.editable and previous_record: def go_previous(): self.screen.current_record = previous_record self.set_cursor() if (not self.screen.parent and previous_record != self.screen.current_record): def save(): if not previous_record.destroyed: if not previous_record.save(): go_previous() if not previous_record.validate(self.get_fields()): go_previous() return True # Delay the save to let GTK process the current event gobject.idle_add(save) elif (previous_record != self.screen.current_record and self.screen.pre_validate): def pre_validate(): if not previous_record.destroyed: if not previous_record.pre_validate(): go_previous() # Delay the pre_validate to let GTK process the current event gobject.idle_add(pre_validate) self.update_sum() def set_value(self): if self.editable: self.treeview.set_value() def reset(self): pass def display(self): self.treeview.display_counter += 1 current_record = self.screen.current_record if (self.reload or not self.treeview.get_model() or (self.screen.group != self.treeview.get_model().group)): model = AdaptModelGroup(self.screen.group, self.children_field) self.treeview.set_model(model) # __select_changed resets current_record to None self.screen.current_record = current_record if current_record: selection = self.treeview.get_selection() path = current_record.get_index_path(model.group) selection.select_path(path) self.reload = False if not current_record: selection = self.treeview.get_selection() selection.unselect_all() self.treeview.queue_draw() if self.editable: self.set_state() self.update_sum() # Set column visibility depending on attributes and domain domain = [] if self.screen.domain: domain.append(self.screen.domain) tab_domain = self.screen.screen_container.get_tab_domain() if tab_domain: domain.append(tab_domain) domain = simplify(domain) decoder = PYSONDecoder(self.screen.context) for column in self.treeview.get_columns(): name = column.name if not name: continue widget = self.get_column_widget(column) if decoder.decode(widget.attrs.get('tree_invisible', '0')): column.set_visible(False) elif name == self.screen.exclude_field: column.set_visible(False) else: inv_domain = domain_inversion(domain, name) if not isinstance(inv_domain, bool): inv_domain = simplify(inv_domain) unique, _, _ = unique_value(inv_domain) column.set_visible(not unique or bool(self.children_field)) def set_state(self): record = self.screen.current_record if record: for field in record.group.fields: field = record.group.fields.get(field, None) if field: field.state_set(record) @delay def update_sum(self): selected_records = self.selected_records for name, label in self.sum_widgets: sum_ = None selected_sum = None loaded = True digit = 0 field = self.screen.group.fields[name] for record in self.screen.group: if not record.get_loaded([name]) and record.id >= 0: loaded = False break value = field.get(record) if value is not None: if sum_ is None: sum_ = value else: sum_ += value if record in selected_records or not selected_records: if selected_sum is None: selected_sum = value else: selected_sum += value if hasattr(field, 'digits'): fdigits = field.digits(record) if fdigits and digit is not None: digit = max(fdigits[1], digit) else: digit = None if loaded: if field.attrs['type'] == 'timedelta': converter = self.screen.context.get( field.attrs.get('converter')) selected_sum = common.timedelta.format( selected_sum, converter) sum_ = common.timedelta.format(sum_, converter) elif digit: selected_sum = locale.format( '%.*f', (digit, selected_sum or 0), True) sum_ = locale.format('%.*f', (digit, sum_ or 0), True) else: selected_sum = locale.format( '%s', selected_sum or 0, True) sum_ = locale.format('%s', sum_ or 0, True) text = '%s / %s' % (selected_sum, sum_) else: text = '-' label.set_text(text) def set_cursor(self, new=False, reset_view=True): self.treeview.grab_focus() model = self.treeview.get_model() if self.screen.current_record and model: path = self.screen.current_record.get_index_path(model.group) if model.get_flags() & gtk.TREE_MODEL_LIST_ONLY: path = (path[0],) focus_column = self.treeview.next_column(path, editable=new) if path[:-1]: self.treeview.expand_to_path(gtk.TreePath(path[:-1])) self.treeview.scroll_to_cell(path, focus_column, use_align=False) current_path = self.treeview.get_cursor()[0] selected_path = \ self.treeview.get_selection().get_selected_rows()[1] path = gtk.TreePath(path) if (current_path != path and path not in selected_path) or new: self.treeview.set_cursor(path, focus_column, new) @property def selected_records(self): def _func_sel_get(model, path, iter_, records): records.append(model.get_value(iter_, 0)) records = [] sel = self.treeview.get_selection() sel.selected_foreach(_func_sel_get, records) return records def get_selected_paths(self): selection = self.treeview.get_selection() model, rows = selection.get_selected_rows() id_paths = [] for row in rows: path = () id_path = [] for node in row: path += (node,) iter_ = model.get_iter(path) id_path.append(model.get_value(iter_, 0).id) id_paths.append(id_path) return id_paths def select_nodes(self, nodes): selection = self.treeview.get_selection() if not nodes: return selection.unselect_all() scroll = False model = self.treeview.get_model() for node in nodes: path = path_convert_id2pos(model, node) if path: selection.select_path(gtk.TreePath(path)) if not scroll: self.treeview.scroll_to_cell(path) scroll = True def get_expanded_paths(self, starting_path=None, starting_id_path=None): # Use id instead of position # because the position may change between load if not starting_path: starting_path = tuple() if not starting_id_path: starting_id_path = [] id_paths = [] model = self.treeview.get_model() if starting_path: iter_ = model.get_iter(gtk.TreePath(starting_path)) else: iter_ = None for path_idx in range(model.iter_n_children(iter_)): path = starting_path + (path_idx,) expanded = self.treeview.row_expanded(gtk.TreePath(path)) if expanded: iter_ = model.get_iter(path) expanded_record = model.get_value(iter_, 0) id_path = starting_id_path + [expanded_record.id] id_paths.append(id_path) child_id_paths = self.get_expanded_paths(path, id_path) id_paths += child_id_paths return id_paths def expand_nodes(self, nodes): model = self.treeview.get_model() for node in nodes: expand_path = path_convert_id2pos(model, node) if expand_path: self.treeview.expand_to_path(gtk.TreePath(expand_path)) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/0000755000175000017500000000000013260723567022621 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/integer.py0000644000175000017500000000263713251060075024624 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from .char import Char import locale class Integer(Char): "Integer" def __init__(self, view, attrs): super(Integer, self).__init__(view, attrs) self.entry.set_width_chars(8) _, _, padding, pack_type = self.widget.query_child_packing( self.entry) self.widget.set_child_packing(self.entry, False, False, padding, pack_type) self.entry.set_max_length(0) self.entry.set_alignment(1.0) self.entry.connect('insert_text', self.sig_insert_text) self.factor = float(attrs.get('factor', 1)) def set_value(self, record, field): return field.set_client(record, self.entry.get_text(), factor=self.factor) def get_client_value(self, record, field): if not field: value = '' else: value = field.get_client(record, factor=self.factor) return value def sig_insert_text(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] if new_value == '-': return try: locale.atoi(new_value) except ValueError: entry.stop_emission('insert-text') tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/richtextbox.py0000644000175000017500000003035413255571102025531 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from gettext import gettext as _ import gtk from .textbox import TextBox from tryton.common import get_toplevel_window from tryton.common.htmltextbuffer import (serialize, deserialize, setup_tags, normalize_markup, remove_tags, register_foreground, FAMILIES, SIZE2SCALE, MIME) from tryton.config import CONFIG SIZES = sorted(SIZE2SCALE.keys()) # Disable serialize/deserialize registration function because it does not work # on GTK-3, the "guint8 *data" is converted into a Gtk.TextIter _use_serialize_func = False class RichTextBox(TextBox): def __init__(self, view, attrs): super(RichTextBox, self).__init__(view, attrs) self.text_buffer = gtk.TextBuffer() setup_tags(self.text_buffer) self.text_buffer.register_serialize_format( str(MIME), serialize, None) self.text_buffer.register_deserialize_format( str(MIME), deserialize, None) self.text_buffer.connect_after('insert-text', self.insert_text_style) self.textview.set_buffer(self.text_buffer) self.textview.connect_after('move-cursor', self.detect_style) self.textview.connect('button-release-event', self.detect_style) self.toolbar = None self.tag_widgets = {} self.tags = {} self.colors = {} if int(self.attrs.get('toolbar', 1)): self.toolbar = self.get_toolbar() def get_toolbar(self): toolbar = gtk.Toolbar() toolbar.set_style({ 'default': False, 'both': gtk.TOOLBAR_BOTH, 'text': gtk.TOOLBAR_TEXT, 'icons': gtk.TOOLBAR_ICONS}[CONFIG['client.toolbar']]) self.widget.pack_start(toolbar, expand=False, fill=True) for icon in ['bold', 'italic', 'underline']: button = gtk.ToggleToolButton('gtk-%s' % icon) button.connect('toggled', self.toggle_props, icon) toolbar.insert(button, -1) self.tag_widgets[icon] = button toolbar.insert(gtk.SeparatorToolItem(), -1) for name, options, active in [ ('family', FAMILIES, FAMILIES.index('normal')), ('size', SIZES, SIZES.index('4')), ]: try: combobox = gtk.ComboBoxText() except AttributeError: combobox = gtk.combo_box_new_text() for option in options: combobox.append_text(option) combobox.set_active(active) combobox.set_focus_on_click(False) combobox.connect('changed', self.change_props, name) tool = gtk.ToolItem() tool.add(combobox) toolbar.insert(tool, -1) self.tag_widgets[name] = combobox toolbar.insert(gtk.SeparatorToolItem(), -1) button = None for icon in ['left', 'center', 'right', 'fill']: name = icon if icon == 'fill': name = 'justify' stock_id = 'gtk-justify-%s' % icon if hasattr(gtk.RadioToolButton, 'new_with_stock_from_widget'): button = gtk.RadioToolButton.new_with_stock_from_widget( button, stock_id) else: button = gtk.RadioToolButton(button, stock_id) button.set_active(icon == 'left') button.connect('toggled', self.toggle_justification, name) toolbar.insert(button, -1) self.tag_widgets[name] = button toolbar.insert(gtk.SeparatorToolItem(), -1) for icon, label in [ ('foreground', _('Foreground')), # TODO ('background', _('Background')), ]: button = gtk.ToolButton('tryton-text-%s' % icon) button.set_label(label) button.connect('clicked', self.toggle_color, icon) toolbar.insert(button, -1) self.tag_widgets[icon] = button return toolbar def get_value(self): start = self.text_buffer.get_start_iter() end = self.text_buffer.get_end_iter() if _use_serialize_func: return self.text_buffer.serialize( self.text_buffer, MIME, start, end) else: return serialize( self.text_buffer, self.text_buffer, start, end, None) def set_value(self, record, field): # avoid modification of not normalized value value = self.get_value() prev_value = field.get_client(record) or '' if value == normalize_markup(prev_value): value = prev_value field.set_client(record, value) @property def modified(self): if self.record and self.field: value = normalize_markup(self.field.get_client(self.record) or '') return value != self.get_value() return False def set_buffer(self, value): self.text_buffer.handler_block_by_func(self.insert_text_style) start = self.text_buffer.get_start_iter() end = self.text_buffer.get_end_iter() self.text_buffer.delete(start, end) if _use_serialize_func: self.text_buffer.deserialize(self.text_buffer, MIME, start, value) else: deserialize( self.text_buffer, self.text_buffer, start, value, self.text_buffer.deserialize_get_can_create_tags(MIME), None) self.text_buffer.handler_unblock_by_func(self.insert_text_style) def _readonly_set(self, value): super(RichTextBox, self)._readonly_set(value) if self.toolbar: self.toolbar.set_sensitive(not value) def detect_style(self, *args): try: start, end = self.text_buffer.get_selection_bounds() except ValueError: start = end = self.text_buffer.get_iter_at_mark( self.text_buffer.get_insert()) def toggle_button(name, values): try: value, = values except ValueError: value = False button = self.tag_widgets[name] button.handler_block_by_func(self.toggle_props) button.set_active(value) button.handler_unblock_by_func(self.toggle_props) def set_combobox(name, indexes): try: index, = indexes except ValueError: index = -1 combobox = self.tag_widgets[name] combobox.handler_block_by_func(self.change_props) combobox.set_active(index) combobox.handler_unblock_by_func(self.change_props) def toggle_justification(names, value): if len(names) != 1: value = False for name in names: button = self.tag_widgets[name] button.handler_block_by_func(self.toggle_justification) button.set_active(value) button.handler_unblock_by_func(self.toggle_justification) bolds, italics, underlines = set(), set(), set() families, sizes, justifications = set(), set(), set() iter_ = start.copy() while True: bold, italic, underline = False, False, False family = FAMILIES.index('normal') size = SIZES.index('4') justification = 'left' for tag in iter_.get_tags(): if not tag.props.name: continue elif tag.props.name == 'bold': bold = True elif tag.props.name == 'italic': italic = True elif tag.props.name == 'underline': underline = True elif tag.props.name.startswith('family'): _, family = tag.props.name.split() family = FAMILIES.index(family) elif tag.props.name.startswith('size'): _, size = tag.props.name.split() size = SIZES.index(size) elif tag.props.name.startswith('justification'): _, justification = tag.props.name.split() bolds.add(bold) italics.add(italic) underlines.add(underline) families.add(family) sizes.add(size) justifications.add(justification) iter_.forward_char() if iter_.compare(end) > 0: iter_ = end if iter_.compare(end) == 0: break for name, values in [ ('bold', bolds), ('italic', italics), ('underline', underlines)]: toggle_button(name, values) set_combobox('family', families) set_combobox('size', sizes) toggle_justification(justifications, True) def insert_text_style(self, text_buffer, iter_, text, length): # Text is already inserted so iter_ point to the end start = iter_.copy() start.backward_chars(length) end = iter_.copy() # Apply tags activated from toolbar for name, widget in self.tag_widgets.iteritems(): self._apply_tool(name, widget, start, end) def _apply_tool(self, name, tool, start, end): # First test RadioToolButton as they inherit from ToggleToolButton if isinstance(tool, gtk.RadioToolButton): name = 'justification %s' % name if not tool.get_active(): remove_tags(self.text_buffer, start, end, name) else: remove_tags(self.text_buffer, start, end, 'justification') self.text_buffer.apply_tag_by_name(name, start, end) elif isinstance(tool, gtk.ToggleToolButton): if tool.get_active(): self.text_buffer.apply_tag_by_name(name, start, end) else: self.text_buffer.remove_tag_by_name(name, start, end) elif isinstance(tool, gtk.ComboBox): value = tool.get_active_text() remove_tags(self.text_buffer, start, end, name) name = '%s %s' % (name, value) self.text_buffer.apply_tag_by_name(name, start, end) def toggle_props(self, toggle, name): try: start, end = self.text_buffer.get_selection_bounds() except ValueError: return self._apply_tool(name, toggle, start, end) def change_props(self, combobox, name): try: start, end = self.text_buffer.get_selection_bounds() except ValueError: return self._apply_tool(name, combobox, start, end) def toggle_justification(self, button, name): try: start, end = self.text_buffer.get_selection_bounds() except ValueError: insert = self.text_buffer.get_insert() start = self.text_buffer.get_iter_at_mark(insert) end = start.copy() start.set_line_offset(0) if not end.ends_line(): end.forward_to_line_end() self._apply_tool(name, button, start, end) def toggle_color(self, button, name): insert = self.text_buffer.get_insert() try: start, end = self.text_buffer.get_selection_bounds() except ValueError: start = end = None else: # Use offset position to preserve across buffer modification start = start.get_offset() end = end.get_offset() dialog = gtk.ColorSelectionDialog(_('Select a color')) dialog.set_transient_for(get_toplevel_window()) colorsel = dialog.get_color_selection() colorsel.set_has_palette(True) color = self.colors.get(name) if color: colorsel.set_current_color(color) if dialog.run() == gtk.RESPONSE_OK: color = colorsel.get_current_color() self.colors[name] = color if start is not None and end is not None: start = self.text_buffer.get_iter_at_offset(start) end = self.text_buffer.get_iter_at_offset(end) tag = register_foreground(self.text_buffer, color) remove_tags(self.text_buffer, start, end, name) self.text_buffer.apply_tag(tag, start, end) dialog.destroy() self.text_buffer.place_cursor( self.text_buffer.get_iter_at_mark(insert)) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/checkbox.py0000644000175000017500000000205013175640533024752 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from .widget import Widget import gettext _ = gettext.gettext class CheckBox(Widget): def __init__(self, view, attrs): super(CheckBox, self).__init__(view, attrs) self.widget = self.mnemonic_widget = gtk.CheckButton() self.widget.connect('focus-out-event', lambda x, y: self._focus_out()) self.widget.connect_after('toggled', self.sig_activate) def _readonly_set(self, value): super(CheckBox, self)._readonly_set(value) # TODO find a better solution to accept focus self.widget.set_sensitive(not value) def set_value(self, record, field): field.set_client(record, self.widget.get_active()) def display(self, record, field): super(CheckBox, self).display(record, field) if not field: self.widget.set_active(False) return False self.widget.set_active(bool(field.get(record))) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/calendar.py0000644000175000017500000001266013251060075024735 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime import gtk import gettext import gobject from .widget import Widget from tryton.common.datetime_ import (Date as DateEntry, Time as TimeEntry, DateTime as DateTimeEntry, add_operators) from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG _ = gettext.gettext class Date(Widget): def __init__(self, view, attrs, _entry=DateEntry): super(Date, self).__init__(view, attrs) self.widget = gtk.HBox() self.entry = self.mnemonic_widget = add_operators(_entry()) self.real_entry.set_property('activates_default', True) self.real_entry.connect('key_press_event', self.sig_key_press) self.real_entry.connect('activate', self.sig_activate) self.real_entry.connect('changed', lambda _: self.send_modified()) self.real_entry.connect('focus-out-event', lambda x, y: self._focus_out()) self.widget.pack_start(self.entry, expand=False, fill=False) @property def real_entry(self): return self.entry def _set_editable(self, value): self.entry.set_editable(value) set_widget_style(self.entry, value) self.entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, value) def _readonly_set(self, value): self._set_editable(not value) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() @classmethod def cast(cls, value): if isinstance(value, datetime.datetime): value = value.date() return value @property def modified(self): if self.record and self.field: field_value = self.cast(self.field.get_client(self.record)) return field_value != self.entry.props.value return False def sig_key_press(self, widget, event): self.send_modified() def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return self.entry.props.value def set_format(self, record, field): if field and record: format_ = field.date_format(record) else: format_ = self.view.screen.date_format self.entry.props.format = format_ def display(self, record, field): super(Date, self).display(record, field) if field and record: value = field.get_client(record) else: value = '' self.entry.props.value = value self.set_format(record, field) class Time(Date): def __init__(self, view, attrs): super(Time, self).__init__(view, attrs, _entry=TimeEntry) self.entry.set_focus_chain([self.entry.get_child()]) self.entry.connect('time-changed', self.changed) def _set_editable(self, value): self.entry.set_sensitive(value) @classmethod def cast(cls, value): if isinstance(value, datetime.datetime): value = value.time() return value @property def real_entry(self): return self.entry.get_child() def display(self, record, field): super(Time, self).display(record, field) def set_format(self, record, field): if field and record: format_ = field.time_format(record) else: format_ = '%X' self.entry.props.format = format_ def changed(self, combobox): def focus_out(): if combobox.props.window: self._focus_out() # Only when changed from pop list if not combobox.get_child().has_focus(): # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) class DateTime(Date): def __init__(self, view, attrs): Widget.__init__(self, view, attrs) self.widget = gtk.HBox() self.entry = self.mnemonic_widget = DateTimeEntry() for child in self.entry.get_children(): add_operators(child) if isinstance(child, gtk.ComboBoxEntry): child.set_focus_chain([child.get_child()]) child = child.get_child() child.set_property('activates_default', True) child.connect('key_press_event', self.sig_key_press) child.connect('activate', self.sig_activate) child.connect('changed', lambda _: self.send_modified()) child.connect('focus-out-event', lambda x, y: self._focus_out()) self.widget.pack_start(self.entry, expand=False, fill=False) @classmethod def cast(cls, value): return value def _set_editable(self, value): for child in self.entry.get_children(): if isinstance(child, gtk.Entry): child.set_editable(value) set_widget_style(child, value) child.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, value) elif isinstance(child, gtk.ComboBoxEntry): child.set_sensitive(value) def set_format(self, record, field): if field and record: date_format = field.date_format(record) time_format = field.time_format(record) else: date_format = self.view.screen.date_format time_format = '%X' self.entry.props.date_format = date_format self.entry.props.time_format = time_format tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/progressbar.py0000644000175000017500000000240413175640533025520 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from .widget import Widget _ = gettext.gettext class ProgressBar(Widget): 'Progress Bar' orientations = { 'left_to_right': gtk.PROGRESS_LEFT_TO_RIGHT, 'right_to_left': gtk.PROGRESS_RIGHT_TO_LEFT, 'bottom_to_top': gtk.PROGRESS_BOTTOM_TO_TOP, 'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM, } def __init__(self, view, attrs): super(ProgressBar, self).__init__(view, attrs) self.widget = self.mnemonic_widget = gtk.ProgressBar() orientation = self.orientations.get(attrs.get('orientation', 'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT) self.widget.set_orientation(orientation) def display(self, record, field): super(ProgressBar, self).display(record, field) if not field: self.widget.set_text('') self.widget.set_fraction(0.0) return False text = field.get_client(record, factor=100) if text: text = _('%s%%') % text self.widget.set_text(text) value = field.get(record) or 0.0 self.widget.set_fraction(value) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/many2many.py0000644000175000017500000002561113255571102025101 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from tryton.gui.window.view_form.screen import Screen from .widget import Widget from tryton.gui.window.win_search import WinSearch from tryton.gui.window.win_form import WinForm import tryton.common as common import gettext from tryton.common.placeholder_entry import PlaceholderEntry from tryton.common.completion import get_completion, update_completion from tryton.common.domain_parser import quote from tryton.common.widget_style import widget_class _ = gettext.gettext class Many2Many(Widget): expand = True def __init__(self, view, attrs): super(Many2Many, self).__init__(view, attrs) self.widget = gtk.Frame() self.widget.set_shadow_type(gtk.SHADOW_NONE) self.widget.get_accessible().set_name(attrs.get('string', '')) vbox = gtk.VBox(homogeneous=False, spacing=5) self.widget.add(vbox) self._readonly = True self._required = False self._position = 0 hbox = gtk.HBox(homogeneous=False, spacing=0) hbox.set_border_width(2) self.title = gtk.Label(attrs.get('string', '')) self.title.set_alignment(0.0, 0.5) hbox.pack_start(self.title, expand=True, fill=True) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) tooltips = common.Tooltips() self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.set_property('width_chars', 13) self.wid_text.connect('focus-out-event', lambda *a: self._focus_out()) self.focus_out = True hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion( create=self.attrs.get('create', True) and common.MODELACCESS[self.attrs['relation']]['create']) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_completion.connect('action-activated', self._completion_action_activated) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() tooltips.set_tip(self.but_add, _('Add existing record')) self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) self.but_remove = gtk.Button() tooltips.set_tip(self.but_remove, _('Remove selected record ')) self.but_remove.connect('clicked', self._sig_remove) img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) self.but_remove.add(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_remove, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) tooltips.enable() frame = gtk.Frame() frame.add(hbox) frame.set_shadow_type(gtk.SHADOW_OUT) vbox.pack_start(frame, expand=False, fill=True) self.screen = Screen(attrs['relation'], view_ids=attrs.get('view_ids', '').split(','), mode=['tree'], views_preload=attrs.get('views', {}), row_activate=self._on_activate, limit=None) self.screen.signal_connect(self, 'record-message', self._sig_label) vbox.pack_start(self.screen.widget, expand=True, fill=True) self.screen.widget.connect('key_press_event', self.on_keypress) self.wid_text.connect('key_press_event', self.on_keypress) def on_keypress(self, widget, event): editable = self.wid_text.get_editable() activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] remove_keys = [gtk.keysyms.Delete, gtk.keysyms.KP_Delete] if not self.wid_completion: activate_keys.append(gtk.keysyms.Return) if widget == self.screen.widget: if event.keyval == gtk.keysyms.F3 and editable: self._sig_add() return True elif event.keyval == gtk.keysyms.F2: self._sig_edit() return True elif event.keyval in remove_keys and editable: self._sig_remove() return True elif widget == self.wid_text: if event.keyval == gtk.keysyms.F3: self._sig_new() return True elif event.keyval == gtk.keysyms.F2: self._sig_add() return True elif event.keyval in activate_keys and self.wid_text.get_text(): self._sig_add() self.wid_text.grab_focus() return False def destroy(self): self.screen.destroy() def _sig_add(self, *args): if not self.focus_out: return domain = self.field.domain_get(self.record) add_remove = self.record.expr_eval(self.attrs.get('add_remove')) if add_remove: domain = [domain, add_remove] context = self.field.get_context(self.record) value = self.wid_text.get_text().decode('utf-8') self.focus_out = False def callback(result): self.focus_out = True if result: ids = [x[0] for x in result] self.screen.load(ids, modified=True) self.screen.display(res_id=ids[0]) self.screen.set_cursor() self.wid_text.set_text('') win = WinSearch(self.attrs['relation'], callback, sel_multi=True, context=context, domain=domain, view_ids=self.attrs.get('view_ids', '').split(','), views_preload=self.attrs.get('views', {}), new=self.attrs.get('create', True), title=self.attrs.get('string')) win.screen.search_filter(quote(value)) win.show() def _sig_remove(self, *args): self.screen.remove(remove=True) def _on_activate(self): self._sig_edit() def _get_screen_form(self): domain = self.field.domain_get(self.record) add_remove = self.record.expr_eval(self.attrs.get('add_remove')) if add_remove: domain = [domain, add_remove] context = self.field.get_context(self.record) # Remove the first tree view as mode is form only view_ids = self.attrs.get('view_ids', '').split(',')[1:] return Screen(self.attrs['relation'], domain=domain, view_ids=view_ids, mode=['form'], views_preload=self.attrs.get('views', {}), context=context) def _sig_edit(self): if not self.screen.current_record: return # Create a new screen that is not linked to the parent otherwise on the # save of the record will trigger the save of the parent screen = self._get_screen_form() screen.load([self.screen.current_record.id]) def callback(result): if result: screen.current_record.save() # Force a reload on next display self.screen.current_record.cancel() # Force a display to clear the CellCache self.screen.display() WinForm(screen, callback, title=self.attrs.get('string')) def _sig_new(self): screen = self._get_screen_form() def callback(result): self.focus_out = True if result: record = screen.current_record self.screen.load([record.id], modified=True) self.wid_text.set_text('') self.wid_text.grab_focus() self.focus_out = False WinForm(screen, callback, new=True, save_current=True, title=self.attrs.get('string'), rec_name=self.wid_text.get_text()) def _readonly_set(self, value): self._readonly = value self._set_button_sensitive() self.wid_text.set_sensitive(not value) self.wid_text.set_editable(not value) self._set_label_state() def _required_set(self, value): self._required = value self._set_label_state() def _set_label_state(self): attrlist = common.get_label_attributes(self._readonly, self._required) self.title.set_attributes(attrlist) widget_class(self.title, 'readonly', self._readonly) widget_class(self.title, 'required', self._required) def _set_button_sensitive(self): if self.record and self.field: field_size = self.record.expr_eval(self.attrs.get('size')) m2m_size = len(self.field.get_eval(self.record)) size_limit = (field_size is not None and m2m_size >= field_size >= 0) else: size_limit = False self.but_add.set_sensitive(bool( not self._readonly and not size_limit)) self.but_remove.set_sensitive(bool( not self._readonly and self._position)) def _sig_label(self, screen, signal_data): self._position = signal_data[0] self._set_button_sensitive() def display(self, record, field): super(Many2Many, self).display(record, field) if field is None: self.screen.new_group() self.screen.current_record = None self.screen.parent = None self.screen.display() return False new_group = field.get_client(record) if id(self.screen.group) != id(new_group): self.screen.group = new_group self.screen.display() return True def set_value(self, record, field): self.screen.current_view.set_value() return True def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.screen.load([record_id], modified=True) self.wid_text.set_text('') self.wid_text.grab_focus() completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if self._readonly: return if not self.record: return model = self.attrs['relation'] update_completion(self.wid_text, self.record, self.field, model) def _completion_action_activated(self, completion, index): if index == 0: self._sig_add() self.wid_text.grab_focus() elif index == 1: self._sig_new() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/textbox.py0000644000175000017500000001513013251060075024654 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from .widget import Widget, TranslateMixin from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG try: import gtkspell except ImportError: gtkspell = None class TextBox(Widget, TranslateMixin): expand = True def __init__(self, view, attrs): super(TextBox, self).__init__(view, attrs) self.widget = gtk.VBox() self.scrolledwindow = gtk.ScrolledWindow() self.scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN) self.scrolledwindow.set_size_request(-1, 80) self.textview = self.mnemonic_widget = self._get_textview() self.textview.connect('focus-out-event', lambda x, y: self._focus_out()) self.textview.connect('key-press-event', self.send_modified) self.scrolledwindow.add(self.textview) self.scrolledwindow.show_all() hbox = gtk.HBox() hbox.pack_start(self.scrolledwindow) self.widget.pack_end(hbox) self.lang = None self.button = None if attrs.get('translate'): self.button = self.translate_button() hbox.pack_start(self.button, False, False) def _get_textview(self): if self.attrs.get('size'): textbuffer = TextBufferLimitSize(int(self.attrs['size'])) textview = gtk.TextView() textview.set_buffer(textbuffer) else: textview = gtk.TextView() textview.set_wrap_mode(gtk.WRAP_WORD) # TODO better tab solution textview.set_accepts_tab(False) return textview def translate_widget(self): scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolledwindow.set_shadow_type(gtk.SHADOW_ETCHED_IN) scrolledwindow.set_size_request(-1, 80) textview = self._get_textview() scrolledwindow.add(textview) return scrolledwindow @staticmethod def translate_widget_set(widget, value): textview = widget.get_child() buf = textview.get_buffer() buf.delete(buf.get_start_iter(), buf.get_end_iter()) buf.insert(buf.get_start_iter(), value or '') @staticmethod def translate_widget_get(widget): textview = widget.get_child() buf = textview.get_buffer() return buf.get_text(buf.get_start_iter(), buf.get_end_iter(), False).decode('utf-8') @staticmethod def translate_widget_set_readonly(widget, value): textview = widget.get_child() textview.set_editable(not value) textview.props.sensitive = not value def _readonly_set(self, value): super(TextBox, self)._readonly_set(value) self.textview.set_editable(not value) set_widget_style(self.textview, not value) if self.button: self.button.set_sensitive(not value) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() if gtkspell: spell = None try: spell = gtkspell.get_from_text_view(self.textview) except Exception: pass if not value and self.attrs.get('spell') \ and CONFIG['client.spellcheck'] \ and self.record: language = self.record.expr_eval(self.attrs['spell']) try: if not spell: spell = gtkspell.Spell(self.textview) if self.lang != language: try: spell.set_language(language) except Exception: spell.detach() del spell self.lang = language except Exception: pass elif spell: spell.detach() del spell @property def modified(self): if self.record and self.field: return self.field.get_client(self.record) != self.get_value() return False def get_value(self): buf = self.textview.get_buffer() iter_start = buf.get_start_iter() iter_end = buf.get_end_iter() return buf.get_text(iter_start, iter_end, False).decode('utf-8') def set_value(self, record, field): field.set_client(record, self.get_value()) def set_buffer(self, value): if value == self.get_value(): return buf = self.textview.get_buffer() buf.delete(buf.get_start_iter(), buf.get_end_iter()) iter_start = buf.get_start_iter() buf.insert(iter_start, value) def display(self, record, field): super(TextBox, self).display(record, field) value = field and field.get(record) if not value: value = '' self.set_buffer(value) if gtkspell: spell = None try: spell = gtkspell.get_from_text_view(self.textview) except Exception: pass if self.attrs.get('spell') and CONFIG['client.spellcheck'] \ and self.record: language = self.record.expr_eval(self.attrs['spell']) try: if not spell: spell = gtkspell.Spell(self.textview) if self.lang != language: try: spell.set_language(language) except Exception: spell.detach() del spell self.lang = language except Exception: pass elif spell: spell.detach() del spell class TextBufferLimitSize(gtk.TextBuffer): __gsignals__ = { 'insert-text': 'override', } def __init__(self, max_length): super(TextBufferLimitSize, self).__init__() self.max_length = max_length def do_insert_text(self, iter, text, length): free_chars = self.max_length - self.get_char_count() # Slice operation needs an unicode string to work as expected text = text.decode('utf-8')[0:free_chars].encode('utf-8') length = len(text) return gtk.TextBuffer.do_insert_text(self, iter, text, length) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/dictionary.py0000644000175000017500000004541013251060075025330 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of this # repository contains the full copyright notices and license terms. import operator import gobject import gtk import locale import decimal import gettext from decimal import Decimal from .widget import Widget from tryton.config import CONFIG from tryton.gui.window.win_search import WinSearch from tryton.common import RPCExecute, RPCException, Tooltips, \ timezoned_date, untimezoned_date from tryton.common.placeholder_entry import PlaceholderEntry from tryton.common.selection import selection_shortcuts from tryton.common.completion import get_completion, update_completion from tryton.common.datetime_ import Date, DateTime from tryton.common.domain_parser import quote from tryton.common.entry_position import reset_position from tryton.common.widget_style import set_widget_style _ = gettext.gettext class DictEntry(object): expand = True fill = True def __init__(self, name, parent_widget): self.name = name self.definition = parent_widget.keys[name] self.parent_widget = parent_widget self.widget = self.create_widget() def create_widget(self): widget = gtk.Entry() widget.connect('key-press-event', self.parent_widget.send_modified) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) return widget def modified(self, value): return self.get_value() != value.get(self.name) def get_value(self): return self.widget.get_text() def set_value(self, value): self.widget.set_text(value or '') reset_position(self.widget) def set_readonly(self, readonly): self.widget.set_editable(not readonly) set_widget_style(self.widget, not readonly) class DictBooleanEntry(DictEntry): def create_widget(self): widget = gtk.CheckButton() widget.connect('toggled', self.parent_widget.send_modified) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) return widget def get_value(self): return self.widget.props.active def set_value(self, value): self.widget.props.active = bool(value) def set_readonly(self, readonly): self.widget.set_sensitive(not readonly) class DictSelectionEntry(DictEntry): expand = False fill = False def create_widget(self): widget = gtk.ComboBoxEntry() # customizing entry child = widget.get_child() child.props.activates_default = True child.connect('changed', self.parent_widget.send_modified) child.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) child.connect('activate', lambda w: self.parent_widget._focus_out()) widget.connect('notify::active', lambda w, e: self.parent_widget._focus_out()) widget.connect( 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) selection_shortcuts(widget) # setting completion and selection model = gtk.ListStore(gobject.TYPE_STRING) model.append(('',)) self._selection = {'': None} width = 10 selection = self.definition['selection'] if self.definition.get('sorted', True): selection.sort(key=operator.itemgetter(1)) for value, name in selection: name = str(name) self._selection[name] = value model.append((name,)) width = max(width, len(name)) widget.set_model(model) widget.set_text_column(0) child.set_width_chars(width) completion = gtk.EntryCompletion() completion.set_inline_selection(True) completion.set_model(model) child.set_completion(completion) completion.set_text_column(0) return widget def get_value(self): child = self.widget.get_child() if not child: # widget is destroyed return text = child.get_text() value = None if text: for txt, val in self._selection.items(): if not val: continue if txt[:len(text)].lower() == text.lower(): value = val if len(txt) == len(text): break return value def set_value(self, value): values = dict(self.definition['selection']) child = self.widget.get_child() child.set_text(values.get(value, '')) reset_position(child) def set_readonly(self, readonly): self.widget.set_sensitive(not readonly) class DictIntegerEntry(DictEntry): expand = False fill = False def create_widget(self): widget = super(DictIntegerEntry, self).create_widget() widget.set_width_chars(8) widget.set_max_length(0) widget.set_alignment(1.0) widget.connect('insert-text', self.sig_insert_text) return widget def sig_insert_text(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] if new_value == '-': return try: locale.atoi(new_value) except ValueError: entry.stop_emission('insert-text') def get_value(self): txt_value = self.widget.get_text() if txt_value: try: return locale.atoi(txt_value) except ValueError: pass return None def set_value(self, value): if value is not None: txt_val = locale.format('%d', value, True) else: txt_val = '' self.widget.set_text(txt_val) reset_position(self.widget) class DictFloatEntry(DictIntegerEntry): def digits(self): default = (16, 2) record = self.parent_widget.record if not record: return default return tuple(y if x is None else x for x, y in zip( record.expr_eval(self.definition.get('digits', default)), default)) def sig_insert_text(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] decimal_point = locale.localeconv()['decimal_point'] if new_value in ('-', decimal_point): return digits = self.digits() try: locale.atof(new_value) except ValueError: entry.stop_emission('insert-text') return new_int = new_value new_decimal = '' if decimal_point in new_value: new_int, new_decimal = new_value.rsplit(decimal_point, 1) if (len(new_int) > digits[0] or len(new_decimal) > digits[1]): entry.stop_emission('insert-text') def get_value(self): txt_value = self.widget.get_text() if txt_value: try: return locale.atof(txt_value) except ValueError: pass return None def set_value(self, value): digits = self.digits() if value is not None: txt_val = locale.format('%.' + str(digits[1]) + 'f', value, True) else: txt_val = '' self.widget.set_width_chars(sum(digits)) self.widget.set_text(txt_val) reset_position(self.widget) class DictNumericEntry(DictFloatEntry): def get_value(self): txt_value = self.widget.get_text() if txt_value: try: return locale.atof(txt_value, Decimal) except decimal.InvalidOperation: pass return None class DictDateTimeEntry(DictEntry): expand = False fill = False def create_widget(self): widget = DateTime() record = self.parent_widget.record field = self.parent_widget.field if record and field: format_ = field.time_format(record) widget.props.format = format_ widget.connect('key_press_event', self.parent_widget.send_modified) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) return widget def get_value(self): return untimezoned_date(self.widget.props.value) def set_value(self, value): self.widget.props.value = timezoned_date(value) class DictDateEntry(DictEntry): expand = False fill = False def create_widget(self): widget = Date() record = self.parent_widget.record field = self.parent_widget.field if record and field: format_ = field.date_format(record) widget.props.format = format_ widget.connect('key_press_event', self.parent_widget.send_modified) widget.connect('focus-out-event', lambda w, e: self.parent_widget._focus_out()) return widget def get_value(self): return self.widget.props.value def set_value(self, value): self.widget.props.value = value DICT_ENTRIES = { 'char': DictEntry, 'boolean': DictBooleanEntry, 'selection': DictSelectionEntry, 'datetime': DictDateTimeEntry, 'date': DictDateEntry, 'integer': DictIntegerEntry, 'float': DictFloatEntry, 'numeric': DictNumericEntry, } class DictWidget(Widget): def __init__(self, view, attrs): super(DictWidget, self).__init__(view, attrs) self.schema_model = attrs['schema_model'] self.keys = {} self.fields = {} self.buttons = {} self.rows = {} self.widget = gtk.Frame() self.widget.set_label(attrs.get('string', '')) self.widget.set_shadow_type(gtk.SHADOW_OUT) vbox = gtk.VBox() self.widget.add(vbox) self.table = gtk.Table(1, 3, homogeneous=False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) vbox.pack_start(self.table, expand=True, fill=True) hbox = gtk.HBox() hbox.set_border_width(2) self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.props.width_chars = 13 self.wid_text.connect('activate', self._sig_activate) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): self.wid_completion = get_completion(search=False, create=False) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) else: self.wid_completion = None self.but_add = gtk.Button() self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) hbox.set_focus_chain([self.wid_text]) vbox.pack_start(hbox, expand=True, fill=True) self.tooltips = Tooltips() self.tooltips.set_tip(self.but_add, _('Add value')) self.tooltips.enable() self._readonly = False self._record_id = None def _new_remove_btn(self): but_remove = gtk.Button() img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) but_remove.add(img_remove) but_remove.set_relief(gtk.RELIEF_NONE) return but_remove def _sig_activate(self, *args): if self.wid_text.get_editable(): self._sig_add() def _sig_add(self, *args): context = self.field.get_context(self.record) value = self.wid_text.get_text().decode('utf-8') domain = self.field.domain_get(self.record) def callback(result): if result: self.add_new_keys([r[0] for r in result]) self.wid_text.set_text('') win = WinSearch(self.schema_model, callback, sel_multi=True, context=context, domain=domain, new=False) win.screen.search_filter(quote(value)) win.show() def add_new_keys(self, ids): context = self.field.get_context(self.record) self.send_modified() try: new_fields = RPCExecute('model', self.schema_model, 'get_keys', ids, context=context) except RPCException: new_fields = [] focus = False for new_field in new_fields: if new_field['name'] not in self.fields: self.keys[new_field['name']] = new_field self.add_line(new_field['name']) if not focus: # Use idle add because it can be called from the callback # of WinSearch while the popup is still there gobject.idle_add( self.fields[new_field['name']].widget.grab_focus) focus = True def _sig_remove(self, button, key, modified=True): del self.fields[key] del self.buttons[key] for widget in self.rows[key]: self.table.remove(widget) widget.destroy() del self.rows[key] if modified: self.send_modified() self.set_value(self.record, self.field) def set_value(self, record, field): field.set_client(record, self.get_value()) def get_value(self): return dict((key, widget.get_value()) for key, widget in self.fields.items()) @property def modified(self): if self.record and self.field: value = self.field.get_client(self.record) return any(widget.modified(value) for widget in self.fields.itervalues()) return False def _readonly_set(self, readonly): self._readonly = readonly self._set_button_sensitive() for widget in self.fields.values(): widget.set_readonly(readonly) self.wid_text.set_sensitive(not readonly) self.wid_text.set_editable(not readonly) def _set_button_sensitive(self): self.but_add.set_sensitive(bool( not self._readonly and self.attrs.get('create', True))) for button in self.buttons.itervalues(): button.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True))) def add_line(self, key): self.fields[key] = DICT_ENTRIES[self.keys[key]['type_']](key, self) field = self.fields[key] alignment = gtk.Alignment( float(self.attrs.get('xalign', 0.0)), float(self.attrs.get('yalign', 0.5)), float(self.attrs.get('xexpand', 1.0)), float(self.attrs.get('yexpand', 1.0))) hbox = gtk.HBox() hbox.pack_start(field.widget, expand=field.expand, fill=field.fill) alignment.add(hbox) n_rows = self.table.props.n_rows self.table.resize(n_rows + 1, 3) if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: text = _(':') + self.keys[key]['string'] else: text = self.keys[key]['string'] + _(':') label = gtk.Label(text) label.set_alignment(1., .5) self.table.attach(label, 0, 1, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) label.set_mnemonic_widget(field.widget) label.show() self.table.attach(alignment, 1, 2, n_rows - 1, n_rows, xoptions=gtk.FILL | gtk.EXPAND, yoptions=False, xpadding=2) alignment.show_all() remove_but = self._new_remove_btn() self.tooltips.set_tip(remove_but, _('Remove "%s"') % self.keys[key]['string']) self.table.attach(remove_but, 2, 3, n_rows - 1, n_rows, xoptions=gtk.FILL, yoptions=False, xpadding=2) remove_but.connect('clicked', self._sig_remove, key) remove_but.show_all() self.rows[key] = [label, alignment, remove_but] self.buttons[key] = remove_but def add_keys(self, keys): context = self.field.get_context(self.record) domain = self.field.domain_get(self.record) batchlen = min(10, CONFIG['client.limit']) for i in xrange(0, len(keys), batchlen): sub_keys = keys[i:i + batchlen] try: key_ids = RPCExecute('model', self.schema_model, 'search', [('name', 'in', sub_keys), domain], 0, CONFIG['client.limit'], None, context=context) except RPCException: key_ids = [] if not key_ids: continue try: values = RPCExecute('model', self.schema_model, 'get_keys', key_ids, context=context) except RPCException: values = [] if not values: continue self.keys.update({k['name']: k for k in values}) def display(self, record, field): super(DictWidget, self).display(record, field) if field is None: return record_id = record.id if record else None if record_id != self._record_id: for key in self.fields.keys(): self._sig_remove(None, key, modified=False) self._record_id = record_id value = field.get_client(record) if field else {} new_key_names = set(value.iterkeys()) - set(self.keys) if new_key_names: self.add_keys(list(new_key_names)) for key, val in sorted(value.iteritems()): if key not in self.keys: continue if key not in self.fields: self.add_line(key) widget = self.fields[key] widget.set_value(val) widget.set_readonly(self._readonly) for key in set(self.fields.keys()) - set(value.keys()): self._sig_remove(None, key, modified=False) self._set_button_sensitive() def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.add_new_keys([record_id]) self.wid_text.set_text('') completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if not self.wid_text.get_editable(): return if not self.record: return update_completion(self.wid_text, self.record, self.field, self.schema_model) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/url.py0000644000175000017500000000705613175640533024001 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from .char import Char import webbrowser import tryton.common as common from tryton.config import CONFIG class URL(Char): "url" def __init__(self, view, attrs): super(URL, self).__init__(view, attrs) self.tooltips = common.Tooltips() self.button = gtk.Button() img = gtk.Image() img.set_from_stock('tryton-web-browser', gtk.ICON_SIZE_SMALL_TOOLBAR) self.button.set_image(img) self.button.set_relief(gtk.RELIEF_NONE) self.button.connect('clicked', self.button_clicked) self.button.set_alignment(0.5, 0.5) self.widget.pack_start(self.button, expand=False, fill=False) self.widget.set_focus_chain([self.entry]) def display(self, record, field): super(URL, self).display(record, field) self.set_tooltips() if record and 'icon' in self.attrs: icon = self.attrs['icon'] if icon in record.group.fields: value = record[icon].get_client(record) or 'tryton-web-browser' else: value = icon common.ICONFACTORY.register_icon(value) img = gtk.Image() img.set_from_stock(value, gtk.ICON_SIZE_SMALL_TOOLBAR) self.button.set_image(img) def set_tooltips(self): value = self.entry.get_text() if value: self.tooltips.enable() self.tooltips.set_tip(self.button, value) else: self.tooltips.set_tip(self.button, '') self.tooltips.disable() def _readonly_set(self, value): super(URL, self)._readonly_set(value) if value: self.entry.hide() else: self.entry.show() if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([self.button]) else: self.widget.set_focus_chain([self.entry]) self.button.set_sensitive(True) def button_clicked(self, widget): value = self.entry.get_text() if value: webbrowser.open(value, new=2) class Email(URL): "email" def button_clicked(self, widget): value = self.entry.get_text() if value: webbrowser.open('mailto:%s' % value, new=2) def set_tooltips(self): value = self.entry.get_text() if value: self.tooltips.enable() self.tooltips.set_tip(self.button, 'mailto:%s' % value) else: self.tooltips.set_tip(self.button, '') self.tooltips.disable() class CallTo(URL): "call to" def button_clicked(self, widget): value = self.entry.get_text() if value: webbrowser.open('callto:%s' % value, new=2) def set_tooltips(self): value = self.entry.get_text() if value: self.tooltips.enable() self.tooltips.set_tip(self.button, 'callto:%s' % value) else: self.tooltips.set_tip(self.button, '') self.tooltips.disable() class SIP(URL): "sip" def button_clicked(self, widget): value = self.entry.get_text() if value: webbrowser.open('sip:%s' % value, new=2) def set_tooltips(self): value = self.entry.get_text() if value: self.tooltips.enable() self.tooltips.set_tip(self.button, 'sip:%s' % value) else: self.tooltips.set_tip(self.button, '') self.tooltips.disable() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/char.py0000644000175000017500000001522513255571102024103 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext import gobject import gtk from .widget import Widget, TranslateMixin from tryton.common import Tooltips from tryton.common.entry_position import reset_position from tryton.common.selection import PopdownMixin, selection_shortcuts from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG _ = gettext.gettext class Char(Widget, TranslateMixin, PopdownMixin): "Char" def __init__(self, view, attrs): super(Char, self).__init__(view, attrs) self.widget = gtk.HBox() self.autocomplete = bool(attrs.get('autocomplete')) if self.autocomplete: self.entry = gtk.ComboBoxEntry() selection_shortcuts(self.entry) focus_entry = self.entry.get_child() self.set_popdown([], self.entry) self.entry.connect('changed', self.changed) self.entry.connect('move-active', self._move_active) self.entry.connect( 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) else: self.entry = gtk.Entry() focus_entry = self.entry self.mnemonic_widget = focus_entry focus_entry.set_property('activates_default', True) focus_entry.connect('activate', self.sig_activate) focus_entry.connect('focus-out-event', lambda x, y: self._focus_out()) focus_entry.connect('key-press-event', self.send_modified) expand, fill = True, True if attrs.get('size'): expand, fill = False, False self.widget.pack_start(self.entry, expand=expand, fill=fill) if attrs.get('translate'): self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'tryton-locale') self.entry.connect('icon-press', self.translate) def translate_widget(self): entry = gtk.Entry() entry.set_property('activates_default', True) if self.record: field_size = self.record.expr_eval(self.attrs.get('size')) entry.set_width_chars(field_size or -1) entry.set_max_length(field_size or 0) return entry @staticmethod def translate_widget_set(widget, value): widget.set_text(value or '') reset_position(widget) @staticmethod def translate_widget_get(widget): return widget.get_text() @staticmethod def translate_widget_set_readonly(widget, value): widget.set_editable(not value) widget.props.sensitive = not value def changed(self, combobox): def focus_out(): if combobox.props.window: self._focus_out() # Only when changed from pop list if not combobox.get_child().has_focus(): # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) @property def modified(self): if self.record and self.field: value = self.get_client_value(self.record, self.field) return value != self.get_value() return False def set_value(self, record, field): entry = self.entry.get_child() if self.autocomplete else self.entry value = entry.get_text() or '' return field.set_client(record, value) def get_value(self): entry = self.entry.get_child() if self.autocomplete else self.entry return entry.get_text() def get_client_value(self, record, field): if not field: value = '' else: value = field.get_client(record) return value def display(self, record, field): super(Char, self).display(record, field) if self.autocomplete: if record: if self.field_name not in record.autocompletion: record.do_autocomplete(self.field_name) selection = record.autocompletion.get(self.field_name, []) else: selection = [] self.set_popdown([(x, x) for x in selection], self.entry) # Set size if self.autocomplete: size_entry = self.entry.get_child() else: size_entry = self.entry if record: field_size = record.expr_eval(self.attrs.get('size')) size_entry.set_width_chars(field_size or -1) size_entry.set_max_length(field_size or 0) else: size_entry.set_width_chars(-1) size_entry.set_max_length(0) value = self.get_client_value(record, field) if not self.autocomplete: self.entry.set_text(value) reset_position(self.entry) else: self.entry.handler_block_by_func(self.changed) if not self.set_popdown_value(self.entry, value) or not value: child = self.entry.get_child() child.set_text(value) reset_position(child) self.entry.handler_unblock_by_func(self.changed) def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): combobox.emit_stop_by_name('move-active') def _readonly_set(self, value): sensitivity = {True: gtk.SENSITIVITY_OFF, False: gtk.SENSITIVITY_AUTO} super(Char, self)._readonly_set(value) if self.autocomplete: entry_editable = self.entry.get_child() self.entry.set_button_sensitivity(sensitivity[value]) else: entry_editable = self.entry entry_editable.set_editable(not value) set_widget_style(entry_editable, not value) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() class Password(Char): def __init__(self, view, attrs): super(Password, self).__init__(view, attrs) self.entry.props.visibility = False self.visibility_checkbox = gtk.CheckButton() self.visibility_checkbox.connect('toggled', self.toggle_visibility) Tooltips().set_tip(self.visibility_checkbox, _('Show plain text')) self.widget.pack_start(self.visibility_checkbox, expand=False) def _readonly_set(self, value): super(Char, self)._readonly_set(value) self.entry.set_editable(not value) self.visibility_checkbox.props.visible = not value if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() def toggle_visibility(self, button): self.entry.props.visibility = not self.entry.props.visibility tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/one2one.py0000644000175000017500000000032313175640533024532 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from .many2one import Many2One class One2One(Many2One): pass tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/__init__.py0000644000175000017500000000022013175640533024720 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/image.py0000644000175000017500000000726513255571102024255 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import urllib from tryton.common import resize_pixbuf, data2pixbuf, BIG_IMAGE_SIZE from .widget import Widget from .binary import BinaryMixin _ = gettext.gettext class Image(BinaryMixin, Widget): def __init__(self, view, attrs): super(Image, self).__init__(view, attrs) self.height = int(attrs.get('height', 100)) self.width = int(attrs.get('width', 300)) self.widget = gtk.VBox(spacing=3) self.event = gtk.EventBox() self.event.drag_dest_set(gtk.DEST_DEFAULT_ALL, [ gtk.TargetEntry.new('text/plain', 0, 0), gtk.TargetEntry.new('text/uri-list', 0, 1), gtk.TargetEntry.new("image/x-xpixmap", 0, 2)], gtk.gdk.ACTION_MOVE) self.event.connect('drag_motion', self.drag_motion) self.event.connect('drag_data_received', self.drag_data_received) self.image = gtk.Image() self.event.add(self.image) self.widget.pack_start(self.event, expand=True, fill=True) toolbar = self.toolbar() # Set button attributes even if not display if not attrs.get('readonly'): alignment = gtk.Alignment(xalign=0.5, yalign=0.5) alignment.add(toolbar) self.widget.pack_start(alignment, expand=False, fill=False) self._readonly = False self.update_img() @property def filters(self): filters = super(Image, self).filters filter_image = gtk.FileFilter() filter_image.set_name(_('Images')) for mime in ("image/png", "image/jpeg", "image/gif"): filter_image.add_mime_type(mime) for pat in ("*.png", "*.jpg", "*.gif", "*.tif", "*.xpm"): filter_image.add_pattern(pat) filters.insert(0, filter_image) return filters def _readonly_set(self, value): self._readonly = value self.but_select.set_sensitive(not value) self.but_clear.set_sensitive(not value) def clear(self, widget=None): super(Image, self).clear(widget=widget) self.update_img() def drag_motion(self, widget, context, x, y, timestamp): if self._readonly: return False context.drag_status(gtk.gdk.ACTION_COPY, timestamp) return True def drag_data_received(self, widget, context, x, y, selection, info, timestamp): if self._readonly: return if info == 0: uri = selection.get_text().split('\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 1: uri = selection.data.split('\r\n')[0] if uri: self.field.set_client(self.record, urllib.urlopen(uri).read()) self.update_img() elif info == 2: data = selection.get_pixbuf() if data: self.field.set_client(self.record, data) self.update_img() def update_img(self): value = None if self.field: value = self.field.get_client(self.record) if isinstance(value, (int, long)): if value > BIG_IMAGE_SIZE: value = False else: value = self.field.get_data(self.record) pixbuf = resize_pixbuf(data2pixbuf(value), self.width, self.height) self.image.set_from_pixbuf(pixbuf) return bool(value) def display(self, record, field): super(Image, self).display(record, field) value = self.update_img() self.update_buttons(bool(value)) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/state_widget.py0000644000175000017500000000612613255571102025651 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import tryton.common as common from tryton.common.widget_style import widget_class class StateMixin(object): def __init__(self, *args, **kwargs): self.attrs = kwargs.pop('attrs') super(StateMixin, self).__init__(*args, **kwargs) def state_set(self, record): if record: state_changes = record.expr_eval(self.attrs.get('states', {})) else: state_changes = {} if state_changes.get('invisible', self.attrs.get('invisible')): self.hide() else: self.show() class Label(StateMixin, gtk.Label): def state_set(self, record): super(Label, self).state_set(record) if 'name' in self.attrs and record: field = record.group.fields[self.attrs['name']] else: field = None if not self.attrs.get('string', True) and field: if record: text = field.get_client(record) or '' else: text = '' self.set_text(text) if record: state_changes = record.expr_eval(self.attrs.get('states', {})) else: state_changes = {} required = ((field and field.attrs.get('required')) or state_changes.get('required')) readonly = ((field and field.attrs.get('readonly')) or state_changes.get('readonly')) attrlist = common.get_label_attributes(readonly, required) self.set_attributes(attrlist) widget_class(self, 'readonly', readonly) widget_class(self, 'required', required) class VBox(StateMixin, gtk.VBox): pass class Image(StateMixin, gtk.Image): pass class Frame(StateMixin, gtk.Frame): def __init__(self, label=None, attrs=None): if not label: # label must be None to have no label widget label = None super(Frame, self).__init__(label=label, attrs=attrs) if not label: self.set_shadow_type(gtk.SHADOW_NONE) self.set_border_width(0) class ScrolledWindow(StateMixin, gtk.ScrolledWindow): pass class Notebook(StateMixin, gtk.Notebook): def state_set(self, record): super(Notebook, self).state_set(record) if record: state_changes = record.expr_eval(self.attrs.get('states', {})) else: state_changes = {} if state_changes.get('readonly', self.attrs.get('readonly')): for widgets in self.widgets.itervalues(): for widget in widgets: widget._readonly_set(True) class Alignment(gtk.Alignment): def __init__(self, widget, attrs): super(Alignment, self).__init__( float(attrs.get('xalign', 0.0)), float(attrs.get('yalign', 0.5)), float(attrs.get('xexpand', 1.0)), float(attrs.get('yexpand', 1.0))) self.add(widget) widget.connect('show', lambda *a: self.show()) widget.connect('hide', lambda *a: self.hide()) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/float.py0000644000175000017500000000334413251060075024270 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import locale from .integer import Integer class Float(Integer): "Float" def __init__(self, view, attrs): super(Float, self).__init__(view, attrs) self.entry.connect('key-press-event', self.key_press_event) def display(self, record, field): super(Float, self).display(record, field) if field: digits = field.digits(record, factor=self.factor) if digits: self.entry.set_width_chars(sum(digits)) else: self.entry.set_width_chars(18) def key_press_event(self, widget, event): for name in ('KP_Decimal', 'KP_Separator'): if event.keyval == gtk.gdk.keyval_from_name(name): event.keyval = int(gtk.gdk.unicode_to_keyval( ord(locale.localeconv()['decimal_point']))) def sig_insert_text(self, entry, new_text, new_text_length, position): if not self.record: entry.stop_emission('insert-text') return value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] decimal_point = locale.localeconv()['decimal_point'] if new_value in ('-', decimal_point): return digits = self.field.digits(self.record, factor=self.factor) try: value = locale.atof(new_value) except ValueError: entry.stop_emission('insert-text') return if digits and not (round(value, digits[1]) == float(value)): entry.stop_emission('insert-text') tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/pyson.py0000644000175000017500000000252313251060075024331 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from .char import Char from tryton.pyson import CONTEXT, PYSONEncoder, PYSONDecoder class PYSON(Char): def __init__(self, view, attrs): super(PYSON, self).__init__(view, attrs) self.encoder = PYSONEncoder() self.decoder = PYSONDecoder(noeval=True) self.entry.connect('key-release-event', self.validate_pyson) def get_encoded_value(self): value = self.get_value() if not value: return value try: return self.encoder.encode(eval(value, CONTEXT)) except Exception: return None def set_value(self, record, field): field.set_client(record, self.get_encoded_value()) def get_client_value(self, record, field): value = super(PYSON, self).get_client_value(record, field) if value: value = repr(self.decoder.decode(value)) return value def validate_pyson(self, *args): icon = gtk.STOCK_OK if self.get_encoded_value() is None: icon = gtk.STOCK_CANCEL self.entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, icon) def _focus_out(self): self.validate_pyson() super(PYSON, self)._focus_out() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/selection.py0000644000175000017500000000726313251060075025154 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject from .widget import Widget from tryton.common.selection import SelectionMixin, selection_shortcuts, \ PopdownMixin from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG class Selection(Widget, SelectionMixin, PopdownMixin): def __init__(self, view, attrs): super(Selection, self).__init__(view, attrs) self.widget = gtk.HBox(spacing=3) self.entry = gtk.ComboBoxEntry() child = self.mnemonic_widget = self.entry.get_child() child.set_property('activates_default', True) child.set_max_length(int(attrs.get('size', 0))) child.set_width_chars(10) selection_shortcuts(self.entry) child.connect('activate', lambda *a: self._focus_out()) child.connect('focus-out-event', lambda *a: self._focus_out()) self.entry.connect('changed', self.changed) self.entry.connect('move-active', self._move_active) self.entry.connect( 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) self.widget.pack_start(self.entry) self.widget.set_focus_chain([child]) self.selection = attrs.get('selection', [])[:] self.attrs = attrs self.init_selection() self.set_popdown(self.selection, self.entry) def changed(self, combobox): def focus_out(): if combobox.props.window: self._focus_out() # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): combobox.emit_stop_by_name('move-active') def _readonly_set(self, value): super(Selection, self)._readonly_set(value) self.entry.get_child().set_editable(not value) set_widget_style(self.entry.get_child(), not value) self.entry.set_button_sensitivity( gtk.SENSITIVITY_OFF if value else gtk.SENSITIVITY_AUTO) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() def get_value(self): if not self.entry.get_child(): # entry is destroyed return return self.get_popdown_value(self.entry) @property def modified(self): if self.record and self.field: return self.field.get(self.record) != self.get_value() return False def set_value(self, record, field): value = self.get_value() if 'relation' in self.attrs and value: value = (value, self.get_popdown_text(self.entry)) field.set_client(record, value) def display(self, record, field): self.update_selection(record, field) self.set_popdown(self.selection, self.entry) if not field: self.entry.set_active(-1) # When setting no item GTK doesn't clear the entry self.entry.get_child().set_text('') return super(Selection, self).display(record, field) value = field.get(record) if isinstance(value, (list, tuple)): # Compatibility with Many2One value = value[0] self.entry.handler_block_by_func(self.changed) if not self.set_popdown_value(self.entry, value): text = self.get_inactive_selection(value) self.set_popdown(self.selection[:] + [(value, text)], self.entry) self.set_popdown_value(self.entry, value) self.entry.handler_unblock_by_func(self.changed) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/one2many.py0000644000175000017500000005250513255571102024720 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import itertools from .widget import Widget from tryton.gui.window.view_form.screen import Screen from tryton.gui.window.win_search import WinSearch from tryton.gui.window.win_form import WinForm import tryton.common as common from tryton.common.placeholder_entry import PlaceholderEntry from tryton.common.completion import get_completion, update_completion from tryton.common.domain_parser import quote from tryton.common.widget_style import widget_class _ = gettext.gettext class One2Many(Widget): expand = True def __init__(self, view, attrs): super(One2Many, self).__init__(view, attrs) self.widget = gtk.Frame() self.widget.set_shadow_type(gtk.SHADOW_NONE) self.widget.get_accessible().set_name(attrs.get('string', '')) vbox = gtk.VBox(homogeneous=False, spacing=2) self.widget.add(vbox) self._readonly = True self._required = False self._position = 0 self._length = 0 self.title_box = hbox = gtk.HBox(homogeneous=False, spacing=0) hbox.set_border_width(2) self.title = gtk.Label(attrs.get('string', '')) self.title.set_alignment(0.0, 0.5) hbox.pack_start(self.title, expand=True, fill=True) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) tooltips = common.Tooltips() but_switch = gtk.Button() tooltips.set_tip(but_switch, _('Switch')) but_switch.connect('clicked', self.switch_view) img_switch = gtk.Image() img_switch.set_from_stock('tryton-fullscreen', gtk.ICON_SIZE_SMALL_TOOLBAR) img_switch.set_alignment(0.5, 0.5) but_switch.add(img_switch) but_switch.set_relief(gtk.RELIEF_NONE) hbox.pack_start(but_switch, expand=False, fill=False) self.but_pre = gtk.Button() tooltips.set_tip(self.but_pre, _('Previous')) self.but_pre.connect('clicked', self._sig_previous) img_pre = gtk.Image() img_pre.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR) img_pre.set_alignment(0.5, 0.5) self.but_pre.add(img_pre) self.but_pre.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_pre, expand=False, fill=False) self.label = gtk.Label('(0,0)') hbox.pack_start(self.label, expand=False, fill=False) self.but_next = gtk.Button() tooltips.set_tip(self.but_next, _('Next')) self.but_next.connect('clicked', self._sig_next) img_next = gtk.Image() img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR) img_next.set_alignment(0.5, 0.5) self.but_next.add(img_next) self.but_next.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_next, expand=False, fill=False) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) self.focus_out = True self.wid_completion = None if attrs.get('add_remove'): self.wid_text = PlaceholderEntry() self.wid_text.set_placeholder_text(_('Search')) self.wid_text.set_property('width_chars', 13) self.wid_text.connect('focus-out-event', lambda *a: self._focus_out()) hbox.pack_start(self.wid_text, expand=True, fill=True) if int(self.attrs.get('completion', 1)): access = common.MODELACCESS[attrs['relation']] self.wid_completion = get_completion( search=access['read'] and access['write'], create=attrs.get('create', True) and access['create']) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_completion.connect('action-activated', self._completion_action_activated) self.wid_text.set_completion(self.wid_completion) self.wid_text.connect('changed', self._update_completion) self.but_add = gtk.Button() tooltips.set_tip(self.but_add, _('Add existing record')) self.but_add.connect('clicked', self._sig_add) img_add = gtk.Image() img_add.set_from_stock('tryton-list-add', gtk.ICON_SIZE_SMALL_TOOLBAR) img_add.set_alignment(0.5, 0.5) self.but_add.add(img_add) self.but_add.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_add, expand=False, fill=False) self.but_remove = gtk.Button() tooltips.set_tip(self.but_remove, _('Remove selected record')) self.but_remove.connect('clicked', self._sig_remove, True) img_remove = gtk.Image() img_remove.set_from_stock('tryton-list-remove', gtk.ICON_SIZE_SMALL_TOOLBAR) img_remove.set_alignment(0.5, 0.5) self.but_remove.add(img_remove) self.but_remove.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_remove, expand=False, fill=False) hbox.pack_start(gtk.VSeparator(), expand=False, fill=True) self.but_new = gtk.Button() tooltips.set_tip(self.but_new, _('Create a new record ')) self.but_new.connect('clicked', self._sig_new) img_new = gtk.Image() img_new.set_from_stock('tryton-new', gtk.ICON_SIZE_SMALL_TOOLBAR) img_new.set_alignment(0.5, 0.5) self.but_new.add(img_new) self.but_new.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_new, expand=False, fill=False) self.but_open = gtk.Button() tooltips.set_tip(self.but_open, _('Edit selected record ')) self.but_open.connect('clicked', self._sig_edit) img_open = gtk.Image() img_open.set_from_stock('tryton-open', gtk.ICON_SIZE_SMALL_TOOLBAR) img_open.set_alignment(0.5, 0.5) self.but_open.add(img_open) self.but_open.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_open, expand=False, fill=False) self.but_del = gtk.Button() tooltips.set_tip(self.but_del, _('Delete selected record ')) self.but_del.connect('clicked', self._sig_remove, False) img_del = gtk.Image() img_del.set_from_stock('tryton-delete', gtk.ICON_SIZE_SMALL_TOOLBAR) img_del.set_alignment(0.5, 0.5) self.but_del.add(img_del) self.but_del.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_del, expand=False, fill=False) self.but_undel = gtk.Button() tooltips.set_tip(self.but_undel, _('Undelete selected record ')) self.but_undel.connect('clicked', self._sig_undelete) img_undel = gtk.Image() img_undel.set_from_stock('tryton-undo', gtk.ICON_SIZE_SMALL_TOOLBAR) img_undel.set_alignment(0.5, 0.5) self.but_undel.add(img_undel) self.but_undel.set_relief(gtk.RELIEF_NONE) hbox.pack_start(self.but_undel, expand=False, fill=False) if attrs.get('add_remove'): hbox.set_focus_chain([self.wid_text]) else: hbox.set_focus_chain([]) tooltips.enable() frame = gtk.Frame() frame.add(hbox) frame.set_shadow_type(gtk.SHADOW_OUT) vbox.pack_start(frame, expand=False, fill=True) self.screen = Screen(attrs['relation'], mode=attrs.get('mode', 'tree,form').split(','), view_ids=attrs.get('view_ids', '').split(','), views_preload=attrs.get('views', {}), row_activate=self._on_activate, exclude_field=attrs.get('relation_field', None), limit=None) self.screen.pre_validate = bool(int(attrs.get('pre_validate', 0))) self.screen.signal_connect(self, 'record-message', self._sig_label) vbox.pack_start(self.screen.widget, expand=True, fill=True) self.screen.widget.connect('key_press_event', self.on_keypress) if self.attrs.get('add_remove'): self.wid_text.connect('key_press_event', self.on_keypress) but_switch.props.sensitive = self.screen.number_of_views > 1 def on_keypress(self, widget, event): if (event.keyval == gtk.keysyms.F3) \ and self.but_new.get_property('sensitive'): self._sig_new(widget) return True if event.keyval == gtk.keysyms.F2 \ and widget == self.screen.widget: self._sig_edit(widget) return True if (event.keyval in (gtk.keysyms.Delete, gtk.keysyms.KP_Delete) and widget == self.screen.widget and self.but_del.get_property('sensitive')): self._sig_remove(widget) return True if event.keyval == gtk.keysyms.Insert and widget == self.screen.widget: self._sig_undelete(widget) return True if self.attrs.get('add_remove'): editable = self.wid_text.get_editable() activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] if not self.wid_completion: activate_keys.append(gtk.keysyms.Return) if (widget == self.wid_text and event.keyval in activate_keys and editable and self.wid_text.get_text()): self._sig_add() self.wid_text.grab_focus() return False def destroy(self): self.screen.destroy() def _on_activate(self): self._sig_edit() def switch_view(self, widget): self.screen.switch_view() @property def modified(self): return self.screen.current_view.modified def _readonly_set(self, value): self._readonly = value self._set_button_sensitive() self._set_label_state() def _required_set(self, value): self._required = value self._set_label_state() def _set_label_state(self): attrlist = common.get_label_attributes(self._readonly, self._required) self.title.set_attributes(attrlist) widget_class(self.title, 'readonly', self._readonly) widget_class(self.title, 'required', self._required) def _set_button_sensitive(self): access = common.MODELACCESS[self.screen.model_name] if self.record and self.field: field_size = self.record.expr_eval(self.attrs.get('size')) o2m_size = len(self.field.get_eval(self.record)) size_limit = (field_size is not None and o2m_size >= field_size >= 0) else: o2m_size = None size_limit = False self.but_new.set_sensitive(bool( not self._readonly and self.attrs.get('create', True) and not size_limit and access['create'])) self.but_del.set_sensitive(bool( not self._readonly and self.attrs.get('delete', True) and self._position and access['delete'])) self.but_undel.set_sensitive(bool( not self._readonly and not size_limit and self._position)) self.but_open.set_sensitive(bool( self._position and access['read'])) self.but_next.set_sensitive(bool( self._position and self._position < self._length)) self.but_pre.set_sensitive(bool( self._position and self._position > 1)) if self.attrs.get('add_remove'): self.but_add.set_sensitive(bool( not self._readonly and not size_limit and access['write'] and access['read'])) self.but_remove.set_sensitive(bool( not self._readonly and self._position and access['write'] and access['read'])) self.wid_text.set_sensitive(self.but_add.get_sensitive()) self.wid_text.set_editable(self.but_add.get_sensitive()) # New button must be added to focus chain to allow keyboard only # creation when there is no existing record on form view. focus_chain = self.title_box.get_focus_chain() or [] if o2m_size == 0 and self.screen.current_view.view_type == 'form': if self.but_new not in focus_chain: focus_chain.append(self.but_new) else: if self.but_new in focus_chain: focus_chain.remove(self.but_new) self.title_box.set_focus_chain(focus_chain) def _validate(self): self.view.set_value() record = self.screen.current_record if record: fields = self.screen.current_view.get_fields() if not record.validate(fields): self.screen.display(set_cursor=True) return False if self.screen.pre_validate and not record.pre_validate(): return False return True def _sequence(self): for view in self.screen.views: if view.view_type == 'tree': sequence = view.attributes.get('sequence') if sequence: return sequence def _sig_new(self, *args): if not common.MODELACCESS[self.screen.model_name]['create']: return if not self._validate(): return if self.attrs.get('product'): self._new_product() else: self._new_single() def _new_single(self): ctx = {} ctx.update(self.field.get_context(self.record)) sequence = self._sequence() def update_sequence(): if sequence: self.screen.group.set_sequence(field=sequence) if self.screen.current_view.editable: self.screen.new() self.screen.current_view.widget.set_sensitive(True) update_sequence() else: field_size = self.record.expr_eval(self.attrs.get('size')) or -1 field_size -= len(self.field.get_eval(self.record)) + 1 WinForm(self.screen, lambda a: update_sequence(), new=True, many=field_size, context=ctx, title=self.attrs.get('string')) def _new_product(self): fields = self.attrs['product'].split(',') product = {} first = self.screen.new(default=False) default = first.default_get() first.set_default(default) def search_set(*args): if not fields: return make_product() field = self.screen.group.fields[fields.pop()] relation = field.attrs.get('relation') if not relation: search_set() domain = field.domain_get(first) context = field.get_context(first) def callback(result): if result: product[field.name] = result win_search = WinSearch(relation, callback, sel_multi=True, context=context, domain=domain, title=self.attrs.get('string')) win_search.win.connect('destroy', search_set) win_search.screen.search_filter() win_search.show() def make_product(first=first): if not product: self.screen.group.remove(first, remove=True) return fields = product.keys() for values in itertools.product(*product.values()): if first: record = first first = None else: record = self.screen.new(default=False) default_value = default.copy() for field, value in zip(fields, values): id_, rec_name = value default_value[field] = id_ default_value[field + '.rec_name'] = rec_name record.set_default(default_value) sequence = self._sequence() if sequence: self.screen.group.set_sequence(field=sequence) search_set() def _sig_edit(self, widget=None): if not common.MODELACCESS[self.screen.model_name]['read']: return if not self._validate(): return record = self.screen.current_record if record: WinForm(self.screen, lambda a: None, title=self.attrs.get('string')) def _sig_next(self, widget): if not self._validate(): return self.screen.display_next() def _sig_previous(self, widget): if not self._validate(): return self.screen.display_prev() def _sig_remove(self, widget, remove=False): access = common.MODELACCESS[self.screen.model_name] if remove: if not access['write'] or not access['read']: return else: if not access['delete']: return self.screen.remove(remove=remove) def _sig_undelete(self, button): self.screen.unremove() def _sig_add(self, *args): if not self.focus_out: return access = common.MODELACCESS[self.screen.model_name] if not access['write'] or not access['read']: return self.view.set_value() domain = self.field.domain_get(self.record) context = self.field.get_context(self.record) domain = [domain, self.record.expr_eval(self.attrs.get('add_remove'))] removed_ids = self.field.get_removed_ids(self.record) domain = ['OR', domain, ('id', 'in', removed_ids)] text = self.wid_text.get_text().decode('utf-8') self.focus_out = False sequence = self._sequence() def callback(result): self.focus_out = True if result: ids = [x[0] for x in result] self.screen.load(ids, modified=True) self.screen.display(res_id=ids[0]) if sequence: self.screen.group.set_sequence(field=sequence) self.screen.set_cursor() self.wid_text.set_text('') win = WinSearch(self.attrs['relation'], callback, sel_multi=True, context=context, domain=domain, view_ids=self.attrs.get('view_ids', '').split(','), views_preload=self.attrs.get('views', {}), new=self.but_new.get_property('sensitive'), title=self.attrs.get('string')) win.screen.search_filter(quote(text)) win.show() def _sig_label(self, screen, signal_data): self._position = signal_data[0] self._length = signal_data[1] if self._position >= 1: name = str(self._position) else: name = '_' line = '(%s/%s)' % (name, self._length) self.label.set_text(line) self._set_button_sensitive() def display(self, record, field): super(One2Many, self).display(record, field) self._set_button_sensitive() if field is None: self.screen.new_group() self.screen.current_record = None self.screen.parent = None self.screen.display() return False new_group = field.get_client(record) if id(self.screen.group) != id(new_group): self.screen.group = new_group if (self.screen.current_view.view_type == 'tree') \ and self.screen.current_view.editable: self.screen.current_record = None domain = [] size_limit = None if record: domain = field.domain_get(record) size_limit = record.expr_eval(self.attrs.get('size')) if self._readonly: if size_limit is None: size_limit = len(self.screen.group) else: size_limit = min(size_limit, len(self.screen.group)) if self.screen.domain != domain: self.screen.domain = domain self.screen.size_limit = size_limit self.screen.display() return True def set_value(self, record, field): self.screen.current_view.set_value() if self.screen.modified(): # TODO check if required record.modified_fields.setdefault(field.name) record.signal('record-modified') return True def _completion_match_selected(self, completion, model, iter_): record_id, = model.get(iter_, 1) self.screen.load([record_id], modified=True) self.wid_text.set_text('') self.wid_text.grab_focus() completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = self.wid_text.get_text() return True def _update_completion(self, widget): if self._readonly: return if not self.record: return model = self.attrs['relation'] domain = self.field.domain_get(self.record) domain = [domain, self.record.expr_eval(self.attrs.get('add_remove'))] removed_ids = self.field.get_removed_ids(self.record) domain = ['OR', domain, ('id', 'in', removed_ids)] update_completion(self.wid_text, self.record, self.field, model, domain=domain) def _completion_action_activated(self, completion, index): if index == 0: self._sig_add() self.wid_text.grab_focus() elif index == 1: self._sig_new() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/reference.py0000644000175000017500000001237513251060075025125 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from .many2one import Many2One from tryton.common.selection import SelectionMixin, PopdownMixin, \ selection_shortcuts from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG _ = gettext.gettext class Reference(Many2One, SelectionMixin, PopdownMixin): def __init__(self, view, attrs): super(Reference, self).__init__(view, attrs) self.widget_combo = gtk.ComboBoxEntry() child = self.widget_combo.get_child() child.connect('activate', lambda *a: self._focus_out()) child.connect('focus-out-event', lambda *a: self._focus_out()) child.get_accessible().set_name(attrs.get('string', '')) self.widget_combo.connect('changed', self.sig_changed_combo) self.widget_combo.connect('move-active', self._move_active) self.widget_combo.connect( 'scroll-event', lambda c, e: c.emit_stop_by_name('scroll-event')) selection_shortcuts(self.widget_combo) self.widget_combo.set_focus_chain([child]) self.widget.pack_start(self.widget_combo, expand=False, fill=True) self.widget.pack_start(gtk.Label('-'), expand=False, fill=False) self.init_selection() self.set_popdown(self.selection, self.widget_combo) self.widget.set_focus_chain([self.widget_combo, self.wid_text]) def get_model(self): active = self.widget_combo.get_active() if active < 0: return '' else: model = self.widget_combo.get_model() return model[active][1] def get_empty_value(self): for name, model in self.widget_combo.get_model(): if model in (None, ''): return model, name return '', '' def _move_active(self, combobox, scroll_type): if not combobox.get_child().get_editable(): combobox.emit_stop_by_name('move-active') def _set_button_sensitive(self): super(Reference, self)._set_button_sensitive() self.widget_combo.get_child().set_editable(not self._readonly) set_widget_style(self.widget_combo.get_child(), not self._readonly) self.widget_combo.set_button_sensitivity( gtk.SENSITIVITY_OFF if self._readonly else gtk.SENSITIVITY_AUTO) if self._readonly and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() @property def modified(self): if self.record and self.field: try: model, name = self.field.get_client(self.record) except (ValueError, TypeError): model, name = self.get_empty_value() return (model != self.get_model() or name != self.wid_text.get_text()) return False def has_target(self, value): if value is None: return False model, value = value.split(',') if not value: value = None else: try: value = int(value) except ValueError: value = None result = model == self.get_model() and value >= 0 return result def value_from_id(self, id_, str_=None): if str_ is None: str_ = '' return self.get_model(), (id_, str_) @staticmethod def id_from_value(value): _, value = value.split(',') return int(value) def sig_changed_combo(self, *args): if not self.changed: return self.wid_text.set_text('') model = self.get_model() if model: value = (model, (-1, '')) else: value = ('', '') self.field.set_client(self.record, value) def set_value(self, record, field): if not self.get_model(): value = self.wid_text.get_text() if not value: field.set_client(record, None) else: field.set_client(record, ('', value)) return else: try: model, name = field.get_client(record) except (ValueError, TypeError): model, name = self.get_empty_value() if (model != self.get_model() or name != self.wid_text.get_text()): field.set_client(record, None) self.set_text('') def set_text(self, value): if value: model, value = value else: model, value = None, None super(Reference, self).set_text(value) self.widget_combo.handler_block_by_func(self.sig_changed_combo) if not self.set_popdown_value(self.widget_combo, model): text = self.get_inactive_selection(model) self.set_popdown( self.selection[:] + [(model, text)], self.widget_combo) self.set_popdown_value(self.widget_combo, value) self.widget_combo.handler_unblock_by_func(self.sig_changed_combo) def display(self, record, field): self.update_selection(record, field) self.set_popdown(self.selection, self.widget_combo) super(Reference, self).display(record, field) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/many2one.py0000644000175000017500000003271613255571102024722 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import gettext from .widget import Widget import tryton.common as common from tryton.gui.window.view_form.screen import Screen from tryton.gui.window.win_search import WinSearch from tryton.gui.window.win_form import WinForm from tryton.common.popup_menu import populate from tryton.common.completion import get_completion, update_completion from tryton.common.entry_position import reset_position from tryton.common.domain_parser import quote from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG _ = gettext.gettext class Many2One(Widget): def __init__(self, view, attrs): super(Many2One, self).__init__(view, attrs) self.widget = gtk.HBox(spacing=0) self.widget.set_property('sensitive', True) self.wid_text = self.mnemonic_widget = gtk.Entry() self.wid_text.set_property('width-chars', 13) self.wid_text.set_property('activates_default', True) self.wid_text.connect('key-press-event', self.send_modified) self.wid_text.connect('key_press_event', self.sig_key_press) self.wid_text.connect('populate-popup', self._populate_popup) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect('changed', self.sig_changed) self.changed = True self.focus_out = True if int(self.attrs.get('completion', 1)): self.wid_text.connect('changed', self._update_completion) self.wid_completion = None self.wid_text.connect('icon-press', self.sig_edit) self.widget.pack_end(self.wid_text, expand=True, fill=True) self._readonly = False def get_model(self): return self.attrs['relation'] def _readonly_set(self, value): self._readonly = value self._set_button_sensitive() if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() def _set_button_sensitive(self): self.wid_text.set_editable(not self._readonly) set_widget_style(self.wid_text, not self._readonly) self.wid_text.set_icon_sensitive( gtk.ENTRY_ICON_PRIMARY, self.read_access) self.wid_text.set_icon_sensitive( gtk.ENTRY_ICON_SECONDARY, not self._readonly) def get_access(self, type_): model = self.get_model() if model: return common.MODELACCESS[model][type_] else: return True @property def read_access(self): return self.get_access('read') @property def create_access(self): return self.attrs.get('create', True) and self.get_access('create') @property def modified(self): if self.record and self.field: value = self.wid_text.get_text() return self.field.get_client(self.record) != value return False @staticmethod def has_target(value): return value is not None @staticmethod def value_from_id(id_, str_=None): if str_ is None: str_ = '' return id_, str_ @staticmethod def id_from_value(value): return value def sig_activate(self): model = self.get_model() if not model or not common.MODELACCESS[model]['read']: return if not self.focus_out or not self.field: return self.changed = False value = self.field.get(self.record) model = self.get_model() self.focus_out = False if model and not self.has_target(value): if (not self._readonly and (self.wid_text.get_text() or self.field.get_state_attrs( self.record)['required'])): domain = self.field.domain_get(self.record) context = self.field.get_context(self.record) text = self.wid_text.get_text().decode('utf-8') def callback(result): if result: self.field.set_client(self.record, self.value_from_id(*result[0]), force_change=True) else: self.set_text('') self.focus_out = True self.changed = True win = WinSearch(model, callback, sel_multi=False, context=context, domain=domain, view_ids=self.attrs.get('view_ids', '').split(','), views_preload=self.attrs.get('views', {}), new=self.create_access, title=self.attrs.get('string')) win.screen.search_filter(quote(text)) if len(win.screen.group) == 1: win.response(None, gtk.RESPONSE_OK) else: win.show() return self.focus_out = True self.changed = True return def get_screen(self): domain = self.field.domain_get(self.record) context = self.field.get_context(self.record) # Remove first tree view as mode is form only view_ids = self.attrs.get('view_ids', '').split(',')[1:] return Screen(self.get_model(), domain=domain, context=context, mode=['form'], view_ids=view_ids, views_preload=self.attrs.get('views', {}), readonly=self._readonly, exclude_field=self.attrs.get('relation_field')) def sig_new(self, *args): model = self.get_model() if not model or not common.MODELACCESS[model]['create']: return self.focus_out = False screen = self.get_screen() def callback(result): if result: self.field.set_client(self.record, self.value_from_id(screen.current_record.id, screen.current_record.rec_name())) self.focus_out = True WinForm(screen, callback, new=True, save_current=True, title=self.attrs.get('string'), rec_name=self.wid_text.get_text()) def sig_edit(self, entry=None, icon_pos=None, *args): model = self.get_model() if not model or not common.MODELACCESS[model]['read']: return if not self.focus_out or not self.field: return self.changed = False self.focus_out = False value = self.field.get(self.record) if (icon_pos == gtk.ENTRY_ICON_SECONDARY and not self._readonly and self.has_target(value)): self.field.set_client(self.record, self.value_from_id(None, '')) self.wid_text.set_text('') self.changed = True self.focus_out = True return if self.has_target(value): screen = self.get_screen() screen.load([self.id_from_value(self.field.get(self.record))]) def callback(result): if result: self.field.set_client(self.record, self.value_from_id(screen.current_record.id, screen.current_record.rec_name()), force_change=True) self.focus_out = True self.changed = True WinForm(screen, callback, save_current=True, title=self.attrs.get('string')) return if not self._readonly: domain = self.field.domain_get(self.record) context = self.field.get_context(self.record) text = self.wid_text.get_text().decode('utf-8') def callback(result): if result: self.field.set_client(self.record, self.value_from_id(*result[0]), force_change=True) self.focus_out = True self.changed = True win = WinSearch(model, callback, sel_multi=False, context=context, domain=domain, view_ids=self.attrs.get('view_ids', '').split(','), views_preload=self.attrs.get('views', {}), new=self.create_access, title=self.attrs.get('string')) win.screen.search_filter(quote(text)) win.show() return self.focus_out = True self.changed = True def sig_key_press(self, widget, event, *args): editable = self.wid_text.get_editable() activate_keys = [gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab] if not self.wid_completion: activate_keys.append(gtk.keysyms.Return) if (event.keyval == gtk.keysyms.F3 and editable and self.create_access): self.sig_new(widget, event) return True elif event.keyval == gtk.keysyms.F2 and self.read_access: self.sig_edit(widget) return True elif (event.keyval in activate_keys and editable): self.sig_activate() elif (self.has_target(self.field.get(self.record)) and editable and event.keyval in (gtk.keysyms.Delete, gtk.keysyms.BackSpace)): self.set_text('') return False def sig_changed(self, *args): if not self.changed: return False value = self.field.get(self.record) if self.has_target(value) and self.modified: def clean(): if not self.wid_text.props.window: return text = self.wid_text.get_text() position = self.wid_text.get_position() self.field.set_client(self.record, self.value_from_id(None, '')) # The value of the field could be different of None # in such case, the original text should not be restored if not self.wid_text.get_text(): # Restore text and position after display self.set_text(text) self.wid_text.set_position(position) gobject.idle_add(clean) return False def get_value(self): return self.wid_text.get_text() def set_value(self, record, field): if field.get_client(record) != self.wid_text.get_text(): field.set_client(record, self.value_from_id(None, '')) self.set_text('') def set_text(self, value): if not value: value = '' self.wid_text.set_text(value) reset_position(self.wid_text) def display(self, record, field): self.changed = False super(Many2One, self).display(record, field) self._set_button_sensitive() self._set_completion() if not field: self.set_text('') self.changed = True return False self.set_text(field.get_client(record)) if self.has_target(field.get(record)): stock1, tooltip1 = 'tryton-open', _('Open the record ') stock2, tooltip2 = 'tryton-clear', _('Clear the record ') else: stock1, tooltip1 = None, '' stock2, tooltip2 = 'tryton-find', _('Search a record ') if not self.wid_text.get_editable(): stock2, tooltip2 = None, '' for pos, stock, tooltip in [(gtk.ENTRY_ICON_PRIMARY, stock1, tooltip1), (gtk.ENTRY_ICON_SECONDARY, stock2, tooltip2)]: self.wid_text.set_icon_from_stock(pos, stock) self.wid_text.set_icon_tooltip_text(pos, tooltip) self.changed = True def _populate_popup(self, widget, menu): value = self.field.get(self.record) if self.has_target(value): # Delay filling of popup as it can take time gobject.idle_add(populate, menu, self.get_model(), self.id_from_value(value), '', self.field) return True def _set_completion(self): if not int(self.attrs.get('completion', 1)): return self.wid_completion = get_completion( search=self.read_access, create=self.create_access) self.wid_completion.connect('match-selected', self._completion_match_selected) self.wid_completion.connect('action-activated', self._completion_action_activated) self.wid_text.set_completion(self.wid_completion) def _completion_match_selected(self, completion, model, iter_): rec_name, record_id = model.get(iter_, 0, 1) # GTK on win32 doesn't like synchronous call to set_client # because it triggers a display which reset the completion gobject.idle_add(self.field.set_client, self.record, self.value_from_id(record_id, rec_name), True) completion_model = self.wid_completion.get_model() completion_model.clear() completion_model.search_text = rec_name return True def _update_completion(self, widget): if self._readonly: return if not self.record: return value = self.field.get(self.record) if self.has_target(value): id_ = self.id_from_value(value) if id_ is not None and id_ >= 0: return model = self.get_model() update_completion(self.wid_text, self.record, self.field, model) def _completion_action_activated(self, completion, index): if index == 0: self.sig_edit() elif index == 1: self.sig_new() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/multiselection.py0000644000175000017500000000733713251060075026231 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of this # repository contains the full copyright notices and license terms. import gtk import gobject from .widget import Widget from tryton.common.selection import SelectionMixin from tryton.common.treeviewcontrol import TreeViewControl from tryton.common.widget_style import set_widget_style class MultiSelection(Widget, SelectionMixin): expand = True def __init__(self, view, attrs): super(MultiSelection, self).__init__(view, attrs) if int(attrs.get('yexpand', self.expand)): self.widget = gtk.ScrolledWindow() self.widget.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.widget.set_shadow_type(gtk.SHADOW_ETCHED_IN) else: self.widget = gtk.VBox() self.widget.get_accessible().set_name(attrs.get('string', '')) self.model = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING) self.tree = TreeViewControl() self.tree.set_model(self.model) self.tree.set_search_column(1) self.tree.connect('focus-out-event', lambda *a: self._focus_out()) self.tree.set_headers_visible(False) selection = self.tree.get_selection() selection.set_mode(gtk.SELECTION_MULTIPLE) selection.connect('changed', self.changed) self.widget.add(self.tree) name_column = gtk.TreeViewColumn() name_cell = gtk.CellRendererText() name_column.pack_start(name_cell) name_column.add_attribute(name_cell, 'text', 1) self.tree.append_column(name_column) self.nullable_widget = False self.init_selection() self.id2path = {} def _readonly_set(self, readonly): super(MultiSelection, self)._readonly_set(readonly) set_widget_style(self.tree, not readonly) selection = self.tree.get_selection() selection.set_select_function(lambda *a: not readonly) @property def modified(self): if self.record and self.field: group = set(r.id for r in self.field.get_client(self.record)) value = set(self.get_value()) return value != group return False def changed(self, selection): def focus_out(): if self.widget.props.window: self._focus_out() # Must be deferred because it triggers a display of the form gobject.idle_add(focus_out) def get_value(self): model, paths = self.tree.get_selection().get_selected_rows() return [model[path][0] for path in paths] def set_value(self, record, field): field.set_client(record, self.get_value()) def display(self, record, field): selection = self.tree.get_selection() selection.handler_block_by_func(self.changed) try: # Remove select_function to allow update, # it will be set back in the super call selection.set_select_function(lambda *a: True) self.update_selection(record, field) self.model.clear() if field is None: return id2path = {} for idx, (value, name) in enumerate(self.selection): self.model.append((value, name)) id2path[value] = idx selection.unselect_all() group = field.get_client(record) for element in group: if (element not in group.record_removed and element not in group.record_deleted and element.id in id2path): selection.select_path(id2path[element.id]) super(MultiSelection, self).display(record, field) finally: selection.handler_unblock_by_func(self.changed) tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/widget.py0000644000175000017500000002353613255571102024455 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import gettext import tryton.common as common from tryton.gui.window.nomodal import NoModal from tryton.common import TRYTON_ICON from tryton.common import RPCExecute, RPCException from tryton.common.widget_style import widget_class _ = gettext.gettext class Widget(object): expand = False def __init__(self, view, attrs): super(Widget, self).__init__() self.view = view self.attrs = attrs self.widget = None self.mnemonic_widget = None self.visible = True self._readonly = False @property def field_name(self): return self.attrs['name'] @property def model_name(self): return self.view.screen.model_name @property def record(self): return self.view.screen.current_record @property def field(self): if self.record: return self.record.group.fields[self.field_name] def destroy(self): pass def sig_activate(self, widget=None): # emulate a focus_out so that the onchange is called if needed self._focus_out() def _readonly_set(self, readonly): self._readonly = readonly def _required_set(self, required): pass def _invisible_widget(self): return self.widget @property def modified(self): return False def send_modified(self, *args): def send(value): if not self.widget.props.window: return if self.record and self.get_value() == value: self.record.signal('record-modified') def get_value(): if not self.widget.props.window: return gobject.timeout_add(300, send, self.get_value()) # Wait the current event is finished to retreive the value gobject.idle_add(get_value) return False def invisible_set(self, value): widget = self._invisible_widget() if value and value != '0': self.visible = False widget.hide() else: self.visible = True widget.show() def _focus_out(self): if not self.field: return False if not self.visible: return False self.set_value(self.record, self.field) def display(self, record, field): if not field: self._readonly_set(self.attrs.get('readonly', True)) self.invisible_set(self.attrs.get('invisible', False)) self._required_set(False) return states = field.get_state_attrs(record) readonly = self.attrs.get('readonly', states.get('readonly', False)) if self.view.screen.readonly: readonly = True self._readonly_set(readonly) widget_class(self.widget, 'readonly', readonly) self._required_set(not readonly and states.get('required', False)) widget_class( self.widget, 'required', not readonly and states.get('required', False)) invalid = states.get('invalid', False) widget_class(self.widget, 'invalid', not readonly and invalid) self.invisible_set(self.attrs.get( 'invisible', states.get('invisible', False))) def set_value(self, record, field): pass class TranslateDialog(NoModal): def __init__(self, widget, languages, readonly): NoModal.__init__(self) self.widget = widget self.win = gtk.Dialog(_('Translation'), self.parent, gtk.DIALOG_DESTROY_WITH_PARENT) self.win.set_position(gtk.WIN_POS_CENTER_ON_PARENT) self.win.set_icon(TRYTON_ICON) self.win.connect('response', self.response) self.accel_group = gtk.AccelGroup() self.win.add_accel_group(self.accel_group) self.win.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL) self.win.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK).add_accelerator( 'clicked', self.accel_group, gtk.keysyms.Return, gtk.gdk.CONTROL_MASK, gtk.ACCEL_VISIBLE) tooltips = common.Tooltips() self.widgets = {} table = gtk.Table(len(languages), 4) table.set_homogeneous(False) table.set_col_spacings(3) table.set_row_spacings(2) table.set_border_width(1) for i, language in enumerate(languages): if gtk.widget_get_default_direction() == gtk.TEXT_DIR_RTL: label = _(':') + language['name'] else: label = language['name'] + _(':') label = gtk.Label(label) label.set_alignment(1.0, 0.0 if self.widget.expand else 0.5) table.attach(label, 0, 1, i, i + 1, xoptions=gtk.FILL) context = dict( language=language['code'], fuzzy_translation=False, ) try: value = RPCExecute('model', self.widget.record.model_name, 'read', [self.widget.record.id], [self.widget.field_name], context={'language': language['code']} )[0][self.widget.field_name] except RPCException: return context['fuzzy_translation'] = True try: fuzzy_value = RPCExecute('model', self.widget.record.model_name, 'read', [self.widget.record.id], [self.widget.field_name], context=context)[0][self.widget.field_name] except RPCException: return widget = self.widget.translate_widget() label.set_mnemonic_widget(widget) self.widget.translate_widget_set(widget, fuzzy_value) self.widget.translate_widget_set_readonly(widget, True) yopt = 0 if self.widget.expand: yopt = gtk.EXPAND | gtk.FILL table.attach(widget, 1, 2, i, i + 1, yoptions=yopt) editing = gtk.CheckButton() editing.connect('toggled', self.editing_toggled, widget) editing.props.sensitive = not readonly tooltips.set_tip(editing, _('Edit')) table.attach(editing, 2, 3, i, i + 1, xoptions=gtk.FILL) fuzzy = gtk.CheckButton() fuzzy.set_active(value != fuzzy_value) fuzzy.props.sensitive = False tooltips.set_tip(fuzzy, _('Fuzzy')) table.attach(fuzzy, 4, 5, i, i + 1, xoptions=gtk.FILL) self.widgets[language['code']] = (widget, editing, fuzzy) tooltips.enable() vbox = gtk.VBox() vbox.pack_start(table, self.widget.expand, True) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) viewport.add(vbox) scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) scrolledwindow.add(viewport) self.win.vbox.pack_start(scrolledwindow, True, True) sensible_allocation = self.sensible_widget.get_allocation() self.win.set_default_size(int(sensible_allocation.width * 0.9), int(sensible_allocation.height * 0.9)) self.register() self.win.show_all() common.center_window(self.win, self.parent, self.sensible_widget) def editing_toggled(self, editing, widget): self.widget.translate_widget_set_readonly(widget, not editing.get_active()) def response(self, win, response): if response == gtk.RESPONSE_OK: for code, widget in self.widgets.iteritems(): widget, editing, fuzzy = widget if not editing.get_active(): continue value = self.widget.translate_widget_get(widget) context = dict( language=code, fuzzy_translation=False, ) try: RPCExecute('model', self.widget.record.model_name, 'write', [self.widget.record.id], { self.widget.field_name: value, }, context=context) except RPCException: pass self.widget.record.cancel() self.widget.view.display() self.destroy() def destroy(self): self.win.destroy() NoModal.destroy(self) class TranslateMixin: def translate_button(self): button = gtk.Button() img = gtk.Image() img.set_from_stock('tryton-locale', gtk.ICON_SIZE_SMALL_TOOLBAR) button.set_image(img) button.set_relief(gtk.RELIEF_NONE) button.connect('clicked', self.translate) return button def translate(self, *args): self.view.set_value() if self.record.id < 0 or self.record.modified: common.message( _('You need to save the record before adding translations.')) return try: lang_ids = RPCExecute('model', 'ir.lang', 'search', [ ('translatable', '=', True), ]) except RPCException: return if not lang_ids: common.message(_('No other language available.')) return try: languages = RPCExecute('model', 'ir.lang', 'read', lang_ids, ['code', 'name']) except RPCException: return TranslateDialog(self, languages, self._readonly) def translate_widget(self): raise NotImplemented @staticmethod def translate_widget_set(widget, value): raise NotImplemented @staticmethod def translate_widget_get(widget): raise NotImplemented @staticmethod def translate_widget_set_readonly(widget, value): raise NotImplemented tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/timedelta.py0000644000175000017500000000352113251060075025130 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk from tryton.config import CONFIG from tryton.common.entry_position import reset_position from tryton.common.widget_style import set_widget_style from .widget import Widget class TimeDelta(Widget): def __init__(self, view, attrs): super(TimeDelta, self).__init__(view, attrs) self.widget = gtk.HBox() self.entry = self.mnemonic_widget = gtk.Entry() self.entry.set_alignment(1.0) self.entry.set_property('activates_default', True) self.entry.connect('activate', self.sig_activate) self.entry.connect('focus-out-event', lambda x, y: self._focus_out()) self.entry.connect('key-press-event', self.send_modified) self.widget.pack_start(self.entry) @property def modified(self): if self.record and self.field: value = self.entry.get_text() return self.field.get_client(self.record) != value return False def set_value(self, record, field): value = self.entry.get_text() return field.set_client(record, value) def get_value(self): return self.entry.get_text() def display(self, record, field): super(TimeDelta, self).display(record, field) if not field: value = '' else: value = field.get_client(record) self.entry.set_text(value) reset_position(self.entry) def _readonly_set(self, value): super(TimeDelta, self)._readonly_set(value) self.entry.set_editable(not value) set_widget_style(self.entry, not value) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() tryton-4.6.5/tryton/gui/window/view_form/view/form_gtk/binary.py0000644000175000017500000001747513255571102024463 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import os import tempfile from tryton.common import common from tryton.common import file_selection, Tooltips, file_open, slugify from tryton.common.entry_position import reset_position from tryton.common.widget_style import set_widget_style from tryton.config import CONFIG from .widget import Widget _ = gettext.gettext class BinaryMixin(Widget): def __init__(self, view, attrs): super(BinaryMixin, self).__init__(view, attrs) self.filename = attrs.get('filename') def toolbar(self): 'Return HBox with the toolbar' hbox = gtk.HBox(spacing=0) tooltips = Tooltips() self.but_save_as = gtk.Button() img_save_as = gtk.Image() img_save_as.set_from_stock('tryton-save-as', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_save_as.set_image(img_save_as) self.but_save_as.set_relief(gtk.RELIEF_NONE) self.but_save_as.connect('clicked', self.save_as) tooltips.set_tip(self.but_save_as, _('Save As...')) hbox.pack_start(self.but_save_as, expand=False, fill=False) self.but_select = gtk.Button() img_select = gtk.Image() img_select.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_select.set_image(img_select) self.but_select.set_relief(gtk.RELIEF_NONE) self.but_select.connect('clicked', self.select) tooltips.set_tip(self.but_select, _('Select...')) hbox.pack_start(self.but_select, expand=False, fill=False) self.but_clear = gtk.Button() img_clear = gtk.Image() img_clear.set_from_stock('tryton-clear', gtk.ICON_SIZE_SMALL_TOOLBAR) self.but_clear.set_image(img_clear) self.but_clear.set_relief(gtk.RELIEF_NONE) self.but_clear.connect('clicked', self.clear) tooltips.set_tip(self.but_clear, _('Clear')) hbox.pack_start(self.but_clear, expand=False, fill=False) tooltips.enable() return hbox @property def filename_field(self): return self.record.group.fields.get(self.filename) @property def filters(self): filter_all = gtk.FileFilter() filter_all.set_name(_('All files')) filter_all.add_pattern("*") return [filter_all] @property def preview(self): return False def update_buttons(self, value): if value: self.but_save_as.show() self.but_select.hide() self.but_clear.show() else: self.but_save_as.hide() self.but_select.show() self.but_clear.hide() def select(self, widget=None): if not self.field: return filters = self.filters filename = file_selection(_('Select'), preview=self.preview, filters=filters) if filename: self.field.set_client(self.record, open(filename, 'rb').read()) if self.filename_field: self.filename_field.set_client(self.record, os.path.basename(filename)) def open_(self, widget=None): if not self.filename_field: return filename = self.filename_field.get(self.record) if not filename: return dtemp = tempfile.mkdtemp(prefix='tryton_') root, ext = os.path.splitext(filename) filename = ''.join([slugify(root), os.extsep, slugify(ext)]) file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: if hasattr(self.field, 'get_data'): fp.write(self.field.get_data(self.record)) else: fp.write(self.field.get(self.record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def save_as(self, widget=None): filename = '' if self.filename_field: filename = self.filename_field.get(self.record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: if hasattr(self.field, 'get_data'): fp.write(self.field.get_data(self.record)) else: fp.write(self.field.get(self.record)) def clear(self, widget=None): if self.filename_field: self.filename_field.set_client(self.record, None) self.field.set_client(self.record, None) class Binary(BinaryMixin, Widget): "Binary" def __init__(self, view, attrs): super(Binary, self).__init__(view, attrs) self.widget = gtk.HBox(spacing=0) self.wid_size = gtk.Entry() self.wid_size.set_width_chars(10) self.wid_size.set_alignment(1.0) self.wid_size.props.sensitive = False if self.filename and attrs.get('filename_visible'): self.wid_text = gtk.Entry() self.wid_text.set_property('activates_default', True) self.wid_text.connect('focus-out-event', lambda x, y: self._focus_out()) self.wid_text.connect_after('key_press_event', self.sig_key_press) self.wid_text.connect('icon-press', self.sig_icon_press) self.widget.pack_start(self.wid_text, expand=True, fill=True) else: self.wid_text = None self.mnemonic_widget = self.wid_text self.widget.pack_start(self.wid_size, expand=not self.filename, fill=True) self.widget.pack_start(self.toolbar(), expand=False, fill=False) def _readonly_set(self, value): self.but_select.set_sensitive(not value) self.but_clear.set_sensitive(not value) if self.wid_text: self.wid_text.set_editable(not value) set_widget_style(self.wid_text, not value) if value and CONFIG['client.fast_tabbing']: self.widget.set_focus_chain([]) else: self.widget.unset_focus_chain() def sig_key_press(self, widget, event, *args): editable = self.wid_text and self.wid_text.get_editable() if event.keyval == gtk.keysyms.F3 and editable: self.sig_new(widget) return True elif event.keyval == gtk.keysyms.F2: if self.filename: self.sig_open(widget) else: self.sig_save_as(widget) return True return False def sig_icon_press(self, widget, icon_pos, event): if icon_pos == gtk.ENTRY_ICON_PRIMARY: self.open_() def display(self, record, field): super(Binary, self).display(record, field) if not field: if self.wid_text: self.wid_text.set_text('') self.wid_size.set_text('') self.but_save_as.hide() return False if hasattr(field, 'get_size'): size = field.get_size(record) else: size = len(field.get(record)) self.wid_size.set_text(common.humanize(size or 0)) reset_position(self.wid_size) if self.wid_text: self.wid_text.set_text(self.filename_field.get(record) or '') reset_position(self.wid_text) if size: stock, tooltip = 'tryton-open', _("Open...") else: stock, tooltip = None, '' pos = gtk.ENTRY_ICON_PRIMARY self.wid_text.set_icon_from_stock(pos, stock) self.wid_text.set_icon_tooltip_text(pos, tooltip) self.update_buttons(bool(size)) return True def set_value(self, record, field): if self.wid_text: self.filename_field.set_client(self.record, self.wid_text.get_text() or False) return tryton-4.6.5/tryton/gui/window/view_form/view/graph.py0000644000175000017500000001301113251060075022444 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import sys import gtk import gettext from . import View from tryton.common import node_attributes, get_toplevel_window, message from tryton.common import file_selection from tryton.config import TRYTON_ICON from .graph_gtk.bar import VerticalBar, HorizontalBar from .graph_gtk.line import Line from .graph_gtk.pie import Pie _ = gettext.gettext class ViewGraph(View): def __init__(self, screen, xml): super(ViewGraph, self).__init__(screen, xml) self.view_type = 'graph' self.widgets = {} self.widget = self.parse(xml) def parse(self, node): xfield = None yfields = [] for node in node.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.tagName == 'x': for child in node.childNodes: if not child.nodeType == child.ELEMENT_NODE: continue xfield = node_attributes(child) field = self.screen.group.fields[xfield['name']] if not xfield.get('string'): xfield['string'] = field.attrs['string'] elif node.tagName == 'y': for child in node.childNodes: if not child.nodeType == child.ELEMENT_NODE: continue yattrs = node_attributes(child) if not yattrs.get('string') and yattrs['name'] != '#': field = self.screen.group.fields[yattrs['name']] yattrs['string'] = field.attrs['string'] yfields.append(yattrs) Widget = self.get_widget(self.attributes.get('type', 'vbar')) widget = Widget(self, xfield, yfields) self.widgets['root'] = widget event = gtk.EventBox() event.add(widget) event.connect('button-press-event', self.button_press) return event WIDGETS = { 'vbar': VerticalBar, 'hbar': HorizontalBar, 'line': Line, 'pie': Pie, } @classmethod def get_widget(cls, name): return cls.WIDGETS[name] def __getitem__(self, name): return None def destroy(self): self.widget.destroy() self.widgets['root'].destroy() self.widgets.clear() def set_value(self): pass def reset(self): pass def display(self): self.widgets['root'].display(self.screen.group) return True def set_cursor(self, new=False, reset_view=True): pass def get_fields(self): return [] def get_buttons(self): return [] def save(self, widget): parent = get_toplevel_window() dia = gtk.Dialog(_('Image Size'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) dia.set_icon(TRYTON_ICON) dia.set_default_response(gtk.RESPONSE_OK) hbox = gtk.HBox(spacing=3) dia.vbox.pack_start(hbox, False, True) hbox.pack_start(gtk.Label(_('Width:')), False, True) spinwidth = gtk.SpinButton() spinwidth.configure(gtk.Adjustment(400.0, 0.0, sys.maxint, 1.0, 10.0), climb_rate=1, digits=0) spinwidth.set_numeric(True) spinwidth.set_activates_default(True) hbox.pack_start(spinwidth, True, True) hbox.pack_start(gtk.Label(_('Height:')), False, True) spinheight = gtk.SpinButton() spinheight.configure(gtk.Adjustment(200.0, 0.0, sys.maxint, 1.0, 10.0), climb_rate=1, digits=0) spinheight.set_numeric(True) spinheight.set_activates_default(True) hbox.pack_start(spinheight, True, True) dia.show_all() filter = gtk.FileFilter() filter.set_name(_('PNG image (*.png)')) filter.add_mime_type('image/png') filter.add_pattern('*.png') while True: response = dia.run() width = spinwidth.get_value_as_int() height = spinheight.get_value_as_int() if response == gtk.RESPONSE_OK: filename = file_selection(_('Save As'), action=gtk.FILE_CHOOSER_ACTION_SAVE, preview=False, filters=[filter]) if width and height and filename: if not filename.endswith('.png'): filename = filename + '.png' try: self.widgets['root'].export_png( filename, width, height) break except MemoryError: message(_('Image size too large.'), dia, gtk.MESSAGE_ERROR) else: break parent.present() dia.destroy() def button_press(self, widget, event): if event.button == 3: menu = gtk.Menu() item = gtk.ImageMenuItem(_('Save As...')) img = gtk.Image() img.set_from_stock('tryton-save-as', gtk.ICON_SIZE_MENU) item.set_image(img) item.connect('activate', self.save) item.show() menu.append(item) menu.popup(None, None, None, event.button, event.time) return True elif event.button == 1: self.widgets['root'].action() tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/0000755000175000017500000000000013260723567022757 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/line.py0000644000175000017500000002407013251060075024247 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # This code is inspired by the pycha project # (http://www.lorenzogil.com/projects/pycha/) import locale import math import datetime import cairo from graph import Graph import tryton.common as common import tryton.rpc as rpc class Line(Graph): def updateGraph(self): yfield2attrs = {} for yfield in self.yfields: yfield2attrs[yfield.get('key', yfield['name'])] = yfield self.points = [] i = 0 keys = self.datas.keys() keys.sort() for xfield in keys: j = 0 for yfield in self.datas[xfield]: xval = i yval = self.datas[xfield][yfield] x = (xval - self.minxval) * self.xscale y = 1.0 - (yval - self.minyval) * self.yscale if self.xrange == 0: x = 1.0 if (not bool(int(yfield2attrs[yfield].get('empty', 1))) and yval == 0): continue point = Point(x, y, xval, yval, xfield, yfield) if (0.0 <= point.x <= 1.0) and (0.0 <= point.y <= 1.0): self.points.append(point) j += 1 i += 1 def drawGraph(self, cr, width, height): key2fill = {} key2interpolation = {} for yfield in self.yfields: key = yfield.get('key', yfield['name']) key2fill[key] = bool(int(yfield.get('fill', 0))) key2interpolation[key] = yfield.get('interpolation', 'linear') def preparePath(key): interpolation = key2interpolation[key] points = (p for p in self.points if p.yname == key) zero = 1.0 + self.minyval * self.yscale cr.new_path() cr.move_to(self.area.x, zero * self.area.h + self.area.y) if interpolation == 'linear': for point in points: cr.line_to(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y) else: previous = Point(0, zero, None, None, None, None) def breakage(previous, point): if interpolation == 'constant-center': return previous.x + ((point.x - previous.x) / 2.0) elif interpolation == 'constant-left': return point.x elif interpolation == 'constant-right': return previous.x for point in points: cr.line_to( breakage(previous, point) * self.area.w + self.area.x, previous.y * self.area.h + self.area.y) cr.line_to( breakage(previous, point) * self.area.w + self.area.x, point.y * self.area.h + self.area.y) cr.line_to(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y) previous = point cr.line_to(breakage(previous, Point(1, zero, None, None, None, None)) * self.area.w + self.area.x, previous.y * self.area.h + self.area.y) cr.line_to(self.area.w + self.area.x, zero * self.area.h + self.area.y) cr.move_to(self.area.x, zero * self.area.h + self.area.y) if key2fill[key]: cr.close_path() else: cr.set_source_rgb(*self.colorScheme[key]) cr.stroke() cr.save() cr.set_line_width(2) if self._getDatasKeys(): transparency = 0.8 / len(self._getDatasKeys()) for key in self._getDatasKeys(): if key2fill[key]: cr.save() r, g, b = self.colorScheme[key] preparePath(key) cr.set_source_rgb(r, g, b) cr.stroke_preserve() cr.restore() # Add soft transparency the area when line is filled cr.set_source_rgba(r, g, b, transparency) cr.fill() # Add gradient top to bottom linear = cairo.LinearGradient( width / 2, 0, width / 2, height) linear.add_color_stop_rgba( 0, r * 0.65, g * 0.65, b * 0.65, transparency) linear.add_color_stop_rgba(1, r, g, b, 0.1) cr.set_source(linear) preparePath(key) cr.fill() else: preparePath(key) for point in self.points: cr.set_source_rgb(*self.colorScheme[point.yname]) cr.move_to(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y) cr.arc(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y, 3, 0, 2 * math.pi) cr.fill() cr.restore() def drawLegend(self, cr, widht, height): super(Line, self).drawLegend(cr, widht, height) cr.save() for point in self.points: if point.highlight: cr.set_line_width(2) cr.set_source_rgb(*common.hex2rgb('#000000')) cr.move_to(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y) cr.arc(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y, 3, 0, 2 * math.pi) cr.stroke() cr.set_source_rgb(*common.highlight_rgb( *self.colorScheme[point.yname])) cr.arc(point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y, 3, 0, 2 * math.pi) cr.fill() cr.restore() def motion(self, widget, event): if not getattr(self, 'area', None): return nearest = None for point in self.points: x = point.x * self.area.w + self.area.x y = point.y * self.area.h + self.area.y l = (event.x - x) ** 2 + (event.y - y) ** 2 if not nearest or l < nearest[1]: nearest = (point, l) dia = self.area.w ** 2 + self.area.h ** 2 keys2txt = {} for yfield in self.yfields: keys2txt[yfield.get('key', yfield['name'])] = yfield['string'] highlight = False draw_points = [] yfields_timedelta = {x.get('key', x['name']): x.get('timedelta') for x in self.yfields if 'timedelta' in x} for point in self.points: if point == nearest[0] and nearest[1] < dia / 100: if not point.highlight: point.highlight = True label = keys2txt[point.yname] label += '\n' if point.yval in yfields_timedelta: converter = None if yfields_timedelta[point.yname]: converter = rpc.CONTEXT.get( yfields_timedelta[point.yname]) label += common.timedelta.format(point.yval, converter) else: label += locale.format('%.2f', point.yval, True) label += '\n' label += str(self.labels[point.xname]) self.popup.set_text(label) draw_points.append(point) else: if point.highlight: point.highlight = False draw_points.append(point) if point.highlight: self.popup.set_position(self, point.x * self.area.w + self.area.x, point.y * self.area.h + self.area.y) highlight = True if highlight: self.popup.show() else: self.popup.hide() if draw_points: minx = self.area.w + self.area.x miny = self.area.h + self.area.y maxx = maxy = 0.0 for point in draw_points: x = self.area.w * point.x + self.area.x y = self.area.h * point.y + self.area.y minx = min(x - 5, minx) miny = min(y - 5, miny) maxx = max(x + 5, maxx) maxy = max(y + 5, maxy) self.queue_draw_area(int(minx - 1), int(miny - 1), int(maxx - minx + 1), int(maxy - miny + 1)) def updateXY(self): super(Line, self).updateXY() if self.xrange != 0: self.xrange -= 1 if self.xrange == 0: self.xscale = 1.0 else: self.xscale = 1.0 / self.xrange def drawAxis(self, cr, width, height): super(Line, self).drawAxis(cr, width, height) self.drawLine(cr, 1.0, 0) def action(self): super(Line, self).action() for point in self.points: if point.highlight: ids = self.ids[point.xname] self.action_keyword(ids) def YLabels(self): ylabels = super(Line, self).YLabels() if all('timedelta' in f for f in self.yfields): converter = {f.get('timedelta') for f in self.yfields} if len(converter) == 1: converter = rpc.CONTEXT.get(converter.pop()) return [ (x[0], common.timedelta.format( datetime.timedelta(seconds=locale.atof(x[1])), converter)) for x in ylabels] return ylabels class Point(object): def __init__(self, x, y, xval, yval, xname, yname): self.x, self.y = x, y self.xval, self.yval = xval, yval self.xname = xname self.yname = yname self.highlight = False tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/bar.py0000644000175000017500000002077213251060075024071 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # This code is inspired by the pycha project # (http://www.lorenzogil.com/projects/pycha/) import locale import math import datetime import cairo from graph import Graph import tryton.common as common import tryton.rpc as rpc class Bar(Graph): def __init__(self, *args, **kwargs): super(Bar, self).__init__(*args, **kwargs) self.bars = [] def drawGraph(self, cr, width, height): def drawBar(bar): cr.set_line_width(0.5) x = self.area.w * bar.x + self.area.x y = self.area.h * bar.y + self.area.y w = self.area.w * bar.w h = self.area.h * bar.h if w < 1 or h < 1: return # don't draw too small self.drawRectangle(cr, x, y, w, h) r, g, b = self.colorScheme[bar.yname] if bar.highlight: r, g, b = common.highlight_rgb(r, g, b) cr.set_source(self.sourceRectangle(x, y, w, h, r, g, b)) cr.fill_preserve() cr.stroke() cr.save() for bar in self.bars: drawBar(bar) cr.restore() def drawRectangle(self, cr, x, y, w, h): radius = 2.5 cr.arc(x + radius, y + radius, radius, 0, 2 * math.pi) cr.arc(x + w - radius, y + radius, radius, 0, 2 * math.pi) cr.arc(x + w - radius, y + h - radius, radius, 0, 2 * math.pi) cr.arc(x + radius, y + h - radius, radius, 0, 2 * math.pi) cr.rectangle(x + radius, y, w - radius * 2, h) cr.rectangle(x, y + radius, w, h - radius * 2) def sourceRectangle(self, x, y, w, h, r, g, b): linear = cairo.LinearGradient((x + w) / 2, y, (x + w) / 2, y + h) linear.add_color_stop_rgb(0, 3.5 * r / 5.0, 3.5 * g / 5.0, 3.5 * b / 5.0) linear.add_color_stop_rgb(1, r, g, b) return linear def motion(self, widget, event): super(Bar, self).motion(widget, event) if not getattr(self, 'area', None): return def intersect(bar, event): x = self.area.w * bar.x + self.area.x y = self.area.h * bar.y + self.area.y w = self.area.w * bar.w h = self.area.h * bar.h if x <= event.x <= x + w and y <= event.y <= y + h: return True return False highlight = False draw_bars = [] yfields_timedelta = {x.get('key', x['name']): x.get('timedelta') for x in self.yfields if 'timedelta' in x} for bar in self.bars: if intersect(bar, event): if not bar.highlight: bar.highlight = True if bar.yname in yfields_timedelta: converter = None if yfields_timedelta[bar.yname]: converter = rpc.CONTEXT.get( yfields_timedelta[bar.yname]) label = common.timedelta.format( datetime.timedelta(seconds=bar.yval), converter) else: label = locale.format('%.2f', bar.yval, True) label += '\n' label += str(self.labels[bar.xname]) self.popup.set_text(label) draw_bars.append(bar) else: if bar.highlight: bar.highlight = False draw_bars.append(bar) if bar.highlight: highlight = True if highlight: self.popup.show() else: self.popup.hide() if draw_bars: minx = self.area.w + self.area.x miny = self.area.h + self.area.y maxx = maxy = 0.0 for bar in draw_bars: x = self.area.w * bar.x + self.area.x y = self.area.h * bar.y + self.area.y minx = int(min(x, minx)) miny = int(min(y, miny)) maxx = int(max(x + self.area.w * bar.w, maxx)) maxy = int(max(y + self.area.h * bar.h, maxy)) self.queue_draw_area(minx - 1, miny - 1, maxx - minx + 2, maxy - miny + 2) def action(self): super(Bar, self).action() for bar in self.bars: if bar.highlight: ids = self.ids[bar.xname] self.action_keyword(ids) class VerticalBar(Bar): 'Vertical Bar Graph' def updateGraph(self): barWidth = self.xscale * 0.9 barMargin = self.xscale * (1.0 - 0.9) / 2 self.bars = [] i = 0 keys = self.datas.keys() keys.sort() for xfield in keys: j = 0 barWidthForSet = barWidth / len(self.datas[xfield]) for yfield in self._getDatasKeys(): xval = i yval = self.datas[xfield][yfield] x = (xval - self.minxval) * self.xscale + \ barMargin + (j * barWidthForSet) y = 1.0 - (yval - self.minyval) * self.yscale w = barWidthForSet h = yval * self.yscale if h < 0: h = abs(h) y -= h rect = Rect(x, y, w, h, xval, yval, xfield, yfield) if (0.0 <= rect.x <= 1.0) and (0.0 <= rect.y <= 1.0): self.bars.append(rect) j += 1 i += 1 def XLabels(self): xlabels = super(VerticalBar, self).XLabels() return [(x[0] + (self.xscale / 2), x[1]) for x in xlabels] def YLabels(self): ylabels = super(VerticalBar, self).YLabels() if all('timedelta' in f for f in self.yfields): converter = {f.get('timedelta') for f in self.yfields} if len(converter) == 1: converter = rpc.CONTEXT.get(converter.pop()) else: converter = None return [ (x[0], common.timedelta.format( datetime.timedelta(seconds=locale.atof(x[1])), converter)) for x in ylabels] return ylabels class HorizontalBar(Bar): 'Horizontal Bar Graph' def updateGraph(self): barWidth = self.xscale * 0.9 barMargin = self.xscale * (1.0 - 0.9) / 2 self.bars = [] i = 0 keys = self.datas.keys() keys.sort() for xfield in keys: j = 0 barWidthForSet = barWidth / len(self.datas[xfield]) for yfield in self._getDatasKeys(): xval = i yval = self.datas[xfield][yfield] x = - self.minyval * self.yscale y = (xval - self.minxval) * self.xscale + \ barMargin + (j * barWidthForSet) w = yval * self.yscale h = barWidthForSet if w < 0: w = abs(w) x -= w rect = Rect(x, y, w, h, xval, yval, xfield, yfield) if (0.0 <= rect.x <= 1.0) and (0.0 <= rect.y <= 1.0): self.bars.append(rect) j += 1 i += 1 def YLabels(self): xlabels = super(HorizontalBar, self).XLabels() return [(1 - (x[0] + (self.xscale / 2)), x[1]) for x in xlabels] def XLabels(self): ylabels = super(HorizontalBar, self).YLabels() if all('timedelta' in f for f in self.yfields): converter = {f.get('timedelta') for f in self.yfields} if len(converter) == 1: converter = rpc.CONTEXT.get(converter.pop()) else: converter = None return [ (x[0], common.timedelta.format( datetime.timedelta(seconds=locale.atof(x[1])), converter)) for x in ylabels] return [(x[0], x[1]) for x in ylabels] def _getLegendPosition(self, width, height): return self.area.x + self.area.w * 0.95 - width, \ self.area.y + self.area.h * 0.05 def drawLines(self, cr, width, height): for w, label in self.XLabels(): self.drawLine(cr, w, 0) class Rect(object): def __init__(self, x, y, w, h, xval, yval, xname, yname): self.x, self.y, self.w, self.h = x, y, w, h self.xval, self.yval = xval, yval self.yname = yname self.xname = xname self.highlight = False tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/pie.py0000644000175000017500000001601713175640533024107 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # This code is inspired by the pycha project # (http://www.lorenzogil.com/projects/pycha/) import math import locale import datetime import cairo from graph import Graph, Area import tryton.common as common import tryton.rpc as rpc class Pie(Graph): def _getDatasKeys(self): return self.datas.keys() def drawLegend(self, cr, width, height): pass def drawAxis(self, cr, width, height): cr.set_source_rgb(*common.hex2rgb('#000000')) for slice in self.slices: normalisedAngle = slice.normalisedAngle() labelx = self.centerx + \ math.sin(normalisedAngle) * (self.radius + 10) labely = self.centery - \ math.cos(normalisedAngle) * (self.radius + 10) label = '%s (%s%%)' % (self.labels[slice.xname], locale.format('%.2f', slice.fraction * 100)) extents = cr.text_extents(label) labelWidth = extents[2] labelHeight = extents[3] x = y = 0 if normalisedAngle <= math.pi * 0.5: x = labelx y = labely - labelHeight elif math.pi / 2 < normalisedAngle <= math.pi: x = labelx y = labely elif math.pi < normalisedAngle <= math.pi * 1.5: x = labelx - labelWidth y = labely else: x = labelx - labelWidth y = labely - labelHeight cr.move_to(x, y) cr.show_text(label) def drawLines(self, cr, width, height): pass def updateArea(self, cr, width, height): width = width - self.leftPadding - self.rightPadding height = height - self.topPadding - self.bottomPadding self.area = Area(self.leftPadding, self.topPadding, width, height) self.centerx = self.area.x + self.area.w * 0.5 self.centery = self.area.y + self.area.h * 0.5 self.radius = min(self.area.w * 0.4, self.area.h * 0.4) def updateGraph(self): self.sum = 0.0 for xkey in self.datas.iterkeys(): key = self.yfields[0].get('key', self.yfields[0]['name']) if self.datas[xkey][key] > 0: self.sum += self.datas[xkey][key] fraction = angle = 0.0 self.slices = [] for xkey in self.datas.iterkeys(): key = self.yfields[0].get('key', self.yfields[0]['name']) value = self.datas[xkey][key] if value > 0: angle += fraction fraction = value / self.sum slice = Slice(xkey, fraction, value, angle) self.slices.append(slice) def drawGraph(self, cr, width, height): cr.set_line_join(cairo.LINE_JOIN_ROUND) cr.save() for slice in self.slices: if slice.isBigEnough(): if bool(int(self.yfields[0].get('fill', 1))): color = self.colorScheme[slice.xname] if slice.highlight: color = common.highlight_rgb(*color) cr.set_source_rgba(*color) slice.draw(cr, self.centerx, self.centery, self.radius) cr.fill() cr.set_source_rgb(*common.hex2rgb( self.attrs.get('background', '#f5f5f5'))) slice.draw(cr, self.centerx, self.centery, self.radius) cr.set_line_width(2) cr.stroke() cr.restore() def motion(self, widget, event): super(Pie, self).motion(widget, event) if not getattr(self, 'area', None): return d = (event.x - self.centerx) ** 2 + (event.y - self.centery) ** 2 if d > self.radius ** 2: self.popup.hide() for slice in self.slices: if slice.highlight: self.queue_draw() slice.highlight = False return self.popup.show() if event.y == self.centery: angle = math.pi / 2 else: angle = math.atan((event.x - self.centerx) / (self.centery - event.y)) if event.x >= self.centerx: if event.y <= self.centery: pass else: angle += math.pi else: if event.y < self.centery: angle += 2 * math.pi else: angle += math.pi for slice in self.slices: if slice.startAngle <= angle <= slice.endAngle: if not slice.highlight: slice.highlight = True if 'timedelta' in self.yfields[0]: converter = self.yfields[0].get('timedelta') if converter: converter = rpc.CONTEXT.get(converter) value = common.timedelta.format( datetime.timedelta( seconds=slice.fraction * self.sum), converter) sum = common.timedelta.format( datetime.timedelta(seconds=self.sum), converter) else: value = locale.format('%.2f', slice.fraction * self.sum) sum = locale.format('%.2f', self.sum) label = '%s (%s%%)\n%s/%s' % (self.labels[slice.xname], locale.format('%.2f', slice.fraction * 100), value, sum) self.popup.set_text(label) self.queue_draw() else: if slice.highlight: slice.highlight = False self.queue_draw() def action(self): super(Pie, self).action() for slice in self.slices: if slice.highlight: ids = self.ids[slice.xname] self.action_keyword(ids) class Slice(object): def __init__(self, xname, fraction, value, angle): self.xname = xname self.fraction = fraction self.value = value self.startAngle = 2 * angle * math.pi self.endAngle = 2 * (angle + fraction) * math.pi self.highlight = False def isBigEnough(self): return abs(self.startAngle - self.endAngle) > 0.001 def draw(self, cr, centerx, centery, radius): cr.new_path() cr.move_to(centerx, centery) cr.arc(centerx, centery, radius, self.startAngle - (math.pi / 2), self.endAngle - (math.pi / 2)) cr.line_to(centerx, centery) cr.close_path() def normalisedAngle(self): normalisedAngle = (self.startAngle + self.endAngle) / 2 if normalisedAngle > 2 * math.pi: normalisedAngle -= 2 * math.pi elif normalisedAngle < 0: normalisedAngle += 2 * math.pi return normalisedAngle tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/graph.py0000644000175000017500000004071113251060075024421 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # This code is inspired by the pycha project # (http://www.lorenzogil.com/projects/pycha/) import gtk from functools import reduce from tryton.common import hex2rgb, generateColorscheme, \ COLOR_SCHEMES, datetime_strftime from tryton.pyson import PYSONDecoder import locale import math import datetime from dateutil.relativedelta import relativedelta import tryton.rpc as rpc import cairo from tryton.action import Action from tryton.gui.window import Window gtk_version = getattr(gtk, 'get_major_version', lambda: 2)() class Popup(object): def __init__(self, widget): self.win = gtk.Window(gtk.WINDOW_POPUP) self.win.set_name('gtk-tooltips') self.win.set_resizable(False) self.win.set_border_width(1) self.win.set_transient_for(widget.window) self.label = gtk.Label() self.win.add(self.label) self.win.connect('enter-notify-event', self.enter) def set_text(self, text): self.label.set_text(text) def set_position(self, widget, x, y): widget_x, widget_y = widget.window.get_origin() allocation = widget.get_allocation() width, height = allocation.width, allocation.height popup_width, popup_height = self.win.get_size() if x < popup_width // 2: x = popup_width // 2 if x > width - popup_width // 2: x = width - popup_width // 2 pos_x = widget_x + x - popup_width // 2 if pos_x < 0: pos_x = 0 if y < popup_height + 5: y = popup_height + 5 if y > height: y = height pos_y = widget_y + y - popup_height - 5 if pos_y < 0: pos_y = 0 self.win.move(int(pos_x), int(pos_y)) def show(self): self.win.show_all() def hide(self): self.win.hide() def destroy(self): self.win.destroy() def enter(self, widget, event): self.win.hide() class Graph(gtk.DrawingArea): 'Graph' if gtk_version == 2: __gsignals__ = {"expose-event": "override"} else: __gsignals__ = {"draw": "override"} def __init__(self, view, xfield, yfields): super(Graph, self).__init__() self.view = view self.xfield = xfield self.yfields = yfields self.datas = {} self.topPadding = 15 self.bottomPadding = 15 self.rightPadding = 30 self.leftPadding = 30 self.set_events(gtk.gdk.POINTER_MOTION_MASK) self.connect('motion-notify-event', self.motion) self.connect('leave-notify-event', self.leave) self.popup = Popup(self) @property def attrs(self): return self.view.attributes @property def model(self): return self.view.screen.model_name def destroy(self): self.popup.destroy() super(Graph, self).destroy() def motion(self, widget, event): self.popup.set_position(self, event.x, event.y) def leave(self, widget, event): self.popup.hide() if gtk_version == 2: # Handle the expose-event by drawing def do_expose_event(self, event): # Create the cairo context cr = self.window.cairo_create() # Restrict Cairo to the exposed area; avoid extra work cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height) cr.clip() self.updateArea(cr, *self.window.get_size()) self.drawBackground(cr, *self.window.get_size()) self.drawLines(cr, *self.window.get_size()) self.drawGraph(cr, *self.window.get_size()) self.drawAxis(cr, *self.window.get_size()) self.drawLegend(cr, *self.window.get_size()) else: def do_draw(self, cr): cr = self.window.cairo_create() width = self.get_allocated_width() height = self.get_allocated_height() self.updateArea(cr, width, height) self.drawBackground(cr, width, height) self.drawLines(cr, width, height) self.drawGraph(cr, width, height) self.drawAxis(cr, width, height) self.drawLegend(cr, width, height) def export_png(self, filename, width, height): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) cx = cairo.Context(surface) self.updateArea(cx, width, height) self.drawBackground(cx, width, height) self.drawLines(cx, width, height) self.drawGraph(cx, width, height) self.drawAxis(cx, width, height) self.drawLegend(cx, width, height) surface.write_to_png(filename.encode('utf-8')) self.queue_draw() def action(self): self.popup.hide() def action_keyword(self, ids): if not ids: return ctx = self.group.context.copy() if 'active_ids' in ctx: del ctx['active_ids'] if 'active_id' in ctx: del ctx['active_id'] event = gtk.get_current_event() allow_similar = False if (event.state & gtk.gdk.CONTROL_MASK or event.state & gtk.gdk.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): return Action.exec_keyword('graph_open', { 'model': self.model, 'id': ids[0], 'ids': ids, }, context=ctx, warning=False) def drawBackground(self, cr, width, height): # Fill the background cr.save() r, g, b = hex2rgb(self.attrs.get('background', '#d5d5d5')) linear = cairo.LinearGradient(width // 2, 0, width // 2, height) linear.add_color_stop_rgb(0, 1, 1, 1) linear.add_color_stop_rgb(1, r, g, b) cr.set_source(linear) cr.rectangle(0, 0, width, height) cr.fill() cr.stroke() cr.restore() def drawGraph(self, cr, width, height): pass def YLabels(self): ylabels = [] if self.yrange == 0.0: base = 1 else: base = 10 ** int(math.log(self.yrange, 10)) for i in xrange(int(self.yrange / base) + 1): val = int(self.minyval / base) * base + i * base h = (val - self.minyval) * self.yscale label = locale.format('%.2f', val, True) ylabels.append((h, label)) return ylabels def XLabels(self): xlabels = [] i = 0.0 keys = self.datas.keys() keys.sort() for key in keys: if self.xrange == 0: w = 1.0 else: w = i / self.xrange xlabels.append((w, str(self.labels[key]))) i += 1 return xlabels def drawAxis(self, cr, width, height): cr.set_source_rgb(*hex2rgb('#000000')) cr.set_line_width(0.5) # Y axis def drawYLabel(h, label): x = self.area.x y = self.area.y + self.area.h - h * self.area.h cr.new_path() cr.move_to(x, y) cr.line_to(x - 3.0, y) cr.close_path() cr.stroke() extends = cr.text_extents(label) labelWidth = extends[2] labelHeight = extends[3] if labelWidth <= self.area.x: cr.move_to(x - 3.0 - labelWidth - 5, y + labelHeight / 2.0) cr.show_text(label) for h, label in self.YLabels(): drawYLabel(h, label) cr.new_path() cr.move_to(self.area.x, self.area.y) cr.line_to(self.area.x, self.area.y + self.area.h) cr.close_path() cr.stroke() # X axis def drawXLabel(w, label): x = self.area.x + w * self.area.w y = self.area.y + self.area.h cr.new_path() cr.move_to(x, y) cr.line_to(x, y + 3.0) cr.close_path() cr.stroke() extends = cr.text_extents(label) labelWidth = extends[2] labelHeight = extends[3] if labelWidth <= self.xscale * self.area.w: cr.move_to(x - labelWidth / 2.0, y + labelHeight + 5) cr.show_text(label) for w, label in self.XLabels(): drawXLabel(w, label) cr.new_path() cr.move_to(self.area.x, self.area.y + self.area.h) cr.line_to(self.area.x + self.area.w, self.area.y + self.area.h) cr.close_path() cr.stroke() def drawLines(self, cr, width, height): for h, label in self.YLabels(): self.drawLine(cr, 0, h) def drawLine(self, cr, x, y): if x: x1 = x2 = self.area.x + x * self.area.w y1 = self.area.y y2 = y1 + self.area.h else: y1 = y2 = self.area.y + self.area.h - y * self.area.h x1 = self.area.x x2 = x1 + self.area.w cr.save() cr.set_source_rgb(*hex2rgb('#A0A0A0')) cr.set_line_width(0.3) cr.new_path() cr.set_dash([5.0, 4.0]) cr.move_to(x1, y1) cr.line_to(x2, y2) cr.close_path() cr.stroke() cr.restore() def drawLegend(self, cr, width, height): if not int(self.attrs.get('legend', 1)): return padding = 4 bullet = 15 width = 0 height = padding keys = self._getDatasKeys() if not keys: return keys2txt = {} for yfield in self.yfields: keys2txt[yfield.get('key', yfield['name'])] = yfield['string'] for key in keys: extents = cr.text_extents(keys2txt[key]) width = max(extents[2], width) height += max(extents[3], bullet) + padding width = padding + bullet + padding + width + padding pos_x, pos_y = self._getLegendPosition(width, height) cr.save() cr.rectangle(pos_x, pos_y, width, height) cr.set_source_rgba(1, 1, 1, 0.8) cr.fill_preserve() cr.set_line_width(0.5) cr.set_source_rgb(*hex2rgb('#000000')) cr.stroke() def drawKey(key, x, y, text_height): cr.rectangle(x, y, bullet, bullet) cr.set_source_rgb(*self.colorScheme[key]) cr.fill_preserve() cr.set_source_rgb(0, 0, 0) cr.stroke() cr.move_to(x + bullet + padding, y + bullet / 2.0 + text_height / 2.0) cr.show_text(keys2txt[key]) cr.set_line_width(0.5) x = pos_x + padding y = pos_y + padding for key in keys: extents = cr.text_extents(keys2txt[key]) drawKey(key, x, y, extents[3]) y += max(extents[3], bullet) + padding cr.restore() def _getLegendPosition(self, width, height): return self.area.x + self.area.w * 0.05, \ self.area.y + self.area.h * 0.05 def display(self, group): self.updateDatas(group) self.setColorScheme() self.updateXY() self.updateGraph() self.queue_draw() def updateDatas(self, group): self.datas = {} self.labels = {} self.ids = {} self.group = group minx = None maxx = None for model in group: x = model[self.xfield['name']].get(model) if not minx: minx = x if not maxx: maxx = x if minx is None and maxx is None: if isinstance(x, datetime.datetime): minx, maxx = datetime.datetime.min, datetime.datetime.max elif isinstance(x, datetime.date): minx, maxx = datetime.date.min, datetime.date.max elif isinstance(x, datetime.timedelta): minx, maxx = datetime.timedelta.min, datetime.timedelta.max try: minx = min(minx, x) maxx = max(maxx, x) except TypeError: continue self.labels[x] = model[self.xfield['name']].get_client(model) self.ids.setdefault(x, []) self.ids[x].append(model.id) self.datas.setdefault(x, {}) for yfield in self.yfields: key = yfield.get('key', yfield['name']) self.datas[x].setdefault(key, 0.0) if yfield.get('domain'): context = rpc.CONTEXT.copy() context['context'] = context.copy() context['_user'] = rpc._USER for field in model.group.fields: context[field] = model[field].get(model) if not PYSONDecoder(context).decode(yfield['domain']): continue if yfield['name'] == '#': self.datas[x][key] += 1 else: value = model[yfield['name']].get(model) if isinstance(value, datetime.timedelta): value = value.total_seconds() self.datas[x][key] += float(value or 0) date_format = self.view.screen.context.get('date_format', '%x') datetime_format = date_format + ' %X' if isinstance(minx, datetime.datetime): date = minx while date <= maxx: self.labels[date] = datetime_strftime(date, datetime_format) self.datas.setdefault(date, {}) for yfield in self.yfields: self.datas[date].setdefault( yfield.get('key', yfield['name']), 0.0) date += relativedelta(days=1) elif isinstance(minx, datetime.date): date = minx while date <= maxx: self.labels[date] = datetime_strftime(date, date_format) self.datas.setdefault(date, {}) for yfield in self.yfields: self.datas[date].setdefault( yfield.get('key', yfield['name']), 0.0) date += relativedelta(days=1) def updateArea(self, cr, width, height): maxylabel = '' for value, label in self.YLabels(): if len(maxylabel) < len(label): maxylabel = label extends = cr.text_extents(maxylabel) yLabelWidth = extends[2] maxxlabel = '' for value, label in self.XLabels(): if len(maxxlabel) < len(label): maxxlabel = label extends = cr.text_extents(maxxlabel) xLabelHeight = extends[3] if yLabelWidth > width / 3.0: yLabelWidth = 0 width = width - self.leftPadding - yLabelWidth - self.rightPadding height = height - self.topPadding - self.bottomPadding - xLabelHeight self.area = Area(self.leftPadding + yLabelWidth, self.topPadding, width, height) def updateXY(self): self.maxxval = len(self.datas) self.minxval = 0.0 self.xrange = self.maxxval - self.minxval if self.xrange == 0: self.xscale = 1.0 else: self.xscale = 1.0 / self.xrange if not self.datas.values(): self.maxyval = 0.0 self.minyval = 0.0 else: self.maxyval = max([reduce(lambda x, y: max(x, y), x.values()) for x in self.datas.values()]) self.minyval = min([reduce(lambda x, y: min(x, y), x.values()) for x in self.datas.values()]) if self.minyval > 0: self.minyval = 0.0 self.yrange = self.maxyval - self.minyval if self.yrange == 0: self.yscale = 1.0 else: self.yscale = 1.0 / self.yrange def updateGraph(self): pass def setColorScheme(self): keys = self._getDatasKeys() color = self.attrs.get('color', 'blue') r, g, b = hex2rgb(COLOR_SCHEMES.get(color, color)) maxcolor = max(max(r, g), b) self.colorScheme = generateColorscheme(color, keys, maxcolor / (len(keys) or 1)) for yfield in self.yfields: if yfield.get('color'): self.colorScheme[yfield.get('key', yfield['name'])] = hex2rgb( COLOR_SCHEMES.get(yfield['color'], yfield['color'])) def _getDatasKeys(self): return [x.get('key', x['name']) for x in self.yfields] class Area(object): def __init__(self, x, y, w, h): self.x, self.y, self.w, self.h = x, y, w, h tryton-4.6.5/tryton/gui/window/view_form/view/graph_gtk/__init__.py0000644000175000017500000000024513175640533025065 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from parser import * tryton-4.6.5/tryton/gui/window/view_form/view/__init__.py0000644000175000017500000000254113251060075023110 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from tryton.common import node_attributes class View(object): view_type = None widget = None view_id = None modified = None editable = None children_field = None def __init__(self, screen, xml): self.screen = screen self.fields = {} self.attributes = node_attributes(xml) screen.set_on_write(self.attributes.get('on_write')) def set_value(self): raise NotImplementedError def get_fields(self): raise NotImplementedError @property def selected_records(self): return [] def get_buttons(self): raise NotImplementedError @staticmethod def parse(screen, xml, children_field): from .list import ViewTree from .form import ViewForm from .graph import ViewGraph from .calendar_ import ViewCalendar root, = xml.childNodes tagname = root.tagName if tagname == 'tree': return ViewTree(screen, root, children_field) elif tagname == 'form': return ViewForm(screen, root) elif tagname == 'graph': return ViewGraph(screen, root) elif tagname == 'calendar': return ViewCalendar(screen, root) tryton-4.6.5/tryton/gui/window/view_form/view/screen_container.py0000644000175000017500000006127013255571102024700 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import gobject import tryton.common as common from tryton.common.domain_parser import quote from tryton.common.placeholder_entry import PlaceholderEntry from tryton.common.treeviewcontrol import TreeViewControl from tryton.common.datetime_ import Date, Time, DateTime, add_operators from tryton.pyson import PYSONDecoder _ = gettext.gettext class Dates(gtk.HBox): def __init__(self, format_=None, _entry=Date): super(Dates, self).__init__() self.from_ = add_operators(_entry()) self.pack_start(self.from_, expand=True, fill=True) self.pack_start(gtk.Label(_('..')), expand=False, fill=False) self.to = add_operators(_entry()) self.pack_start(self.to, expand=True, fill=True) if format_: self.from_.props.format = format_ self.to.props.format = format_ def _get_value(self, widget): value = widget.props.value if value: return common.datetime_strftime(value, widget.props.format) def get_value(self): from_ = self._get_value(self.from_) to = self._get_value(self.to) if from_ and to: if from_ != to: return '%s..%s' % (quote(from_), quote(to)) else: return quote(from_) elif from_: return '>=%s' % quote(from_) elif to: return '<=%s' % quote(to) def connect_activate(self, callback): self.from_.connect('activate', callback) self.to.connect('activate', callback) def set_values(self, from_, to): self.from_.props.value = from_ self.to.props.value = to class Times(Dates): def __init__(self, format_, _entry=Time): super(Times, self).__init__(_entry=_entry) def connect_activate(self, callback): for widget in self.from_.get_children() + self.to.get_children(): widget.get_child().connect('activate', callback) class DateTimes(Dates): def __init__(self, date_format, time_format, _entry=DateTime): super(DateTimes, self).__init__(_entry=_entry) self.from_.props.date_format = date_format self.to.props.date_format = date_format self.from_.props.time_format = time_format self.to.props.time_format = time_format def _get_value(self, widget): value = widget.props.value if value: return common.datetime_strftime(value, widget.props.date_format + ' ' + widget.props.time_format) def connect_activate(self, callback): for widget in self.from_.get_children() + self.to.get_children(): if isinstance(widget, Date): widget.connect('activate', callback) elif isinstance(widget, Time): widget.get_child().connect('activate', callback) class Selection(gtk.ScrolledWindow): def __init__(self, selections): super(Selection, self).__init__() self.treeview = TreeViewControl() model = gtk.ListStore(gobject.TYPE_STRING) for selection in selections: model.append((selection,)) self.treeview.set_model(model) column = gtk.TreeViewColumn() cell = gtk.CellRendererText() column.pack_start(cell) column.add_attribute(cell, 'text', 0) self.treeview.append_column(column) self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE) self.treeview.set_headers_visible(False) self.add(self.treeview) self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.set_shadow_type(gtk.SHADOW_ETCHED_IN) def get_value(self): values = [] model, paths = self.treeview.get_selection().get_selected_rows() if not paths: return for path in paths: iter_ = model.get_iter(path) values.append(model.get_value(iter_, 0)) return ';'.join(quote(v) for v in values) class ScreenContainer(object): def __init__(self, tab_domain): self.viewport = gtk.Viewport() self.viewport.set_shadow_type(gtk.SHADOW_NONE) self.vbox = gtk.VBox(spacing=3) self.alternate_viewport = gtk.Viewport() self.alternate_viewport.set_shadow_type(gtk.SHADOW_NONE) self.alternate_view = False self.search_window = None self.search_table = None self.last_search_text = '' self.tab_domain = tab_domain or [] self.tab_counter = [] tooltips = common.Tooltips() self.filter_vbox = gtk.VBox(spacing=0) self.filter_vbox.set_border_width(0) hbox = gtk.HBox(homogeneous=False, spacing=0) self.search_entry = PlaceholderEntry() self.search_entry.set_placeholder_text(_('Search')) self.search_entry.set_alignment(0.0) self.search_entry.set_icon_from_stock( gtk.ENTRY_ICON_PRIMARY, 'tryton-find') self.search_entry.set_icon_tooltip_text( gtk.ENTRY_ICON_PRIMARY, _('Open filters')) self.completion = gtk.EntryCompletion() self.completion.set_model(gtk.ListStore(str)) self.completion.set_text_column(0) self.completion.props.inline_selection = True self.completion.props.popup_set_width = False self.completion.set_match_func(lambda *a: True) self.completion.connect('match-selected', self.match_selected) self.search_entry.connect('activate', self.activate) self.search_entry.set_completion(self.completion) self.search_entry.connect('key-press-event', self.key_press) self.search_entry.connect('focus-in-event', self.focus_in) self.search_entry.connect('icon-press', self.icon_press) hbox.pack_start(self.search_entry, expand=True, fill=True) def popup(widget): menu = widget._menu for child in menu.get_children(): menu.remove(child) if not widget.props.active: menu.popdown() return def menu_position(menu, data=None): widget_allocation = widget.get_allocation() if hasattr(widget.window, 'get_root_coords'): x, y = widget.window.get_root_coords( widget_allocation.x, widget_allocation.y) else: x, y = widget.window.get_origin() x += widget_allocation.x y += widget_allocation.y return (x, y + widget_allocation.height, False) for id_, name, domain in self.bookmarks(): menuitem = gtk.MenuItem(name) menuitem.connect('activate', self.bookmark_activate, domain) menu.add(menuitem) menu.show_all() menu.popup(None, None, menu_position, 0, 0) def deactivate(menuitem, togglebutton): togglebutton.props.active = False but_bookmark = gtk.ToggleButton() self.but_bookmark = but_bookmark tooltips.set_tip(but_bookmark, _('Show bookmarks of filters')) img_bookmark = gtk.Image() img_bookmark.set_from_stock('tryton-bookmark', gtk.ICON_SIZE_SMALL_TOOLBAR) img_bookmark.set_alignment(0.5, 0.5) but_bookmark.add(img_bookmark) but_bookmark.set_relief(gtk.RELIEF_NONE) menu = gtk.Menu() menu.set_property('reserve-toggle-size', False) menu.connect('deactivate', deactivate, but_bookmark) but_bookmark._menu = menu but_bookmark.connect('toggled', popup) hbox.pack_start(but_bookmark, expand=False, fill=False) but_prev = gtk.Button() self.but_prev = but_prev tooltips.set_tip(but_prev, _('Previous')) but_prev.connect('clicked', self.search_prev) img_prev = gtk.Image() img_prev.set_from_stock('tryton-go-previous', gtk.ICON_SIZE_SMALL_TOOLBAR) img_prev.set_alignment(0.5, 0.5) but_prev.add(img_prev) but_prev.set_relief(gtk.RELIEF_NONE) hbox.pack_start(but_prev, expand=False, fill=False) but_next = gtk.Button() self.but_next = but_next tooltips.set_tip(but_next, _('Next')) but_next.connect('clicked', self.search_next) img_next = gtk.Image() img_next.set_from_stock('tryton-go-next', gtk.ICON_SIZE_SMALL_TOOLBAR) img_next.set_alignment(0.5, 0.5) but_next.add(img_next) but_next.set_relief(gtk.RELIEF_NONE) hbox.pack_start(but_next, expand=False, fill=False) hbox.show_all() hbox.set_focus_chain([self.search_entry]) self.filter_vbox.pack_start(hbox, expand=False, fill=False) hseparator = gtk.HSeparator() hseparator.show() self.filter_vbox.pack_start(hseparator, expand=False, fill=False) if self.tab_domain: self.notebook = gtk.Notebook() try: self.notebook.props.homogeneous = True except AttributeError: # No more supported by GTK+3 pass self.notebook.set_scrollable(True) for name, domain, count in self.tab_domain: hbox = gtk.HBox(spacing=3) label = gtk.Label('_' + name) label.set_use_underline(True) hbox.pack_start(label, expand=True, fill=True) counter = gtk.Label() hbox.pack_start(counter, expand=False, fill=True) hbox.show_all() self.notebook.append_page(gtk.VBox(), hbox) self.tab_counter.append(counter) self.filter_vbox.pack_start(self.notebook, expand=True, fill=True) self.notebook.show_all() # Set the current page before connecting to switch-page to not # trigger the search a second times. self.notebook.set_current_page(0) self.notebook.get_nth_page(0).pack_end(self.viewport) self.notebook.connect('switch-page', self.switch_page) self.notebook.connect_after('switch-page', self.switch_page_after) filter_expand = True else: self.notebook = None self.vbox.pack_end(self.viewport) filter_expand = False self.vbox.pack_start(self.filter_vbox, expand=filter_expand, fill=True) self.but_next.set_sensitive(False) self.but_prev.set_sensitive(False) tooltips.enable() def destroy(self): if self.search_window: self.search_window.hide() def widget_get(self): return self.vbox def set_screen(self, screen): self.screen = screen self.but_bookmark.set_sensitive(bool(list(self.bookmarks()))) self.bookmark_match() def show_filter(self): if self.filter_vbox: self.filter_vbox.show() if self.notebook: self.notebook.set_show_tabs(True) if self.viewport in self.vbox.get_children(): self.vbox.remove(self.viewport) self.notebook.get_nth_page(self.notebook.get_current_page() ).pack_end(self.viewport) def hide_filter(self): if self.filter_vbox: self.filter_vbox.hide() if self.notebook: self.notebook.set_show_tabs(False) if self.viewport not in self.vbox.get_children(): self.notebook.get_nth_page(self.notebook.get_current_page() ).remove(self.viewport) self.vbox.pack_end(self.viewport) def set(self, widget): viewport1 = self.viewport viewport2 = self.alternate_viewport if self.alternate_view: viewport1, viewport2 = viewport2, viewport1 if viewport1.get_child(): viewport1.remove(viewport1.get_child()) if widget == viewport2.get_child(): viewport2.remove(widget) viewport1.add(widget) viewport1.show_all() def update(self): res = self.screen.search_complete(self.get_text()) model = self.completion.get_model() model.clear() for r in res: model.append([r.strip()]) def get_text(self): return self.search_entry.get_text().decode('utf-8') def set_text(self, value): self.search_entry.set_text(value) self.bookmark_match() def bookmarks(self): for id_, name, domain in common.VIEW_SEARCH[self.screen.model_name]: if self.screen.domain_parser.stringable(domain): yield id_, name, domain def bookmark_activate(self, menuitem, domain): self.set_text(self.screen.domain_parser.string(domain)) self.do_search() def bookmark_match(self): icon_stock = self.search_entry.get_icon_stock(gtk.ENTRY_ICON_SECONDARY) current_text = self.get_text() if current_text: current_domain = self.screen.domain_parser.parse(current_text) self.search_entry.set_icon_activatable(gtk.ENTRY_ICON_SECONDARY, bool(current_text)) self.search_entry.set_icon_sensitive(gtk.ENTRY_ICON_SECONDARY, bool(current_text)) for id_, name, domain in self.bookmarks(): text = self.screen.domain_parser.string(domain) domain = self.screen.domain_parser.parse(text.decode('utf-8')) if (text == current_text or domain == current_domain): if icon_stock != 'tryton-star': self.search_entry.set_icon_from_stock( gtk.ENTRY_ICON_SECONDARY, 'tryton-star') self.search_entry.set_icon_tooltip_text( gtk.ENTRY_ICON_SECONDARY, _('Remove this bookmark')) return id_ if icon_stock != 'tryton-unstar': self.search_entry.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'tryton-unstar') if current_text: self.search_entry.set_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY, _('Bookmark this filter')) elif self.search_entry.get_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY): self.search_entry.set_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY, None) def search_next(self, widget=None): self.screen.search_next(self.get_text()) def search_prev(self, widget=None): self.screen.search_prev(self.get_text()) def switch_page(self, notebook, page, page_num): current_page = notebook.get_nth_page(notebook.get_current_page()) current_page.remove(self.viewport) new_page = notebook.get_nth_page(page_num) new_page.pack_end(self.viewport) def switch_page_after(self, notebook, page, page_num): self.do_search() notebook.grab_focus() self.screen.count_tab_domain() def get_tab_domain(self): if not self.notebook: return [] idx = self.notebook.get_current_page() if idx < 0: return [] return self.tab_domain[idx][1] def set_tab_counter(self, count, idx=None): if not self.tab_counter or not self.notebook: return if idx is None: idx = self.notebook.get_current_page() if idx < 0: return label = self.tab_counter[idx] tooltip = common.Tooltips() if count is None: label.set_label('') tooltip.set_tip(label, '') else: tooltip.set_tip(label, '%d' % count) fmt = '(%d)' if count > 99: fmt = '(%d+)' count = 99 label.set_label(fmt % count) def match_selected(self, completion, model, iter): def callback(): if not self.search_entry.props.window: return self.update() self.search_entry.emit('changed') gobject.idle_add(callback) def activate(self, widget): if not self.search_entry.get_selection_bounds(): self.do_search(widget) def do_search(self, widget=None): self.screen.search_filter(self.get_text()) def set_cursor(self, new=False, reset_view=True): if self.filter_vbox: self.search_entry.grab_focus() def key_press(self, widget, event): def keypress(): if not self.search_entry.props.window: return self.update() self.bookmark_match() gobject.idle_add(keypress) def icon_press(self, widget, icon_pos, event): if icon_pos == gtk.ENTRY_ICON_PRIMARY: self.search_box(widget) elif icon_pos == gtk.ENTRY_ICON_SECONDARY: icon_stock = self.search_entry.get_icon_stock(icon_pos) model_name = self.screen.model_name if icon_stock == 'tryton-unstar': text = self.get_text() if not text: return name = common.ask(_('Bookmark Name:')) if not name: return domain = self.screen.domain_parser.parse(text) common.VIEW_SEARCH.add(model_name, name, domain) self.set_text(self.screen.domain_parser.string(domain)) elif icon_stock == 'tryton-star': id_ = self.bookmark_match() common.VIEW_SEARCH.remove(model_name, id_) # Refresh icon and bookmark button self.bookmark_match() self.but_bookmark.set_sensitive(bool(list(self.bookmarks()))) def focus_in(self, widget, event): self.update() self.search_entry.emit('changed') def search_box(self, widget): def window_hide(window, *args): window.hide() self.search_entry.grab_focus() def key_press(widget, event): if event.keyval == gtk.keysyms.Escape: window_hide(widget) return True return False def search(): self.search_window.hide() text = '' for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): value = quote(entry.get_active_text()) or None elif isinstance(entry, (Dates, Selection)): value = entry.get_value() else: value = quote(entry.get_text()) or None if value is not None: text += quote(label) + ': ' + value + ' ' self.set_text(text) self.do_search() # Store text after doing the search # because domain parser could simplify the text self.last_search_text = self.get_text() if not self.search_window: self.search_window = gtk.Window() self.search_window.set_transient_for(widget.get_toplevel()) self.search_window.set_type_hint( gtk.gdk.WINDOW_TYPE_HINT_POPUP_MENU) self.search_window.set_destroy_with_parent(True) self.search_window.set_decorated(False) self.search_window.set_deletable(False) self.search_window.connect('delete-event', window_hide) self.search_window.connect('key-press-event', key_press) self.search_window.connect('focus-out-event', window_hide) def toggle_window_hide(combobox, shown): if combobox.props.popup_shown: self.search_window.handler_block_by_func(window_hide) else: self.search_window.handler_unblock_by_func(window_hide) vbox = gtk.VBox() fields = [f for f in self.screen.domain_parser.fields.itervalues() if f.get('searchable', True)] self.search_table = gtk.Table(rows=len(fields), columns=2) self.search_table.set_homogeneous(False) self.search_table.set_border_width(5) self.search_table.set_row_spacings(2) self.search_table.set_col_spacings(2) # Fill table with fields self.search_table.fields = [] for i, field in enumerate(fields): label = gtk.Label(field['string']) label.set_alignment(0.0, 0.0) self.search_table.attach(label, 0, 1, i, i + 1, yoptions=gtk.FILL) yoptions = False if field['type'] == 'boolean': if hasattr(gtk, 'ComboBoxText'): entry = gtk.ComboBoxText() else: entry = gtk.combo_box_new_text() entry.connect('notify::popup-shown', toggle_window_hide) entry.append_text('') selections = (_('True'), _('False')) for selection in selections: entry.append_text(selection) elif field['type'] == 'selection': selections = tuple(x[1] for x in field['selection']) entry = Selection(selections) yoptions = gtk.FILL | gtk.EXPAND elif field['type'] in ('date', 'datetime', 'time'): date_format = self.screen.context.get('date_format', '%x') if field['type'] == 'date': entry = Dates(date_format) elif field['type'] in ('datetime', 'time'): time_format = PYSONDecoder({}).decode(field['format']) if field['type'] == 'time': entry = Times(time_format) elif field['type'] == 'datetime': entry = DateTimes(date_format, time_format) entry.connect_activate(lambda *a: search()) else: entry = gtk.Entry() entry.connect('activate', lambda *a: search()) label.set_mnemonic_widget(entry) self.search_table.attach(entry, 1, 2, i, i + 1, yoptions=yoptions) self.search_table.fields.append((field['string'], entry)) scrolled = gtk.ScrolledWindow() scrolled.add_with_viewport(self.search_table) scrolled.set_shadow_type(gtk.SHADOW_NONE) scrolled.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) vbox.pack_start(scrolled, expand=True, fill=True) find_button = gtk.Button(_('Find')) find_button.connect('clicked', lambda *a: search()) find_img = gtk.Image() find_img.set_from_stock('tryton-find', gtk.ICON_SIZE_SMALL_TOOLBAR) find_button.set_image(find_img) hbuttonbox = gtk.HButtonBox() hbuttonbox.set_spacing(5) hbuttonbox.pack_start(find_button) hbuttonbox.set_layout(gtk.BUTTONBOX_END) vbox.pack_start(hbuttonbox, expand=False, fill=True) self.search_window.add(vbox) vbox.show_all() new_size = map(sum, zip(self.search_table.size_request(), scrolled.size_request())) self.search_window.set_default_size(*new_size) parent = widget.get_toplevel() widget_x, widget_y = widget.translate_coordinates(parent, 0, 0) widget_allocation = widget.get_allocation() # Resize the window to not be out of the parent width, height = self.search_window.get_default_size() allocation = parent.get_allocation() delta_width = allocation.width - (widget_x + width) delta_height = allocation.height - (widget_y + widget_allocation.height + height) if delta_width < 0: width += delta_width if delta_height < 0: height += delta_height self.search_window.resize(width, height) # Move the window under the button if hasattr(widget.window, 'get_root_coords'): x, y = widget.window.get_root_coords( widget_allocation.x, widget_allocation.y) else: x, y = widget.window.get_origin() self.search_window.move( x, y + widget_allocation.height) self.search_window.show() self.search_window.grab_focus() if self.last_search_text.strip() != self.get_text().strip(): for label, entry in self.search_table.fields: if isinstance(entry, gtk.ComboBox): entry.set_active(-1) elif isinstance(entry, Dates): entry.set_values(None, None) elif isinstance(entry, Selection): entry.treeview.get_selection().unselect_all() else: entry.set_text('') if self.search_table.fields: self.search_table.fields[0][1].grab_focus() tryton-4.6.5/tryton/gui/window/view_form/view/calendar_.py0000644000175000017500000001141613251060075023262 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from functools import wraps import gtk import datetime import gettext from tryton.common import node_attributes from . import View try: from .calendar_gtk.calendar_ import Calendar_ from .calendar_gtk.toolbar import Toolbar except ImportError, e: Calendar_ = None Toolbar = None _ = gettext.gettext def goocalendar_required(func): "Decorator for goocalendar required" @wraps(func) def wrapper(self, *args, **kwargs): if 'goocalendar' not in self.widgets: return return func(self, *args, **kwargs) return wrapper class ViewCalendar(View): def __init__(self, screen, xml): super(ViewCalendar, self).__init__(screen, xml) self.view_type = 'calendar' self.editable = False self.widgets = {} self.widget = self.parse(xml) def parse(self, node): vbox = gtk.VBox() if not Calendar_: return vbox fields = [] for node in node.childNodes: if node.nodeType != node.ELEMENT_NODE: continue if node.tagName == 'field': fields.append(node_attributes(node)) goocalendar = Calendar_(attrs=self.attributes, screen=self.screen, fields=fields) toolbar = Toolbar(goocalendar) self.widgets['toolbar'] = toolbar goocalendar.connect('view-changed', self.on_view_changed, toolbar) goocalendar.connect('page-changed', self.on_page_changed, toolbar) goocalendar.connect('event-pressed', self.on_event_pressed) goocalendar.connect('event-activated', self.on_event_activated) goocalendar.connect('event-released', self.on_event_released) goocalendar.connect('day-pressed', self.on_day_pressed) goocalendar.connect('day-activated', self.on_day_activated) self.widgets['goocalendar'] = goocalendar scrolledWindow = gtk.ScrolledWindow() scrolledWindow.add_with_viewport(goocalendar) vbox.pack_start(toolbar, False, False) vbox.pack_start(scrolledWindow, True, True) return vbox def on_page_changed(self, goocalendar, day, toolbar): toolbar.update_displayed_date() if goocalendar.update_domain(): self.screen.search_filter() def on_view_changed(self, goocalendar, view, toolbar): toolbar.update_displayed_date() if goocalendar.update_domain(): self.screen.search_filter() def on_event_pressed(self, goocalendar, event): self.screen.current_record = event.record def on_event_activated(self, goocalendar, event): self.screen.switch_view('form') def on_event_released(self, goocalendar, event): dtstart = self.attributes['dtstart'] dtend = self.attributes.get('dtend') record = event.record group = record.group previous_start = record[dtstart].get(record) new_start = event.start new_end = event.end if not isinstance(previous_start, datetime.datetime): new_start = event.start.date() new_end = event.end.date() if event.end else None if previous_start <= new_start: if dtend: group.fields[dtend].set_client(record, new_end) group.fields[dtstart].set_client(record, new_start) else: group.fields[dtstart].set_client(record, new_start) if dtend: group.fields[dtend].set_client(record, new_end) goocalendar.select(new_start) record.save() def on_day_pressed(self, goocalendar, day): self.screen.current_record = None def on_day_activated(self, goocalendar, day): self.screen.new() def __getitem__(self, name): return None @goocalendar_required def destroy(self): self.widget.destroy() self.widgets['goocalendar'].destroy() @goocalendar_required def get_selected_date(self): return self.widgets['goocalendar'].selected_date @goocalendar_required def set_default_date(self, record, selected_date): self.widgets['goocalendar'].set_default_date(record, selected_date) def current_domain(self): if 'goocalendar' in self.widgets: return self.widgets['goocalendar'].current_domain() else: # No need to load any record as nothing will be shown return [('id', '=', -1)] def set_value(self): pass def reset(self): pass @goocalendar_required def display(self): self.widgets['goocalendar'].display(self.screen.group) def set_cursor(self, new=False, reset_view=True): pass def get_fields(self): return [] tryton-4.6.5/tryton/gui/window/view_form/view/form.py0000644000175000017500000004601613251060075022321 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import operator import gtk import gettext from collections import defaultdict from . import View from tryton.common.focus import (get_invisible_ancestor, find_focused_child, next_focus_widget, find_focusable_child, find_first_focus_widget) from tryton.common import Tooltips, node_attributes, ICONFACTORY from tryton.common.button import Button from tryton.config import CONFIG from .form_gtk.calendar import Date, Time, DateTime from .form_gtk.float import Float from .form_gtk.integer import Integer from .form_gtk.selection import Selection from .form_gtk.char import Char, Password from .form_gtk.timedelta import TimeDelta from .form_gtk.checkbox import CheckBox from .form_gtk.reference import Reference from .form_gtk.binary import Binary from .form_gtk.textbox import TextBox from .form_gtk.one2many import One2Many from .form_gtk.many2many import Many2Many from .form_gtk.many2one import Many2One from .form_gtk.url import Email, URL, CallTo, SIP from .form_gtk.image import Image as Image2 from .form_gtk.progressbar import ProgressBar from .form_gtk.one2one import One2One from .form_gtk.richtextbox import RichTextBox from .form_gtk.dictionary import DictWidget from .form_gtk.multiselection import MultiSelection from .form_gtk.pyson import PYSON from .form_gtk.state_widget import (Label, VBox, Image, Frame, ScrolledWindow, Notebook, Alignment) _ = gettext.gettext class Container(object): def __init__(self, col=4): if CONFIG['client.modepda']: col = 1 if col < 0: col = 0 self.col = col self.table = gtk.Table(1, col) self.table.set_homogeneous(False) self.table.set_col_spacings(0) self.table.set_row_spacings(0) self.table.set_border_width(0) self.last = (0, 0) self.tooltips = Tooltips() self.tooltips.enable() def add_row(self): height, width = self.last self.table.resize(height + 1, self.col or width) self.last = (height + 1, 0) def add_col(self): height, width = self.last self.table.resize(height or 1, width + 1) self.last = (height, width + 1) def add(self, widget, attributes): colspan = attributes.get('colspan', 1) if self.col > 0: height, width = self.last if colspan > self.col: colspan = self.col if width + colspan > self.col: self.add_row() else: self.add_col() height, width = self.last self.last = height, width + colspan if not widget: return yopt = 0 if attributes.get('yexpand'): yopt = gtk.EXPAND if attributes.get('yfill'): if yopt: yopt |= gtk.FILL else: yopt = gtk.FILL xopt = 0 if attributes.get('xexpand', True): xopt = gtk.EXPAND if attributes.get('xfill', True): if xopt: xopt |= gtk.FILL else: xopt = gtk.FILL if attributes.get('help'): self.tooltips.set_tip(widget, attributes['help']) widget.show_all() self.table.attach(widget, width, width + colspan, height, height + 1, yoptions=yopt, xoptions=xopt, ypadding=1, xpadding=2) class ViewForm(View): editable = True def __init__(self, screen, xml): super(ViewForm, self).__init__(screen, xml) self.view_type = 'form' self.widgets = defaultdict(list) self.state_widgets = [] self.notebooks = [] container = self.parse(xml) vbox = gtk.VBox() vp = gtk.Viewport() vp.set_shadow_type(gtk.SHADOW_NONE) vp.add(container.table) scroll = gtk.ScrolledWindow() scroll.add(vp) scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scroll.set_placement(gtk.CORNER_TOP_LEFT) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_ETCHED_IN) viewport.add(scroll) vbox.pack_start(viewport, expand=True, fill=True) self.widget = vbox self._viewport = vp def parse(self, node, container=None): if not container: node_attrs = node_attributes(node) container = Container(int(node_attrs.get('col', 4))) mnemonics = {} for node in node.childNodes: if node.nodeType != node.ELEMENT_NODE: continue node_attrs = node_attributes(node) for b_field in ('readonly', 'homogeneous'): if b_field in node_attrs: node_attrs[b_field] = bool(int(node_attrs[b_field])) for i_field in ('yexpand', 'yfill', 'xexpand', 'xfill', 'colspan', 'position'): if i_field in node_attrs: node_attrs[i_field] = int(node_attrs[i_field]) parser = getattr(self, '_parse_%s' % node.tagName) widget = parser(node, container, node_attrs) if not widget: continue name = node_attrs.get('name') if node.tagName == 'label' and name: mnemonics[name] = widget if node.tagName == 'field': if name in mnemonics and widget.mnemonic_widget: mnemonics.pop(name).set_mnemonic_widget( widget.mnemonic_widget) return container def _parse_image(self, node, container, attributes): ICONFACTORY.register_icon(attributes['name']) image = Image(attrs=attributes) image.set_from_stock(attributes['name'], gtk.ICON_SIZE_DIALOG) self.state_widgets.append(image) container.add(image, attributes) def _parse_separator(self, node, container, attributes): if 'name' in attributes: field = self.screen.group.fields[attributes['name']] for attr in ('states', 'string'): if attr not in attributes and attr in field.attrs: attributes[attr] = field.attrs[attr] vbox = VBox(attrs=attributes) if attributes.get('string'): label = Label(attributes['string'], attrs=attributes) label.set_alignment(float(attributes.get('xalign', 0.0)), float(attributes.get('yalign', 0.5))) vbox.pack_start(label) self.state_widgets.append(label) vbox.pack_start(gtk.HSeparator()) self.state_widgets.append(vbox) container.add(vbox, attributes) def _parse_label(self, node, container, attributes): if 'name' in attributes: field = self.screen.group.fields[attributes['name']] if attributes['name'] == self.screen.exclude_field: container.add(None, attributes) return if 'states' not in attributes and 'states' in field.attrs: attributes['states'] = field.attrs['states'] if 'string' not in attributes: if gtk.widget_get_default_direction() == \ gtk.TEXT_DIR_RTL: attributes['string'] = _(':') + field.attrs['string'] else: attributes['string'] = field.attrs['string'] + _(':') if CONFIG['client.modepda']: attributes['xalign'] = 0.0 label = Label(attributes.get('string', ''), attrs=attributes) label.set_alignment(float(attributes.get('xalign', 1.0)), float(attributes.get('yalign', 0.0))) label.set_angle(int(attributes.get('angle', 0))) attributes.setdefault('xexpand', 0) self.state_widgets.append(label) container.add(label, attributes) return label def _parse_newline(self, node, container, attributes): container.add_row() def _parse_button(self, node, container, attributes): button = Button(attributes) button.connect('clicked', self.button_clicked) self.state_widgets.append(button) container.add(button, attributes) def _parse_notebook(self, node, container, attributes): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) attributes.setdefault('colspan', 4) notebook = Notebook(attrs=attributes) notebook.set_scrollable(True) notebook.set_border_width(3) # Force to display the first time it switches on a page # This avoids glitch in position of widgets def switch(notebook, page, page_num): if not self.widget: # Not yet finish to parse return notebook.grab_focus() self.display() notebook.disconnect(handler_id) handler_id = notebook.connect('switch-page', switch) self.state_widgets.append(notebook) self.notebooks.append(notebook) container.add(notebook, attributes) self.parse(node, notebook) def _parse_page(self, node, notebook, attributes): tab_box = gtk.HBox(spacing=3) if 'name' in attributes: field = self.screen.group.fields[attributes['name']] if attributes['name'] == self.screen.exclude_field: return for attr in ('states', 'string'): if attr not in attributes and attr in field.attrs: attributes[attr] = field.attrs[attr] label = gtk.Label('_' + attributes['string'].replace('_', '__')) label.set_use_underline(True) tab_box.pack_start(label) if 'icon' in attributes: ICONFACTORY.register_icon(attributes['icon']) pixbuf = tab_box.render_icon(attributes['icon'], gtk.ICON_SIZE_SMALL_TOOLBAR) icon = gtk.Image() icon.set_from_pixbuf(pixbuf) tab_box.pack_start(icon) tab_box.show_all() viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) scrolledwindow = ScrolledWindow(attrs=attributes) scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolledwindow.add(viewport) scrolledwindow.show_all() self.state_widgets.append(scrolledwindow) notebook.append_page(scrolledwindow, tab_box) container = self.parse(node) viewport.add(container.table) def _parse_field(self, node, container, attributes): name = attributes['name'] field = self.screen.group.fields[name] if (name not in self.screen.group.fields or name == self.screen.exclude_field): container.add(None, attributes) return if 'widget' not in attributes: attributes['widget'] = field.attrs['type'] for i_field in ('width', 'height'): if i_field in attributes: attributes[i_field] = int(attributes[i_field]) for attr in ('relation', 'domain', 'selection', 'relation_field', 'string', 'help', 'views', 'add_remove', 'sort', 'context', 'size', 'filename', 'autocomplete', 'translate', 'create', 'delete', 'selection_change_with', 'schema_model'): if attr in field.attrs and attr not in attributes: attributes[attr] = field.attrs[attr] Widget = self.get_widget(attributes['widget']) widget = Widget(self, attributes) self.widgets[name].append(widget) if Widget.expand: attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) if attributes.get('height') or attributes.get('width'): widget.widget.set_size_request( int(attributes.get('width', -1)), int(attributes.get('height', -1))) container.add(Alignment(widget.widget, attributes), attributes) return widget def _parse_group(self, node, container, attributes): group = self.parse(node) group.table.set_homogeneous(attributes.get('homogeneous', False)) if 'name' in attributes: field = self.screen.group.fields[attributes['name']] if attributes['name'] == self.screen.exclude_field: container.add(None, attributes) return for attr in ('states', 'string'): if attr not in attributes and attr in field.attrs: attributes[attr] = field.attrs[attr] frame = Frame(attributes.get('string'), attrs=attributes) frame.add(group.table) self.state_widgets.append(frame) container.add(frame, attributes) def _parse_paned(self, node, container, attributes, Paned): attributes.setdefault('yexpand', True) attributes.setdefault('yfill', True) paned = Paned() if 'position' in attributes: paned.set_position(attributes['position']) container.add(paned, attributes) self.parse(node, paned) def _parse_hpaned(self, node, container, attributes): self._parse_paned(node, container, attributes, gtk.HPaned) def _parse_vpaned(self, node, container, attributes): self._parse_paned(node, container, attributes, gtk.VPaned) def _parse_child(self, node, paned, attributes): container = self.parse(node) if not paned.get_child1(): pack = paned.pack1 else: pack = paned.pack2 pack(container.table, resize=True, shrink=True) WIDGETS = { 'date': Date, 'datetime': DateTime, 'time': Time, 'float': Float, 'numeric': Float, 'integer': Integer, 'biginteger': Integer, 'selection': Selection, 'char': Char, 'password': Password, 'timedelta': TimeDelta, 'boolean': CheckBox, 'reference': Reference, 'binary': Binary, 'text': TextBox, 'one2many': One2Many, 'many2many': Many2Many, 'many2one': Many2One, 'email': Email, 'url': URL, 'callto': CallTo, 'sip': SIP, 'image': Image2, 'progressbar': ProgressBar, 'one2one': One2One, 'richtext': RichTextBox, 'dict': DictWidget, 'multiselection': MultiSelection, 'pyson': PYSON, } @classmethod def get_widget(cls, name): return cls.WIDGETS[name] def get_fields(self): return self.widgets.keys() def __getitem__(self, name): return self.widgets[name][0] def destroy(self): for widget_name in self.widgets.keys(): for widget in self.widgets[widget_name]: widget.destroy() self.widget.destroy() def set_value(self, focused_widget=False): record = self.screen.current_record if record: for name, widgets in self.widgets.iteritems(): if name in record.group.fields: field = record.group.fields[name] for widget in widgets: if (not focused_widget or widget.widget.is_focus() or (isinstance(widget.widget, gtk.Container) and widget.widget.get_focus_child())): widget.set_value(record, field) @property def selected_records(self): if self.screen.current_record: return [self.screen.current_record] return [] @property def modified(self): return any(w.modified for widgets in self.widgets.itervalues() for w in widgets) def get_buttons(self): return [b for b in self.state_widgets if isinstance(b, gtk.Button)] def reset(self): record = self.screen.current_record if record: for name, widgets in self.widgets.iteritems(): field = record.group.fields.get(name) if field and 'invalid' in field.get_state_attrs(record): for widget in widgets: field.get_state_attrs(record)['invalid'] = False widget.display(record, field) def display(self): record = self.screen.current_record if record: # Force to set fields in record # Get first the lazy one to reduce number of requests fields = [(name, field.attrs.get('loading', 'eager')) for name, field in record.group.fields.iteritems()] fields.sort(key=operator.itemgetter(1), reverse=True) for field, _ in fields: record[field].get(record) focused_widget = find_focused_child(self.widget) for name, widgets in self.widgets.iteritems(): field = None if record: field = record.group.fields.get(name) if field: field.state_set(record) for widget in widgets: widget.display(record, field) for widget in self.state_widgets: widget.state_set(record) if focused_widget: invisible_ancestor = get_invisible_ancestor(focused_widget) if invisible_ancestor: new_focused_widget = next_focus_widget(invisible_ancestor) if new_focused_widget: new_focused_widget.grab_focus() return True def set_cursor(self, new=False, reset_view=True): focus_widget = None if reset_view or not self.widget.has_focus(): if reset_view: for notebook in self.notebooks: notebook.set_current_page(0) if self.attributes.get('cursor') in self.widgets: focus_widget = find_focusable_child(self.widgets[ self.attributes['cursor']][0].widget) else: child = find_focusable_child(self._viewport) if child: child.grab_focus() record = self.screen.current_record if record: invalid_widgets = [] for name in record.invalid_fields: widgets = self.widgets.get(name, []) for widget in widgets: invalid_widget = find_focusable_child(widget.widget) if invalid_widget: invalid_widgets.append(invalid_widget) if invalid_widgets: focus_widget = find_first_focus_widget( self._viewport, invalid_widgets) if focus_widget: for notebook in self.notebooks: for i in range(notebook.get_n_pages()): child = notebook.get_nth_page(i) if focus_widget.is_ancestor(child): notebook.set_current_page(i) focus_widget.grab_focus() def button_clicked(self, widget): widget.handler_block_by_func(self.button_clicked) try: self.screen.button(widget.attrs) finally: widget.handler_unblock_by_func(self.button_clicked) tryton-4.6.5/tryton/gui/window/view_form/view/list_gtk/0000755000175000017500000000000013260723567022631 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/view/list_gtk/__init__.py0000644000175000017500000000022013175640533024730 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. tryton-4.6.5/tryton/gui/window/view_form/view/list_gtk/widget.py0000644000175000017500000010045213255571102024456 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime import os import tempfile import gtk import gettext import webbrowser from functools import wraps, partial from tryton.gui.window.win_search import WinSearch from tryton.gui.window.win_form import WinForm from tryton.gui.window.view_form.screen import Screen from tryton.common import file_selection, file_open, slugify import tryton.common as common from tryton.common.cellrendererbutton import CellRendererButton from tryton.common.cellrenderertext import CellRendererText, \ CellRendererTextCompletion from tryton.common.cellrenderertoggle import CellRendererToggle from tryton.common.cellrenderercombo import CellRendererCombo from tryton.common.cellrendererinteger import CellRendererInteger from tryton.common.cellrendererfloat import CellRendererFloat from tryton.common.cellrendererbinary import CellRendererBinary from tryton.common.cellrendererclickablepixbuf import \ CellRendererClickablePixbuf from tryton.common import data2pixbuf from tryton.common.completion import get_completion, update_completion from tryton.common.selection import SelectionMixin, PopdownMixin from tryton.common.datetime_ import CellRendererDate, CellRendererTime from tryton.common.datetime_strftime import datetime_strftime from tryton.common.domain_parser import quote _ = gettext.gettext def send_keys(renderer, editable, position, treeview): editable.connect('key_press_event', treeview.on_keypressed) editable.editing_done_id = editable.connect('editing_done', treeview.on_editing_done) if isinstance(editable, (gtk.ComboBoxEntry, gtk.ComboBox)): def changed(combobox): # "changed" signal is also triggered by text editing # so only trigger editing-done if a row is active if combobox.get_active_iter(): treeview.on_editing_done(combobox) editable.connect('changed', changed) def realized(func): "Decorator for treeview realized" @wraps(func) def wrapper(self, *args, **kwargs): if (hasattr(self.view.treeview, 'get_realized') and not self.view.treeview.get_realized()): return return func(self, *args, **kwargs) return wrapper class CellCache(list): methods = ('set_active', 'set_sensitive', 'set_property') def apply(self, cell): for method, args, kwargs in self: getattr(cell, method)(*args, **kwargs) def decorate(self, cell): def decorate(func): @wraps(func) def wrapper(*args, **kwargs): self.append((func.__name__, args, kwargs)) return func(*args, **kwargs) wrapper.previous = func return wrapper for method in self.methods: if getattr(cell, method, None): setattr(cell, method, decorate(getattr(cell, method))) cell.decorated = True return cell def undecorate(self, cell): for method in self.methods: if getattr(cell, method, None): setattr(cell, method, getattr(cell, method).previous) del cell.decorated @classmethod def cache(cls, func): @wraps(func) def wrapper(self, column, cell, store, iter): if not hasattr(self, 'display_counters'): self.display_counters = {} if not hasattr(self, 'cell_caches'): self.cell_caches = {} record = store.get_value(iter, 0) counter = self.view.treeview.display_counter if (self.display_counters.get(record.id) != counter): if getattr(cell, 'decorated', None): func(self, column, cell, store, iter) else: cache = cls() cache.decorate(cell) func(self, column, cell, store, iter) cache.undecorate(cell) self.cell_caches[record.id] = cache self.display_counters[record.id] = counter else: self.cell_caches[record.id].apply(cell) return wrapper class Cell(object): pass class Affix(Cell): def __init__(self, view, attrs, protocol=None): super(Affix, self).__init__() self.attrs = attrs self.protocol = protocol self.icon = attrs.get('icon') if protocol: self.renderer = CellRendererClickablePixbuf() self.renderer.connect('clicked', self.clicked) if not self.icon: self.icon = 'tryton-web-browser' elif self.icon: self.renderer = gtk.CellRendererPixbuf() else: self.renderer = gtk.CellRendererText() self.view = view @realized @CellCache.cache def setter(self, column, cell, store, iter_): record = store.get_value(iter_, 0) field = record[self.attrs['name']] field.state_set(record, states=('invisible',)) invisible = field.get_state_attrs(record).get('invisible', False) cell.set_property('visible', not invisible) if self.icon: if self.icon in record.group.fields: value = record[self.icon].get_client(record) or '' else: value = self.icon common.ICONFACTORY.register_icon(value) pixbuf = self.view.treeview.render_icon(stock_id=value, size=gtk.ICON_SIZE_BUTTON, detail=None) cell.set_property('pixbuf', pixbuf) else: text = self.attrs.get('string', '') if not text: text = field.get_client(record) or '' cell.set_property('text', text) def clicked(self, renderer, path): store = self.view.treeview.get_model() record = store.get_value(store.get_iter(path), 0) value = record[self.attrs['name']].get(record) if value: if self.protocol == 'email': value = 'mailto:%s' % value elif self.protocol == 'callto': value = 'callto:%s' % value elif self.protocol == 'sip': value = 'sip:%s' % value webbrowser.open(value, new=2) class GenericText(Cell): align = 0 def __init__(self, view, attrs, renderer=None): super(GenericText, self).__init__() self.attrs = attrs if renderer is None: renderer = CellRendererText self.renderer = renderer() self.renderer.connect('editing-started', self.editing_started) if not isinstance(self.renderer, CellRendererBinary): self.renderer.connect_after('editing-started', send_keys, view.treeview) self.renderer.set_property('yalign', 0) self.view = view @property def field_name(self): return self.attrs['name'] @property def model_name(self): return self.view.screen.model_name @realized @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) text = self.get_textual_value(record) if isinstance(cell, CellRendererToggle): cell.set_active(bool(text)) else: cell.set_sensitive(not (record.deleted or record.removed)) if isinstance(cell, (CellRendererText, CellRendererDate, CellRendererCombo)): cell.set_property('strikethrough', record.deleted) cell.set_property('text', text) field = record[self.attrs['name']] editable = getattr(self.view.treeview, 'editable', False) states = ('invisible',) if editable: states = ('readonly', 'required', 'invisible') field.state_set(record, states=states) invisible = field.get_state_attrs(record).get('invisible', False) cell.set_property('visible', not invisible) if editable: readonly = self.attrs.get('readonly', field.get_state_attrs(record).get('readonly', False)) if invisible: readonly = True if isinstance(cell, CellRendererToggle): cell.set_property('activatable', not readonly) elif isinstance(cell, (gtk.CellRendererProgress, CellRendererButton, gtk.CellRendererPixbuf)): pass else: cell.set_property('editable', not readonly) else: if isinstance(cell, CellRendererToggle): cell.set_property('activatable', False) cell.set_property('xalign', self.align) def open_remote(self, record, create, changed=False, text=None, callback=None): raise NotImplementedError def get_textual_value(self, record): if not record: return '' return record[self.attrs['name']].get_client(record) def value_from_text(self, record, text, callback=None): field = record[self.attrs['name']] field.set_client(record, text) if callback: callback() def editing_started(self, cell, editable, path): return False def _get_record_field(self, path): store = self.view.treeview.get_model() record = store.get_value(store.get_iter(path), 0) field = record.group.fields[self.attrs['name']] return record, field class Char(GenericText): @realized @CellCache.cache def setter(self, column, cell, store, iter_): super(Char, self).setter(column, cell, store, iter_) cell.set_property('single-paragraph-mode', True) class Text(GenericText): pass class Int(GenericText): align = 1 def __init__(self, view, attrs, renderer=None): if renderer is None: renderer = CellRendererInteger super(Int, self).__init__(view, attrs, renderer=renderer) self.factor = float(attrs.get('factor', 1)) def get_textual_value(self, record): if not record: return '' return record[self.attrs['name']].get_client( record, factor=self.factor) def value_from_text(self, record, text, callback=None): field = record[self.attrs['name']] field.set_client(record, text, factor=self.factor) if callback: callback() class Boolean(GenericText): align = 0.5 def __init__(self, view, attrs=None, renderer=None): if renderer is None: renderer = CellRendererToggle super(Boolean, self).__init__(view, attrs, renderer=renderer) self.renderer.connect('toggled', self._sig_toggled) def _sig_toggled(self, renderer, path): store = self.view.treeview.get_model() record = store.get_value(store.get_iter(path), 0) field = record[self.attrs['name']] if not self.attrs.get('readonly', field.get_state_attrs(record).get('readonly', False)): value = record[self.attrs['name']].get_client(record) record[self.attrs['name']].set_client(record, int(not value)) self.view.treeview.set_cursor(path) return True class URL(Char): @realized @CellCache.cache def setter(self, column, cell, store, iter): super(URL, self).setter(column, cell, store, iter) record = store.get_value(iter, 0) field = record[self.attrs['name']] field.state_set(record, states=('readonly',)) readonly = field.get_state_attrs(record).get('readonly', False) cell.set_property('visible', not readonly) class Date(GenericText): def __init__(self, view, attrs, renderer=None): if renderer is None: renderer = CellRendererDate super(Date, self).__init__(view, attrs, renderer=renderer) @realized def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) field = record[self.attrs['name']] self.renderer.props.format = self.get_format(record, field) super(Date, self).setter(column, cell, store, iter) def get_format(self, record, field): if field and record: return field.date_format(record) else: return '%x' def get_textual_value(self, record): if not record: return '' value = record[self.attrs['name']].get_client(record) if value: return datetime_strftime(value, self.renderer.props.format) else: return '' class Time(Date): def __init__(self, view, attrs, renderer=None): if renderer is None: renderer = CellRendererTime super(Time, self).__init__(view, attrs, renderer=renderer) def get_format(self, record, field): if field and record: return field.time_format(record) else: return '%X' def get_textual_value(self, record): if not record: return '' value = record[self.attrs['name']].get_client(record) if value is not None: if isinstance(value, datetime.datetime): value = value.time() return value.strftime(self.renderer.props.format) else: return '' class TimeDelta(GenericText): align = 1 class Float(Int): def __init__(self, view, attrs, renderer=None): if renderer is None: renderer = CellRendererFloat super(Float, self).__init__(view, attrs, renderer=renderer) @realized def setter(self, column, cell, store, iter): super(Float, self).setter(column, cell, store, iter) record = store.get_value(iter, 0) field = record[self.attrs['name']] digits = field.digits(record, factor=self.factor) cell.digits = digits class Binary(GenericText): align = 0.5 def __init__(self, view, attrs, renderer=None): self.filename = attrs.get('filename') if renderer is None: renderer = partial(CellRendererBinary, bool(self.filename)) super(Binary, self).__init__(view, attrs, renderer=renderer) self.renderer.connect('select', self.select_binary) self.renderer.connect('open', self.open_binary) self.renderer.connect('save', self.save_binary) self.renderer.connect('clear', self.clear_binary) def get_textual_value(self, record): pass def value_from_text(self, record, text, callback=None): if callback: callback() @realized @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) field = record[self.attrs['name']] if hasattr(field, 'get_size'): size = field.get_size(record) else: size = len(field.get(record)) cell.set_property('size', common.humanize(size) if size else '') states = ('invisible',) if getattr(self.view.treeview, 'editable', False): states = ('readonly', 'required', 'invisible') field.state_set(record, states=states) invisible = field.get_state_attrs(record).get('invisible', False) cell.set_property('visible', not invisible) if getattr(self.view.treeview, 'editable', False): readonly = self.attrs.get('readonly', field.get_state_attrs(record).get('readonly', False)) if invisible: readonly = True cell.set_property('editable', not readonly) def select_binary(self, renderer, path): record, field = self._get_record_field(path) filename = '' filename = file_selection(_('Open...')) if filename: field.set_client(record, open(filename, 'rb').read()) if self.filename: filename_field = record.group.fields[self.filename] filename_field.set_client(record, os.path.basename(filename)) def open_binary(self, renderer, path): if not self.filename: return dtemp = tempfile.mkdtemp(prefix='tryton_') record, field = self._get_record_field(path) filename_field = record.group.fields.get(self.filename) filename = filename_field.get(record) if not filename: return root, ext = os.path.splitext(filename) filename = ''.join([slugify(root), os.extsep, slugify(ext)]) file_path = os.path.join(dtemp, filename) with open(file_path, 'wb') as fp: if hasattr(field, 'get_data'): fp.write(field.get_data(record)) else: fp.write(field.get(record)) root, type_ = os.path.splitext(filename) if type_: type_ = type_[1:] file_open(file_path, type_) def save_binary(self, renderer, path): filename = '' record, field = self._get_record_field(path) if self.filename: filename_field = record.group.fields.get(self.filename) filename = filename_field.get(record) filename = file_selection(_('Save As...'), filename=filename, action=gtk.FILE_CHOOSER_ACTION_SAVE) if filename: with open(filename, 'wb') as fp: if hasattr(field, 'get_data'): fp.write(field.get_data(record)) else: fp.write(field.get(record)) def clear_binary(self, renderer, path): record, field = self._get_record_field(path) if self.filename: filename_field = record.group.fields[self.filename] filename_field.set_client(record, None) field.set_client(record, None) class Image(GenericText): align = 0.5 def __init__(self, view, attrs=None, renderer=None): if renderer is None: renderer = gtk.CellRendererPixbuf super(Image, self).__init__(view, attrs, renderer) self.renderer.set_fixed_size(self.attrs.get('width', -1), self.attrs.get('height', -1)) @realized @CellCache.cache def setter(self, column, cell, store, iter_): record = store.get_value(iter_, 0) field = record[self.field_name] value = field.get_client(record) if isinstance(value, (int, long)): if value > common.BIG_IMAGE_SIZE: value = None else: value = field.get_data(record) pixbuf = data2pixbuf(value) if (self.attrs.get('width', -1) != -1 or self.attrs.get('height', -1) != -1): pixbuf = common.resize_pixbuf(pixbuf, self.attrs['width'], self.attrs['height']) cell.set_property('pixbuf', pixbuf) def get_textual_value(self, record): if not record: return '' return str(record[self.attrs['name']].get_size(record)) class M2O(GenericText): def __init__(self, view, attrs, renderer=None): if renderer is None and int(attrs.get('completion', 1)): renderer = partial(CellRendererTextCompletion, self.set_completion) super(M2O, self).__init__(view, attrs, renderer=renderer) def value_from_text(self, record, text, callback=None): field = record.group.fields[self.attrs['name']] if not text: field.set_client(record, (None, '')) if callback: callback() return relation = record[self.attrs['name']].attrs['relation'] domain = record[self.attrs['name']].domain_get(record) context = record[self.attrs['name']].get_context(record) win = self.search_remote(record, relation, text, domain=domain, context=context, callback=callback) if len(win.screen.group) == 1: win.response(None, gtk.RESPONSE_OK) else: win.show() def open_remote(self, record, create=True, changed=False, text=None, callback=None): field = record.group.fields[self.attrs['name']] relation = field.attrs['relation'] access = common.MODELACCESS[relation] if (create and not (self.attrs.get('create', True) and access['create'])): return elif not access['read']: return domain = field.domain_get(record) context = field.get_context(record) if create: obj_id = None elif not changed: obj_id = field.get(record) else: self.search_remote(record, relation, text, domain=domain, context=context, callback=callback).show() return screen = Screen(relation, domain=domain, context=context, mode=['form'], view_ids=self.attrs.get('view_ids', '').split(','), exclude_field=field.attrs.get('relation_field')) def open_callback(result): if result: value = (screen.current_record.id, screen.current_record.rec_name()) field.set_client(record, value, force_change=True) if callback: callback() if obj_id: screen.load([obj_id]) WinForm(screen, open_callback, save_current=True, title=field.attrs.get('string')) else: WinForm(screen, open_callback, new=True, save_current=True, title=field.attrs.get('string'), rec_name=text) def search_remote(self, record, relation, text, domain=None, context=None, callback=None): field = record.group.fields[self.attrs['name']] relation = field.attrs['relation'] access = common.MODELACCESS[relation] create_access = self.attrs.get('create', True) and access['create'] def search_callback(found): value = None if found: value = found[0] field.set_client(record, value) if callback: callback() win = WinSearch(relation, search_callback, sel_multi=False, context=context, domain=domain, view_ids=self.attrs.get('view_ids', '').split(','), new=create_access, title=self.attrs.get('string')) win.screen.search_filter(quote(text.decode('utf-8'))) return win def set_completion(self, entry, path): if entry.get_completion(): entry.set_completion(None) access = common.MODELACCESS[self.attrs['relation']] completion = get_completion( search=access['read'], create=self.attrs.get('create', True) and access['create']) completion.connect('match-selected', self._completion_match_selected, path) completion.connect('action-activated', self._completion_action_activated, path) entry.set_completion(completion) entry.connect('key-press-event', self._key_press, path) entry.connect('changed', self._update_completion, path) def _key_press(self, entry, event, path): record, field = self._get_record_field(path) if (field.get(record) is not None and event.keyval in (gtk.keysyms.Delete, gtk.keysyms.BackSpace)): entry.set_text('') field.set_client(record, None) return False def _completion_match_selected(self, completion, model, iter_, path): record, field = self._get_record_field(path) rec_name, record_id = model.get(iter_, 0, 1) field.set_client(record, (record_id, rec_name)) completion.get_entry().set_text(rec_name) completion_model = completion.get_model() completion_model.clear() completion_model.search_text = rec_name return True def _update_completion(self, entry, path): record, field = self._get_record_field(path) if field.get(record) is not None: return model = field.attrs['relation'] update_completion(entry, record, field, model) def _completion_action_activated(self, completion, index, path): record, field = self._get_record_field(path) entry = completion.get_entry() entry.handler_block(entry.editing_done_id) def callback(): entry.handler_unblock(entry.editing_done_id) entry.set_text(field.get_client(record)) if index == 0: self.open_remote(record, create=False, changed=True, text=entry.get_text(), callback=callback) elif index == 1: self.open_remote(record, create=True, callback=callback) else: entry.handler_unblock(entry.editing_done_id) class O2O(M2O): pass class O2M(GenericText): align = 0.5 def get_textual_value(self, record): return '( ' + str(len(record[self.attrs['name']] .get_eval(record))) + ' )' def value_from_text(self, record, text, callback=None): if callback: callback() def open_remote(self, record, create=True, changed=False, text=None, callback=None): group = record.value[self.attrs['name']] field = record.group.fields[self.attrs['name']] relation = field.attrs['relation'] context = field.get_context(record) access = common.MODELACCESS[relation] if not access['read']: return screen = Screen(relation, mode=['tree', 'form'], view_ids=self.attrs.get('view_ids', '').split(','), exclude_field=field.attrs.get('relation_field')) screen.pre_validate = bool(int(self.attrs.get('pre_validate', 0))) screen.group = group def open_callback(result): if callback: callback() WinForm(screen, open_callback, view_type='tree', context=context, title=field.attrs.get('string')) class M2M(O2M): def open_remote(self, record, create=True, changed=False, text=None, callback=None): group = record.value[self.attrs['name']] field = record.group.fields[self.attrs['name']] relation = field.attrs['relation'] context = field.get_context(record) domain = field.domain_get(record) screen = Screen(relation, mode=['tree', 'form'], view_ids=self.attrs.get('view_ids', '').split(','), exclude_field=field.attrs.get('relation_field')) screen.group = group def open_callback(result): if callback: callback() WinForm(screen, open_callback, view_type='tree', domain=domain, context=context, title=field.attrs.get('string')) class Selection(GenericText, SelectionMixin, PopdownMixin): def __init__(self, *args, **kwargs): if 'renderer' not in kwargs: kwargs['renderer'] = CellRendererCombo super(Selection, self).__init__(*args, **kwargs) self.init_selection() # Use a variable let Python holding reference when calling set_property model = self.get_popdown_model(self.selection)[0] self.renderer.set_property('model', model) self.renderer.set_property('text-column', 0) def get_textual_value(self, record): field = record[self.attrs['name']] self.update_selection(record, field) value = field.get(record) text = dict(self.selection).get(value, '') if value and not text: text = self.get_inactive_selection(value) return text def value_from_text(self, record, text, callback=None): if callback: callback() def editing_started(self, cell, editable, path): super(Selection, self).editing_started(cell, editable, path) store = self.view.treeview.get_model() record = store.get_value(store.get_iter(path), 0) field = record[self.attrs['name']] set_value = lambda *a: self.set_value(editable, record, field) editable.get_child().connect('activate', set_value) editable.get_child().connect('focus-out-event', set_value) editable.connect('changed', set_value) self.update_selection(record, field) self.set_popdown(self.selection, editable) value = field.get(record) if not self.set_popdown_value(editable, value): self.get_inactive_selection(value) self.set_popdown_value(editable, value) return False def set_value(self, editable, record, field): value = self.get_popdown_value(editable) if 'relation' in self.attrs and value: value = (value, editable.get_active_text()) field.set_client(record, value) return False class Reference(GenericText, SelectionMixin): def __init__(self, view, attrs, renderer=None): super(Reference, self).__init__(view, attrs, renderer=renderer) self.init_selection() def get_textual_value(self, record): field = record[self.attrs['name']] self.update_selection(record, field) value = field.get_client(record) if not value: model, name = '', '' else: model, name = value if model: return dict(self.selection).get(model, model) + ',' + name else: return name def value_from_text(self, record, text, callback=None): if callback: callback() class ProgressBar(object): align = 0.5 orientations = { 'left_to_right': gtk.PROGRESS_LEFT_TO_RIGHT, 'right_to_left': gtk.PROGRESS_RIGHT_TO_LEFT, 'bottom_to_top': gtk.PROGRESS_BOTTOM_TO_TOP, 'top_to_bottom': gtk.PROGRESS_TOP_TO_BOTTOM, } def __init__(self, view, attrs): super(ProgressBar, self).__init__() self.view = view self.attrs = attrs self.renderer = gtk.CellRendererProgress() orientation = self.orientations.get(self.attrs.get('orientation', 'left_to_right'), gtk.PROGRESS_LEFT_TO_RIGHT) if hasattr(self.renderer, 'set_orientation'): self.renderer.set_orientation(orientation) else: self.renderer.set_property('orientation', orientation) self.renderer.set_property('yalign', 0) @realized @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) field = record[self.attrs['name']] field.state_set(record, states=('invisible',)) invisible = field.get_state_attrs(record).get('invisible', False) cell.set_property('visible', not invisible) text = self.get_textual_value(record) if text: text = _('%s%%') % text cell.set_property('text', text) value = field.get(record) or 0.0 cell.set_property('value', value * 100) def open_remote(self, record, create, changed=False, text=None, callback=None): raise NotImplementedError def get_textual_value(self, record): return record[self.attrs['name']].get_client(record, factor=100) or '' def value_from_text(self, record, text, callback=None): field = record[self.attrs['name']] field.set_client(record, float(text)) if callback: callback() class Button(object): def __init__(self, view, attrs): super(Button, self).__init__() self.attrs = attrs self.renderer = CellRendererButton(attrs.get('string', _('Unknown'))) self.view = view self.renderer.connect('clicked', self.button_clicked) self.renderer.set_property('yalign', 0) @realized @CellCache.cache def setter(self, column, cell, store, iter): record = store.get_value(iter, 0) states = record.expr_eval(self.attrs.get('states', {})) if record.group.readonly or record.readonly: states['readonly'] = True invisible = states.get('invisible', False) cell.set_property('visible', not invisible) readonly = states.get('readonly', False) cell.set_property('sensitive', not readonly) parent = record.parent if record else None while parent: if parent.modified: cell.set_property('sensitive', False) break parent = parent.parent # TODO icon def button_clicked(self, widget, path): if not path: return True store = self.view.treeview.get_model() record = store.get_value(store.get_iter(path), 0) state_changes = record.expr_eval( self.attrs.get('states', {})) if state_changes.get('invisible') \ or state_changes.get('readonly'): return True widget.handler_block_by_func(self.button_clicked) try: self.view.screen.button(self.attrs) finally: widget.handler_unblock_by_func(self.button_clicked) tryton-4.6.5/tryton/gui/window/view_form/view/list_gtk/editabletree.py0000644000175000017500000002701013251060075025620 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import gobject from itertools import islice, cycle from tryton.common import MODELACCESS from tryton.common.datetime_ import Date, Time _ = gettext.gettext class TreeView(gtk.TreeView): display_counter = 0 def __init__(self, view): super(TreeView, self).__init__() self.view = view def next_column(self, path, column=None, editable=True, _sign=1): columns = self.get_columns() if column is None: column = columns[-1 if _sign > 0 else 0] model = self.get_model() record = model.get_value(model.get_iter(path), 0) if _sign < 0: columns.reverse() current_idx = columns.index(column) + 1 for column in islice(cycle(columns), current_idx, len(columns) + current_idx): if not column.name: continue widget = self.view.get_column_widget(column) field = record[column.name] field.state_set(record, states=('readonly', 'invisible')) invisible = field.get_state_attrs(record).get('invisible', False) if not column.get_visible(): invisible = True if editable: readonly = widget.attrs.get('readonly', field.get_state_attrs(record).get('readonly', False)) else: readonly = False if not (invisible or readonly): return column def prev_column(self, path, column=None, editable=True): return self.next_column(path, column=column, editable=editable, _sign=-1) class EditableTreeView(TreeView): leaving_record_events = (gtk.keysyms.Up, gtk.keysyms.Down, gtk.keysyms.Return) leaving_events = leaving_record_events + (gtk.keysyms.Tab, gtk.keysyms.ISO_Left_Tab, gtk.keysyms.KP_Enter) def __init__(self, position, view): super(EditableTreeView, self).__init__(view) self.editable = position def on_quit_cell(self, current_record, column, value, callback=None): field = current_record[column.name] widget = self.view.get_column_widget(column) # The value has not changed and is valid ... do nothing. if value == widget.get_textual_value(current_record) \ and field.validate(current_record): if callback: callback() return widget.value_from_text(current_record, value, callback=callback) def on_open_remote(self, current_record, column, create, value, entry=None, callback=None): widget = self.view.get_column_widget(column) if value != widget.get_textual_value(current_record) or not value: changed = True else: changed = False try: widget.open_remote(current_record, create, changed, value, callback=callback) except NotImplementedError: pass def on_create_line(self): access = MODELACCESS[self.view.screen.model_name] model = self.get_model() limit = (self.view.screen.size_limit is not None and (len(model) >= self.view.screen.size_limit >= 0)) if not access['create'] or limit: return if self.editable == 'top': method = model.prepend else: method = model.append new_record = model.group.new() res = method(new_record) sequence = self.view.attributes.get('sequence') if sequence: model.group.set_sequence(field=sequence) return res def set_cursor(self, path, focus_column=None, start_editing=False): self.grab_focus() if focus_column: widget = self.view.get_column_widget(focus_column) if isinstance(widget.renderer, gtk.CellRendererToggle): start_editing = False self.scroll_to_cell(path, focus_column, use_align=False) super(EditableTreeView, self).set_cursor(path, focus_column, start_editing) def set_value(self): path, column = self.get_cursor() model = self.get_model() if not path or not column or not column.name: return True record = model.get_value(model.get_iter(path), 0) field = record[column.name] if hasattr(field, 'editabletree_entry'): entry = field.editabletree_entry if isinstance(entry, (Date, Time)): entry.activate() txt = entry.props.value elif isinstance(entry, gtk.Entry): txt = entry.get_text() else: txt = entry.get_active_text() self.on_quit_cell(record, column, txt) return True def on_keypressed(self, entry, event): path, column = self.get_cursor() model = self.get_model() record = model.get_value(model.get_iter(path), 0) self.display_counter += 1 # Force a display leaving = False if event.keyval == gtk.keysyms.Right: if isinstance(entry, gtk.Entry): if entry.get_position() >= \ len(entry.get_text().decode('utf-8')) \ and not entry.get_selection_bounds(): leaving = True else: leaving = True elif event.keyval == gtk.keysyms.Left: if isinstance(entry, gtk.Entry): if entry.get_position() <= 0 \ and not entry.get_selection_bounds(): leaving = True else: leaving = True if event.keyval in self.leaving_events or leaving: if isinstance(entry, (Date, Time)): entry.activate() txt = entry.props.value elif isinstance(entry, gtk.Entry): txt = entry.get_text() else: txt = entry.get_active_text() keyval = event.keyval entry.handler_block(entry.editing_done_id) def callback(): entry.handler_unblock(entry.editing_done_id) field = record[column.name] # Must wait the edited entry came back in valid state if field.validate(record): if (keyval in (gtk.keysyms.Tab, gtk.keysyms.KP_Enter) or (keyval == gtk.keysyms.Right and leaving)): gobject.idle_add(self.set_cursor, path, self.next_column(path, column), True) elif (keyval == gtk.keysyms.ISO_Left_Tab or (keyval == gtk.keysyms.Left and leaving)): gobject.idle_add(self.set_cursor, path, self.prev_column(path, column), True) elif keyval in self.leaving_record_events: fields = self.view.widgets.keys() if not record.validate(fields): invalid_fields = record.invalid_fields col = None for col in self.get_columns(): if col.name in invalid_fields: break gobject.idle_add(self.set_cursor, path, col, True) return if ((self.view.screen.pre_validate and not record.pre_validate()) or (not self.view.screen.parent and not record.save())): gobject.idle_add(self.set_cursor, path, column, True) return entry.handler_block(entry.editing_done_id) if keyval == gtk.keysyms.Up: self._key_up(path, model, column) elif keyval == gtk.keysyms.Down: self._key_down(path, model, column) elif keyval == gtk.keysyms.Return: if self.editable == 'top': new_path = self._key_up(path, model) else: new_path = self._key_down(path, model) gobject.idle_add(self.set_cursor, new_path, self.next_column(new_path), True) entry.handler_unblock(entry.editing_done_id) else: gobject.idle_add(self.set_cursor, path, column, True) self.on_quit_cell(record, column, txt, callback=callback) return True elif event.keyval in (gtk.keysyms.F3, gtk.keysyms.F2): if isinstance(entry, gtk.Entry): value = entry.get_text() else: value = entry.get_active_text() entry.handler_block(entry.editing_done_id) def callback(): widget = self.view.get_column_widget(column) value = widget.get_textual_value(record) if isinstance(entry, gtk.Entry): entry.set_text(value) else: entry.set_active_text(value) entry.handler_unblock(entry.editing_done_id) self.on_open_remote(record, column, create=(event.keyval == gtk.keysyms.F3), value=value, callback=callback) else: field = record[column.name] if isinstance(entry, gtk.Entry): entry.set_max_length(int(field.attrs.get('size', 0))) # store in the record the entry widget to get the value in # set_value field.editabletree_entry = entry def remove_widget(widget): if hasattr(field, 'editabletree_entry'): del field.editabletree_entry entry.connect('remove-widget', remove_widget) record.modified_fields.setdefault(column.name) return False return True def _key_down(self, path, model, column=None): if path[0] == len(model) - 1 and self.editable == 'bottom': self.on_create_line() new_path = (path[0] + 1) % len(model) if not column: column = self.next_column(new_path) self.set_cursor(new_path, column, True) self.scroll_to_cell(new_path) return new_path def _key_up(self, path, model, column=None): if path[0] == 0 and self.editable == 'top': self.on_create_line() new_path = 0 else: new_path = (path[0] - 1) % len(model) if not column: column = self.next_column(new_path) self.set_cursor(new_path, column, True) self.scroll_to_cell(new_path) return new_path def on_editing_done(self, entry): path, column = self.get_cursor() if not path: return True model = self.get_model() record = model.get_value(model.get_iter(path), 0) if isinstance(entry, (Date, Time)): entry.activate() self.on_quit_cell(record, column, entry.props.value) elif isinstance(entry, gtk.Entry): self.on_quit_cell(record, column, entry.get_text()) elif isinstance(entry, (gtk.ComboBoxEntry, gtk.ComboBox)): self.on_quit_cell(record, column, entry.get_active_text()) tryton-4.6.5/tryton/gui/window/view_form/view/calendar_gtk/0000755000175000017500000000000013260723567023427 5ustar cedced00000000000000tryton-4.6.5/tryton/gui/window/view_form/view/calendar_gtk/toolbar.py0000644000175000017500000002151113251060075025427 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime import calendar import gettext import gtk from tryton.gui import Main from tryton.common.datetime_ import popup_position, popup_show, popup_hide _ = gettext.gettext class Toolbar(gtk.Toolbar): def __init__(self, goocalendar): super(Toolbar, self).__init__() self.goocalendar = goocalendar self.accel_group = Main.get_main().accel_group today_button = gtk.ToolButton() today_button.set_label(_('Today')) today_button.set_homogeneous(False) today_button.connect("clicked", self.on_today_button_clicked) today_button.add_accelerator("clicked", self.accel_group, gtk.keysyms.t, gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) self.insert(today_button, -1) arrow_left = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_NONE) go_back = gtk.ToolButton() go_back.set_icon_widget(arrow_left) go_back.set_label(_("go back")) go_back.set_expand(False) go_back.set_homogeneous(False) go_back.connect("clicked", self.on_go_back_clicked) self.insert(go_back, -1) self.current_page_label = gtk.Label("") self.current_page = gtk.ToggleToolButton() self.current_page.set_label_widget(self.current_page_label) self.current_page.connect("clicked", self.on_current_page_clicked) self.insert(self.current_page, -1) self.__cal_popup = gtk.Window(gtk.WINDOW_POPUP) self.__cal_popup.set_events( self.__cal_popup.get_events() | gtk.gdk.KEY_PRESS_MASK) self.__cal_popup.set_resizable(False) self.__cal_popup.connect('delete-event', self.on_cal_popup_closed) self.__cal_popup.connect( 'key-press-event', self.on_cal_popup_key_pressed) self.__cal_popup.connect( 'button-press-event', self.on_cal_popup_button_pressed) gtkcal = gtk.Calendar() gtkcal.connect('day-selected', self.on_gtkcal_day_selected) gtkcal.connect( 'day-selected-double-click', self.on_gtkcal_day_selected_double_click) gtkcal.set_display_options( gtk.CALENDAR_SHOW_HEADING | gtk.CALENDAR_SHOW_WEEK_NUMBERS | gtk.CALENDAR_SHOW_DAY_NAMES) gtkcal.set_no_show_all(True) self.__cal_popup.add(gtkcal) gtkcal.show() self.gtkcal = gtkcal self.goocalendar.connect('day-selected', self.on_goocalendar_day_selected) arrow_right = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) go_forward = gtk.ToolButton() go_forward.set_icon_widget(arrow_right) go_forward.set_label(_("go forward")) go_forward.set_expand(False) go_forward.set_homogeneous(False) go_forward.connect("clicked", self.on_go_forward_clicked) self.insert(go_forward, -1) arrow_left = gtk.Arrow(gtk.ARROW_LEFT, gtk.SHADOW_NONE) previous_year = gtk.ToolButton() previous_year.set_icon_widget(arrow_left) previous_year.set_label(_("previous year")) previous_year.set_expand(False) previous_year.set_homogeneous(False) previous_year.connect("clicked", self.on_previous_year_clicked) self.insert(previous_year, -1) self.current_year_label = gtk.Label("") current_year = gtk.ToolItem() current_year.add(self.current_year_label) self.insert(current_year, -1) arrow_right = gtk.Arrow(gtk.ARROW_RIGHT, gtk.SHADOW_NONE) next_year = gtk.ToolButton() next_year.set_icon_widget(arrow_right) next_year.set_label(_("next year")) next_year.set_expand(False) next_year.set_homogeneous(False) next_year.connect("clicked", self.on_next_year_clicked) self.insert(next_year, -1) blank_widget = gtk.ToolItem() blank_widget.set_expand(True) self.insert(blank_widget, -1) week_button = gtk.RadioToolButton() week_button.set_label(_('Week View')) week_button.connect("clicked", self.on_week_button_clicked) week_button.add_accelerator("clicked", self.accel_group, gtk.keysyms.w, gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) self.insert(week_button, -1) if hasattr(gtk.RadioToolButton, 'new_from_widget'): month_button = gtk.RadioToolButton.new_from_widget(week_button) else: month_button = gtk.RadioToolButton(week_button) month_button.set_label_widget(gtk.Label(_('Month View'))) month_button.connect("clicked", self.on_month_button_clicked) month_button.add_accelerator("clicked", self.accel_group, gtk.keysyms.m, gtk.gdk.MODIFIER_MASK, gtk.ACCEL_VISIBLE) self.insert(month_button, -1) buttons = { 'month': month_button, 'week': week_button } buttons[self.goocalendar.view].set_active(True) self.update_displayed_date() self.set_style(gtk.TOOLBAR_ICONS) def update_displayed_date(self): date = self.goocalendar.selected_date year = date.timetuple()[0] month = date.timetuple()[1] day = date.timetuple()[2] self.current_year_label.set_text(str(year)) if self.goocalendar.view == "month": new_label = calendar.month_name[month] self.current_page_label.set_text(new_label) elif self.goocalendar.view == "week": week_number = datetime.date(year, month, day).isocalendar()[1] new_label = _('Week') + ' ' + str(week_number) new_label += ' (' + calendar.month_name[month] + ')' self.current_page_label.set_text(new_label) def on_today_button_clicked(self, widget): self.goocalendar.select(datetime.date.today()) def on_go_back_clicked(self, widget): self.goocalendar.previous_page() def on_current_page_clicked(self, widget): if widget.get_active(): self.__cal_popup.set_transient_for(widget.get_toplevel()) popup_position(widget, self.__cal_popup) popup_show(self.__cal_popup) def on_cal_popup_closed(self, widget): self.cal_popup_hide() return True def on_cal_popup_key_pressed(self, widget, event): if event.keyval != gtk.keysyms.Escape: return False widget.stop_emission('key-press-event') self.cal_popup_hide() return True def on_cal_popup_button_pressed(self, widget, event): child = event.window if child != widget.window: while child: if child == widget.window: return False child = child.get_parent() self.cal_popup_hide() return True def cal_popup_hide(self): popup_hide(self.__cal_popup) self.current_page.set_active(False) def on_gtkcal_day_selected(self, gtkcal): year, month, day = gtkcal.get_date() month += 1 # months go from 1 to 12 instead of from 0 to 11 self.goocalendar.select(datetime.date(year, month, day)) def on_gtkcal_day_selected_double_click(self, gtkcal): self.cal_popup_hide() def on_goocalendar_day_selected(self, goocalendar, day): # months go from 0 to 11 in gtk.Calendar instead of 1 to 12 new_date = self.goocalendar.selected_date self.gtkcal.select_month(new_date.month - 1, new_date.year) self.gtkcal.handler_block_by_func(self.on_gtkcal_day_selected) self.gtkcal.select_day(new_date.day) self.gtkcal.handler_unblock_by_func(self.on_gtkcal_day_selected) def on_go_forward_clicked(self, widget): self.goocalendar.next_page() def on_previous_year_clicked(self, widget): date = datetime.datetime.combine(self.goocalendar.selected_date, datetime.time(0)) year, month, day = date.timetuple()[:3] year -= 1 cal = calendar.Calendar(self.goocalendar.firstweekday) next_month_days = [d for d in cal.itermonthdays(year, month)] if day not in next_month_days: day = max(next_month_days) self.goocalendar.select(datetime.datetime(year, month, day)) def on_next_year_clicked(self, widget): date = datetime.datetime.combine(self.goocalendar.selected_date, datetime.time(0)) year, month, day = date.timetuple()[:3] year += 1 cal = calendar.Calendar(self.goocalendar.firstweekday) next_month_days = [d for d in cal.itermonthdays(year, month)] if day not in next_month_days: day = max(next_month_days) self.goocalendar.select(datetime.datetime(year, month, day)) def on_week_button_clicked(self, widget): self.goocalendar.set_view("week") def on_month_button_clicked(self, widget): self.goocalendar.set_view("month") tryton-4.6.5/tryton/gui/window/view_form/view/calendar_gtk/dates_period.py0000644000175000017500000000163613175640533026445 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import datetime class DatesPeriod(): """ This class represents a period of time between two dates or two datetimes. """ def __init__(self, start, end): assert type(start) == type(end) self.start = start self.end = end def is_in(self, period): return self.start >= period.start and self.end <= period.end def get_dates(self, format_datetime=False): if not format_datetime: return self.start, self.end midnight = datetime.time(0) start = datetime.datetime.combine(self.start, midnight) end = datetime.datetime.combine(self.end, midnight) return start, end def __str__(self): string = self.start.__str__() + ' => ' + self.end.__str__() return string tryton-4.6.5/tryton/gui/window/view_form/view/calendar_gtk/__init__.py0000644000175000017500000000022013175640533025526 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. tryton-4.6.5/tryton/gui/window/view_form/view/calendar_gtk/calendar_.py0000644000175000017500000001054213251060075025677 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import calendar import datetime import goocalendar from dates_period import DatesPeriod class Calendar_(goocalendar.Calendar): 'Calendar' def __init__(self, attrs, screen, fields, event_store=None): super(Calendar_, self).__init__( event_store, attrs.get('mode', 'month')) self.attrs = attrs self.screen = screen self.fields = fields self.event_store = event_store self.current_domain_period = self.get_displayed_period() def set_default_date(self, record, selected_date): dtstart = self.attrs['dtstart'] record[dtstart].set(record, datetime.datetime.combine(selected_date, datetime.time(0))) def get_displayed_period(self): cal = calendar.Calendar(self.firstweekday) if self.view == 'week': week = goocalendar.util.my_weekdatescalendar(cal, self.selected_date) first_date = week[0] last_date = week[6] last_date += datetime.timedelta(1) elif self.view == 'month': weeks = goocalendar.util.my_monthdatescalendar(cal, self.selected_date) first_date = weeks[0][0] last_date = weeks[5][6] last_date += datetime.timedelta(1) displayed_period = DatesPeriod(first_date, last_date) return displayed_period def update_domain(self): displayed_period = self.get_displayed_period() if not displayed_period.is_in(self.current_domain_period): self.current_domain_period = displayed_period return True return False def current_domain(self): first_datetime, last_datetime = \ self.current_domain_period.get_dates(True) dtstart = self.attrs['dtstart'] dtend = self.attrs.get('dtend') or dtstart domain = ['OR', ['AND', (dtstart, '>=', first_datetime), (dtstart, '<', last_datetime)], ['AND', (dtend, '>=', first_datetime), (dtend, '<', last_datetime)], ['AND', (dtstart, '<', first_datetime), (dtend, '>', last_datetime)]] return domain def get_colors(self, record): text_color = None if self.attrs.get('color'): text_color = record[self.attrs['color']].get(record) bg_color = 'lightblue' if self.attrs.get('background_color'): bg_color = record[self.attrs['background_color']].get( record) return text_color, bg_color def display(self, group): dtstart = self.attrs['dtstart'] dtend = self.attrs.get('dtend') if self.screen.current_record: record = self.screen.current_record date = record[dtstart].get(record) if date: # select the day of the current record self.select(date) if self._event_store: self._event_store.clear() else: event_store = goocalendar.EventStore() self.event_store = event_store for record in group: if not record[dtstart].get(record): continue start = record[dtstart].get_client(record) if dtend: end = record[dtend].get_client(record) else: end = None midnight = datetime.time(0) all_day = False if not isinstance(start, datetime.datetime): start = datetime.datetime.combine(start, midnight) if end and not isinstance(end, datetime.datetime): end = datetime.datetime.combine(end, midnight) all_day = True elif not end: all_day = True # Skip invalid event if end is not None and start > end: continue text_color, bg_color = self.get_colors(record) label = '\n'.join(record[attrs['name']].get_client(record) for attrs in self.fields).rstrip() event = goocalendar.Event(label, start, end, text_color=text_color, bg_color=bg_color, all_day=all_day) event.record = record self._event_store.add(event) self.grab_focus(self.get_root_item()) tryton-4.6.5/tryton/gui/window/view_form/__init__.py0000644000175000017500000000023613175640533022145 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import screen tryton-4.6.5/tryton/gui/window/about.py0000644000175000017500000011061013260723566017524 0ustar cedced00000000000000# -*- coding: utf-8 -*- # This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext import webbrowser from tryton.config import TRYTON_ICON, CONFIG from tryton.common import get_toplevel_window from tryton import __version__ COPYRIGHT = '''\ Copyright (C) 2010-2018 Nicolas Évrard. Copyright (C) 2007-2018 Cédric Krier. Copyright (C) 2007-2011 Bertrand Chenal. Copyright (C) 2008-2018 B2CK SPRL. Copyright (C) 2008-2011 Udo Spallek. Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR. Copyright (C) 2007-2009 Lorenzo Gil Sanchez. Copyright (C) 2004-2008 Tiny SPRL. ''' AUTHORS = [ 'Bertrand Chenal ', 'Cédric Krier ', 'Franz Wiesinger', 'Hartmut Goebel', 'Korbinian Preisler ', 'Mathias Behrle ', 'Nicolas Évrard ', 'Sednacom ', 'Udo Spallek ', ] LICENSE = ''' GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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 Lesser General Public License instead of this License. But first, please read .''' _ = gettext.gettext class About(object): def __init__(self): if hasattr(gtk, 'about_dialog_set_email_hook'): gtk.about_dialog_set_email_hook(lambda widget, link: webbrowser.open(link, new=2)) if hasattr(gtk, 'about_dialog_set_url_hook'): gtk.about_dialog_set_url_hook(lambda widget, link: webbrowser.open(link, new=2)) parent = get_toplevel_window() self.win = gtk.AboutDialog() self.win.set_transient_for(parent) self.win.set_name(CONFIG['client.title']) self.win.set_version(__version__) self.win.set_copyright(COPYRIGHT) self.win.set_license(LICENSE) self.win.set_website('http://www.tryton.org/') self.win.set_authors(AUTHORS) self.win.set_logo(TRYTON_ICON) self.win.run() parent.present() self.win.destroy() def open(self, dialog, link): webbrowser.open(link, new=2) tryton-4.6.5/tryton/gui/window/shortcuts.py0000644000175000017500000001061013251060075020434 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from tryton.config import TRYTON_ICON from tryton.common import get_toplevel_window _ = gettext.gettext class Shortcuts(object): 'Shortcuts window' def __init__(self): self.parent = get_toplevel_window() self.dialog = gtk.Dialog(_('Keyboard Shortcuts'), self.parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG, (gtk.STOCK_OK, gtk.RESPONSE_OK)) self.dialog.set_icon(TRYTON_ICON) self.dialog.set_default_response(gtk.RESPONSE_OK) notebook = gtk.Notebook() self.dialog.vbox.pack_start(notebook) shortcuts = [ (_('Text Entries Shortcuts'),), (' + X', _('Cut selected text')), (' + C', _('Copy selected text')), (' + V', _('Paste copied text')), ('', _('Next widget')), (' + ', _('Previous widget')), (_('Relation Entries Shortcuts'),), ('', _('Create new relation')), ('', _('Open/Search relation')), (_('List Entries Shortcuts'),), ('', _('Create new line')), ('', _('Open relation')), ('', _('Mark line for deletion')), ('', _('Unmark line for deletion')), ] notebook.append_page(self._fill_table(shortcuts), gtk.Label(_('Edition Widgets'))) shortcuts = [ (_('Move Cursor'),), ('', _('Move to right')), ('', _('Move to left')), ('', _('Move up')), ('', _('Move down')), ('', _('Move up of one page')), ('', _('Move down of one page')), ('', _('Move to top')), ('', _('Move to bottom')), ('', _('Move to parent')), (_('Selection'),), (' + a', _('Select all')), (' + /', _('Select all')), (' + + a', _('Unselect all')), (' + + /', _('Unselect all')), ('', _('Select parent')), ('', _('Select/Activate current row')), (' + ', _('Select/Activate current row')), ('', _('Select/Activate current row')), ('', _('Select/Activate current row')), (' + ', _('Toggle selection')), (_('Expand/Collapse'),), ('+', _('Expand row')), ('-', _('Collapse row')), ('', _('Toggle row')), (' + ', _('Collapse all rows')), (' + ', _('Expand all rows')), ] notebook.append_page(self._fill_table(shortcuts), gtk.Label(_('Tree view'))) self.dialog.show_all() def _fill_table(self, shortcuts): table = gtk.Table(len(shortcuts), 2) table.set_col_spacings(15) table.set_row_spacings(3) table.set_border_width(8) i = 0 for shortcut in shortcuts: if len(shortcut) == 1: label = gtk.Label() if '\n' not in shortcut[0]: label.set_markup('' + shortcut[0] + '') else: label.set_text(shortcut[0]) label.set_alignment(0, 0.5) label.set_padding(2, 0) table.attach(label, 0, 2, i, i + 1, yoptions=False, xoptions=gtk.FILL) elif len(shortcut) == 2: label = gtk.Label() label.set_text(shortcut[0]) label.set_alignment(0, 0.5) table.attach(label, 0, 1, i, i + 1, yoptions=False, xoptions=gtk.FILL) label = gtk.Label() label.set_text(shortcut[1]) label.set_alignment(0, 0.5) table.attach(label, 1, 2, i, i + 1, yoptions=False, xoptions=gtk.FILL) i += 1 return table def run(self): 'Run the window' self.dialog.run() self.parent.present() self.dialog.destroy() tryton-4.6.5/tryton/gui/main.py0000644000175000017500000015135613255571102016032 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os import sys import gettext from urlparse import urlparse, parse_qsl import urllib import gobject import gtk import json import webbrowser import threading import tryton.rpc as rpc from tryton.common import RPCExecute, RPCException, RPCContextReload from tryton.config import CONFIG, TRYTON_ICON, get_config_dir import tryton.common as common from tryton.pyson import PYSONDecoder from tryton.jsonrpc import object_hook from tryton.action import Action from tryton.exceptions import TrytonServerError, TrytonError, \ TrytonServerUnavailable from tryton.gui.window import Window from tryton.gui.window.preference import Preference from tryton.gui.window import Limit from tryton.gui.window import Email from tryton.gui.window.dblogin import DBLogin from tryton.gui.window.about import About from tryton.gui.window.shortcuts import Shortcuts from tryton.common.cellrendererclickablepixbuf import \ CellRendererClickablePixbuf import tryton.translate as translate import tryton.plugins from tryton.common.placeholder_entry import PlaceholderEntry if os.environ.get('GTKOSXAPPLICATION'): import gtkosx_application else: gtkosx_application = None try: import gtkspell except ImportError: gtkspell = None _ = gettext.gettext _MAIN = [] class Main(object): window = None tryton_client = None def __init__(self, tryton_client): super(Main, self).__init__() Main.tryton_client = tryton_client self.window = gtk.Window() self._width = int(CONFIG['client.default_width']) self._height = int(CONFIG['client.default_height']) if CONFIG['client.maximize']: self.window.maximize() self.window.set_default_size(self._width, self._height) self.window.set_resizable(True) self.set_title() self.window.set_icon(TRYTON_ICON) self.window.connect("destroy", Main.sig_quit) self.window.connect("delete_event", self.sig_close) self.window.connect('configure_event', self.sig_configure) self.window.connect('window_state_event', self.sig_window_state) self.accel_group = gtk.AccelGroup() self.window.add_accel_group(self.accel_group) self.macapp = None if gtkosx_application is not None: self.macapp = gtkosx_application.Application() self.macapp.connect("NSApplicationBlockTermination", self.sig_close) gtk.accel_map_add_entry('/Connection/Connect', gtk.keysyms.O, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Connection/Quit', gtk.keysyms.Q, gtk.gdk.CONTROL_MASK) if sys.platform != 'darwin': gtk.accel_map_add_entry('/User/Reload Menu', gtk.keysyms.T, gtk.gdk.MOD1_MASK) gtk.accel_map_add_entry('/User/Toggle Menu', gtk.keysyms.T, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/User/Global Search', gtk.keysyms.K, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/User/Home', gtk.keysyms.H, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/New', gtk.keysyms.N, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Save', gtk.keysyms.S, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Duplicate', gtk.keysyms.D, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) gtk.accel_map_add_entry('/Form/Delete', gtk.keysyms.D, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Next', gtk.keysyms.Page_Down, 0) gtk.accel_map_add_entry('/Form/Previous', gtk.keysyms.Page_Up, 0) gtk.accel_map_add_entry('/Form/Switch View', gtk.keysyms.L, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Close', gtk.keysyms.W, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Previous Tab', gtk.keysyms.Left, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Next Tab', gtk.keysyms.Right, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Reload', gtk.keysyms.R, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Attachments', gtk.keysyms.T, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) gtk.accel_map_add_entry('/Form/Notes', gtk.keysyms.O, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) gtk.accel_map_add_entry('/Form/Relate', gtk.keysyms.R, gtk.gdk.CONTROL_MASK | gtk.gdk.SHIFT_MASK) gtk.accel_map_add_entry('/Form/Actions', gtk.keysyms.E, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Report', gtk.keysyms.P, gtk.gdk.CONTROL_MASK) gtk.accel_map_add_entry('/Form/Search', gtk.keysyms.F, gtk.gdk.CONTROL_MASK) gtk.accel_map_load(os.path.join(get_config_dir(), 'accel.map')) self.tooltips = common.Tooltips() self.vbox = gtk.VBox() self.window.add(self.vbox) self.menubar = None self.global_search_entry = None self.menuitem_user = None self.menuitem_favorite = None self.buttons = {} self.pane = gtk.HPaned() self.vbox.pack_start(self.pane, True, True) self.pane.connect('button-press-event', self.on_paned_button_press_event) self.menu_screen = None self.menu_expander = gtk.Expander() self.menu_expander.connect('notify::expanded', self.menu_expanded) if self.menu_expander.get_direction() == gtk.TEXT_DIR_RTL: self.menu_expander.set_direction(gtk.TEXT_DIR_LTR) else: self.menu_expander.set_direction(gtk.TEXT_DIR_RTL) self.menu_expander.set_expanded(CONFIG['menu.expanded']) self.pane.add1(self.menu_expander) self.notebook = gtk.Notebook() self.notebook.popup_enable() self.notebook.set_scrollable(True) self.notebook.connect_after('switch-page', self._sig_page_changt) self.pane.add2(self.notebook) self.set_menubar() self.window.show_all() self.pages = [] self.previous_pages = {} self.current_page = 0 self.last_page = 0 self.dialogs = [] if CONFIG['client.modepda']: self.radiomenuitem_pda.set_active(True) else: self.radiomenuitem_normal.set_active(True) settings = gtk.settings_get_default() # Due to a bug in old version of pyGTk gtk-button-images can # not be set when there is no buttons gtk.Button() try: settings.set_property('gtk-button-images', True) except TypeError: pass try: settings.set_property('gtk-can-change-accels', CONFIG['client.can_change_accelerators']) except TypeError: pass # Register plugins tryton.plugins.register() if self.macapp is not None: self.macapp.ready() _MAIN.append(self) def set_menubar(self): if self.menubar: self.menubar.destroy() menubar = gtk.MenuBar() self.menubar = menubar self.vbox.pack_start(menubar, False, True) self.vbox.reorder_child(menubar, 0) menuitem_connection = gtk.MenuItem( _('_Connection'), use_underline=True) menubar.add(menuitem_connection) menu_connection = self._set_menu_connection() menuitem_connection.set_submenu(menu_connection) menu_connection.set_accel_group(self.accel_group) menu_connection.set_accel_path('/Connection') menuitem_user = gtk.MenuItem(_('_User'), use_underline=True) if self.menuitem_user: menuitem_user.set_sensitive( self.menuitem_user.get_property('sensitive')) else: menuitem_user.set_sensitive(False) self.menuitem_user = menuitem_user menubar.add(menuitem_user) menu_user = self._set_menu_user() menuitem_user.set_submenu(menu_user) menu_user.set_accel_group(self.accel_group) menu_user.set_accel_path('/User') menuitem_options = gtk.MenuItem(_('_Options'), use_underline=True) menubar.add(menuitem_options) menu_options = self._set_menu_options() menuitem_options.set_submenu(menu_options) menu_options.set_accel_group(self.accel_group) menu_options.set_accel_path('/Options') menuitem_favorite = gtk.MenuItem(_('Fa_vorites'), use_underline=True) if self.menuitem_favorite: menuitem_favorite.set_sensitive( self.menuitem_favorite.get_property('sensitive')) else: menuitem_favorite.set_sensitive(False) self.menuitem_favorite = menuitem_favorite menubar.add(menuitem_favorite) menuitem_favorite.set_accel_path('/Favorites') def favorite_activate(widget): if (not menuitem_favorite.get_submenu() or not menuitem_favorite.get_submenu().get_children()): self.favorite_set() menuitem_favorite.connect('select', favorite_activate) menuitem_help = gtk.MenuItem(_('_Help'), use_underline=True) menubar.add(menuitem_help) menu_help = self._set_menu_help() menuitem_help.set_submenu(menu_help) menu_help.set_accel_group(self.accel_group) menu_help.set_accel_path('/Help') if self.macapp is not None: self.menubar.set_no_show_all(True) self.macapp.set_menu_bar(self.menubar) self.macapp.insert_app_menu_item(self.aboutitem, 0) menuitem_connection.show_all() menuitem_user.show_all() menuitem_options.show_all() menuitem_favorite.show_all() menuitem_help.show_all() else: self.menubar.show_all() def set_global_search(self): self.global_search_entry = PlaceholderEntry() self.global_search_entry.set_placeholder_text(_('Search')) global_search_completion = gtk.EntryCompletion() global_search_completion.set_match_func(lambda *a: True) global_search_completion.set_model(gtk.ListStore( gtk.gdk.Pixbuf, str, str, int, str)) pixbuf_cell = gtk.CellRendererPixbuf() global_search_completion.pack_start(pixbuf_cell, False) global_search_completion.add_attribute(pixbuf_cell, 'pixbuf', 0) text_cell = gtk.CellRendererText() global_search_completion.pack_start(text_cell) global_search_completion.add_attribute(text_cell, "markup", 1) global_search_completion.props.popup_set_width = True self.global_search_entry.set_completion(global_search_completion) self.global_search_entry.set_icon_from_stock(gtk.ENTRY_ICON_PRIMARY, 'gtk-find') def match_selected(completion, model, iter_): model, record_id, model_name = model.get(iter_, 2, 3, 4) if model == self.menu_screen.model_name: Action.exec_keyword('tree_open', { 'model': model, 'id': record_id, 'ids': [record_id], }, context=self.menu_screen.context.copy()) else: Window.create(model, res_id=record_id, mode=['form', 'tree'], name=model_name) self.global_search_entry.set_text('') return True global_search_completion.connect('match-selected', match_selected) def update(widget, search_text, callback=None): def end(): if callback: callback() return False if search_text != widget.get_text().decode('utf-8'): return end() gmodel = global_search_completion.get_model() if not search_text or not gmodel: gmodel.clear() gmodel.search_text = search_text return end() if getattr(gmodel, 'search_text', None) == search_text: return end() def set_result(result): try: result = result() except RPCException: result = [] if search_text != widget.get_text().decode('utf-8'): if callback: callback() return False gmodel.clear() for r in result: _, model, model_name, record_id, record_name, icon = r if icon: text = common.to_xml(record_name) common.ICONFACTORY.register_icon(icon) pixbuf = widget.render_icon(stock_id=icon, size=gtk.ICON_SIZE_BUTTON, detail=None) else: text = '%s:\n %s' % ( common.to_xml(model_name), common.to_xml(record_name)) pixbuf = None gmodel.append([pixbuf, text, model, record_id, model_name]) gmodel.search_text = search_text # Force display of popup widget.emit('changed') end() RPCExecute('model', 'ir.model', 'global_search', search_text, CONFIG['client.limit'], self.menu_screen.model_name, context=self.menu_screen.context, callback=set_result) return False def changed(widget): search_text = widget.get_text().decode('utf-8') gobject.timeout_add(300, update, widget, search_text) def activate(widget): def message(): gmodel = global_search_completion.get_model() if not len(gmodel): common.message(_('No result found.')) else: widget.emit('changed') search_text = widget.get_text().decode('utf-8') update(widget, search_text, message) self.global_search_entry.connect('changed', changed) self.global_search_entry.connect('activate', activate) def show_global_search(self): self.pane.get_child1().set_expanded(True) self.global_search_entry.grab_focus() def set_title(self, value=''): if CONFIG['login.profile']: login_info = CONFIG['login.profile'] else: login_info = '%s@%s/%s' % ( CONFIG['login.login'], CONFIG['login.host'], CONFIG['login.db']) titles = [CONFIG['client.title'], login_info] if value: titles.append(value) self.window.set_title(' - '.join(titles)) try: style_context = self.window.get_style_context() except AttributeError: pass else: for name in style_context.list_classes(): if name.startswith('profile-'): style_context.remove_class(name) if CONFIG['login.profile']: style_context.add_class( 'profile-%s' % CONFIG['login.profile']) def _set_menu_connection(self): menu_connection = gtk.Menu() imagemenuitem_connect = gtk.ImageMenuItem(_('_Connect...'), self.accel_group) imagemenuitem_connect.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-connect', gtk.ICON_SIZE_MENU) imagemenuitem_connect.set_image(image) imagemenuitem_connect.connect('activate', self.sig_login) imagemenuitem_connect.set_accel_path('/Connection/Connect') menu_connection.add(imagemenuitem_connect) imagemenuitem_disconnect = gtk.ImageMenuItem(_('_Disconnect')) imagemenuitem_disconnect.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-disconnect', gtk.ICON_SIZE_MENU) imagemenuitem_disconnect.set_image(image) imagemenuitem_disconnect.connect('activate', self.sig_logout) imagemenuitem_disconnect.set_accel_path( '/Connection/Disconnect') menu_connection.add(imagemenuitem_disconnect) imagemenuitem_close = gtk.ImageMenuItem(_('_Quit...'), self.accel_group) imagemenuitem_close.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-log-out', gtk.ICON_SIZE_MENU) imagemenuitem_close.set_image(image) imagemenuitem_close.connect('activate', self.sig_close) imagemenuitem_close.set_accel_path('/Connection/Quit') if self.macapp is None: menu_connection.add(gtk.SeparatorMenuItem()) menu_connection.add(imagemenuitem_close) return menu_connection def _set_menu_user(self): menu_user = gtk.Menu() imagemenuitem_preference = gtk.ImageMenuItem(_('_Preferences...')) imagemenuitem_preference.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-preferences-system-session', gtk.ICON_SIZE_MENU) imagemenuitem_preference.set_image(image) imagemenuitem_preference.connect('activate', self.sig_user_preferences) imagemenuitem_preference.set_accel_path('/User/Preferences') menu_user.add(imagemenuitem_preference) menu_user.add(gtk.SeparatorMenuItem()) imagemenuitem_menu = gtk.ImageMenuItem(_('_Menu Reload'), self.accel_group) imagemenuitem_menu.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-start-here', gtk.ICON_SIZE_MENU) imagemenuitem_menu.set_image(image) imagemenuitem_menu.connect('activate', lambda *a: self.sig_win_menu()) imagemenuitem_menu.set_accel_path('/User/Reload Menu') menu_user.add(imagemenuitem_menu) imagemenuitem_menu_toggle = gtk.ImageMenuItem(_('_Menu Toggle'), self.accel_group) imagemenuitem_menu_toggle.set_use_underline(True) imagemenuitem_menu_toggle.connect('activate', lambda *a: self.menu_toggle()) imagemenuitem_menu_toggle.set_accel_path('/User/Toggle Menu') menu_user.add(imagemenuitem_menu_toggle) imagemenuitem_global_search = gtk.ImageMenuItem(_('_Global Search'), self.accel_group) imagemenuitem_global_search.set_use_underline(True) image = gtk.Image() image.set_from_stock('gtk-find', gtk.ICON_SIZE_MENU) imagemenuitem_global_search.set_image(image) imagemenuitem_global_search.connect('activate', lambda *a: self.show_global_search()) imagemenuitem_global_search.set_accel_path( '/User/Global Search') menu_user.add(imagemenuitem_global_search) return menu_user def _set_menu_options(self): menu_options = gtk.Menu() menuitem_toolbar = gtk.MenuItem(_('_Toolbar'), use_underline=True) menu_options.add(menuitem_toolbar) menu_toolbar = gtk.Menu() menu_toolbar.set_accel_group(self.accel_group) menu_toolbar.set_accel_path('/Options/Toolbar') menuitem_toolbar.set_submenu(menu_toolbar) radiomenuitem_default = gtk.RadioMenuItem(label=_('_Default'), use_underline=True) radiomenuitem_default.connect('activate', lambda x: self.sig_toolbar('default')) radiomenuitem_default.set_accel_path( '/Options/Toolbar/Default') menu_toolbar.add(radiomenuitem_default) if (CONFIG['client.toolbar'] or 'both') == 'default': radiomenuitem_default.set_active(True) radiomenuitem_both = gtk.RadioMenuItem(group=radiomenuitem_default, label=_('_Text and Icons'), use_underline=True) radiomenuitem_both.connect('activate', lambda x: self.sig_toolbar('both')) radiomenuitem_both.set_accel_path( '/Options/Toolbar/Text and Icons') menu_toolbar.add(radiomenuitem_both) if (CONFIG['client.toolbar'] or 'both') == 'both': radiomenuitem_both.set_active(True) radiomenuitem_icons = gtk.RadioMenuItem(group=radiomenuitem_default, label=_('_Icons'), use_underline=True) radiomenuitem_icons.connect('activate', lambda x: self.sig_toolbar('icons')) radiomenuitem_icons.set_accel_path('/Options/Toolbar/Icons') menu_toolbar.add(radiomenuitem_icons) if (CONFIG['client.toolbar'] or 'both') == 'icons': radiomenuitem_icons.set_active(True) radiomenuitem_text = gtk.RadioMenuItem(group=radiomenuitem_default, label=_('_Text'), use_underline=True) radiomenuitem_text.connect('activate', lambda x: self.sig_toolbar('text')) radiomenuitem_text.set_accel_path('/Options/Toolbar/Text') menu_toolbar.add(radiomenuitem_text) if (CONFIG['client.toolbar'] or 'both') == 'text': radiomenuitem_text.set_active(True) # Menubar accelerators menuitem_menubar = gtk.MenuItem(_('_Menubar'), use_underline=True) menu_options.add(menuitem_menubar) menu_menubar = gtk.Menu() menu_menubar.set_accel_group(self.accel_group) menu_menubar.set_accel_path('/Options/Menubar') menuitem_menubar.set_submenu(menu_menubar) checkmenuitem_accel = gtk.CheckMenuItem(_('Change Accelerators'), use_underline=True) checkmenuitem_accel.connect('activate', lambda menuitem: self.sig_accel_change(menuitem.get_active())) checkmenuitem_accel.set_accel_path('/Options/Menubar/Accel') menu_menubar.add(checkmenuitem_accel) if CONFIG['client.can_change_accelerators']: checkmenuitem_accel.set_active(True) menuitem_mode = gtk.MenuItem(_('_Mode'), use_underline=True) menu_options.add(menuitem_mode) menu_mode = gtk.Menu() menu_mode.set_accel_group(self.accel_group) menu_mode.set_accel_path('/Options/Mode') menuitem_mode.set_submenu(menu_mode) radiomenuitem_normal = gtk.RadioMenuItem(label=_('_Normal'), use_underline=True) self.radiomenuitem_normal = radiomenuitem_normal radiomenuitem_normal.connect('activate', lambda x: self.sig_mode_change(False)) radiomenuitem_normal.set_accel_path('/Options/Mode/Normal') menu_mode.add(radiomenuitem_normal) radiomenuitem_pda = gtk.RadioMenuItem(group=radiomenuitem_normal, label=_('_PDA'), use_underline=True) self.radiomenuitem_pda = radiomenuitem_pda radiomenuitem_pda.connect('activate', lambda x: self.sig_mode_change(True)) radiomenuitem_pda.set_accel_path('/Options/Mode/PDA') menu_mode.add(radiomenuitem_pda) menuitem_form = gtk.MenuItem(_('_Form'), use_underline=True) menu_options.add(menuitem_form) menu_form = gtk.Menu() menu_form.set_accel_group(self.accel_group) menu_form.set_accel_path('/Options/Form') menuitem_form.set_submenu(menu_form) checkmenuitem_save_width_height = gtk.CheckMenuItem( _('Save Width/Height'), use_underline=True) checkmenuitem_save_width_height.connect('activate', lambda menuitem: CONFIG.__setitem__('client.save_width_height', menuitem.get_active())) checkmenuitem_save_width_height.set_accel_path( '/Options/Form/Save Width Height') menu_form.add(checkmenuitem_save_width_height) if CONFIG['client.save_width_height']: checkmenuitem_save_width_height.set_active(True) checkmenuitem_save_tree_state = gtk.CheckMenuItem( _('Save Tree State'), use_underline=True) checkmenuitem_save_tree_state.connect('activate', lambda menuitem: CONFIG.__setitem__( 'client.save_tree_state', menuitem.get_active())) checkmenuitem_save_tree_state.set_accel_path( '/Options/Form/Save Tree State') menu_form.add(checkmenuitem_save_tree_state) if CONFIG['client.save_tree_state']: checkmenuitem_save_tree_state.set_active(True) checkmenuitem_fast_tabbing = gtk.CheckMenuItem( _('Fast Tabbing'), use_underline=True) checkmenuitem_fast_tabbing.connect('activate', lambda menuitem: CONFIG.__setitem__('client.fast_tabbing', menuitem.get_active())) checkmenuitem_fast_tabbing.set_accel_path( '/Options/Form/Fast Tabbing') menu_form.add(checkmenuitem_fast_tabbing) checkmenuitem_fast_tabbing.set_active(CONFIG['client.fast_tabbing']) if gtkspell: checkmenuitem_spellcheck = gtk.CheckMenuItem(_('Spell Checking'), use_underline=True) checkmenuitem_spellcheck.connect('activate', lambda menuitem: CONFIG.__setitem__('client.spellcheck', menuitem.get_active())) checkmenuitem_spellcheck.set_accel_path( '/Options/Form/Spell Checking') menu_form.add(checkmenuitem_spellcheck) if CONFIG['client.spellcheck']: checkmenuitem_spellcheck.set_active(True) imagemenuitem_win_prev = gtk.ImageMenuItem(_('_Previous Tab'), self.accel_group) imagemenuitem_win_prev.set_use_underline(True) imagemenuitem_win_prev.connect('activate', self.sig_win_prev) imagemenuitem_win_prev.set_accel_path('/Form/Previous Tab') menu_form.add(imagemenuitem_win_prev) imagemenuitem_win_next = gtk.ImageMenuItem(_('_Next Tab'), self.accel_group) imagemenuitem_win_next.set_use_underline(True) imagemenuitem_win_next.connect('activate', self.sig_win_next) imagemenuitem_win_next.set_accel_path('/Form/Next Tab') menu_form.add(imagemenuitem_win_next) menuitem_limit = gtk.MenuItem(_('Search Limit...'), use_underline=True) self.menuitem_limit = menuitem_limit menuitem_limit.connect('activate', self.sig_limit) menuitem_limit.set_accel_path('/Options/Search Limit') menu_options.add(menuitem_limit) menuitem_email = gtk.MenuItem(_('_Email...'), use_underline=True) self.menuitem_email = menuitem_email menuitem_email.connect('activate', self.sig_email) menuitem_email.set_accel_path('/Options/Email') menu_options.add(menuitem_email) menu_options.add(gtk.SeparatorMenuItem()) imagemenuitem_opt_save = gtk.ImageMenuItem(_('_Save Options')) imagemenuitem_opt_save.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-save', gtk.ICON_SIZE_MENU) imagemenuitem_opt_save.set_image(image) imagemenuitem_opt_save.connect('activate', lambda x: CONFIG.save()) imagemenuitem_opt_save.set_accel_path('/Options/Save Options') menu_options.add(imagemenuitem_opt_save) return menu_options def _set_menu_help(self): menu_help = gtk.Menu() imagemenuitem_shortcuts = gtk.ImageMenuItem( _('_Keyboard Shortcuts...')) imagemenuitem_shortcuts.set_use_underline(True) image = gtk.Image() image.set_from_stock('tryton-help', gtk.ICON_SIZE_MENU) imagemenuitem_shortcuts.set_image(image) imagemenuitem_shortcuts.connect('activate', self.sig_shortcuts) imagemenuitem_shortcuts.set_accel_path( '/Help/Keyboard Shortcuts') menu_help.add(imagemenuitem_shortcuts) imagemenuitem_about = gtk.ImageMenuItem(_('_About...')) imagemenuitem_about.set_use_underline(True) image = gtk.Image() image.set_from_stock('gtk-about', gtk.ICON_SIZE_MENU) imagemenuitem_about.set_image(image) imagemenuitem_about.connect('activate', self.sig_about) imagemenuitem_about.set_accel_path('/Help/About') self.aboutitem = imagemenuitem_about if self.macapp is None: menu_help.add(gtk.SeparatorMenuItem()) menu_help.add(imagemenuitem_about) return menu_help @staticmethod def get_main(): return _MAIN[0] def favorite_set(self): if not self.menu_screen: return False def _action_favorite(widget, id_): event = gtk.get_current_event() allow_similar = (event.state & gtk.gdk.MOD1_MASK or event.state & gtk.gdk.SHIFT_MASK) with Window(allow_similar=allow_similar): Action.exec_keyword('tree_open', { 'model': self.menu_screen.model_name, 'id': id_, 'ids': [id_], }) def _manage_favorites(widget): Window.create(self.menu_screen.model_name + '.favorite', mode=['tree', 'form'], name=_('Manage Favorites')) try: favorites = RPCExecute('model', self.menu_screen.model_name + '.favorite', 'get', process_exception=False) except Exception: return False menu = self.menuitem_favorite.get_submenu() if not menu: menu = gtk.Menu() for id_, name, icon in favorites: if icon: common.ICONFACTORY.register_icon(icon) menuitem = gtk.ImageMenuItem(name) image = gtk.Image() image.set_from_stock(icon, gtk.ICON_SIZE_MENU) menuitem.set_image(image) else: menuitem = gtk.MenuItem(name) menuitem.connect('activate', _action_favorite, id_) menu.add(menuitem) menu.add(gtk.SeparatorMenuItem()) manage_favorites = gtk.MenuItem(_('Manage Favorites'), use_underline=True) manage_favorites.connect('activate', _manage_favorites) menu.add(manage_favorites) menu.show_all() self.menuitem_favorite.set_submenu(menu) return True def favorite_unset(self): had_submenu = self.menuitem_favorite.get_submenu() self.menuitem_favorite.set_submenu(None) # Set a submenu to get keyboard shortcut working self.menuitem_favorite.set_submenu(gtk.Menu()) if self.macapp and had_submenu: # As the select event is not managed by the mac menu, # it is done using a timeout gobject.timeout_add(1000, lambda: not self.favorite_set()) def sig_accel_change(self, value): CONFIG['client.can_change_accelerators'] = value return self.sig_accel() def sig_accel(self): menubar = CONFIG['client.can_change_accelerators'] settings = gtk.settings_get_default() if menubar: settings.set_property('gtk-can-change-accels', True) else: settings.set_property('gtk-can-change-accels', False) def sig_mode_change(self, pda_mode=False): CONFIG['client.modepda'] = pda_mode return def sig_toolbar(self, option): CONFIG['client.toolbar'] = option if option == 'default': barstyle = False elif option == 'both': barstyle = gtk.TOOLBAR_BOTH elif option == 'text': barstyle = gtk.TOOLBAR_TEXT elif option == 'icons': barstyle = gtk.TOOLBAR_ICONS for page_idx in range(self.notebook.get_n_pages()): page = self.get_page(page_idx) page.toolbar.set_style(barstyle) def sig_limit(self, widget): Limit().run() def sig_email(self, widget): Email().run() def sig_win_next(self, widget): page = self.notebook.get_current_page() if page == len(self.pages) - 1: page = -1 self.notebook.set_current_page(page + 1) def sig_win_prev(self, widget): page = self.notebook.get_current_page() self.notebook.set_current_page(page - 1) def get_preferences(self): def _set_preferences(prefs): try: prefs = prefs() except RPCException: prefs = {} threads = [] for target in ( common.ICONFACTORY.load_icons, common.MODELACCESS.load_models, common.MODELHISTORY.load_history, common.VIEW_SEARCH.load_searches, ): t = threading.Thread(target=target) threads.append(t) t.start() for t in threads: t.join() if prefs and 'language_direction' in prefs: translate.set_language_direction(prefs['language_direction']) CONFIG['client.language_direction'] = \ prefs['language_direction'] self.sig_win_menu(prefs=prefs) for action_id in prefs.get('actions', []): Action.execute(action_id, {}) self.set_title(prefs.get('status_bar', '')) if prefs and 'language' in prefs: translate.setlang(prefs['language'], prefs.get('locale')) if CONFIG['client.lang'] != prefs['language']: self.set_menubar() self.favorite_unset() CONFIG['client.lang'] = prefs['language'] # Set placeholder after language is set to get correct translation if self.global_search_entry: self.global_search_entry.set_placeholder_text(_('Search')) CONFIG.save() def _get_preferences(): RPCExecute('model', 'res.user', 'get_preferences', False, callback=_set_preferences) RPCContextReload(_get_preferences) def sig_user_preferences(self, widget): if not self.close_pages(): return False Preference(rpc._USER, self.get_preferences) def sig_win_close(self, widget=None): self._sig_remove_book(widget, self.notebook.get_nth_page(self.notebook.get_current_page())) def sig_login(self, widget=None): if not self.sig_logout(widget, disconnect=False): return language = CONFIG['client.lang'] try: host, port, database, username = DBLogin().run() except TrytonError, exception: if exception.faultCode == 'QueryCanceled': return raise func = lambda parameters: rpc.login( host, port, database, username, parameters, language) self.set_title() # Adds username/profile while password is asked try: common.Login(func) except TrytonError, exception: if exception.faultCode == 'QueryCanceled': return raise except TrytonServerError, exception: if exception.faultCode.startswith('404'): return self.sig_login() raise self.get_preferences() self.favorite_unset() self.menuitem_favorite.set_sensitive(True) self.menuitem_user.set_sensitive(True) if CONFIG.arguments: url = CONFIG.arguments.pop() self.open_url(url) return True def close_pages(self): if self.notebook.get_n_pages(): if not common.sur( _('The following action requires to close all tabs.\n' 'Do you want to continue?')): return False res = True while res: wid = self.get_page() if wid: if not wid.sig_close(): return False res = self._win_del() else: res = False if self.menu_screen: self.menu_screen.save_tree_state() self.menu_screen.destroy() self.menu_screen = None self.menu_expander_clear() return True def sig_logout(self, widget=None, disconnect=True): try: if not self.close_pages(): return False except TrytonServerUnavailable: pass self.set_title() self.favorite_unset() self.menuitem_favorite.set_sensitive(False) self.menuitem_user.set_sensitive(False) if disconnect: rpc.logout() return True def sig_about(self, widget): About() def sig_shortcuts(self, widget): Shortcuts().run() def menu_toggle(self): expander = self.pane.get_child1() if expander: expander.set_expanded(not expander.get_expanded()) @property def menu_expander_size(self): return self.menu_expander.style_get_property('expander-size') def menu_expanded(self, expander, *args): expanded = expander.get_expanded() CONFIG['menu.expanded'] = expanded if expanded: self.pane.set_position(int(CONFIG['menu.pane'])) if self.menu_screen: self.menu_screen.set_cursor() else: CONFIG['menu.pane'] = self.pane.get_position() self.pane.set_position(self.menu_expander_size) self.notebook.grab_focus() def menu_expander_clear(self): if self.menu_expander.get_child(): self.menu_expander.remove(self.menu_expander.get_child()) expanded = self.menu_expander.get_expanded() CONFIG['menu.expanded'] = expanded if expanded: CONFIG['menu.pane'] = self.pane.get_position() def on_paned_button_press_event(self, paned, event): expander = self.pane.get_child1() if expander: return not expander.get_expanded() return False def sig_win_menu(self, prefs=None): from tryton.gui.window.view_form.screen import Screen if not prefs: try: prefs = RPCExecute('model', 'res.user', 'get_preferences', False) except RPCException: return False vbox = gtk.VBox() if hasattr(vbox, 'set_vexpand'): vbox.set_vexpand(True) self.set_global_search() vbox.pack_start(self.global_search_entry, False, False) vbox.show_all() if self.menu_screen: self.menu_screen.save_tree_state() self.menu_screen = None self.menu_expander_clear() action = PYSONDecoder().decode(prefs['pyson_menu']) view_ids = [] if action.get('views', []): view_ids = [x[0] for x in action['views']] elif action.get('view_id', False): view_ids = [action['view_id'][0]] ctx = rpc.CONTEXT.copy() decoder = PYSONDecoder(ctx) action_ctx = decoder.decode(action.get('pyson_context') or '{}') domain = decoder.decode(action['pyson_domain']) screen = Screen(action['res_model'], mode=['tree'], view_ids=view_ids, domain=domain, context=action_ctx, readonly=True, limit=None) # Use alternate view to not show search box screen.screen_container.alternate_view = True screen.switch_view(view_type=screen.current_view.view_type) vbox.pack_start(screen.screen_container.alternate_viewport, True, True) treeview = screen.current_view.treeview treeview.set_headers_visible(False) self.menu_expander.add(vbox) # Favorite column column = gtk.TreeViewColumn() column.name = None column._type = None favorite_renderer = CellRendererClickablePixbuf() column.pack_start(favorite_renderer, expand=False) def favorite_setter(column, cell, store, iter_): menu = store.get_value(iter_, 0) favorite = menu.value.get('favorite') if favorite: stock_id = 'tryton-star' elif favorite is False: stock_id = 'tryton-unstar' else: stock_id = '' pixbuf = treeview.render_icon(stock_id=stock_id, size=gtk.ICON_SIZE_MENU, detail=None) cell.set_property('pixbuf', pixbuf) column.set_cell_data_func(favorite_renderer, favorite_setter) def toggle_favorite(renderer, path, treeview): if treeview.props.window: self.toggle_favorite(renderer, path, treeview) favorite_renderer.connect('clicked', lambda *a: gobject.idle_add(toggle_favorite, *a), treeview) # Unset fixed height mode to add column treeview.set_fixed_height_mode(False) treeview.set_property( 'enable-grid-lines', gtk.TREE_VIEW_GRID_LINES_NONE) treeview.append_column(column) screen.search_filter() screen.display(set_cursor=True) self.menu_screen = screen def toggle_favorite(self, renderer, path, treeview): store = treeview.get_model() iter_ = store.get_iter(path) menu = store.get_value(iter_, 0) favorite = menu.value.get('favorite') if favorite: value = False method = 'unset' elif favorite is False: value = True method = 'set' else: return try: RPCExecute('model', self.menu_screen.model_name + '.favorite', method, menu.id) except RPCException: return menu.value['favorite'] = value store.row_changed(path, iter_) self.favorite_unset() @classmethod def sig_quit(cls, widget=None): rpc.logout() CONFIG['client.default_width'] = Main.get_main()._width CONFIG['client.default_height'] = Main.get_main()._height CONFIG.save() gtk.accel_map_save(os.path.join(get_config_dir(), 'accel.map')) cls.tryton_client.quit_mainloop() sys.exit() def sig_close(self, widget, event=None): if not self.sig_logout(widget): return True Main.sig_quit() def sig_configure(self, widget, event): if hasattr(event, 'width') \ and hasattr(event, 'height'): self._width = int(event.width) self._height = int(event.height) return False def sig_window_state(self, widget, event): CONFIG['client.maximize'] = (event.new_window_state == gtk.gdk.WINDOW_STATE_MAXIMIZED) return False def win_add(self, page, hide_current=False, allow_similar=True): if not allow_similar: for other_page in self.pages: if page == other_page: current_page = self.notebook.get_current_page() page_num = self.notebook.page_num(other_page.widget) other_page.widget.props.visible = True self.notebook.set_current_page(page_num) # In order to focus the page if current_page == page_num: self._sig_page_changt(self.notebook, None, page_num) return previous_page_id = self.notebook.get_current_page() previous_widget = self.notebook.get_nth_page(previous_page_id) if previous_widget and hide_current: page_id = previous_page_id + 1 else: page_id = -1 self.previous_pages[page] = previous_widget self.pages.append(page) hbox = gtk.HBox(spacing=3) icon_w, icon_h = gtk.icon_size_lookup(gtk.ICON_SIZE_SMALL_TOOLBAR)[-2:] if page.icon is not None: common.ICONFACTORY.register_icon(page.icon) image = gtk.Image() image.set_from_stock(page.icon, gtk.ICON_SIZE_SMALL_TOOLBAR) hbox.pack_start(image, expand=False, fill=False) name = page.name label = gtk.Label(common.ellipsize(name, 20)) self.tooltips.set_tip(label, page.name) self.tooltips.enable() label.set_alignment(0.0, 0.5) hbox.pack_start(label, expand=True, fill=True) button = gtk.Button() img = gtk.Image() img.set_from_stock('tryton-close', gtk.ICON_SIZE_MENU) width, height = img.size_request() button.set_relief(gtk.RELIEF_NONE) button.set_can_focus(False) button.add(img) self.tooltips.set_tip(button, _('Close Tab')) button.connect('clicked', self._sig_remove_book, page.widget) hbox.pack_start(button, expand=False, fill=False) x, y = gtk.icon_size_lookup_for_settings(button.get_settings(), gtk.ICON_SIZE_MENU)[-2:] button.set_size_request(x, y) hbox.show_all() label_menu = gtk.Label(page.name) label_menu.set_alignment(0.0, 0.5) self.notebook.insert_page_menu(page.widget, hbox, label_menu, page_id) self.notebook.set_tab_reorderable(page.widget, True) self.notebook.set_current_page(page_id) def _sig_remove_book(self, widget, page_widget): for page in self.pages: if page.widget == page_widget: if not page.widget.props.sensitive: return page_num = self.notebook.page_num(page.widget) self.notebook.set_current_page(page_num) res = page.sig_close() if not res: return self._win_del(page_widget) def _win_del(self, page_widget=None): if page_widget: page_id = self.notebook.page_num(page_widget) else: page_id = int(self.notebook.get_current_page()) page_widget = self.notebook.get_nth_page(page_id) if page_id != -1: page = None for i in range(len(self.pages)): if self.pages[i].widget == page_widget: page = self.pages.pop(i) page.signal_unconnect(self) break self.notebook.remove_page(page_id) next_page_id = -1 to_pop = [] for i in self.previous_pages: if self.previous_pages[i] == page_widget: to_pop.append(i) if i.widget == page_widget: if self.previous_pages[i]: next_page_id = self.notebook.page_num( self.previous_pages[i]) to_pop.append(i) to_pop.reverse() for i in to_pop: self.previous_pages.pop(i) if hasattr(page, 'destroy'): page.destroy() del page current_widget = self.notebook.get_nth_page(next_page_id) if current_widget: current_widget.props.visible = True self.notebook.set_current_page(next_page_id) if not self.pages and self.menu_screen: self.menu_screen.set_cursor() return self.notebook.get_current_page() != -1 def get_page(self, page_id=None): if page_id is None: page_id = self.notebook.get_current_page() if page_id == -1: return None page_widget = self.notebook.get_nth_page(page_id) for page in self.pages: if page.widget == page_widget: return page return None def _sig_page_changt(self, notebook, page, page_num): self.last_page = self.current_page last_form = self.get_page(self.current_page) if last_form: for dialog in last_form.dialogs: dialog.hide() self.current_page = self.notebook.get_current_page() current_form = self.get_page(self.current_page) def set_cursor(): if self.current_page == self.notebook.get_current_page(): current_form.set_cursor() # Using idle_add because the gtk.TreeView grabs the focus at the # end of the event gobject.idle_add(set_cursor) for dialog in current_form.dialogs: dialog.show() def _open_url(self, url): urlp = urlparse(url) if not urlp.scheme == 'tryton': return urlp = urlparse('http' + url[6:]) hostname = common.get_hostname(urlp.netloc) port = common.get_port(urlp.netloc) database, path = map(urllib.unquote, (urlp.path[1:].split('/', 1) + [''])[:2]) if (not path or hostname != rpc._HOST or int(port) != rpc._PORT or database != rpc._DATABASE): return type_, path = (path.split('/', 1) + [''])[:2] params = {} if urlp.params: try: params.update(dict(parse_qsl(urlp.params, strict_parsing=True))) except ValueError: return def open_model(path): model, path = (path.split('/', 1) + [''])[:2] if not model: return res_id = None mode = None try: view_ids = json.loads(params.get('views', 'false')) limit = json.loads(params.get('limit', 'null')) name = json.loads(params.get('name', '""')) search_value = json.loads(params.get('search_value', '[]'), object_hook=object_hook) domain = json.loads(params.get('domain', '[]'), object_hook=object_hook) context = json.loads(params.get('context', '{}'), object_hook=object_hook) context_model = params.get('context_model') except ValueError: return if path: try: res_id = int(path) except ValueError: return mode = ['form', 'tree'] try: Window.create(model, view_ids=view_ids, res_id=res_id, domain=domain, context=context, context_model=context_model, mode=mode, name=name, limit=limit, search_value=search_value) except Exception: # Prevent crashing the client return def open_wizard(wizard): if not wizard: return try: data = json.loads(params.get('data', '{}'), object_hook=object_hook) direct_print = json.loads(params.get('direct_print', 'false')) email_print = json.loads(params.get('email_print', 'false')) email = json.loads(params.get('email', 'null')) name = json.loads(params.get('name', '""')) window = json.loads(params.get('window', 'false')) context = json.loads(params.get('context', '{}'), object_hook=object_hook) except ValueError: return try: Window.create_wizard(wizard, data, direct_print=direct_print, email_print=email_print, email=email, name=name, context=context, window=window) except Exception: # Prevent crashing the client return def open_report(report): if not report: return try: data = json.loads(params.get('data'), object_hook=object_hook) direct_print = json.loads(params.get('direct_print', 'false')) email_print = json.loads(params.get('email_print', 'false')) email = json.loads(params.get('email', 'null')) context = json.loads(params.get('context', '{}'), object_hook=object_hook) except ValueError: return try: Action.exec_report(report, data, direct_print=direct_print, email_print=email_print, email=email, context=context) except Exception: # Prevent crashing the client return def open_url(): try: url = json.loads(params.get('url', 'false')) except ValueError: return if url: webbrowser.open(url, new=2) if type_ == 'model': open_model(path) elif type_ == 'wizard': open_wizard(path) elif type_ == 'report': open_report(path) elif type_ == 'url': open_url() self.window.present() def open_url(self, url): def idle_open_url(): with gtk.gdk.lock: self._open_url(url) return False gobject.idle_add(idle_open_url) tryton-4.6.5/tryton/gui/__init__.py0000644000175000017500000000024313175640533016637 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from main import * tryton-4.6.5/tryton/rpc.py0000644000175000017500000001170413251060075015074 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import httplib import logging import socket import ssl import os from functools import partial from tryton.jsonrpc import ServerProxy, ServerPool, Fault from tryton.fingerprints import Fingerprints from tryton.config import get_config_dir from tryton.ipc import Server as IPCServer from tryton.exceptions import TrytonServerError, TrytonServerUnavailable from tryton.config import CONFIG CONNECTION = None _USER = None _USERNAME = '' _HOST = '' _PORT = None _DATABASE = '' CONTEXT = {} _VIEW_CACHE = {} _TOOLBAR_CACHE = {} _KEYWORD_CACHE = {} _CA_CERTS = os.path.join(get_config_dir(), 'ca_certs') if not os.path.isfile(_CA_CERTS): _CA_CERTS = None _FINGERPRINTS = Fingerprints() ServerProxy = partial(ServerProxy, fingerprints=_FINGERPRINTS, ca_certs=_CA_CERTS) ServerPool = partial(ServerPool, fingerprints=_FINGERPRINTS, ca_certs=_CA_CERTS) def db_list(host, port): try: connection = ServerProxy(host, port) logging.getLogger(__name__).info('common.db.list()') result = connection.common.db.list() logging.getLogger(__name__).debug(repr(result)) return result except Fault, exception: if exception.faultCode == 'AccessDenied': logging.getLogger(__name__).debug('AccessDenied') return [] else: logging.getLogger(__name__).debug(repr(None)) return None def server_version(host, port): try: connection = ServerProxy(host, port) logging.getLogger(__name__).info( 'common.server.version(None, None)') result = connection.common.server.version() logging.getLogger(__name__).debug(repr(result)) return result except (Fault, socket.error, ssl.SSLError, ssl.CertificateError), e: logging.getLogger(__name__).error(e) return None def login(host, port, database, username, parameters, language=None): global CONNECTION, _USER, _USERNAME, _HOST, _PORT, _DATABASE global _VIEW_CACHE, _TOOLBAR_CACHE, _KEYWORD_CACHE connection = ServerProxy(host, port, database) logging.getLogger(__name__).info('common.db.login(%s, %s, %s)' % (username, 'x' * 10, language)) result = connection.common.db.login(username, parameters, language) logging.getLogger(__name__).debug(repr(result)) _USER = result[0] _USERNAME = username session = ':'.join(map(str, [username] + result)) if CONNECTION is not None: CONNECTION.close() CONNECTION = ServerPool(host, port, database, session=session) _HOST = host _PORT = port _DATABASE = database _VIEW_CACHE = {} _TOOLBAR_CACHE = {} _KEYWORD_CACHE = {} IPCServer(host, port, database).run() def logout(): global CONNECTION, _USER, _USERNAME, _HOST, _PORT, _DATABASE global _VIEW_CACHE, _TOOLBAR_CACHE, _KEYWORD_CACHE if IPCServer.instance: IPCServer.instance.stop() if CONNECTION is not None: try: logging.getLogger(__name__).info('common.db.logout()') with CONNECTION() as conn: conn.common.db.logout() except (Fault, socket.error, httplib.CannotSendRequest): pass CONNECTION.close() CONNECTION = None _USER = None _USERNAME = '' _HOST = '' _PORT = None _DATABASE = '' _VIEW_CACHE = {} _TOOLBAR_CACHE = {} _KEYWORD_CACHE = {} def _execute(blocking, *args): global CONNECTION, _USER if CONNECTION is None: raise TrytonServerError('403') key = False model = args[1] method = args[2] if not CONFIG['dev']: if method == 'fields_view_get': key = str(args) if key in _VIEW_CACHE: return _VIEW_CACHE[key] elif method == 'view_toolbar_get': key = str(args) if key in _TOOLBAR_CACHE: return _TOOLBAR_CACHE[key] elif model == 'ir.action.keyword' and method == 'get_keyword': key = str(args) if key in _KEYWORD_CACHE: return _KEYWORD_CACHE[key] try: name = '.'.join(args[:3]) args = args[3:] logging.getLogger(__name__).info('%s%s' % (name, args)) with CONNECTION() as conn: result = getattr(conn, name)(*args) except (httplib.CannotSendRequest, socket.error), exception: raise TrytonServerUnavailable(*exception.args) if not CONFIG['dev']: if key and method == 'fields_view_get': _VIEW_CACHE[key] = result elif key and method == 'view_toolbar_get': _TOOLBAR_CACHE[key] = result elif key and model == 'ir.action.keyword' and method == 'get_keyword': _KEYWORD_CACHE[key] = result logging.getLogger(__name__).debug(repr(result)) return result def execute(*args): return _execute(True, *args) def execute_nonblocking(*args): return _execute(False, *args) tryton-4.6.5/tryton/client.py0000644000175000017500000002511013255571102015564 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. """ %prog [options] """ import sys try: import cdecimal # Use cdecimal globally if 'decimal' not in sys.modules: sys.modules['decimal'] = cdecimal except ImportError: import decimal sys.modules['cdecimal'] = decimal import os Gdk = None Gtk = None if os.environ.get('GTK_VERSION', '2').startswith('3'): import pygtkcompat pygtkcompat.enable() pygtkcompat.enable_gtk(version='3.0') try: pygtkcompat.enable_goocanvas() except ValueError: pass from gi.repository import GdkPixbuf _unset = object() Gdk = sys.modules['gtk.gdk'] # XXX this prevents isinstance test Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new Gtk = sys.modules['gtk'] Gtk.widget_set_default_direction = Gtk.Widget.set_default_direction Gtk.accel_map_add_entry = Gtk.AccelMap.add_entry Gtk.accel_map_load = Gtk.AccelMap.load Gtk.accel_map_save = Gtk.AccelMap.save Gtk.PROGRESS_LEFT_TO_RIGHT = (Gtk.Orientation.HORIZONTAL, False) Gtk.PROGRESS_RIGHT_TO_LEFT = (Gtk.Orientation.HORIZONTAL, True) Gtk.PROGRESS_BOTTOM_TO_TOP = (Gtk.Orientation.VERTICAL, True) Gtk.PROGRESS_TOP_TO_BOTTOM = (Gtk.Orientation.VERTICAL, False) Gtk.CLIPBOARD_PRIMARY = Gdk.Atom.intern('PRIMARY', True) Gtk.CLIPBOARD_CLIPBOARD = Gdk.Atom.intern('CLIPBOARD', True) orig_tree_view_column_set_cell_data_func = ( Gtk.TreeViewColumn.set_cell_data_func) def set_cell_data_func(self, cell, func, user_data=_unset): def callback(*args): if args[-1] == _unset: args = args[:-1] return func(*args) orig_tree_view_column_set_cell_data_func( self, cell, callback, user_data) Gtk.TreeViewColumn.set_cell_data_func = set_cell_data_func Gtk.TreeViewColumn.get_cell_renderers = Gtk.TreeViewColumn.get_cells orig_set_orientation = Gtk.ProgressBar.set_orientation def set_orientation(self, orientation): orientation, inverted = orientation orig_set_orientation(self, orientation) self.set_inverted(inverted) Gtk.ProgressBar.set_orientation = set_orientation orig_set_orientation = Gtk.CellRendererProgress.set_orientation def set_orientation(self, orientation): orientation, inverted = orientation orig_set_orientation(self, orientation) self.set_property('inverted', inverted) Gtk.CellRendererProgress.set_orientation = set_orientation orig_popup = Gtk.Menu.popup def popup(self, parent_menu_shell, parent_menu_item, func, button, activate_time, data=None): if func: def position_func(menu, x, y, user_data=None): return func(menu, user_data) else: position_func = None orig_popup(self, parent_menu_shell, parent_menu_item, position_func, data, button, activate_time) Gtk.Menu.popup = popup def get_active_text(self): active = self.get_active() if active < 0: return None else: model = self.get_model() index = self.get_property('entry-text-column') return model[active][index] Gtk.ComboBox.get_active_text = get_active_text Gtk.GenericCellRenderer.__gobject_init__ = Gtk.GenericCellRenderer.__init__ from gi.repository import Pango Pango.SCALE_XX_SMALL = 1 / (1.2 * 1.2 * 1.2) Pango.SCALE_X_SMALL = 1 / (1.2 * 1.2) Pango.SCALE_SMALL = 1 / 1.2 Pango.SCALE_MEDIUM = 1 Pango.SCALE_LARGE = 1.2 Pango.SCALE_X_LARGE = 1.2 * 1.2 Pango.SCALE_XX_LARGE = 1.2 * 1.2 * 1.2 def make_attr_constructor(method): def constructor(value, start_index, end_index): attr = getattr(Pango, method)(value) attr.start_index = start_index if end_index >= 0: attr.end_index = end_index return attr return constructor def make_attr_2_constructor(method): def constructor(one, two, start_index, end_index): attr = getattr(Pango, method)(one, two) attr.start_index = start_index if end_index >= 0: attr.end_index = end_index return attr return constructor def make_attr_3_constructor(method): def constructor(one, two, three, start_index, end_index): attr = getattr(Pango, method)(one, two, three) attr.start_index = start_index if end_index >= 0: attr.end_index = end_index return attr return constructor for method, name, constructor in [ ('attr_language_new', 'AttrLanguage', make_attr_constructor), ('attr_family_new', 'AttrFamily', make_attr_constructor), ('attr_foreground_new', 'AttrForeground', make_attr_3_constructor), ('attr_background_new', 'AttrBackground', make_attr_3_constructor), ('attr_size_new', 'AttrSize', make_attr_constructor), ('attr_size_new_absolute', 'AttrSizeAbsolute', make_attr_constructor), ('attr_style_new', 'AttrStyle', make_attr_constructor), ('attr_weight_new', 'AttrWeight', make_attr_constructor), ('attr_variant_new', 'AttrVariant', make_attr_constructor), ('attr_stretch_new', 'AttrStretch', make_attr_constructor), ('attr_font_desc_new', 'AttrFontDesc', make_attr_constructor), ('attr_underline_new', 'AttrUnderline', make_attr_constructor), ('attr_underline_color_new', 'AttrUnderlineColor', make_attr_3_constructor), ('attr_strikethrough_new', 'AttrStrikethrough', make_attr_constructor), ('attr_strikethrough_color_new', 'AttrStrikethroughColor', make_attr_3_constructor), ('attr_rise_new', 'AttrRise', make_attr_constructor), ('attr_scale_new', 'AttrScale', make_attr_constructor), ('attr_fallback_new', 'AttrFallback', make_attr_constructor), ('attr_letter_spacing_new', 'AttrLetterSpacing', make_attr_constructor), ('attr_shape_new', 'AttrShape', make_attr_2_constructor), ]: if hasattr(Pango, method): setattr(Pango, name, constructor(method)) else: import pygtk pygtk.require('2.0') import gtk if not hasattr(gtk, 'TreePath'): gtk.TreePath = tuple if not hasattr(gtk, 'TargetEntry'): gtk.TargetEntry = lambda *a: a gtk.TargetEntry.new = lambda *a: a if not hasattr(gtk, 'CLIPBOARD_PRIMARY'): gtk.CLIPBOARD_PRIMARY = 'PRIMARY' gtk.CLIPBOARD_CLIPBOARD = 'CLIPBOARD' import gobject try: # Import earlier otherwise there is a segmentation fault on MSYS2 import goocalendar except ImportError: pass gobject.threads_init() from urlparse import urlparse import threading import tryton.common as common from tryton.config import CONFIG, get_config_dir from tryton import translate from tryton import gui from tryton.ipc import Client as IPCClient import time import signal if not hasattr(gtk.gdk, 'lock'): class _Lock(object): __enter__ = gtk.gdk.threads_enter def __exit__(*ignored): gtk.gdk.threads_leave() gtk.gdk.lock = _Lock() if sys.platform == 'win32': class Dialog(gtk.Dialog): def run(self): with gtk.gdk.lock: return super(Dialog, self).run() gtk.Dialog = Dialog CSS = """ .readonly entry { background-color: @insensitive_bg_color; } .required entry { border-color: darker(@unfocused_borders); } .invalid entry { border-color: @error_color; } """ if Gdk and Gtk: screen = Gdk.Screen.get_default() style_context = Gtk.StyleContext() provider = Gtk.CssProvider() provider.load_from_data(CSS) style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION) theme_path = os.path.join(get_config_dir(), 'theme.css') if os.path.exists(theme_path): provider = Gtk.CssProvider() provider.load_from_path(theme_path) style_context.add_provider_for_screen( screen, provider, Gtk.STYLE_PROVIDER_PRIORITY_USER) class TrytonClient(object): "Tryton client" def __init__(self): CONFIG.parse() if CONFIG.arguments: url, = CONFIG.arguments urlp = urlparse(url) if urlp.scheme == 'tryton': urlp = urlparse('http' + url[6:]) hostname = common.get_hostname(urlp.netloc) port = common.get_port(urlp.netloc) database, _ = (urlp.path[1:].split('/', 1) + [None])[:2] if IPCClient(hostname, port, database).write(url): sys.exit(0) CONFIG['login.host'] = urlp.netloc CONFIG['login.db'] = database CONFIG['login.expanded'] = True translate.set_language_direction(CONFIG['client.language_direction']) translate.setlang(CONFIG['client.lang']) self.quit_client = (threading.Event() if sys.platform == 'win32' else None) common.ICONFACTORY.load_client_icons() def quit_mainloop(self): if sys.platform == 'win32': self.quit_client.set() else: if gtk.main_level() > 0: gtk.main_quit() def run(self): main = gui.Main(self) signal.signal(signal.SIGINT, lambda signum, frame: main.sig_quit()) signal.signal(signal.SIGTERM, lambda signum, frame: main.sig_quit()) if hasattr(signal, 'SIGQUIT'): signal.signal(signal.SIGQUIT, lambda signum, frame: main.sig_quit()) def excepthook(*args): import common import traceback detail = ''.join(traceback.format_exception(*args)) common.error(str(args[1]), detail) sys.excepthook = excepthook main.sig_login() if sys.platform == 'win32': # http://faq.pygtk.org/index.py?req=show&file=faq21.003.htp def sleeper(): time.sleep(.001) return 1 gobject.timeout_add(400, sleeper) try: if sys.platform == 'win32': while not self.quit_client.isSet(): with gtk.gdk.lock: gtk.main_iteration() else: gtk.main() except KeyboardInterrupt: CONFIG.save() gtk.accel_map_save(os.path.join(get_config_dir(), 'accel.map')) if __name__ == "__main__": CLIENT = TrytonClient() CLIENT.run() tryton-4.6.5/tryton/signal_event.py0000644000175000017500000000235213175640533016775 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Signal event" class SignalEvent(object): "Signal event" def __init__(self): self.__connects = {} def signal(self, signal, signal_data=None): for fnct, data, key in self.__connects.get(signal, []): fnct(self, signal_data, *data) return True def signal_connected(self, signal): return bool(self.__connects.get(signal)) def signal_connect(self, key, signal, fnct, *data): self.__connects.setdefault(signal, []) if (fnct, data, key) not in self.__connects[signal]: self.__connects[signal].append((fnct, data, key)) return True def signal_unconnect(self, key, signal=None): if signal is None: signal = self.__connects.keys() else: signal = [signal] for sig in signal: i = 0 while i < len(self.__connects[sig]): if self.__connects[sig][i][2] is key: del self.__connects[sig][i] else: i += 1 return True def destroy(self): self.__connects = {} tryton-4.6.5/tryton/fingerprints.py0000644000175000017500000000256513251060075017027 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import os from tryton.config import get_config_dir KNOWN_HOSTS_PATH = os.path.join(get_config_dir(), 'known_hosts') class Fingerprints(dict): def __init__(self): super(Fingerprints, self).__init__() self.load() def load(self): if not os.path.isfile(KNOWN_HOSTS_PATH): return with open(KNOWN_HOSTS_PATH) as known_hosts: for line in known_hosts: line = line.strip() try: host, sha1 = line.split(' ') except ValueError: host, sha1 = line, '' # Skip current implementation to avoid save dict.__setitem__(self, host, sha1) def save(self): with open(KNOWN_HOSTS_PATH, 'w') as known_hosts: known_hosts.writelines('%s %s' % (host, sha1) + os.linesep for host, sha1 in self.iteritems()) def __setitem__(self, key, value): assert isinstance(key, basestring) if value: assert len(value) == 59 # len of formated sha1 else: value = '' changed = value != self.get(key) super(Fingerprints, self).__setitem__(key, value) if changed: self.save() tryton-4.6.5/tryton/jsonrpc.py0000644000175000017500000002636713251060075016001 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import xmlrpclib import json import ssl import httplib from decimal import Decimal import datetime import socket import gzip import StringIO import hashlib import base64 import threading import errno from functools import partial from contextlib import contextmanager import string __all__ = ["ResponseError", "Fault", "ProtocolError", "Transport", "ServerProxy", "ServerPool"] CONNECT_TIMEOUT = 5 DEFAULT_TIMEOUT = None class ResponseError(xmlrpclib.ResponseError): pass class Fault(xmlrpclib.Fault): def __init__(self, faultCode, faultString='', **extra): super(Fault, self).__init__(faultCode, faultString, **extra) self.args = faultString def __repr__(self): return ( "" % (repr(self.faultCode), repr(self.faultString)) ) class ProtocolError(xmlrpclib.ProtocolError): pass def object_hook(dct): if '__class__' in dct: if dct['__class__'] == 'datetime': return datetime.datetime(dct['year'], dct['month'], dct['day'], dct['hour'], dct['minute'], dct['second'], dct['microsecond']) elif dct['__class__'] == 'date': return datetime.date(dct['year'], dct['month'], dct['day']) elif dct['__class__'] == 'time': return datetime.time(dct['hour'], dct['minute'], dct['second'], dct['microsecond']) elif dct['__class__'] == 'timedelta': return datetime.timedelta(seconds=dct['seconds']) elif dct['__class__'] == 'bytes': cast = bytearray if bytes == str else bytes return cast(base64.decodestring(dct['base64'])) elif dct['__class__'] == 'Decimal': return Decimal(dct['decimal']) return dct class JSONEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime.date): if isinstance(obj, datetime.datetime): return {'__class__': 'datetime', 'year': obj.year, 'month': obj.month, 'day': obj.day, 'hour': obj.hour, 'minute': obj.minute, 'second': obj.second, 'microsecond': obj.microsecond, } return {'__class__': 'date', 'year': obj.year, 'month': obj.month, 'day': obj.day, } elif isinstance(obj, datetime.time): return {'__class__': 'time', 'hour': obj.hour, 'minute': obj.minute, 'second': obj.second, 'microsecond': obj.microsecond, } elif isinstance(obj, datetime.timedelta): return {'__class__': 'timedelta', 'seconds': obj.total_seconds(), } elif isinstance(obj, (bytes, bytearray)): return {'__class__': 'bytes', 'base64': base64.encodestring(obj), } elif isinstance(obj, Decimal): return {'__class__': 'Decimal', 'decimal': str(obj), } return super(JSONEncoder, self).default(obj) class JSONParser(object): def __init__(self, target): self.__targer = target def feed(self, data): self.__targer.feed(data) def close(self): pass class JSONUnmarshaller(object): def __init__(self): self.data = [] def feed(self, data): self.data.append(data) def close(self): return json.loads(''.join(self.data), object_hook=object_hook) class Transport(xmlrpclib.Transport, xmlrpclib.SafeTransport): accept_gzip_encoding = True encode_threshold = 1400 # common MTU def __init__(self, fingerprints=None, ca_certs=None, session=None): xmlrpclib.Transport.__init__(self) self._connection = (None, None) self.__fingerprints = fingerprints self.__ca_certs = ca_certs self.session = session def getparser(self): target = JSONUnmarshaller() parser = JSONParser(target) return parser, target def get_host_info(self, host): host, extra_headers, x509 = xmlrpclib.Transport.get_host_info( self, host) if extra_headers is None: extra_headers = [] if self.session: auth = base64.encodestring(self.session) auth = string.join(string.split(auth), "") # get rid of whitespace extra_headers.append( ('Authorization', 'Session ' + auth), ) extra_headers.append(('Connection', 'keep-alive')) return host, extra_headers, x509 def send_content(self, connection, request_body): connection.putheader("Content-Type", "application/json") if (self.encode_threshold is not None and self.encode_threshold < len(request_body) and gzip): connection.putheader("Content-Encoding", "gzip") buffer = StringIO.StringIO() output = gzip.GzipFile(mode='wb', fileobj=buffer) output.write(request_body) output.close() buffer.seek(0) request_body = buffer.getvalue() connection.putheader("Content-Length", str(len(request_body))) connection.endheaders() if request_body: connection.send(request_body) def make_connection(self, host): if self._connection and host == self._connection[0]: return self._connection[1] host, self._extra_headers, x509 = self.get_host_info(host) ssl_ctx = ssl.create_default_context(cafile=self.__ca_certs) class HTTPSConnection(httplib.HTTPSConnection): def connect(self): sock = socket.create_connection((self.host, self.port), self.timeout) if self._tunnel_host: self.sock = sock self._tunnel() self.sock = ssl_ctx.wrap_socket( sock, server_hostname=self.host) def http_connection(): self._connection = host, httplib.HTTPConnection(host, timeout=CONNECT_TIMEOUT) self._connection[1].connect() sock = self._connection[1].sock sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) def https_connection(allow_http=False): self._connection = host, HTTPSConnection(host, timeout=CONNECT_TIMEOUT) try: self._connection[1].connect() sock = self._connection[1].sock sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) try: peercert = sock.getpeercert(True) except socket.error: peercert = None def format_hash(value): return reduce(lambda x, y: x + y[1].upper() + ((y[0] % 2 and y[0] + 1 < len(value)) and ':' or ''), enumerate(value), '') return format_hash(hashlib.sha1(peercert).hexdigest()) except ssl.SSLError: if allow_http: http_connection() else: raise fingerprint = '' if self.__fingerprints is not None and host in self.__fingerprints: if self.__fingerprints[host]: fingerprint = https_connection() else: http_connection() else: fingerprint = https_connection(allow_http=True) if self.__fingerprints is not None: self.__fingerprints[host] = fingerprint self._connection[1].timeout = DEFAULT_TIMEOUT self._connection[1].sock.settimeout(DEFAULT_TIMEOUT) return self._connection[1] class ServerProxy(xmlrpclib.ServerProxy): __id = 0 def __init__(self, host, port, database='', verbose=0, fingerprints=None, ca_certs=None, session=None): self.__host = '%s:%s' % (host, port) if database: self.__handler = '/%s/' % database else: self.__handler = '/' self.__transport = Transport(fingerprints, ca_certs, session) self.__verbose = verbose def __request(self, methodname, params): self.__id += 1 id_ = self.__id request = json.dumps({ 'id': id_, 'method': methodname, 'params': params, }, cls=JSONEncoder, separators=(',', ':')) try: response = self.__transport.request( self.__host, self.__handler, request, verbose=self.__verbose ) except (socket.error, httplib.HTTPException), v: if (isinstance(v, socket.error) and v.args[0] == errno.EPIPE): raise # try one more time self.__transport.close() response = self.__transport.request( self.__host, self.__handler, request, verbose=self.__verbose ) except xmlrpclib.ProtocolError, e: raise Fault(str(e.errcode), e.errmsg) except: self.__transport.close() raise if response['id'] != id_: raise ResponseError('Invalid response id (%s) excpected %s' % (response['id'], id_)) if response.get('error'): raise Fault(*response['error']) return response['result'] def close(self): self.__transport.close() @property def ssl(self): return isinstance(self.__transport.make_connection(self.__host), httplib.HTTPSConnection) class ServerPool(object): keep_max = 4 def __init__(self, *args, **kwargs): self.ServerProxy = partial(ServerProxy, *args, **kwargs) self._lock = threading.Lock() self._pool = [] self._used = {} self.session = None def getconn(self): with self._lock: if self._pool: conn = self._pool.pop() else: conn = self.ServerProxy() self._used[id(conn)] = conn return conn def putconn(self, conn): with self._lock: self._pool.append(conn) del self._used[id(conn)] # Remove oldest connections while len(self._pool) > self.keep_max: conn = self._pool.pop() conn.close() def close(self): with self._lock: for conn in self._pool + self._used.values(): conn.close() self._pool = [] self._used.clear() @property def ssl(self): for conn in self._pool + self._used.values(): return conn.ssl return False @contextmanager def __call__(self): conn = self.getconn() yield conn self.putconn(conn) tryton-4.6.5/tryton/ipc.py0000644000175000017500000001176613251060075015073 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. """ Inter-Process Communication """ import tempfile import os import threading import select import time from tryton.config import get_config_dir __all__ = ['Server', 'Client'] class IPCServer(object): thread = None running = None instance = None def __init__(self, hostname, port, database): from tryton.common import slugify if Server.instance: Server.instance.stop() self.hostname = slugify(hostname) self.port = port self.database = slugify(database) self.config = os.path.join(get_config_dir(), '%s@%s@%s' % (self.hostname, self.port, self.database)) self.tmpdir = tempfile.mkdtemp(prefix='.tryton') Server.instance = self def setup(self): raise NotImplemented def run(self): self.setup() self.running = True self.thread = threading.Thread(target=self._read) self.thread.start() def clean(self): raise NotImplemented def stop(self): self.running = False self.thread.join() self.thread = None self.clean() Server.instance = None def _read(self): raise NotImplemented class FileServer(IPCServer): def setup(self): config = open(self.config, 'w') print >> config, self.tmpdir def clean(self): try: os.remove(self.config) os.rmdir(self.tmpdir) except OSError: pass def _read(self): to_remove = set() while self.running: for filename in os.listdir(self.tmpdir): path = os.path.join(self.tmpdir, filename) if not os.path.isfile(path): continue if path in to_remove: continue try: data = open(path, 'r').readline() except IOError: pass if data and data[-1] != '\n': continue to_remove.add(path) if data: from tryton.gui.main import Main Main.get_main().open_url(data[:-1]) if not os.path.exists(self.config): self.setup() for path in to_remove.copy(): try: os.remove(path) except OSError: continue to_remove.remove(path) time.sleep(1) class FIFOServer(IPCServer): def setup(self): self.filename = os.path.join(self.tmpdir, 'Socket') os.mkfifo(self.filename, 0600) if os.path.lexists(self.config): os.remove(self.config) os.symlink(self.filename, self.config) def clean(self): try: os.remove(self.config) os.rmdir(self.tmpdir) except OSError: pass def _read(self): fifo = os.fdopen(os.open(self.filename, os.O_RDONLY | os.O_NONBLOCK)) data = '' while self.running: try: rlist, _, _ = select.select([fifo], [], [], 1) except select.error: continue if rlist: try: data += fifo.readline() except IOError: pass if data and data[-1] != '\n': continue if data: from tryton.gui.main import Main Main.get_main().open_url(data.strip()) data = '' if not os.path.lexists(self.config): os.symlink(self.filename, self.config) class IPCClient(object): def __init__(self, hostname, port, database): self.hostname = hostname self.port = port self.database = database self.filename = os.path.join(get_config_dir(), '%s@%s@%s' % (hostname, port, database)) def write(self, message): raise NotImplemented class FileClient(IPCClient): def __init__(self, hostname, port, database): super(FileClient, self).__init__(hostname, port, database) def write(self, message): if not os.path.exists(self.filename): return False tmpdir = open(self.filename, 'r').readline().strip() _, tmpfile = tempfile.mkstemp(dir=tmpdir, text=True) with open(tmpfile, 'w') as tmpfile: print >> tmpfile, message return True class FIFOClient(IPCClient): def __init__(self, hostname, port, database): super(FIFOClient, self).__init__(hostname, port, database) def write(self, message): if not os.path.lexists(self.filename): return False fifo = open(self.filename, 'w') print >> fifo, message return True if hasattr(os, 'mkfifo'): Server = FIFOServer Client = FIFOClient else: Server = FileServer Client = FileClient tryton-4.6.5/tryton/__init__.py0000644000175000017500000000024613255571102016050 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. __version__ = "4.6.5" tryton-4.6.5/tryton/exceptions.py0000644000175000017500000000054113175640533016476 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from jsonrpc import Fault TrytonServerError = Fault class TrytonServerUnavailable(Exception): pass class TrytonError(Exception): def __init__(self, faultCode): self.faultCode = faultCode tryton-4.6.5/tryton/data/0000755000175000017500000000000013260723567014660 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/0000755000175000017500000000000013260723567016117 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/hu_HU/0000755000175000017500000000000013260723567017127 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/hu_HU/LC_MESSAGES/0000755000175000017500000000000013260723567020714 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/hu_HU/LC_MESSAGES/tryton.po0000644000175000017500000010651713255571102022613 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "Alternatív beállítási adatok megadása" #: tryton/config.py:73 msgid "development mode" msgstr "Fejlesztői mód" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "Általános belépési szint:INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "Belépési szint megadása: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "Bejelentkezési név megadása" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "Szerver név megadása" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Túl sok paraméter" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "A fájl „%s” nem található" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Nem lehet a következő konfigurációs fájlba írni: „%s”" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Nem lehet beállítani a csoportot: %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Válasszon műveletet" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Nincs megadva művelet" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Kapcsolódás" #: tryton/common/common.py:250 msgid "Server:" msgstr "Szerver:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Kiválasztás" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Kiválasztva" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Mentés másként…" #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Ne adja be többet ezt a figyelmeztetést" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Akarja folyatni?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Jóváhagyás" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Aktualizálási ellentét" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "aktualizálási ellentét az aktuális adatszó írásánál\n" "\n" "Ez az adatszó másképp került megváltoztatásra, amíg Ön feldolgozta\n" "Megoldási lehetőségek\n" "\"Mégse\", hogy a mentés folyamatát megszakítsa\n" "\"Összehasonlít\", hogy az adat megváltoztatott verzióját megtekintse\n" "\"Felülír\", hogy a mentett verziót felülírja" #: tryton/common/common.py:766 msgid "Compare" msgstr "Összehasonlítás" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Felülír" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Hiba" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Hibabejelentés" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Alkalmazási hiba" #: tryton/common/common.py:832 msgid "Error: " msgstr "Hiba:" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Az online hibabejelentéshez szükség van %s fiókra" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Hiba bejelentése" #: tryton/common/common.py:899 msgid "User:" msgstr "Felhasználó:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Jelszó:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Ez a hiba egy másik felhasználó által már be lett jelentve \n" "Az Ön felhasználóneve az érdekeltségi listára felkerült." #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Új hibabejelentés létesítése ezzel az ID -vel" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Kapcsolási hiba!\n" "Hibás felhasználónév vagy jelszó " #: tryton/common/common.py:986 msgid "Exception:" msgstr "Kivétel:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Az utolsó kapcsolás óta a szerver ujjlenyomata változott!\n" "A kliens nem lép kapcsolatba a szerverrel, amíg az ujjlenyomat nem felel meg a szerverével." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Biztonsági kockázat" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Kapcsolási hiba!\n" "Nem kapcsolódik a szerverrel!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Hálózati hiba" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "keresés..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Készítve..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Érték" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Megjelenített érték" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Formátum" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Megjelenítési formátum" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Naptár megnyitása" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Dátumformátum" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Mutatott dátumformátum" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "J" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Igaz" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "w" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Hamis" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Szerkesztés…" #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Mellékletek..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Műveletek" #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Kapcsolatok..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Jelentés..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "E-Mail..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Nyomtatás..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "J" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "W" #: tryton/common/timedelta.py:29 msgid "d" msgstr "t" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Felhasználó" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Beállítások" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_vorit" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Segítség" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Keresés" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Nincs találat" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Kapcsolódás…" #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Kapcsolat bontása" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Kilépés..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Beállítások…" #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "Menü újra mentése" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Menü átkapcsolása" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Globális keresés" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Eszköztár" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Alapértelmezett" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Szöveg és ikonok" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "Ikonok" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Szöveg" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Menüsáv" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Gyorsbillentyűk módosítása" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "Mód" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "Normál" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Űrlap" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Szélesség/magasság mentése" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Menünézet mentése" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Helyesírás ellenőrzés" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "Előző lap" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Következő lap" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Keresés limit" #: tryton/gui/main.py:655 msgid "_Email..." msgstr "E-mail..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Beállítások mentése" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Gyorsbillentyűk" #: tryton/gui/main.py:687 msgid "_About..." msgstr "Felett" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Kedvencek kezelése..." #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "A következő művelethez az összes lap bezárása szükséges\n" "Folytatja?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Lap bezárása" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Melléklet(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Profilszerkesztő" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Hozzáadás" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Eltávolítás" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Host:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Adatbank:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Adatbanklista lekérdezése..." #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Felhasználónév:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Inkompatibilis szerververzió" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Nem sikerült csatlakozni a kiszolgálóhoz" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Bejelentkezés" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Mégse" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "_Mégse" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "Kapcsolódik" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Kapcsolódás helyreállítása a Tryton szerverhez." #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "Profilok kezelése" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Host-/adatbank adatok" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Felhasználónév:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "E-mail" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "E-mail beállítások" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Parancssor:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Az elérhető helyettesítők jelmagyarázata:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "-hoz, -hez" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Tárgy:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Szöveg:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Melléklet:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Melléklet(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Legalább egy adatot kell kiválasztani." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Által létrehozva" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Létrehozás dátuma" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Utolsó módosítás" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Módosítás dátuma " #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Típus:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Biztos törölni szeretné?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Biztos törölni szeretné?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Adat nincs törölve!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Adat törölve" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "A másolaton dolgozik" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Adat mentve" #: tryton/gui/window/form.py:423 msgid " of " msgstr "-tól" #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Adat módosítva\n" "Szeretne menteni?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Művelet" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Művelet indítása" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Kapcsolat" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Kapcsolat adatainak megnyitása" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Jelentés" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Jelentés megnyitása" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "E-mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Jelentést e-mailon küldeni" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Nyomtatás" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Jelentés nyomtatása" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Ismeretlen" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Korlátozás" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Keresési beállítások" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Korlát:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Beállítások" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Felhasználói beállítások szerkesztése" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Beállítások" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Szerkesztés" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Szerkesztés kiválasztása" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Szerkesztés:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Gyorsbillentyűk" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Gyorsbillentyű szövegbeíráshoz" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Kijelölt szöveg kiválasztása" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "_Kijelölt szöveg másolása" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Kijelölt szöveg beillesztése" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Következő Widget" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Előző Widget" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Gyorsbillentyű az összekötő mezők beírásához" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Új kapcsolat létrehozása" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Kapcsolatok keresése/megnyitása" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Gyorsbillentyűk lista mezők beírásához" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Új sor létrehozása" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Kapcsolat megnyitása" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Kijelölés törlésre" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "A törlési kijelölés visszavonása" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Widget szerkesztéshez" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Nézet váltása" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Nézet váltása" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Előző" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Előző adat" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Következő" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Következő adat" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Keresés" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Új" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Új bejegyzés létrehozása" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Mentés" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Bejegyzés mentése" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Frissítés/ visszavonás" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Frissítés/ visszavonás" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "Másolat" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Törlés..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Napló megtekintése…" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Feldolgozások megtekintése" #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "Csatolmány" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Melléklet hozzáadása az üzenethez." #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Műveletek" #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "Kapcsolat megnyitása" #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "Jelentés megnyitása..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "Jelentés per e-mail" #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Nyomtatás…" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Adat exportálása" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Adat importálása" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Lap bezárása" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "összes mező" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Törlés" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV Paraméter" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Kódolás:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Mezőnév" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "CSV ként exportálni" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Előre megadott export" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Név" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Export mentése" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Export törlése" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Megnyitás" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Mentés" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Mezőnév hozzáadása" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (string)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Mi legyen az export neve?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "'%s' definiálásának figyelembe vétele?" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d adat mentve" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d adatok mentve!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Sikertelen művelet!\n" "Error message:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Hivatkozás" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Hozzáad" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Mező eltávolítása" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Új adat létrehozása." #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Kiválasztott adatok törlése" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Törlés visszavonása" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Előző" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Következő" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Nézet váltása" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "CSV-ből adatok importálása" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Automatikus felismerés" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Importadatok:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Megnyitás..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Átugrandó sorok:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Először ki kell jelölni legalább egy fájlt." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Hiba a CSV fájl megnyitásakor" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Hiba az adat feldolgozásnál a %s mezőben." #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d adat importálva..." #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d adat importálva..." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Wizard" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Által létrehozva" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Létrehozás dátuma" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Által módosítva" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Módosítás dátuma" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "A menü láthatósága nem állítható be" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Kép mérete" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Szélesség:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Magasság:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG Kép (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Mentés másként" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Kép túl nagy!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Szűrő könyvjelzők megjelenítése" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Könyvjelző eltávolítása" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "A szűrőt könyvjelzőként hozzáadni" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Könyvjelző neve:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Keresés" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Ma" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Heti nézet" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Havi nézet" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Hét" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Törlés" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Összes fájl" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Magyarázat mutatása" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Érték hozzáadása" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "„%s” eltávolítása" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Képek" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Meglévő adat hozzáadása" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Kijelölt adat törlése" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Adat megnyitása" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Adat keresése" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "A kiválasztott adat eltávolítása" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "A kiválasztott adat átdolgozása" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Fordítás" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Szerkesztés" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Életlen" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Az adatot menteni kell, mielőtt egy fordítást hozzá lehet adni!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Más nyelv nem használható!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Nézet elfordítása" tryton-4.6.5/tryton/data/locale/hu_HU/LC_MESSAGES/tryton.mo0000644000175000017500000004050013260723565022605 0ustar cedced00000000000000A$ ,-)2\mu  .Gg { #% %4 IUZ^m&v     #0J bo  )7F X bn   7?OU lv|&     $ <G[k p{ "+ C!Qsy   '= LY h v      #/AI^x    . 7C JT o {      ( : K R \ r       !!#!=!M!_!n!w!~!I!}! ]"4~""" """" " ###(#$C#%h###### $ $$ "$,$ 2$@$ E$ O$p$w$ ~$$$$ $ $$$ $ $ $ $$ $ % % % '%1%A%G%V%\%c%s%% % %%%%% %% %%%% & & !&+& 4& ?&L& T&_& e&s& {&&&&&&&& && && & '''<0'm''''')))G)X)`)p) )))))))T)6+K+ ^+j+ s+~+++&+++ ,),G,c,, ,,,,',,-- - -&-.-M-V-m-|- - --- -4-. /.<.+Z.....2.$/9/N/a/ t/ //$/ ///0)0:0A0 ^0 h0+u0&00000 111,<1i1 o1y1 11111 11 1 1 2.2 72 B2L2 U2`2v2|22 22222223.#3 R3_3h3 {3+33333334 "4 .4 :4D4Z4 i4v4 4 4444 44444 55 5 '545T5j55 5!5*556 6)6/6>6M6\6 d6q6 66 6666 6 6646*7C7*_777 77 7 7 788"878L8k88 8888888 8 99 .989 T9b9%k999999"9J:e: :<; D;O; R;];n;; ; ;; ;;$;%;&%<*L<w< <%< <<<<==(= -=9= S=`= g=q=s= w== = ==== = == =>>> 3>=>P>W> j>v>}>>>>> >>> >?? ?#?3?7?J? S?_? n?{?????? ??@@ ,@9@H@J@[@ c@n@!p@@ @ @@*@A@A:AA of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUndelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: hu_HU Language-Team: hu_HU Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 -tól"%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:összes mezőFields selectedElőre megadott exportaktualizálási ellentét az aktuális adatszó írásánál Ez az adatszó másképp került megváltoztatásra, amíg Ön feldolgozta Megoldási lehetőségek "Mégse", hogy a mentés folyamatát megszakítsa "Összehasonlít", hogy az adat megváltoztatott verzióját megtekintse "Felülír", hogy a mentett verziót felülírjaKészítve...keresés...CsatolmányMűveletMűveletekHozzáadMezőnév hozzáadásaAdd a note to the recordMelléklet hozzáadása az üzenethez.Meglévő adat hozzáadásaÉrték hozzáadásaÖsszes fájlNe adja be többet ezt a figyelmeztetéstBiztos törölni szeretné?Biztos törölni szeretné?Melléklet(%d)Melléklet:Mellékletek...Szöveg:Könyvjelző neve:A szűrőt könyvjelzőként hozzáadniHiba bejelentéseBy: CC:CSV ParaméterKapcsolódik_MégseGyorsbillentyűk módosításaTörlésClear the record Lap bezárásaCollapse all rowsCollapse rowParancssor:ÖsszehasonlításAktualizálási ellentétJóváhagyásKapcsolódás helyreállítása a Tryton szerverhez.Copy URL into clipboardCopy _URL..._Kijelölt szöveg másolásaNem sikerült csatlakozni a kiszolgálóhozÚj bejegyzés létrehozásaÚj adat létrehozása.Új sor létrehozásaÚj kapcsolat létrehozásaÚj hibabejelentés létesítése ezzel az ID -velLétrehozás dátumaLétrehozás dátumaÁltal létrehozvaÁltal létrehozvaKijelölt szöveg kiválasztásaAdatbank:DátumformátumKiválasztott adatok törléseDelimiter:Megjelenítési formátumMutatott dátumformátumMegjelenített értékAkarja folyatni?E-mailJelentést e-mailon küldeniE-Mail...SzerkesztésFelhasználói beállítások szerkesztéseA kiválasztott adat átdolgozásaSzerkesztés…Widget szerkesztéshezE-mailE-mail beállításokKódolás:HibaHiba a CSV fájl megnyitásakorHiba az adat feldolgozásnál a %s mezőben.Hiba:Kivétel:Expand all rowsExpand rowExpand/CollapseCSV ként exportálniFa_voritHamisFast TabbingAdatbanklista lekérdezése...MezőnévA fájl „%s” nem találhatóImportadatok:KeresésForegroundFormátumÉletlenMagasság:Host-/adatbank adatokHost:IDID:Kép méreteKépekCSV-ből adatok importálásaInkompatibilis szerververzióGyorsbillentyűkMódosítás dátuma Utolsó módosításMűvelet indításaAz elérhető helyettesítők jelmagyarázata:KorlátozásKorlát:Átugrandó sorok:HivatkozásGyorsbillentyűk lista mezők beírásáhozBejelentkezésMKedvencek kezelése...Kijelölés törlésreTípus:Módosítás dátumaÁltal módosítvaHavi nézetMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNévKövetkezőKövetkező adatKövetkező WidgetNincs találatNote(%d)Notes (%s)Notes...MegnyitásOpen filtersKapcsolat adatainak megnyitásaKapcsolat megnyitásaJelentés megnyitásaNaptár megnyitásaMegnyitás...Kapcsolatok keresése/megnyitása'%s' definiálásának figyelembe vétele?PNG Kép (*.png)Jelszó:Kijelölt szöveg beillesztésePort:Pre-validationBeállításokBeállításokElőzőElőző adatElőző WidgetNyomtatásJelentés nyomtatásaNyomtatás...ProfilProfilszerkesztőProfil:Quote char:KapcsolatKapcsolatok...Gyorsbillentyű az összekötő mezők beírásához„%s” eltávolításaMező eltávolításaA kiválasztott adat eltávolításaKijelölt adat törléseKönyvjelző eltávolításaJelentésHibabejelentésJelentés...SzerkesztésSzerkesztés:MentésMentés máskéntMentés másként…Menünézet mentéseSzélesség/magasság mentéseBejegyzés mentéseKeresésSearch %sKeresési beállításokKeresés limitAdat kereséseSelectSelect a colorSzerkesztés kiválasztásaSelect allSelect parentVálasszon műveletetSelect...Select/Activate current rowKiválasztásSzerver:Szűrő könyvjelzők megjelenítéseMagyarázat mutatásaFeldolgozások megtekintéseHelyesírás ellenőrzésTárgy:Nézet váltásaGyorsbillentyű szövegbeíráshozA következő művelethez az összes lap bezárása szükséges Folytatja?Ez a hiba egy másik felhasználó által már be lett jelentve Az Ön felhasználóneve az érdekeltségi listára felkerült.The values of "%s" are not validAz online hibabejelentéshez szükség van %s fiókra-hoz, -hezMaToggle rowToggle selectionTúl sok paraméterNézet elfordításaFordításTree viewIgazKapcsolódásUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sNem lehet beállítani a csoportot: %sA menü láthatósága nem állítható beTörlés visszavonásaIsmeretlenA törlési kijelölés visszavonásaUnselect allFelhasználónév:Felhasználó:Felhasználónév:ÉrtékNapló megtekintése…HétHeti nézetMi legyen az export neve?Szélesség:WizardFelülírJYesKiválasztvaFelett_Műveletek_Hozzáadás_MégseLap bezárása_Kapcsolódás…_Connection_Copy URL_Alapértelmezett_Törlés...Kapcsolat bontásaMásolatJelentés per e-mailE-mail...Adat exportálásaŰrlapGlobális keresés_SegítségIkonokAdat importálása_GyorsbillentyűkProfilok kezeléseMenü újra mentéseMenü átkapcsolása_MenüsávMód_Új_KövetkezőKövetkező lapNormál_Notes..._BeállításokPDA_Beállítások…_ElőzőElőző lap_Nyomtatás…Kilépés...Kapcsolat megnyitásaFrissítés/ visszavonás_EltávolításJelentés megnyitása..._MentésBeállítások mentése_KeresésNézet váltása_SzövegSzöveg és ikonok_Eszköztár_FelhasználótFejlesztői módgo backgo forwardhÁltalános belépési szint:INFOmnext yearprevious yearsAlternatív beállítási adatok megadásaBelépési szint megadása: DEBUG, INFO, WARNING, ERROR, CRITICALBejelentkezési név megadásawWJtryton-4.6.5/tryton/data/locale/fr/0000755000175000017500000000000013260723567016526 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/fr/LC_MESSAGES/0000755000175000017500000000000013260723567020313 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/fr/LC_MESSAGES/tryton.po0000644000175000017500000011121313255571102022177 0ustar cedced00000000000000# French (France) translations for tryton. # Copyright (C) 2008-2013 B2CK # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2008-2013. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "spécifier un fichier de configuration alternatif" #: tryton/config.py:73 msgid "development mode" msgstr "mode développement" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "logger tout au niveau INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "spécifie le niveau de log : DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "spécifier l'utilisateur de login" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "spécifier le nom du serveur:port" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Trop d'arguments" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Fichier « %s » non trouvé" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "Impossible d'écrire le fichier de configuration %s." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Impossible de sélectionner la locale %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Sélectionnez votre action" #: tryton/action/main.py:197 msgid "No action defined." msgstr "Pas d'action définie." #: tryton/common/button.py:56 msgid "By: " msgstr "Par: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Connexion Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Serveur :" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port :" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Sélection" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Votre sélection :" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Enregistrer sous..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Toujours ignorer cet avertissement." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Souhaitez-vous continuer ?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Confirmation" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Erreur d'accès concurrent" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Attention, accès en écriture concurrents :\n" "\n" "Cet enregistrement a été édité pendant que vous étiez en train de le modifier.\n" " Choisissez :\n" " - « Annuler » pour annuler vos modifications ;\n" " - « Comparer » pour voir la nouvelle version ;\n" " - « Écraser » pour sauver vos modifications." #: tryton/common/common.py:766 msgid "Compare" msgstr "Comparer" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Écraser" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Erreur" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Rapporter un bogue" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Erreur Applicative." #: tryton/common/common.py:832 msgid "Error: " msgstr "Erreur : " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Pour rapporter un bogue vous devez avoir un compte sur %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Bug Tracker" #: tryton/common/common.py:899 msgid "User:" msgstr "Utilisateur :" #: tryton/common/common.py:907 msgid "Password:" msgstr "Mot de passe :" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Le même bogue a été déjà rapporté par un autre utilisateur.\n" "Pour vous garder informé, votre nom d'utilisateur a été ajouté à la liste de suivi de ce bogue" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Un nouveau bogue a été créé avec l'ID " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Erreur de connexion.\n" "Mauvais nom d'utilisateur ou mot de passe." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Exception :" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "L'empreinte digitale du serveur a changé depuis la dernière connexion.\n" "Les connexions à ce serveur sont annulées tant que son empreinte n'est pas corrigée." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Alerte sécurité." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Erreur de connexion.\n" "Impossible de se connecter au serveur." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Erreur réseau." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Recherche..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Créer..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "Impossible de rechercher la complétion de %s" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Valeur" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Valeur affichée" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Format" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Format d'affichage" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Ouvrir le calendrier" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Format de date" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Format de date affichée" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "y" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Oui" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Vrai" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "v" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Faux" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Éditer..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Attachements..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notes..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Actions..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Relation..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Rapport..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "Email..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Imprimer..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "A" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "S" #: tryton/common/timedelta.py:29 msgid "d" msgstr "j" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_Connexion" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Utilisateur" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Options" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_voris" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Aide" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Recherche" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Aucun résultat trouvé." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Connecter..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Déconnecter" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Quitter..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Préférences..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Recharger le menu" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Montrer / Cacher le _menu" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Recherche _globale" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Barre d'outils" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Défaut" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Textes et Icônes" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Icônes" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Textes" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Barre de menu" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Changer les raccourcis" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Mode" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Formulaire" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Sauver largeur / hauteur" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Sauver l'état des arbres" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Tabulation rapide" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Vérifier l'orthographe" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "Onglet _précédent" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Onglet _suivant" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Limite la recherche à..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Email..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Sauver les options" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Raccourcis _clavier..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_À Propos..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "_Gérer les favoris" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "L'action suivante nécessite de fermer tous les onglets.\n" "Voulez-vous continuer ?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Fermer l'onglet" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Attachements (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Éditeur de profil" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Ajouter" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Enlever" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Hôte :" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Base de données :" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Récupération de la liste des bases de données" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Nom d'utilisateur :" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Version du serveur incompatible" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Impossible de se connecter au serveur" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Connexion" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "A_nnuler" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Annuler la connexion au serveur Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "C_onnecter" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Se connecter au serveur Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profil :" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Gestionnaire de profils" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Hôte / Port" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Nom d'utilisateur :" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Email" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Paramètres d'email" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Commande :" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Légende des symboles :" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "À :" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC :" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Sujet :" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Corps :" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Attachement :" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Attachement(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Note(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Vous devez sélectionner un enregistrement." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID :" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Créé par l'utilisateur :" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Date de création :" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Dernière modification par :" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Date de dernière modification :" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modèle :" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Êtes-vous sûr de vouloir supprimer cet enregistrement ?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Êtes-vous sûr de vouloir supprimer ces enregistrements ?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Enregistrements non supprimés." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Enregistrements supprimés." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Sur les enregistrement(s) dupliqué(s) maintenant." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Enregistrement sauvegardé." #: tryton/gui/window/form.py:423 msgid " of " msgstr " de " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Cet enregistrement a été modifié\n" "voulez-vous le sauvegarder ?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Actions" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Lancer une action" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Relation" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Ouvrir les enregistrements liés" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Rapport" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Ouvrir un rapport" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Email" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Rapport par email" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Imprimer" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Imprimer un rapport" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_Copier l'URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Copier l'URL dans le presse-papiers" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Inconnu" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limite" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Limite de recherche" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Limite :" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notes (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Préférences" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Éditer les préférences utilisateur" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Préférence" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Révision" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Sélectionner une révision" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Révision :" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Raccourcis clavier" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Raccourcis des champs texte" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Couper le texte sélectionné" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Copier le texte sélectionné" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Coller le texte copié" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Widget suivant" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Widget précédent" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Raccourcis des champs relation" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Créer une nouvelle relation" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Ouvrir/Chercher une relation" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Raccourcis des listes" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Créer une nouvelle ligne" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Ouvrir une relation" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Marquer la ligne pour suppression" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Annuler le marquage de la ligne pour suppression" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Widgets d'édition" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Déplacer le curseur" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Déplacer vers la droite" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Déplacer vers la gauche" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Déplacer vers le haut" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Déplacer vers le bas" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Déplacer vers le haut d'une page" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Déplacer vers le bas d'une page" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Déplacer au dessus" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Déplacer en bas" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Déplacer au parent" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Tout sélectionner" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Désélectionner tout" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Sélectionner le parent" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Sélectionner/Activer la ligne courante" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Basculer la sélection" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Déplier/Replier" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Déplier la ligne" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Replier la ligne" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Basculer la ligne" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Replier toutes les lignes" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Déplier toutes les lignes" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Vue arborescente" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_Changer de vue" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "Changer de vue" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Précédent" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Enregistrement précédent" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Sui_vant" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Enregistrement suivant" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Recherche" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nouveau" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Créer un nouvel enregistrement" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Sauver" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Sauver cet enregistrement" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_Recharger/Annuler" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "Recharger/Annuler" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Dupliquer" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Su_pprimer..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Voir les _Logs..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Afficher les révisions..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "_Pièce jointes..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Ajouter un attachement à l'enregistrement" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Notes..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Ajouter une note à l'enregistrement" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Actions..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Relation..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Rapport..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_Email..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Imprimer..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Export de données..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Import de données..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "Copier l'_URL" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Fermer l'onglet" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Tout les champs" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Effacer" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Champs sélectionnés" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Paramètres CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Délimiteur :" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Caractère de guillemet :" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codage :" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nom du champ" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exporter en CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Exportations prédéfinies" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nom" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_Sauver l'exportation" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_Supprimer l'exportation" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Ouvrir" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Sauver" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Ajouter les noms des champs" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (string)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "%s (nom de l'enregistrement)" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "%s (nom de l'enregistrement)" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Quel est le nom de cet export ?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Surcharger la définition « %s » ?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "%d enregistrement sauvé." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "%d enregistrements sauvés." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Échec de l'opération.\n" "Message d'erreur :\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Lien" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Ajouter" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Supprimer " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Créer un nouvel enregistrement" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Supprimer l'enregistrement sélectionné" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Restaurer l'enregistrement sélectionné" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Précédent" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Suivant" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Basculer" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importer depuis un CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "Détection _automatique" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Fichier à importer :" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Ouvrir..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Lignes à ignorer :" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Vous devez d'abord sélectionner un fichier d'import." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Erreur d'ouverture du fichier CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Erreur lors du traitement du fichier du champ %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "%d enregistrement importé." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "%d enregistrements importés." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Rechercher %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "Impossible de supprimer l'assistant %s" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Assistant" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Créé par l'utilisateur" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Date de création" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Modifié par l'utilisateur" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Date de modification" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, python-format msgid "Unable to get view tree state for %s" msgstr "Impossible d'obtenir l'état de la vue arbre de %s" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Impossible de définir l'état de la vue arbre" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "« %s » n'est pas valide selon son domaine" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "« %s » est requis" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Les valeurs de « %s » ne sont pas valides" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Pré-validation" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr " :" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Taille de l'image" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Largeur :" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Hauteur :" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "image PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Enregistrer sous" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "Taille de l'image trop grande." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Ouvrir les filtres" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Montrer les marques-pages des filtres" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Supprimer ce marque-page" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Sauver ce filtre" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Nom du marque-page :" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Chercher" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Aujourd'hui" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "revenir" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "avancer" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "année précédente" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "année suivante" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Vue semaine" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Vue mois" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Semaine" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Sélectionner..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Effacer" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Tous les fichiers" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Sélectionner" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Montrer en text clair" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Ajouter une valeur" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Supprimer « %s »" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Images" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Ajouter un enregistrement existant" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Supprimer l'enregistrement sélectionné" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Ouvrir l'enregistrement " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Effacer l'enregistrement " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Chercher un enregistrement" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Supprimer l'enregistrement sélectionné" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Éditer l'enregistrement sélectionné" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Couleur du texte" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Sélectionner une couleur" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Traduction" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Éditer" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Floue" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "" "Vous devez sauvegarder l'enregistrement avant d'ajouter des traductions." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "Pas d'autre langue disponible." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Traduire la vue" tryton-4.6.5/tryton/data/locale/fr/LC_MESSAGES/tryton.mo0000644000175000017500000004663613260723565022224 0ustar cedced00000000000000d< \])b #&+.24F]w]n   3#F%j   &"I]c z   +2"U mz % 4BQ c my    (BJZ` w&     "/ GRfv { "2L d!r  ' 2 > H ^ m z       ! !1! :!E!N! S!`! u! !!!!!#!!" #"-"?"E" T" _"k"t""" """"" " """# #!# <# H# T#a#x### # ## ### ##$$$$ +$5$K$[$p$$$$ $ $$ $$ $% %%%5%G%V%_% f%r%I%}%Q& &5'46'k'o' u'''' ' ''''$'% (F(^(|(((( ( (( () )) ) ')H)O)(V) ))))%)7)* * )*5* :*G*O* V* a* m* y*** * * * * ******++++ <+ I+V+_+e+j+ p+z+ ++++ + + ++ + ++ +, , ,!, ),6,<,L,U,[,],n, v,, ,, , ,,,<,- 2-S-U-W-Y-.-.///K/e///// //////000!90>[01111 111$ 2*.2"Y2|22#22:2;3P3`3o33333 3333 3&3424:4Y4i44 444 44?4;05#l5 55%55#6&6@6*]66666677-%7S7b7u7777777%7* 8 58@8S8Y8 m8w8!~818 8 8899(989A9F90X9 9999999 9 9 ::::/:N:U:l::!:::: ; ;;0;5; K;U;W;!k; ;;;;;; ;<.<G<[<t<<!<<<<<<==9=R= [=f=o=v= ===== > >.)>'X>>>>>> > > >>?&?/? C?O?V? i?s????? ??@,@A@(Q@-z@@@@ @ @ @@AA*ADA]A wA AAAAA AAB3BFB^ByB'B B B%BBCC7C@CICXCQtCClD- EA;E@}EE EEEE F F%F6F;F&LF2sF-F(F.F4,G-aGG0GGGGHHH0H 8H DH eH pH2zHHHH+H5HHIgI {I IIIIII I I IJ J "J 0J >J IJ SJ]J tJJJJJJJJJK%K+K4K=KMK UK_KhKmK KK K K KKK KKK L L+L;LCLVL fLsLuLLLLLLLLL1LCM!TM!vMMMM of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: fr Language-Team: fr Plural-Forms: nplurals=2; plural=(n > 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 de « %s » n'est pas valide selon son domaine« %s » est requis%d enregistrement importé.%d enregistrement sauvé.%d enregistrements importés.%d enregistrements sauvés.%s (%s)%s (nom de l'enregistrement)%s (nom de l'enregistrement)%s (string)%s%%, ,…..... :Tout les champsChamps sélectionnésExportations prédéfiniesAttention, accès en écriture concurrents : Cet enregistrement a été édité pendant que vous étiez en train de le modifier. Choisissez : - « Annuler » pour annuler vos modifications ; - « Comparer » pour voir la nouvelle version ; - « Écraser » pour sauver vos modifications.Créer...Recherche..._Pièce jointes...ActionsActions...AjouterAjouter les noms des champsAjouter une note à l'enregistrementAjouter un attachement à l'enregistrementAjouter un enregistrement existantAjouter une valeurTous les fichiersToujours ignorer cet avertissement.Erreur Applicative.Êtes-vous sûr de vouloir supprimer cet enregistrement ?Êtes-vous sûr de vouloir supprimer ces enregistrements ?Attachement(%d)Attachement :Attachements (%s)Attachements...Corps :Nom du marque-page :Sauver ce filtreBug TrackerPar: CC :Paramètres CSVC_onnecterAnnuler la connexion au serveur TrytonChanger les raccourcisEffacerEffacer l'enregistrement Fermer l'ongletReplier toutes les lignesReplier la ligneCommande :ComparerErreur d'accès concurrentConfirmationSe connecter au serveur TrytonErreur de connexion. Mauvais nom d'utilisateur ou mot de passe.Erreur de connexion. Impossible de se connecter au serveur.Copier l'URL dans le presse-papiersCopier l'_URLCopier le texte sélectionnéImpossible de se connecter au serveurCréer un nouvel enregistrementCréer un nouvel enregistrementCréer une nouvelle ligneCréer une nouvelle relationUn nouveau bogue a été créé avec l'ID Date de créationDate de création :Créé par l'utilisateurCréé par l'utilisateur :Couper le texte sélectionnéBase de données :Format de dateSupprimer l'enregistrement sélectionnéDélimiteur :Format d'affichageFormat de date affichéeValeur affichéeSouhaitez-vous continuer ?EmailRapport par emailEmail...ÉditerÉditer les préférences utilisateurÉditer l'enregistrement sélectionnéÉditer...Widgets d'éditionEmailParamètres d'emailCodage :ErreurErreur d'ouverture du fichier CSVErreur lors du traitement du fichier du champ %s.Erreur : Exception :Déplier toutes les lignesDéplier la ligneDéplier/ReplierExporter en CSVFa_vorisFauxTabulation rapideRécupération de la liste des bases de donnéesNom du champFichier « %s » non trouvéFichier à importer :ChercherCouleur du texteFormatFloueHauteur :Hôte / PortHôte :IDID :Taille de l'imageTaille de l'image trop grande.ImagesImporter depuis un CSVVersion du serveur incompatibleRaccourcis clavierDate de dernière modification :Dernière modification par :Lancer une actionLégende des symboles :LimiteLimite :Lignes à ignorer :LienRaccourcis des listesConnexionM_Gérer les favorisMarquer la ligne pour suppressionModèle :Date de modificationModifié par l'utilisateurVue moisDéplacer le curseurDéplacer vers le basDéplacer vers le bas d'une pageDéplacer en basDéplacer vers la gaucheDéplacer au parentDéplacer vers la droiteDéplacer au dessusDéplacer vers le hautDéplacer vers le haut d'une pageNomErreur réseau.SuivantEnregistrement suivantWidget suivantPas d'action définie.Pas d'autre langue disponible.Aucun résultat trouvé.Note(%d)Notes (%s)Notes...OuvrirOuvrir les filtresOuvrir les enregistrements liésOuvrir une relationOuvrir un rapportOuvrir le calendrierOuvrir l'enregistrement Ouvrir...Ouvrir/Chercher une relationÉchec de l'opération. Message d'erreur : %sSurcharger la définition « %s » ?image PNG (*.png)Mot de passe :Coller le texte copiéPort :Pré-validationPréférencePréférencesPrécédentEnregistrement précédentWidget précédentImprimerImprimer un rapportImprimer...ProfilÉditeur de profilProfil :Caractère de guillemet :Enregistrement sauvegardé.Enregistrements non supprimés.Enregistrements supprimés.RelationRelation...Raccourcis des champs relationRecharger/AnnulerSupprimer « %s »Supprimer Supprimer l'enregistrement sélectionnéSupprimer l'enregistrement sélectionnéSupprimer ce marque-pageRapportRapporter un bogueRapport...RévisionRévision :SauverEnregistrer sousEnregistrer sous...Sauver l'état des arbresSauver largeur / hauteurSauver cet enregistrementRechercheRechercher %sLimite de rechercheLimite la recherche à...Chercher un enregistrementAlerte sécurité.SélectionnerSélectionner une couleurSélectionner une révisionTout sélectionnerSélectionner le parentSélectionnez votre actionSélectionner...Sélectionner/Activer la ligne couranteSélectionServeur :Montrer les marques-pages des filtresMontrer en text clairAfficher les révisions...Vérifier l'orthographeSujet :BasculerChanger de vueRaccourcis des champs texteL'action suivante nécessite de fermer tous les onglets. Voulez-vous continuer ?Le même bogue a été déjà rapporté par un autre utilisateur. Pour vous garder informé, votre nom d'utilisateur a été ajouté à la liste de suivi de ce bogueL'empreinte digitale du serveur a changé depuis la dernière connexion. Les connexions à ce serveur sont annulées tant que son empreinte n'est pas corrigée.Les valeurs de « %s » ne sont pas validesCet enregistrement a été modifié voulez-vous le sauvegarder ?Pour rapporter un bogue vous devez avoir un compte sur %sÀ :Aujourd'huiBasculer la ligneBasculer la sélectionTrop d'argumentsTraduire la vueTraductionVue arborescenteVraiConnexion TrytonImpossible de supprimer l'assistant %sImpossible d'obtenir l'état de la vue arbre de %sImpossible de rechercher la complétion de %sImpossible de sélectionner la locale %sImpossible de définir l'état de la vue arbreImpossible d'écrire le fichier de configuration %s.Restaurer l'enregistrement sélectionnéInconnuAnnuler le marquage de la ligne pour suppressionDésélectionner toutNom d'utilisateur :Utilisateur :Nom d'utilisateur :ValeurVoir les _Logs...SemaineVue semaineQuel est le nom de cet export ?Largeur :AssistantSur les enregistrement(s) dupliqué(s) maintenant.ÉcraserAOuiVous devez sélectionner un enregistrement.Vous devez d'abord sélectionner un fichier d'import.Vous devez sauvegarder l'enregistrement avant d'ajouter des traductions.Votre sélection :_À Propos..._Actions..._AjouterDétection _automatiqueA_nnuler_Effacer_Fermer l'onglet_Connecter..._Connexion_Copier l'URL_Défaut_Supprimer l'exportationSu_pprimer..._Déconnecter_Dupliquer_Email..._Email..._Export de données..._FormulaireRecherche _globale_Aide_Icônes_Import de données...Raccourcis _clavier..._Gestionnaire de profils_Recharger le menuMontrer / Cacher le _menu_Barre de menu_Mode_NouveauSui_vantOnglet _suivant_Normal_Notes..._Options_PDA_Préférences..._PrécédentOnglet _précédent_Imprimer..._Quitter..._Relation..._Recharger/Annuler_Enlever_Rapport..._Sauver_Sauver l'exportation_Sauver les options_Recherche_Changer de vue_Textes_Textes et Icônes_Barre d'outils_Utilisateurjmode développementreveniravancerhlogger tout au niveau INFOmannée suivanteannée précédentesspécifier un fichier de configuration alternatifspécifie le niveau de log : DEBUG, INFO, WARNING, ERROR, CRITICALspécifier l'utilisateur de loginspécifier le nom du serveur:portvSytryton-4.6.5/tryton/data/locale/pt_BR/0000755000175000017500000000000013260723567017125 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/pt_BR/LC_MESSAGES/0000755000175000017500000000000013260723567020712 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/pt_BR/LC_MESSAGES/tryton.po0000644000175000017500000011001213255571102022572 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "especificar arquivo de configuração alternativo" #: tryton/config.py:73 msgid "development mode" msgstr "modo de desenvolvimento" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "Registrar (log) tudo com nível INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" "Especifique o nível de registro (log level): DEBUG, INFO, WARNING, ERROR, " "CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "Especifique o nome do usuário" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "Especifique o servidor hostname:porta" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Muitos argumentos" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Arquivo \"%s\" não encontrado" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "Não foi possível gravar o arquivo de configuração %s." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Não foi possível definir as configurações regionais %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Selecione sua ação" #: tryton/action/main.py:197 msgid "No action defined." msgstr "Nenhuma ação definida." #: tryton/common/button.py:56 msgid "By: " msgstr "Por: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Conexão ao Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Servidor:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Porta:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Seleção" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Sua seleção:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Salvar como..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Sempre ignorar este aviso." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Você deseja prosseguir?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Confirmação" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Exceção de concorrência" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Aviso de Escrita Concorrente:\n" "\n" "Este registro foi modificado enquanto você o editava.\n" " Escolha:\n" " - \"Cancelar\" para cancelar a gravação;\n" " - \"Comparar\" para ver a versão modificada;\n" " - \"Gravar\" para salvar a versão atual." #: tryton/common/common.py:766 msgid "Compare" msgstr "Comparar" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Gravar mesmo assim" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Erro" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Reportar erro (bug)" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Erro da aplicação." #: tryton/common/common.py:832 msgid "Error: " msgstr "Erro: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Para reportar erros você deve ter uma conta em %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Sistema de registro de erros" #: tryton/common/common.py:899 msgid "User:" msgstr "Usuário:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Senha:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "O mesmo erro já foi reportado por outro usuário.\n" "Para mantê-lo informado, seu nome de usuário foi adicionado à lista de acompanhamento deste caso" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Criar novo erro (bug) com ID " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Erro de conexão.\n" "Usuário ou senha incorretos." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Exceção:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "A identidade (fingerprint) do servidor mudou desde a última conexão.\n" "O programa não se conectará a este servidor até que sua identidade seja corrigida." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Risco de segurança." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Erro de conexão.\n" "Não foi possível se conectar ao servidor." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Erro na rede." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Buscar..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Criar..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "Não foi possível encontrar complementos de %s" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Valor" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Valor exibido" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Formato" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Formato de exibição" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Abrir o calendário" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Formato de Data" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Formato de data exibido" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "s" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Sim" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Verdadeiro" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "v" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Falso" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Editar..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Anexos..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notas..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Ações..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Relacionado..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Relatório..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "E-mail..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Imprimir..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "A" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "s" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_Conexão" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Usuário" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Opções" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_voritos" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Ajuda" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Busca" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Nenhum resultado encontrado." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Conectar..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Desconectar" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Sair..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Preferências..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Recarregar Menu" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "_Alternar Menu" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "_Busca Global" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Barra de Ferramentas" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Padrão" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Texto e Ícones" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Ícones" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Texto" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Barra do Menu" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Mudar teclas de atalho" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Modo" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Formulário" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Gravar Largura/Altura" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Gravar Estado da Árvore" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Tabulação rápida" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Verificar Ortografia" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Aba Anterior" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_Próxima Aba" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Limite de Buscas..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Email..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Salvar Opções" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Atalhos do Teclado..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Sobre..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Gerenciar Favoritos" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "A ação seguinte requer que todas as abas sejam fechadas.\n" "Você deseja prosseguir?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Fechar Aba" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Anexos (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Editor de Perfil" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Perfil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Adicionar" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Remover" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Servidor:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Banco de Dados:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Obtendo a lista de bancos de dados" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Usuário:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Versão do servidor incompatível" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Não foi possível se conectar ao servidor" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Entrar" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Cancelar" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Cancelar a conexão com o servidor do Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "C_onectar" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Conectar ao servidor do Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Perfil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Gerenciar Perfis" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Informações do Servidor / Banco de Dados" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Nome de Usuário:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Email" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Enviar preferências do programa por email" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Linha de Comado:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Legenda de posições de palavras disponíveis:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Para:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Assunto:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Conteúdo:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Anexo:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Anexo(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Nota(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Você deve selecionar um registro." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Criado por:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Data de criação:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Última Modificação por:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Data da última modificação:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modelo:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Você tem certeza que deseja apagar este registro?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Você tem certeza que deseja apagar estes registros?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Registros não apagados." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Registros apagados." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Trabalhando no(s) registro(s) duplicados(s)." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Registro gravado." #: tryton/gui/window/form.py:423 msgid " of " msgstr " de " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Este registro foi modificado\n" "você deseja salvá-lo?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Ação" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Executar ação" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Relacionar" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Abrir registros relacionados" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Relatório" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Abrir relatório" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "E-Mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Enviar relatório por e-mail" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Imprimir" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Imprimir relatório" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_Copiar URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Copiar URL para a área de transferência" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Desconhecido" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limite" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Preferências de limite de buscas" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Limite:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notas (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Preferências" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Editar preferências do usuário" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Preferência" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Revisão" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Selecione uma revisão" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Revisão:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Atalhos do teclado" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Atalhos de entradas de texto" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Recortar o texto selecionado" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Copiar o texto selecionado" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Colar o texto copiado" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Próximo campo" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Campo anterior" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Atalhos para campos de relações" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Criar nova relação" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Abrir/Buscar relação" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Atalhos em listas" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Criar nova linha" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Abrir relação" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Marcar para apagar linha" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Desmarcar linha para apagar" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Controles de edição" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Mover cursor" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Mover para a direita" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Mover para a esquerda" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Mover para cima" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Mover para baixo" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Mover uma página para cima" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Mover uma página para baixo" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Mover para o topo" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Mover para o final" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Mover para o pai" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Selecionar todos" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Desmarcar Todos" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Selecionar pai" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Selecionar/Ativar linha atual" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Alternar seleção" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Expandir/Recolher" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Expandir a linha" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Recolher a linha" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Alternar linha" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Recolher todas as linhas" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Expandir todas as linhas" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Exibição em árvore" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_Alternar Exibição" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "Alternar" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Anterior" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Registro Anterior" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Próximo" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Próximo Registro" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Buscar" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Novo" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Criar novo registro" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Salvar" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Gravar este registro" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_Recarregar/Desfazer" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "Recarregar/Desfazer" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplicado" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Apagar..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Ver _Logs..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Mostrar revisões..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "A_nexos..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Adicionar um anexo ao registro" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Notas..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Adicionar uma nota ao registro" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Ações..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Relacionar" #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Relatório..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_E-Mail..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Imprimir..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Exportar Dados..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importar Dados..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "Copiar _URL..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Fechar aba" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Todos os campos" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Limpar" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Campos selecionados" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Parâmetros CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Delimitador:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Caractere de citação:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codificação:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nome do campo" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exportar para CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Exportações pré-definidas" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nome" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_Gravar exportação" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_Apagar exportação" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Abrir" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Gravar" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Adicionar _nomes de campos" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (texto)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "%s (nome do modelo)" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "%s (nome do registro) " #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Qual é o nome dessa exportação?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Sobrescrever a definição '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "%d registro gravado." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "%d registros gravados." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Operação Falhou.\n" "Mensagem de erro:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Vínculo" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Adicionar" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Remover " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Criar novo registro " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Apagar o registro selecionado " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Recuperar o registro selecionado " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Anterior" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Próximo" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Alternar" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importar de CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "_Auto-Detectar" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Arquivo para importar:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Abrir..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Linhas a ignorar:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Primeiro você deve selecionar um arquivo para importar." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Erro ao abrir arquivo CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Erro ao processar o arquivo no campo %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "%d registros importados." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "%d registros importados." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Buscar %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "Não é possível apagar o assistente %s" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Assistente" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Criado por" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Data de criação" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Editado por" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Data de modificação" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, python-format msgid "Unable to get view tree state for %s" msgstr "Não foi possível obter o estado da visualização em árvore para %s" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Não foi possível definir o estado da visão em árvore" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" não é válido de acordo com seu domínio" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "\"%s\" é obrigatório" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Os valores de \"%s\" não são válidos" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Pré-validação" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Tamanho da imagem" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Largura:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Altura:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "Imagem PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Salvar como" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "Imagem muito grande." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Abrir filtros" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Mostrar filtros favoritos" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Remover este favorito" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Marcar este filtro como favorito" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Nome do favorito:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Localizar" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Hoje" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "voltar" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "avançar" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "ano anterior" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "próximo ano" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Visão Semanal" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Visão Mensal" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Semana" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Selecionar..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Limpar" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Todos os arquivos" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Selecionar" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Mostrar em formato texto" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Adicionar valor" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Remover \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Imagens" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Adicionar um registro existente" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Remover registro selecionado " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Abrir o registro " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Apagar o registro " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Buscar um registro " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Remover o registro selecionado" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Editar o registro selecionado " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Cor de primeiro plano" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Selecione uma cor" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Tradução" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Editar" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Vago" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "Você precisa salvar o registro antes de adicionar traduções." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "Não há outros idiomas disponíveis." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Traduzir visão" tryton-4.6.5/tryton/data/locale/pt_BR/LC_MESSAGES/tryton.mo0000644000175000017500000004544513260723565022620 0ustar cedced00000000000000d< \])b #&+.24F]w]n   3#F%j   &"I]c z   +2"U mz % 4BQ c my    (BJZ` w&     "/ GRfv { "2L d!r  ' 2 > H ^ m z       ! !1! :!E!N! S!`! u! !!!!!#!!" #"-"?"E" T" _"k"t""" """"" " """# #!# <# H# T#a#x### # ## ### ##$$$$ +$5$K$[$p$$$$ $ $$ $$ $% %%%5%G%V%_% f%r%I%}%Q& &5'46'k'o' u'''' ' ''''$'% (F(^(|(((( ( (( () )) ) ')H)O)(V) ))))%)7)* * )*5* :*G*O* V* a* m* y*** * * * * ******++++ <+ I+V+_+e+j+ p+z+ ++++ + + ++ + ++ +, , ,!, ),6,<,L,U,[,],n, v,, ,, , ,,,<,- 2-S-U-W-Y-./.!/6/O/d/}//// /////////#0>0.1>1 O1Z1 a1 l1v1111112,22A24t2 22 2 2 22 23+31353 E3,O3|333 333334 4*4/I4=y4)444* 565J5c5t5555 5 5566# 6 D6Q6g6 6666 66 6"6 7)7?7*E7p777(77 77788 '82888"L8 o8}88 88888*8 999"949I9Q9!a99999/9:::1:::L:S:U:i::: : : ::::;;/;D;V;f;; ;;;;;%;;< $</<8< ><L<i<y<<<<<'< <=0=7=M=T= e= r====== ===== >>6> J>U>!d>> > >>">> ?? ,?:? C?M? T?`?o???? ?!???@ &@1@C@Z@k@z@ @@ @ @@@AA,A5A>AGASdAAOB%B4C9GCCCCCCC CC CC(DF8D/D:D8D9#E&]E EEEE E EE EEE" F/F 8F,CFpFFF"F8F?F%G 4G >G JGUG dGnG vG G G GGG G G G G GG H H)H0H9HLHcHuHHHHH H HH H HHH H I I I )I5IJISIbIjIIIIIII IIIIJJ$J6J 8J EJRJ1TJSJJ%JK!K#K of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: pt_BR Language-Team: pt_BR Plural-Forms: nplurals=2; plural=(n > 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 de "%s" não é válido de acordo com seu domínio"%s" é obrigatório%d registros importados.%d registro gravado.%d registros importados.%d registros gravados.%s (%s)%s (nome do modelo)%s (nome do registro) %s (texto)%s%%, ,….....:Todos os camposCampos selecionadosExportações pré-definidasAviso de Escrita Concorrente: Este registro foi modificado enquanto você o editava. Escolha: - "Cancelar" para cancelar a gravação; - "Comparar" para ver a versão modificada; - "Gravar" para salvar a versão atual.Criar...Buscar...A_nexos...AçãoAções...AdicionarAdicionar _nomes de camposAdicionar uma nota ao registroAdicionar um anexo ao registroAdicionar um registro existenteAdicionar valorTodos os arquivosSempre ignorar este aviso.Erro da aplicação.Você tem certeza que deseja apagar este registro?Você tem certeza que deseja apagar estes registros?Anexo(%d)Anexo:Anexos (%s)Anexos...Conteúdo:Nome do favorito:Marcar este filtro como favoritoSistema de registro de errosPor: CC:Parâmetros CSVC_onectarCancelar a conexão com o servidor do TrytonMudar teclas de atalhoLimparApagar o registro Fechar AbaRecolher todas as linhasRecolher a linhaLinha de Comado:CompararExceção de concorrênciaConfirmaçãoConectar ao servidor do TrytonErro de conexão. Usuário ou senha incorretos.Erro de conexão. Não foi possível se conectar ao servidor.Copiar URL para a área de transferênciaCopiar _URL...Copiar o texto selecionadoNão foi possível se conectar ao servidorCriar novo registroCriar novo registro Criar nova linhaCriar nova relaçãoCriar novo erro (bug) com ID Data de criaçãoData de criação:Criado porCriado por:Recortar o texto selecionadoBanco de Dados:Formato de DataApagar o registro selecionado Delimitador:Formato de exibiçãoFormato de data exibidoValor exibidoVocê deseja prosseguir?E-MailEnviar relatório por e-mailE-mail...EditarEditar preferências do usuárioEditar o registro selecionado Editar...Controles de ediçãoEmailEnviar preferências do programa por emailCodificação:ErroErro ao abrir arquivo CSVErro ao processar o arquivo no campo %s.Erro: Exceção:Expandir todas as linhasExpandir a linhaExpandir/RecolherExportar para CSVFa_voritosFalsoTabulação rápidaObtendo a lista de bancos de dadosNome do campoArquivo "%s" não encontradoArquivo para importar:LocalizarCor de primeiro planoFormatoVagoAltura:Informações do Servidor / Banco de DadosServidor:IDID:Tamanho da imagemImagem muito grande.ImagensImportar de CSVVersão do servidor incompatívelAtalhos do tecladoData da última modificação:Última Modificação por:Executar açãoLegenda de posições de palavras disponíveis:LimiteLimite:Linhas a ignorar:VínculoAtalhos em listasEntrarMGerenciar FavoritosMarcar para apagar linhaModelo:Data de modificaçãoEditado porVisão MensalMover cursorMover para baixoMover uma página para baixoMover para o finalMover para a esquerdaMover para o paiMover para a direitaMover para o topoMover para cimaMover uma página para cimaNomeErro na rede.PróximoPróximo RegistroPróximo campoNenhuma ação definida.Não há outros idiomas disponíveis.Nenhum resultado encontrado.Nota(%d)Notas (%s)Notas...AbrirAbrir filtrosAbrir registros relacionadosAbrir relaçãoAbrir relatórioAbrir o calendárioAbrir o registro Abrir...Abrir/Buscar relaçãoOperação Falhou. Mensagem de erro: %sSobrescrever a definição '%s'?Imagem PNG (*.png)Senha:Colar o texto copiadoPorta:Pré-validaçãoPreferênciaPreferênciasAnteriorRegistro AnteriorCampo anteriorImprimirImprimir relatórioImprimir...PerfilEditor de PerfilPerfil:Caractere de citação:Registro gravado.Registros não apagados.Registros apagados.RelacionarRelacionado...Atalhos para campos de relaçõesRecarregar/DesfazerRemover "%s"Remover Remover o registro selecionadoRemover registro selecionado Remover este favoritoRelatórioReportar erro (bug)Relatório...RevisãoRevisão:GravarSalvar comoSalvar como...Gravar Estado da ÁrvoreGravar Largura/AlturaGravar este registroBuscaBuscar %sPreferências de limite de buscasLimite de Buscas...Buscar um registro Risco de segurança.SelecionarSelecione uma corSelecione uma revisãoSelecionar todosSelecionar paiSelecione sua açãoSelecionar...Selecionar/Ativar linha atualSeleçãoServidor:Mostrar filtros favoritosMostrar em formato textoMostrar revisões...Verificar OrtografiaAssunto:AlternarAlternarAtalhos de entradas de textoA ação seguinte requer que todas as abas sejam fechadas. Você deseja prosseguir?O mesmo erro já foi reportado por outro usuário. Para mantê-lo informado, seu nome de usuário foi adicionado à lista de acompanhamento deste casoA identidade (fingerprint) do servidor mudou desde a última conexão. O programa não se conectará a este servidor até que sua identidade seja corrigida.Os valores de "%s" não são válidosEste registro foi modificado você deseja salvá-lo?Para reportar erros você deve ter uma conta em %sPara:HojeAlternar linhaAlternar seleçãoMuitos argumentosTraduzir visãoTraduçãoExibição em árvoreVerdadeiroConexão ao TrytonNão é possível apagar o assistente %sNão foi possível obter o estado da visualização em árvore para %sNão foi possível encontrar complementos de %sNão foi possível definir as configurações regionais %sNão foi possível definir o estado da visão em árvoreNão foi possível gravar o arquivo de configuração %s.Recuperar o registro selecionado DesconhecidoDesmarcar linha para apagarDesmarcar TodosNome de Usuário:Usuário:Usuário:ValorVer _Logs...SemanaVisão SemanalQual é o nome dessa exportação?Largura:AssistenteTrabalhando no(s) registro(s) duplicados(s).Gravar mesmo assimASimVocê deve selecionar um registro.Primeiro você deve selecionar um arquivo para importar.Você precisa salvar o registro antes de adicionar traduções.Sua seleção:_Sobre..._Ações..._Adicionar_Auto-Detectar_Cancelar_Limpar_Fechar aba_Conectar..._Conexão_Copiar URL_Padrão_Apagar exportação_Apagar..._Desconectar_Duplicado_E-Mail..._Email..._Exportar Dados..._Formulário_Busca Global_Ajuda_Ícones_Importar Dados..._Atalhos do Teclado..._Gerenciar Perfis_Recarregar Menu_Alternar Menu_Barra do Menu_Modo_Novo_Próximo_Próxima Aba_Normal_Notas..._Opções_PDA_Preferências..._Anterior_Aba Anterior_Imprimir..._Sair..._Relacionar_Recarregar/Desfazer_Remover_Relatório..._Salvar_Gravar exportação_Salvar Opções_Buscar_Alternar Exibição_Texto_Texto e Ícones_Barra de Ferramentas_Usuáriodmodo de desenvolvimentovoltaravançarhRegistrar (log) tudo com nível INFOmpróximo anoano anteriorsespecificar arquivo de configuração alternativoEspecifique o nível de registro (log level): DEBUG, INFO, WARNING, ERROR, CRITICALEspecifique o nome do usuárioEspecifique o servidor hostname:portavsstryton-4.6.5/tryton/data/locale/zh_CN/0000755000175000017500000000000013260723567017120 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/zh_CN/LC_MESSAGES/0000755000175000017500000000000013260723567020705 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/zh_CN/LC_MESSAGES/tryton.po0000644000175000017500000010412413255571102022574 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "备选配置文件" #: tryton/config.py:73 msgid "development mode" msgstr "开发模式" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "INFO级别记录日志" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "设置日志级别: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "设置登录用户" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "设置服务器名称" #: tryton/config.py:87 msgid "Too much arguments" msgstr "参数太多" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "没找到文件 \"%s\" " #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "无法写入配置文件 %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "无法设置语言地域 %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "选择一项操作" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "没有定义任何操作 !" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "服务器连接" #: tryton/common/common.py:250 msgid "Server:" msgstr "服务器:" #: tryton/common/common.py:268 msgid "Port:" msgstr "端口:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "选择" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "已选择:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "另存为..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "下次不再提示." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "继续此项操作 ?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "确认" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "并行操作异常" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "同步操作警告:\n" "\n" "数据已被更改.\n" "请选择:\n" " - \"取消\" 不保存;\n" " - \"对比\" 查看变更的数据;\n" " - \"覆写\" 保存当前数据." #: tryton/common/common.py:766 msgid "Compare" msgstr "对比" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "覆写" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "错误" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "报告Bug" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "程序错误 !" #: tryton/common/common.py:832 msgid "Error: " msgstr "错误:" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "提交Bug报告,需要 %s账户" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Bug 追踪器" #: tryton/common/common.py:899 msgid "User:" msgstr "用户名:" #: tryton/common/common.py:907 msgid "Password:" msgstr "密码:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "已有其他用户报告相同bug.\n" "用户名已加入通知列表,将随时接收相关信息" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Bug 已提交备案" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "连接错误!\n" "用户名或密码有误!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "异常:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "服务器指纹与上次连接不同!\n" "指纹问题处理后,才能同服务器连接." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "安全隐患 !" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "连接错误 !\n" "无法连接服务器 !" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "网络连接错误!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "查找..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "创建..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "值" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "显示" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "格式" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "显示格式" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "打开日历" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "日期格式" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "日期显示格式" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "y" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "True" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "t" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "False" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "编辑..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "附件文档..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "操作..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "关联..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "报告..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "用电子邮件发送..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "打印..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "年" #: tryton/common/timedelta.py:27 msgid "M" msgstr "月" #: tryton/common/timedelta.py:28 msgid "w" msgstr "星期" #: tryton/common/timedelta.py:29 msgid "d" msgstr "日" #: tryton/common/timedelta.py:30 msgid "h" msgstr "时" #: tryton/common/timedelta.py:31 msgid "m" msgstr "分" #: tryton/common/timedelta.py:32 msgid "s" msgstr "秒" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "用户(_U)" #: tryton/gui/main.py:236 msgid "_Options" msgstr "选项(_O)" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "收藏(_V)" #: tryton/gui/main.py:260 msgid "_Help" msgstr "帮助(_H)" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "查找" #: tryton/gui/main.py:372 msgid "No result found." msgstr "无符合条件的数据." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "连接数据服务(_C)..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "断开数据服务(_D)" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "退出(_Q)..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "设置偏好(_P)..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "重载菜单(_M)" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "关闭/打开侧导航栏(_T)" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "查找(_F)" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "工具栏(_T)" #: tryton/gui/main.py:502 msgid "_Default" msgstr "默认设置(_D)" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "图标文字(_R)" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "显示图标(_I)" #: tryton/gui/main.py:532 msgid "_Text" msgstr "显示文字(_T)" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "菜单栏(_M)" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "启用加速" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "工作模式(_M)" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "桌面(_N)" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "PDA模式(_P)" #: tryton/gui/main.py:582 msgid "_Form" msgstr "表单视图(_F)" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "保存窗体大小" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "保存导航状态" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "快速切换标签" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "开启拼写检查" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "上一标签(_P)" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "下一标签(_N)" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "数据查询..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "电子邮件(_E)..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "保存设置(_S)" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "快捷键(K)..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "关于(_A)..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "收藏管理..." #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "该操作需要关闭打开的项目\n" "是否继续?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "关闭标签" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "附件文档(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "数据服务配置器" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "配置列表" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "添加(_A)" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "删除(_R)" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "主机:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "服务标识:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "获取服务列表..." #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "用户名:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "服务器版本与客户端不兼容" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "无法连接服务器" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "登录" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "取消(_C)" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "取消与服务器的连接" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "连机(_O)" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "连接数据服务器" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "配置:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "管理配置(_M)" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "数据服务器:" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "用户:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "邮件" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "电子邮件相关设置" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "电子邮件程序命令行" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "替换变量列表:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "收件人:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "抄送:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "主题:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "内容:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "附件:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "附件文档(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "选择需要操作的项目" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "标识:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "创建者:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "创建日期:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "最近更改:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "最近更改日期:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "模型:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "确定要删除此项吗?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "确定要删除这些项目?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "所选项目未删除成功." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "项目已成功删除" #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "当前处理的是项目的副本." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "保存成功." #: tryton/gui/window/form.py:423 msgid " of " msgstr "of" #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "记录有改动, 是否保存?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "操作" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "执行操作" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "关联" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "打开关联项目" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "报告(_R)..." #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "打开报表" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "邮件发送" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "用电子邮件发送报表" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "打印" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "打印报表" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "未知" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "限制" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "查询限制..." #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "限制:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "偏好" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "设置用户偏好..." #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "偏好" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "版本" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "选择版本" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "版本:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "快捷键" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "文本相关" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "剪切" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "复制" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "粘贴" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "下一个文本" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "上一个文本" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "关联操作" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "新建关联" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "打开. 查找关联" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "列表项相关" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "新建一行" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "打开关联项" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "标定删除选择" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "取消删除选择" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "编辑界面" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "光标移动" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "右移" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "左移" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "上移" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "下移" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "上移一页" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "下移一页" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "移到顶端" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "移到底部" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "上一级" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "全选" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "全不选" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "选择上一级" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "选择/激活当前行" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "切换状态" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "展开/收起" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "展开" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "收起" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "切换状态" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "收起所有" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "展开所有" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "树形导航" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "切换视图(_S)" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "切换视图(_S)" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "向前(_P)" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "前一项" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "向后(_N)" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "后一项" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "查找(_S)" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "新建(_N)" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "新建项目" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "保存(_S)" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "保存项目" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "刷新/撤销(_R)" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "刷新/撤销(_R)" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "复制(_D)" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "删除(_D)..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "日志(_V)..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "显示版本..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "附件(_T)..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "给当前项添加附件" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "操作(_A)..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "关联(_L)..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "报告(_R)..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "邮件发送(_E)..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "打印(_P)..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "导出数据(_X)" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "导入数据(_I)" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "关闭标签页(_C)" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "数据项" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "清除" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV 参数" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "编码:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "列名" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "导出到CSV文件" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "导出设定" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "名称" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "保存设定" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "删除设定" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "打开" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "保存" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "添加列名称(_F)" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (string)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "导出设定的名称" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "替换设定 '%s' ?" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d 项保存成功!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d 项目保存成功!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "操作失败!\n" "相关错误信息:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "链接" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "添加" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "删除 " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "新建项目 " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "删除选择项 " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "回滚删除项 " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "向前" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "向后" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "切换" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "从 CSV 导入" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "自动设置" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "数据文件:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "打开..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "跳过行:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "选择导入的文件!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "打开CSV出错 !" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "处理数值 %s 时出错" #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d 项导入成功!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d 项导入成功!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "向导" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "标识" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "创建者" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "创建日期" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "修改者" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "修改日期" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "无法设置视图树状态" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "根据域设置,\"%s\"不可用" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "\"%s\" 是必填项" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "无法获得\"%s\" 的值" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "预校验" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "图片尺寸" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "宽:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "高:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG 图片格式 (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "另存为" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "图片尺寸过大 !" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "显示筛选器书签" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "移除书签" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "收藏筛选器" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "书签名称:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "查找" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "今天" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "周视图" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "月视图" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "周" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "选择..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "清除" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "所有文件" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "选择" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "显示纯文本" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "添加条目" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "删除\"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "图片" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "添加现存条目" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "删除选择项 " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "打开条目 " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "查找条目 " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "删除所选条目" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "编辑所选条目" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "字体颜色" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "选择颜色" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "翻译" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "编辑" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "模糊" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "请先保存已翻译条目,再增加新翻译 !" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "没有其他可翻译语言!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "翻译视图" tryton-4.6.5/tryton/data/locale/zh_CN/LC_MESSAGES/tryton.mo0000644000175000017500000003626213260723565022610 0ustar cedced00000000000000FL |}) %?%6GW ^im~  #%E T`ou & ( : GU] s /C \j y    3 : HRWm &   -8 H Va gt   "+Na{ !+2D V a mw     ! *5> CP e s   "+;K Q^go~      # @ U \ g q z         !!"!1! C! N!\! o!y! !!!!!!!!"I"}c" "4#7#;# A#L#]#p# # ####$#%#$*$H$g$o$ $ $$ $$ $$ $ $$$(% +%8%:%>%]% m% w%%% % % % %% % % % % %% &&"&(&/&?&V& g& t&&&&& && &&&& & & && ' '' '+' 1'?' G'T'Z'j's'y'{'' '' '' ' '''<'9(P(R(T(V())*"***:* K*W*\*_*a*r***;+L+ ]+k+ r+|+++++ + ++ ,&,E,V,^,n, v,, ,, , , ,, ,,, - -(-/-K-R-e-l-- --- -- - -- . . ,. 6.A. H. V.c. y. .... .../ // 6/ @/M/T/m/u/|//// // // ///0'0.0 D0R0 Y0f0m0t0y0000 000$0 00 1 1"181?1 G1R1Y1i1p1t111 1 1 1 11 1 11 11 22 2'2.2 52?2O2i2 r2}22 222 2 2 222 3#3+323 :3D3K3R3 Y3c3s3 z3 3 333 3 333 4 4 4 '4 24?4R4 h4 u4 4 4444 4 444 44 455(5:5 A5 N5[5b5r5 555 555556 6 646_R66(6 66 7 7 7 ,797 @7M7R7b7$}7%777888 08:8 B8 M8X8 \8j8 n8x888"88888 8 8 9 9 9%999 S9 _9i9 z99 99999 9 9 ::,:<:M:^: |:: : :: : : : :: ;; ; .; <;J; \; g; u;; ;;;; ; ;; ;; < <<'< +< 5<C<G<9Z<<<<< of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUndelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.Your selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: zh_Hans_CN Language-Team: zh_Hans_CN Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 of根据域设置,"%s"不可用"%s" 是必填项%s (%s)%s (model name)%s (record name)%s (string)%s%%..:数据项Fields selected导出设定同步操作警告: 数据已被更改. 请选择: - "取消" 不保存; - "对比" 查看变更的数据; - "覆写" 保存当前数据.创建...查找...附件(_T)...操作操作...添加添加列名称(_F)Add a note to the record给当前项添加附件添加现存条目添加条目所有文件下次不再提示.确定要删除此项吗?确定要删除这些项目?附件文档(%d)附件:附件文档...内容:书签名称:收藏筛选器Bug 追踪器By: 抄送:CSV 参数连机(_O)取消与服务器的连接启用加速清除Clear the record 关闭标签收起所有收起电子邮件程序命令行对比并行操作异常确认连接数据服务器Copy URL into clipboardCopy _URL...复制无法连接服务器新建项目新建项目 新建一行新建关联Bug 已提交备案创建日期创建日期:创建者创建者:剪切服务标识:日期格式删除选择项 Delimiter:显示格式日期显示格式显示继续此项操作 ?邮件发送用电子邮件发送报表用电子邮件发送...编辑设置用户偏好...编辑所选条目编辑...编辑界面邮件电子邮件相关设置编码:错误打开CSV出错 !处理数值 %s 时出错错误:异常:展开所有展开展开/收起导出到CSV文件收藏(_V)False快速切换标签获取服务列表...列名没找到文件 "%s" 数据文件:查找字体颜色格式模糊高:数据服务器:主机:标识标识:图片尺寸图片从 CSV 导入服务器版本与客户端不兼容快捷键最近更改日期:最近更改:执行操作替换变量列表:限制限制:跳过行:链接列表项相关登录月收藏管理...标定删除选择模型:修改日期修改者月视图光标移动下移下移一页移到底部左移上一级右移移到顶端上移上移一页名称向后后一项下一个文本无符合条件的数据.Note(%d)Notes (%s)Notes...打开Open filters打开关联项目打开关联项打开报表打开日历打开...打开. 查找关联替换设定 '%s' ?PNG 图片格式 (*.png)密码:粘贴端口:预校验偏好偏好向前前一项上一个文本打印打印报表打印...配置列表数据服务配置器配置:Quote char:保存成功.所选项目未删除成功.项目已成功删除关联关联...关联操作删除"%s"删除 删除所选条目删除选择项 移除书签报告(_R)...报告Bug报告...版本版本:保存另存为另存为...保存导航状态保存窗体大小保存项目查找Search %s查询限制...数据查询...查找条目 选择选择颜色选择版本全选选择上一级选择一项操作选择...选择/激活当前行选择服务器:显示筛选器书签显示纯文本显示版本...开启拼写检查主题:切换文本相关该操作需要关闭打开的项目 是否继续?已有其他用户报告相同bug. 用户名已加入通知列表,将随时接收相关信息无法获得"%s" 的值提交Bug报告,需要 %s账户收件人:今天切换状态切换状态参数太多翻译视图翻译树形导航True服务器连接Unable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %s无法设置语言地域 %s无法设置视图树状态回滚删除项 未知取消删除选择全不选用户:用户名:用户名:值日志(_V)...周周视图导出设定的名称宽:向导当前处理的是项目的副本.覆写年Yes选择需要操作的项目已选择:关于(_A)...操作(_A)...添加(_A)取消(_C)关闭标签页(_C)连接数据服务(_C)..._Connection_Copy URL默认设置(_D)删除(_D)...断开数据服务(_D)复制(_D)邮件发送(_E)...电子邮件(_E)...导出数据(_X)表单视图(_F)查找(_F)帮助(_H)显示图标(_I)导入数据(_I)快捷键(K)...管理配置(_M)重载菜单(_M)关闭/打开侧导航栏(_T)菜单栏(_M)工作模式(_M)新建(_N)向后(_N)下一标签(_N)桌面(_N)_Notes...选项(_O)PDA模式(_P)设置偏好(_P)...向前(_P)上一标签(_P)打印(_P)...退出(_Q)...关联(_L)...刷新/撤销(_R)删除(_R)报告(_R)...保存(_S)保存设置(_S)查找(_S)切换视图(_S)显示文字(_T)图标文字(_R)工具栏(_T)用户(_U)日开发模式go backgo forward时INFO级别记录日志分next yearprevious year秒备选配置文件设置日志级别: DEBUG, INFO, WARNING, ERROR, CRITICAL设置登录用户t星期ytryton-4.6.5/tryton/data/locale/ja_JP/0000755000175000017500000000000013260723567017102 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ja_JP/LC_MESSAGES/0000755000175000017500000000000013260723567020667 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ja_JP/LC_MESSAGES/tryton.po0000644000175000017500000010734213255571102022563 0ustar cedced00000000000000# Japanese (Japan) translations for tryton. # Copyright (C) 2010 B2CK # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2010. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "代替設定ファイルを指定" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "全てをINFOレベルでログを取る" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "ログインユーザーを指定" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "サーバーホスト名を指定" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "ファイル \"%s\" が見つかりません" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "設定ファイル %s が書きこめません!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "%s ロケールに設定できません" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "動作を選択する" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "動作が定義されていません!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton接続" #: tryton/common/common.py:250 msgid "Server:" msgstr "サーバー名:" #: tryton/common/common.py:268 msgid "Port:" msgstr "ポート番号:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "選択" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "あなたの選択:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "名前を付けて保存" #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "常にこの警告を無視する。" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "確認" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "並列性例外" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "並列書込警告:\n" "\n" "このレコードは編集中に変更されました。\n" " 選択肢:\n" " - \"キャンセル\"で保存を中止する\n" " - \"比較\"で変更されたものを見る\n" " - \"とにかく書き込む\"で現在の物を書き込む。" #: tryton/common/common.py:766 msgid "Compare" msgstr "比較" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "とにかく書き込む" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "エラー" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "バグ報告" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "アプリケーションエラー!" #: tryton/common/common.py:832 msgid "Error: " msgstr "エラー:" #: tryton/common/common.py:852 #, python-format, fuzzy, python-format msgid "To report bugs you must have an account on %s" msgstr "記録しておきたいバグを報告%s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "バグトラッカー" #: tryton/common/common.py:899 msgid "User:" msgstr "ユーザー:" #: tryton/common/common.py:907 msgid "Password:" msgstr "パスワード:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "別のユーザーに同じバグが報告されています。\n" "お知らせするためにこの問題の通知リストにあなたのユーザー名を追加しました。" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "新しいバグがID番号と一緒に作成されました" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "接続エラー!\n" "ユーザー名またはパスワードが違います!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "例外:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "このサーバーのフィンガープリントが最後の接続から変化しています!\n" "フィンガープリントが訂正されるまで接続を停止します。" #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "セキュリティリスク!" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "接続エラー!\n" "サーバーに接続できません!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "ネットワーク エラー!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "偽" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "ノーマル(_N)" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "カレンダーを開く" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "真" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "偽" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "終了(_Q)" #: tryton/common/popup_menu.py:89 #, fuzzy msgid "Attachments..." msgstr "添付:" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 #, fuzzy msgid "Actions..." msgstr "実行(_A)" #: tryton/common/popup_menu.py:110 #, fuzzy msgid "Relate..." msgstr "削除(_D)" #: tryton/common/popup_menu.py:111 #, fuzzy msgid "Report..." msgstr "データのインポート(_I)" #: tryton/common/popup_menu.py:112 #, fuzzy msgid "E-Mail..." msgstr "Eメール(_E)" #: tryton/common/popup_menu.py:113 #, fuzzy msgid "Print..." msgstr "印刷(_P)" #: tryton/common/timedelta.py:26 msgid "Y" msgstr "年" #: tryton/common/timedelta.py:27 msgid "M" msgstr "月" #: tryton/common/timedelta.py:28 msgid "w" msgstr "週" #: tryton/common/timedelta.py:29 msgid "d" msgstr "日" #: tryton/common/timedelta.py:30 msgid "h" msgstr "時" #: tryton/common/timedelta.py:31 msgid "m" msgstr "分" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "ユーザー(_U)" #: tryton/gui/main.py:236 msgid "_Options" msgstr "オプション(_O)" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "ヘルプ(_H)" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "検索" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "接続(_C)" #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "切断(_D)" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "終了(_Q)" #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "設定(_P)" #: tryton/gui/main.py:460 #, fuzzy msgid "_Menu Reload" msgstr "再読み込み(_R)" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "ツールバー(_T)" #: tryton/gui/main.py:502 msgid "_Default" msgstr "デフォルト(_D)" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "テキストとアイコン(_T)" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "アイコン(_I)" #: tryton/gui/main.py:532 msgid "_Text" msgstr "テキスト(_T)" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "メニューバー(_M)" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "アクセラレーターの変更" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "モード(_M)" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "ノーマル(_N)" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "フォーム(_F)" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "幅/高さを保存" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "スペルチェック" #: tryton/gui/main.py:635 #, fuzzy msgid "_Previous Tab" msgstr "前(_P)" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "" #: tryton/gui/main.py:655 msgid "_Email..." msgstr "Eメール(_E)" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "オプションの保存(_S)" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "キーボードショートカット(_K)" #: tryton/gui/main.py:687 msgid "_About..." msgstr "Trytonについて" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "タブを閉じる" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "添付(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "追加(_A)" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "削除(_R)" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 #, fuzzy msgid "Host:" msgstr "ポート番号:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "データベース:" #: tryton/gui/window/dblogin.py:98 #, fuzzy msgid "Fetching databases list" msgstr "新規データベースセットアップ:" #: tryton/gui/window/dblogin.py:114 #, fuzzy msgid "Username:" msgstr "ユーザー名:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 #, fuzzy msgid "Incompatible version of the server" msgstr "サーバのバージョンが非互換です!" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 #, fuzzy msgid "Could not connect to the server" msgstr "サーバーに接続できませんでした!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "ログイン" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "キャンセル(_C)" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Trytonサーバへの接続を中止する" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "接続(_N)" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Trytonサーバーへ接続する" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "ユーザー名:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Eメール" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Emailプログラムの設定" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "コマンドライン:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "利用できるプレースホルダーの凡例:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "宛先:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "題名:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "本文:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "添付:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "添付(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "レコードを一つ選択して下さい!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "作成ユーザー:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "作成日:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "最終更新ユーザー:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "最終更新日:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "モデル:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "このレコードを削除しますか?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "このレコードを削除しますか?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "レコードが削除されませんでした!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "レコードが削除されました!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "重複したレコードで作業中です!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "レコードが保存されました!" #: tryton/gui/window/form.py:423 msgid " of " msgstr " 中 " #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "レコードが変更されています\n" "保存しますか?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "実行" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Relate" msgstr "作成(_C)" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Open related records" msgstr "レコードを開く" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Report" msgstr "レポート" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Open report" msgstr "レコードを開く" #: tryton/gui/window/form.py:501 #, fuzzy msgid "E-Mail" msgstr "Eメール" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "印刷" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "未知" #: tryton/gui/window/limit.py:17 #, fuzzy msgid "Limit" msgstr "リミット:" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "リミット:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "設定" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "個人設定の編集" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "設定" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "前" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "選択" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "前" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "キーボードショートカット" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "テキストエントリショートカット" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "選択されたテキストを切り取り" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "選択されたテキストをコピー" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "コピーされたテキストを貼り付け" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "次のウィジェット" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "前のウィジェット" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "リレーションエントリショートカット" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "新しいリレーションを作る" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "リレーションを開く/検索" #: tryton/gui/window/shortcuts.py:36 #, fuzzy msgid "List Entries Shortcuts" msgstr "テキストエントリショートカット" #: tryton/gui/window/shortcuts.py:37 #, fuzzy msgid "Create new line" msgstr "新しいリレーションを作る" #: tryton/gui/window/shortcuts.py:38 #, fuzzy msgid "Open relation" msgstr "リレーションを開く/検索" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "エディションウィジェット" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "ビューの切替(_S)" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "ビューの切替(_S)" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "前(_P)" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "前のレコード" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "次(_N)" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "次のレコード" #: tryton/gui/window/tabcontent.py:59 #, fuzzy msgid "_Search" msgstr "検索" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "新規(_N)" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "レコードの新規作成" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "保存(_S)" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "レコードの保存" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "再読み込み/やり直し(_R)" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "再読み込み/やり直し(_R)" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "複製(_D)" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "削除(_D)" #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "ログの閲覧(_L)" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 #, fuzzy msgid "A_ttachments..." msgstr "添付:" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "レコードに添付を追加する" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "実行(_A)" #: tryton/gui/window/tabcontent.py:119 #, fuzzy msgid "_Relate..." msgstr "削除(_D)" #: tryton/gui/window/tabcontent.py:125 #, fuzzy msgid "_Report..." msgstr "データのインポート(_I)" #: tryton/gui/window/tabcontent.py:130 #, fuzzy msgid "_E-Mail..." msgstr "Eメール(_E)" #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "印刷(_P)" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "データのエクスポート(_E)" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "データのインポート(_I)" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "タブを閉じる(_C)" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "全てのフィールド" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "クリア" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSVパラメータ" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "エンコーディング:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "フィールド名" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "CSVにエクスポート" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "定義済みエキスポート" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "名前" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "エクスポートを保存" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "エクスポートを削除" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "開く" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "保存" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "フィールド名を追加(_F)" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "このエクスポートの名前は何ですか?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d レコード保存されました!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d レコード保存されました!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "操作が失敗しました!\n" "エラーメッセージ:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "リンク" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "追加" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 #, fuzzy msgid "Create a new record " msgstr "レコードの新規作成" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 #, fuzzy msgid "Delete selected record " msgstr "選択したレコードを削除" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 #, fuzzy msgid "Undelete selected record " msgstr "選択したレコードを削除" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "前" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "次" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "切替" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "CSVからインポート" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "自動検出" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "インポートするファイル:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "開く" #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "スキップする行:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "最初にインポートするファイルを選択して下さい!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "CSVファイルを開くときにエラーが起こりました" #: tryton/gui/window/win_import.py:141 #, python-format, fuzzy, python-format msgid "Error processing the file at field %s." msgstr "ファイルの%sフィールドの処理でエラーが起こりました。" #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d レコードをインポートしました!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d レコードをインポートしました。" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "ウィザード" #: tryton/gui/window/view_form/screen/screen.py:194 #, fuzzy msgid "ID" msgstr "日" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "作成ユーザー:" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "作成日:" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "最終更新日:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "最終更新日:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "%s ロケールに設定できません" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "%s ロケールに設定できません" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "画像サイズ" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "幅:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "高さ:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG画像 (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "名前をつけて保存" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "画像サイズが大きすぎます!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "検索" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "本文:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "ビューの切替" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "ビューの切替" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "クリア" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "全てのファイル" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "画像" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 #, fuzzy msgid "Add existing record" msgstr "レコードの保存" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 #, fuzzy msgid "Remove selected record " msgstr "選択したレコードを削除" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "レコードを開く" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 #, fuzzy msgid "Search a record " msgstr "レコードを検索する" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 #, fuzzy msgid "Remove selected record" msgstr "選択したレコードを削除" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 #, fuzzy msgid "Edit selected record " msgstr "選択したレコードを編集" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 #, fuzzy msgid "Translation" msgstr "翻訳を追加" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "翻訳を追加する前にレコードを保存して下さい!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "他の利用できる言語はありません" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "翻訳ビュー" tryton-4.6.5/tryton/data/locale/ja_JP/LC_MESSAGES/tryton.mo0000644000175000017500000003310513260723565022563 0ustar cedced00000000000000 l) &27:<Neev  # %0V eqw &  * < IW_ u $3 E O [fu  0 8C S^ n |    )<V n!|   +8 G Uai}     (2DJ Y dpy      !,1 9DTfw ~     (BRds|I} b  %'?G ` mx ~        )3 < G S ^hx~   # 3 =G P]e k y      <. k     ")"E"V"^"n" """"""%""#$$$&$F$$_$ $$$$($($ %&%.%6%E%Z%p%u%y% %*%!% %%&& *&7&N&U&e&!l&& &'&&$&;' X'c'*w'' ' ''''( (((-($C( h(s(( (?( ()) )#)3) L)W) [)h)*{)")) ))))* ** *$9*^*o* *1* ** * *+ ++ 1+ <+ H+R+h+ w++ + +++++++,, ,%,., 5,B,"I,l,,,-,,,,,- --5- <-I-Q-`- i-3u- - -- ---..-.A.W. ^.h.~... . .. ...//+/;/M/c/k/-r/I// 00 0000 1 1 11%81'^111 11 111112"222K2O2S2g2 z2 222 2 2 22 2 2 33" 3C3T3 c3q33(33 33 4 44 !4+4 <4F4Z4 _4j4 r4 }4 4 4 44445$585I5M5^5 f5q5(u55 5 55!5<5!6=6?6C6 of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...ActionAddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCreate a new recordCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEditEdit User PreferencesEdition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationID:Image SizeImagesImport from CSVKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:Limit:Lines to Skip:LinkLoginMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportProfileProfile EditorProfile:Quote char:Relation Entries ShortcutsRemove "%s"Remove Remove this bookmarkReport BugSaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo:Toggle rowToggle selectionToo much argumentsTranslate viewTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUnknownUnmark line for deletionUnselect allUser name:User:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Print..._Quit..._Reload/Undo_Remove_Save_Save Options_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: ja_JP Language-Team: ja_JP Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 中 "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:全てのフィールドFields selected定義済みエキスポート並列書込警告: このレコードは編集中に変更されました。 選択肢: - "キャンセル"で保存を中止する - "比較"で変更されたものを見る - "とにかく書き込む"で現在の物を書き込む。Create...Search...実行追加フィールド名を追加(_F)Add a note to the recordレコードに添付を追加するAdd value全てのファイル常にこの警告を無視する。このレコードを削除しますか?このレコードを削除しますか?添付(%d)添付:本文:Bookmark Name:Bookmark this filterバグトラッカーBy: CC:CSVパラメータ接続(_N)Trytonサーバへの接続を中止するアクセラレーターの変更クリアClear the record タブを閉じるCollapse all rowsCollapse rowコマンドライン:比較並列性例外確認Trytonサーバーへ接続するCopy URL into clipboardCopy _URL...選択されたテキストをコピーレコードの新規作成新しいリレーションを作る新しいバグがID番号と一緒に作成されました作成日:作成ユーザー:選択されたテキストを切り取りデータベース:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEdit個人設定の編集エディションウィジェットEメールEmailプログラムの設定エンコーディング:エラーCSVファイルを開くときにエラーが起こりましたエラー:例外:Expand all rowsExpand rowExpand/CollapseCSVにエクスポートFa_vorites偽Fast Tabbingフィールド名ファイル "%s" が見つかりませんインポートするファイル:検索ForegroundFuzzy高さ:Host / Database informationID:画像サイズ画像CSVからインポートキーボードショートカット最終更新日:最終更新ユーザー:Launch action利用できるプレースホルダーの凡例:リミット:スキップする行:リンクログイン月Manage FavoritesMark line for deletionモデル:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one page名前次次のレコード次のウィジェットNo result found.Note(%d)Notes (%s)Notes...開くOpen filters開くリレーションを開く/検索Override '%s' definition?PNG画像 (*.png)パスワード:コピーされたテキストを貼り付けポート番号:Pre-validation設定設定前前のレコード前のウィジェット印刷Print reportProfileProfile EditorProfile:Quote char:リレーションエントリショートカットRemove "%s"Remove Remove this bookmarkバグ報告保存名前をつけて保存名前を付けて保存Save Tree State幅/高さを保存レコードの保存検索Search %sSearch Limit SettingsSearch Limit...SelectSelect a colorSelect allSelect parent動作を選択するSelect...Select/Activate current row選択サーバー名:Show bookmarks of filtersShow plain textShow revisions...スペルチェック題名:切替テキストエントリショートカットThe following action requires to close all tabs. Do you want to continue?別のユーザーに同じバグが報告されています。 お知らせするためにこの問題の通知リストにあなたのユーザー名を追加しました。The values of "%s" are not valid宛先:Toggle rowToggle selectionToo much arguments翻訳ビューTree view真Tryton接続Unable to delete wizard %sUnable to search for completion of %s%s ロケールに設定できません未知Unmark line for deletionUnselect allユーザー名:ユーザー:ログの閲覧(_L)Weekこのエクスポートの名前は何ですか?幅:ウィザードとにかく書き込む年Yesあなたの選択:Trytonについて実行(_A)追加(_A)キャンセル(_C)タブを閉じる(_C)接続(_C)_Connection_Copy URLデフォルト(_D)削除(_D)切断(_D)複製(_D)Eメール(_E)データのエクスポート(_E)フォーム(_F)_Global Searchヘルプ(_H)アイコン(_I)データのインポート(_I)キーボードショートカット(_K)_Manage profiles_Menu Toggleメニューバー(_M)モード(_M)新規(_N)次(_N)_Next Tabノーマル(_N)_Notes...オプション(_O)_PDA設定(_P)前(_P)印刷(_P)終了(_Q)再読み込み/やり直し(_R)削除(_R)保存(_S)オプションの保存(_S)ビューの切替(_S)テキスト(_T)テキストとアイコン(_T)ツールバー(_T)ユーザー(_U)日development modego backgo forward時全てをINFOレベルでログを取る分next yearprevious years代替設定ファイルを指定specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALログインユーザーを指定t週ytryton-4.6.5/tryton/data/locale/lt/0000755000175000017500000000000013260723567016536 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/lt/LC_MESSAGES/0000755000175000017500000000000013260723567020323 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/lt/LC_MESSAGES/tryton.po0000644000175000017500000010624113255571102022214 0ustar cedced00000000000000# Lithuanian (Lithuania) translations for tryton. # Copyright (C) 2011 B2CK # This file is distributed under the same license as the tryton project. # Giedrius Slavinskas , 2011. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "" #: tryton/config.py:128 #, python-format msgid "Unable to write config file %s." msgstr "" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Nepavyko nustatyti lokalės %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Pasirinkite veiksmą" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Nėra apibrėžtų veiksmų!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton prisijungimas" #: tryton/common/common.py:250 msgid "Server:" msgstr "Serveris:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Prievadas:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Pasirinkimas" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Jūsų pasirinkimas:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Įrašyti kaip..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Daugiau nepaisyti šio pranešimo." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Ar tikrai norite vykdyti?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Patvirtinimas" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Lygiagretaus duomenų rašymo klaida" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Perspėjimas dėl lygiagretaus duomenų rašymo:\n" "\n" "Šis įrašas buvo pakeistas tuo metu kol redagavote.\n" " Pasirinkite:\n" " - \"Atšaukti\", kad atšaukti pakeitimus;\n" " - \"Palyginti\", kad peržiūrėti pakeistą versiją;\n" " - \"Rašyti visvien\", kad išsaugoti jūsų turimą versiją." #: tryton/common/common.py:766 msgid "Compare" msgstr "Palyginti" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Rašyti visvien" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Klaida" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Pranešti apie klaidą" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Programos klaida!" #: tryton/common/common.py:832 msgid "Error: " msgstr "Klaida: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Klaidų pranešimui reikalinga naudotojo paskyra %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Klaidų pėdsekys" #: tryton/common/common.py:899 msgid "User:" msgstr "Naudotojas:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Slaptažodis:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Ta pati klaida jau buvo pranešta kito naudotojo.\n" "Norėdami informuoti apie klaidos tvarkymo eigą, jūsų naudotojo vardas buvo pridėtas prie klaidos pranešimo sąrašo" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Užregistruoti naują klaidą su ID" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Prisijungimo klaida!\n" "Neteisingas naudotojo vardas arba slaptažodis!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Klaida:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Serverio identifikatorius (fingerprint) pasikeitė nuo paskutinio prisijungimo!\n" "Programa nustos jungtis su šiuos serveriui, kol bus sutvarkytas identifikatorius." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Saugumo pavojus!" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Prisijungimo klaida!\n" "Nepavyko prisijungti prie serverio!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Tinklo klaida!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Ieškoti..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Sukurti..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "Pridėti reikšmę" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 #, fuzzy msgid "Displayed value" msgstr "Pridėti reikšmę" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "Sta_ndartinis" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "Atverti kalendorių " #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "t" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Tiesa" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "t" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Netiesa" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "Išei_ti..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Priedai..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Veiksmai..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Susiję įrašai..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Ataskaita..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "El. paštas..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Spausdinti..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "Y" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "w" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Naudotojas" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Parinktys" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "_Mėgstami" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Žinynas" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Ieškoti" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Nerasta rezultatų." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Prisijungti..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Atsijungti" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Išei_ti..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "Nus_tatymai..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "Pekrauti meniu" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Įjungti/išjungti _meniu" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Globali paieška" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Įrankių _juosta" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Numatytasis" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Tekstas ir piktogramos" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "P_iktogramos" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Tekstas" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Meniu juosta" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Keisti trumpinius" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Rėžimas" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "Sta_ndartinis" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Forma" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Įsiminti plotį/aukštį" #: tryton/gui/main.py:602 #, fuzzy msgid "Save Tree State" msgstr "Įsiminti hierarchinio sąrašo išskleistas šakas" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Rašybos klaidų tikrinimas" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Buvusi kortelė" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Kita kortelė" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Paieškos ribojimas..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_El. paštas..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Iš_saugoti pasirinktis" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Trumpiniai..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Apie..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "_Tvarkyti mėgstamus" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Atliekant šį veiksmą bus uždarytos visos kortelės.\n" "Ar norite tęsti?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Uždaryti kortelę" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Priedai(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Profilių tvarkymas" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profilis" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Pridėti" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Ištrinti" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Serveris:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Duomenų bazė:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Gaunamas duomenų bazių sąrašas" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Naudotojas:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Nesuderinama serverio versija" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Nepavyko prisijungti prie serverio" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Prisijungti" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Atsisakyti" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Atšaukti prisijungimą prie Tryton serverio" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "_Prisijungti" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Prisijungti prie Tryton serverio" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profilis:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Tvarkyti profilius" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Serverio / duomenų bazės duomenys" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Naudotojas:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "El. paštas" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "El. pašto programos nustatymai" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Komandinė eilutė:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Galimos žymekliai:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Kam:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Tema:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Turinys:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Priedas:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Priedai(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Pasirinkite bent vieną įrašą!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Sukūrė naudotojas:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Sukūrimo data:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Paskutinį kartą redagavo:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Paskutinio redagavimo data:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modelis:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Ar tikrai norite ištrinti šį įrašą?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Ar tikrai norite ištrinti šiuos įrašus?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Įrašai nebuvo ištrinti!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Įrašai ištrinti!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Dabar dirbate su įrašo(-ų) kopija(-omis)!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Įrašas išsaugotas!" #: tryton/gui/window/form.py:423 msgid " of " msgstr " iš " #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Šis įrašas buvo pakeistas\n" "Ar norite jį išsaugoti?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Veiksmai" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Vykdyti veiksmą" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Susijęs" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Atverti susijusius įrašus" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Ataskaitos" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Atverti ataskaitą" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Siuntimas" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Siųsti ataskaitą el. paštu" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Spausdinimas" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Spausdinti ataskaitą" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Nežinomas" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Riba" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Paieškos ribojimo nustatymai" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Riba:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Nustatymai" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Keisti naudotojo nustatymus" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Nustatymai" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "Buvęs" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "Pasirinkimas" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "Buvęs" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Spartieji klavišai" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Teksto laukų trumpiniai" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Iškirpti pažymėtą tekstą" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Kopijuoti pažymėtą tekstą" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Įdėti nukopijuotą tekstą" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Peršokti į kitą lauką" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Grįžti į buvusį lauką" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Sąryšinių laukų trumpiniai" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Kurti naują sąryšį" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Atverti/ieškoti sąryšinio įrašo" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Sąrašo laukų trumpiniai" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Kurti naują eilutę" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Atverti sąryšį" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Pažymėti eilutę ištrinimui" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Nužymėti eilutę ištrinimui" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Trumpiniai pagal laukus" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_Perjungti rodymą" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "_Perjungti rodymą" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Buvęs" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Buvęs įrašas" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Kitas" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Kitas įrašas" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "I_eškoti" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Naujas" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Sukurti naują įrašą" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Saugoti" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Išsaugoti šį įrašą" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Pe_rkrauti/atšaukti" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Pe_rkrauti/atšaukti" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "Sukurti ko_piją" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Ištrinti..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Žiūrėti _žurnalus..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "P_riedas:" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Prisegti failą prie įrašo" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Veiksmai..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Susiję įrašai..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Ataskaita..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "Siųsti _el. paštu..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Spausdinti..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Eksportuoti duomenis..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importuoti duomenis..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Uždaryti _kortelę" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Galimi laukai" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Valyti" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV parametrai" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Koduotė:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Lauko pavadinimas" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Eksportuoti CSV formatu" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Išsaugoti eksportavimo šablonai" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Pavadinimas" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Išsaugoti šabloną" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Ištrinti šabloną" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Atvėrimas" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Išsaugoti" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Pridėti laukų pavadinimus" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Kokiu pavadinimu išsaugoti šį eksportavimo šabloną?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d įrašas išsaugotas!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d įrašai išsaugoti!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Veiksmas neįvykdytas!\n" "Klaidos pranešimas:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Nuoroda" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Pridėti" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Šalinti " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Sukurti naują įrašą " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Pašalinti pasirinktą įrašą " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Atkurti pasirinktą įrašą " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Buvęs" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Kitas" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Perjungti" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importuoti iš CSV failo" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Aptikti automatiškai" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Importuoti iš failo:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Atverti..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Praleisti eilutes:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Pasirinkite failą iš kurio importuosite!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Klaida atveriant CSV failą" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Klaida apdorojant failą ties lauku %s." #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d įrašas importuotas!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d įrašai importuoti!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Vedlys" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "Sukūrė naudotojas:" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "Sukūrimo data:" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "Paskutinio redagavimo data:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "Paskutinio redagavimo data:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "Nepavyko nustatyti lokalės %s" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "Nepavyko nustatyti lokalės %s" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Paveiklėlio dydis" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Plotis:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Aukštis" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG paveikslėlis (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Įrašyti kaip" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Paveikslėlis yra per didelis!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Rodyti filtrų žymeles" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Šalinti šią žymelę" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Sukurti šio filtro žymelę" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Žymelės pavadinimas:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Rasti" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "Turinys:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "Perjungti rodymą" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "Perjungti rodymą" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Valyti" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Visi failai" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Rodyti paprastą tekstą" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Pridėti reikšmę" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Šalinti \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Paveikslėliai" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Pridėti turimą įrašą" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Pašalinti pasirinktą įrašą " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Atverti įrašą " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Ieškoti įrašo " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Pašalinti pasirinktą įrašą" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Keisti pasirinktą įrašą " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Vertimas" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Keisti" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Neaiškus" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Išsaugokite įrašą prieš pridedant vertimą!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Jokia kita kalba nėra prieinama!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Vertimų peržiūra" tryton-4.6.5/tryton/data/locale/lt/LC_MESSAGES/tryton.mo0000644000175000017500000003706713260723565022232 0ustar cedced000000000000001 ,-)2\mu  .Gg { #% %4 IUZ^m&v     #0J bo * < FR oz   ! 8BH&_      '7 <GMUqwz ~" !8>ETYpvx      49 > JVg p{    *0 ? JV_o      #@U \ gqv ~   ' :D `jrI}. 4 ! !!"!5! D! P!Z!_!q!%!!!! "" *" 7"B" H" R"`" e""" """" " """ " " " "# # # '# 2# =#G#W#]#l#r#y### # ##### ## #$ $$ $ )$ 7$A$ J$ U$b$ j$u$ {$$ $$$$$$$$ $$ $ % % %&%(%<F%% %%%%%')''''' '( ( ((#((:(#c()) )) )))) *&*@* S*"_*)*+* ** **++5+G+L+P+ _+,l++++++ ++ ,$, >, L,m, ,,",,,--#4-X-h-}-- -%- --- . '.1.O.^.e. .. .. ...'/;/D/L/ \/g/w/ // /"////0 0 0)0#20 V0`0c0g0z000000 111161<1O1W1 r1~1111 1 111 12 2 "2.262 J2V2\2k222 22 2 2222 3$3?3Y3 s33 33 3 3333 4 4 #414:4 N4 X4d4m44 444%45 5&5 =5 J5U5d5v555 555566 6 (666 K6U6 q6 ~666666 66I7Z7 8:'8b8 g8r8888 8888%8989"X9 {99 9 9 9 99989-:5:<:L:N:R:g: p: }: ::: : : : : ::;;,;E;L; ]; g;t;;;;; ; ;;; < < < &<1<6<E<M<^< m<y<< < <<< <<<== -=9=;=L= T=_= a== = ===<== >1>3>5> of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationHost:IDID:Image SizeImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...SaveSave AsSave As...Save Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:Toggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: lt Language-Team: lt Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 iš "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:Galimi laukaiFields selectedIšsaugoti eksportavimo šablonaiPerspėjimas dėl lygiagretaus duomenų rašymo: Šis įrašas buvo pakeistas tuo metu kol redagavote. Pasirinkite: - "Atšaukti", kad atšaukti pakeitimus; - "Palyginti", kad peržiūrėti pakeistą versiją; - "Rašyti visvien", kad išsaugoti jūsų turimą versiją.Sukurti...Ieškoti...P_riedas:VeiksmaiVeiksmai...PridėtiPridėti laukų pavadinimusAdd a note to the recordPrisegti failą prie įrašoPridėti turimą įrašąPridėti reikšmęVisi failaiDaugiau nepaisyti šio pranešimo.Ar tikrai norite ištrinti šį įrašą?Ar tikrai norite ištrinti šiuos įrašus?Priedai(%d)Priedas:Priedai...Turinys:Žymelės pavadinimas:Sukurti šio filtro žymelęKlaidų pėdsekysBy: CC:CSV parametrai_PrisijungtiAtšaukti prisijungimą prie Tryton serverioKeisti trumpiniusValytiClear the record Uždaryti kortelęCollapse all rowsCollapse rowKomandinė eilutė:PalygintiLygiagretaus duomenų rašymo klaidaPatvirtinimasPrisijungti prie Tryton serverioCopy URL into clipboardCopy _URL...Kopijuoti pažymėtą tekstąNepavyko prisijungti prie serverioSukurti naują įrašąSukurti naują įrašą Kurti naują eilutęKurti naują sąryšįUžregistruoti naują klaidą su IDSukūrimo data:Sukūrė naudotojas:Iškirpti pažymėtą tekstąDuomenų bazė:Date FormatPašalinti pasirinktą įrašą Delimiter:Display formatDisplayed date formatAr tikrai norite vykdyti?SiuntimasSiųsti ataskaitą el. paštuEl. paštas...KeistiKeisti naudotojo nustatymusKeisti pasirinktą įrašą Trumpiniai pagal laukusEl. paštasEl. pašto programos nustatymaiKoduotė:KlaidaKlaida atveriant CSV failąKlaida apdorojant failą ties lauku %s.Klaida: Klaida:Expand all rowsExpand rowExpand/CollapseEksportuoti CSV formatu_MėgstamiNetiesaFast TabbingGaunamas duomenų bazių sąrašasLauko pavadinimasFile "%s" not foundImportuoti iš failo:RastiForegroundNeaiškusAukštisServerio / duomenų bazės duomenysServeris:IDID:Paveiklėlio dydisPaveikslėliaiImportuoti iš CSV failoNesuderinama serverio versijaSpartieji klavišaiPaskutinio redagavimo data:Paskutinį kartą redagavo:Vykdyti veiksmąGalimos žymekliai:RibaRiba:Praleisti eilutes:NuorodaSąrašo laukų trumpiniaiPrisijungtiM_Tvarkyti mėgstamusPažymėti eilutę ištrinimuiModelis:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pagePavadinimasKitasKitas įrašasPeršokti į kitą laukąNerasta rezultatų.Note(%d)Notes (%s)Notes...AtvėrimasOpen filtersAtverti susijusius įrašusAtverti sąryšįAtverti ataskaitąAtverti...Atverti/ieškoti sąryšinio įrašoOverride '%s' definition?PNG paveikslėlis (*.png)Slaptažodis:Įdėti nukopijuotą tekstąPrievadas:Pre-validationNustatymaiNustatymaiBuvęsBuvęs įrašasGrįžti į buvusį laukąSpausdinimasSpausdinti ataskaitąSpausdinti...ProfilisProfilių tvarkymasProfilis:Quote char:SusijęsSusiję įrašai...Sąryšinių laukų trumpiniaiŠalinti "%s"Šalinti Pašalinti pasirinktą įrašąPašalinti pasirinktą įrašą Šalinti šią žymelęAtaskaitosPranešti apie klaidąAtaskaita...IšsaugotiĮrašyti kaipĮrašyti kaip...Įsiminti plotį/aukštįIšsaugoti šį įrašąIeškotiSearch %sPaieškos ribojimo nustatymaiPaieškos ribojimas...Ieškoti įrašo SelectSelect a colorSelect allSelect parentPasirinkite veiksmąSelect...Select/Activate current rowPasirinkimasServeris:Rodyti filtrų žymelesRodyti paprastą tekstąShow revisions...Rašybos klaidų tikrinimasTema:PerjungtiTeksto laukų trumpiniaiAtliekant šį veiksmą bus uždarytos visos kortelės. Ar norite tęsti?Ta pati klaida jau buvo pranešta kito naudotojo. Norėdami informuoti apie klaidos tvarkymo eigą, jūsų naudotojo vardas buvo pridėtas prie klaidos pranešimo sąrašoThe values of "%s" are not validKlaidų pranešimui reikalinga naudotojo paskyra %sKam:Toggle rowToggle selectionToo much argumentsVertimų peržiūraVertimasTree viewTiesaTryton prisijungimasUnable to delete wizard %sUnable to search for completion of %sNepavyko nustatyti lokalės %sUnable to write config file %s.Atkurti pasirinktą įrašą NežinomasNužymėti eilutę ištrinimuiUnselect allNaudotojas:Naudotojas:Naudotojas:Žiūrėti _žurnalus...WeekKokiu pavadinimu išsaugoti šį eksportavimo šabloną?Plotis:VedlysRašyti visvienYYesJūsų pasirinkimas:_Apie..._Veiksmai..._Pridėti_AtsisakytiUždaryti _kortelę_Prisijungti..._Connection_Copy URL_Numatytasis_Ištrinti..._AtsijungtiSukurti ko_pijąSiųsti _el. paštu..._El. paštas..._Eksportuoti duomenis..._FormaGlobali paieška_ŽinynasP_iktogramos_Importuoti duomenis..._Trumpiniai..._Tvarkyti profiliusPekrauti meniuĮjungti/išjungti _meniu_Meniu juosta_Rėžimas_Naujas_KitasKita kortelėSta_ndartinis_Notes..._Parinktys_PDANus_tatymai..._Buvęs_Buvusi kortelė_Spausdinti...Išei_ti..._Susiję įrašai...Pe_rkrauti/atšaukti_Ištrinti_Ataskaita..._SaugotiIš_saugoti pasirinktisI_eškoti_Perjungti rodymą_Tekstas_Tekstas ir piktogramosĮrankių _juosta_Naudotojasddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwttryton-4.6.5/tryton/data/locale/de/0000755000175000017500000000000013260723567016507 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/de/LC_MESSAGES/0000755000175000017500000000000013260723567020274 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/de/LC_MESSAGES/tryton.po0000644000175000017500000011072213255571102022164 0ustar cedced00000000000000# German (Germany) translations for tryton. # Copyright (C) 2008-2014 MBSolutions # This file is distributed under the same license as the tryton project. # Udo Spallek , 2008. # Mathias Behrle , 2008-2014. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "Alternative Konfigurationsdatei angeben" #: tryton/config.py:73 msgid "development mode" msgstr "Entwicklungsmodus" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "Allgemeiner Log-Level: INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "Loglevel angeben: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "Anmeldename angeben" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "Name des Servers angeben" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Zu viele Argumente" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Datei \"%s\" nicht gefunden" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "Kann Konfigurationsdatei '%s' nicht schreiben." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Kann locale %s nicht setzen." #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Aktion wählen" #: tryton/action/main.py:197 msgid "No action defined." msgstr "Keine Aktion definiert." #: tryton/common/button.py:56 msgid "By: " msgstr "Von: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Verbindung" #: tryton/common/common.py:250 msgid "Server:" msgstr "Server:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Auswahl" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Ihre Auswahl:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Speichern unter..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Diese Warnung künftig nicht mehr anzeigen." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Fortfahren?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Bestätigung" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Aktualisierungskonflikt" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Aktualisierungskonflikt beim Schreiben des aktuellen Datensatzes:\n" "\n" "Dieser Datensatz wurde anderweitig geändert, während Sie ihn bearbeitet haben.\n" " Lösungsmöglichkeiten:\n" " - \"Abbrechen\" um den Speichervorgang abzubrechen,\n" " - \"Vergleichen\" um die geänderte Version des Datensatzes zu betrachten,\n" " - \"Überschreiben\" um die gespeicherte Version mit Ihrer Version zu überschreiben." #: tryton/common/common.py:766 msgid "Compare" msgstr "Vergleichen" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Überschreiben" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Fehler" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Fehler berichten" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Anwendungsfehler." #: tryton/common/common.py:832 msgid "Error: " msgstr "Fehler:" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "" "Um Fehler online berichten zu können, benötigen Sie ein Konto auf %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Fehler melden" #: tryton/common/common.py:899 msgid "User:" msgstr "Anmeldename:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Passwort:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Derselbe Fehlerbericht wurde bereits von einem anderen Benutzer berichtet.\n" "Zu Ihrer Information wurde Ihr Benutzername auf der Interessentenliste eingetragen." #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Neuer Fehlerbericht angelegt mit ID " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Verbindungsfehler.\n" "Anmeldename oder Passwort fehlerhaft." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Ausnahme:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Der Fingerabdruck des Servers hat sich seit der letzten Verbindung geändert.\n" "Der Client wird sich nicht mehr zu diesem Server verbinden bis der Fingerabdruck wieder dem des Servers entspricht." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Sicherheitsrisiko." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Verbindungsfehler.\n" "Kann nicht zum Server verbinden." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Netzwerkfehler." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Suche..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Erstelle..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Wert" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Angezeigter Wert" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Format" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Angezeigtes Format" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Kalender öffnen" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Datumsformat" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Angezeigtes Datumsformat" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "J" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Ja" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Wahr" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "w" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Falsch" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Bearbeiten..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Anhänge..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notizen..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Aktionen..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Beziehungen..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Berichte..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "E-Mail..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Drucken..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "J" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "W" #: tryton/common/timedelta.py:29 msgid "d" msgstr "t" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_Verbindung" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Benutzer" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Einstellungen" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_voriten" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Hilfe" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Suchen" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Kein Ergebnis." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Verbinden..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Verbindung _trennen" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Beenden..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Einstellungen..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Menü neu laden" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Menü _umschalten" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "_Globale Suche" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Werkzeugleiste" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Standard" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Text _und Symbole" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Symbole" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Text" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Menüleiste" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Schnelltasten ändern" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Modus" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Formular" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Breite/Höhe speichern" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Menüansicht speichern" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Schneller Feldwechsel mit Tabulatortaste" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Rechtschreibkorrektur" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Vorherige Registerkarte" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_Nächste Registerkarte" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Suchlimitierung..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_E-Mail..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Einstellungen _speichern" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Schnelltasten..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Über..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Favoriten verwalten" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Die folgende Aktion erfordert die Schließung aller Registerkarten.\n" "Fortfahren?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Registerkarte schließen" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Anhänge (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Profilbearbeitung" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Hinzufügen" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Entfernen" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Host:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Datenbank:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Datenbankliste wird abgefragt..." #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Anmeldename:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Inkompatible Serverversion" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Kann nicht zum Server verbinden!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Anmeldung" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Abbrechen" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Abbrechen" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "_Verbinden" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Verbindung zum Tryton Server herstellen" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Profile verwalten" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Host-/Datenbankdetails" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Anmeldename:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "E-Mail" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Einstellungen E-Mail" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Kommandozeile:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Legende der verfügbaren Platzhalter:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "An:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Betreff:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Textkörper:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Anhang:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Anhänge(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Notiz(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Ein Datensatz muss ausgewählt werden." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Erstellt von" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Erstellt am" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Zuletzt verändert von" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Zuletzt verändert am" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modell:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Möchten Sie diesen Datensatz wirklich löschen?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Möchten Sie diese Datensätze wirklich löschen?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Die Datensätze wurden nicht gelöscht." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Die Datensätze wurden gelöscht." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Sie arbeiten nun an dem/den duplizierten Datensatz/Datensätzen." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Der Datensatz wurde gespeichert." #: tryton/gui/window/form.py:423 msgid " of " msgstr " von " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Datensatz geändert.\n" "Soll der Datensatz gespeichert werden?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Aktion" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Aktion ausführen" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Beziehung" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Datensätze einer Beziehung öffnen" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Bericht" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Bericht öffnen" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "E-Mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Bericht per E-Mail senden" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Drucken" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Bericht drucken" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "URL kopieren" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "URL in Zwischenablage kopieren" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Unbekannt" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limitierung" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Einstellung Suchlimitierung" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Limit:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notizen (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Einstellungen" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Benutzereinstellungen bearbeiten" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Einstellung" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Bearbeitung" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Bearbeitung auswählen" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Bearbeitung:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Schnelltasten" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Schnelltasten für Texteinträge" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Ausgewählten Text ausschneiden" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Ausgewählten Text kopieren" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Ausgewählten Text einfügen" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Nächstes Widget" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Vorheriges Widget" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Schnelltasten für Einträge in verknüpften Feldern" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Neue Beziehung erstellen" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Beziehung suchen/öffnen" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Schnelltasten für Einträge in Listenfelder" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Neue Zeile erstellen" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Beziehung öffnen" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Zeile zum Löschen markieren" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Löschmarkierung für Zeile aufheben" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Widgets zur Bearbeitung" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Cursor bewegen" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Nach rechts bewegen" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Nach links bewegen" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Nach oben bewegen" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Nach unten bewegen" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Eine Seite nach oben bewegen" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Eine Seite nach unten bewegen" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "An den Anfang bewegen" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Zum Ende bewegen" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Zum übergeordneten Datensatz bewegen" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Alle auswählen" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Auswahl aufheben" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Übergeordneten Datensatz auswählen" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Aktuelle Zeile auswählen/aktivieren" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Auswahl umkehren" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Ausklappen/Einklappen" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Zeile ausklappen" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Zeile einklappen" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Auswahl für Zeile umkehren" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Alle Zeilen einklappen" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Alle Zeilen ausklappen" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Baumansicht" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_Ansicht wechseln" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "_Ansicht wechseln" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Vorheriger" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Vorheriger Datensatz" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Nächster" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Nächster Datensatz" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Suche" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Neu" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Neuen Datensatz erstellen" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Speichern" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Diesen Datensatz speichern" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Neu laden/_Rückgängig" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Neu laden/_Rückgängig" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplizieren" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Löschen..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "_Protokoll ansehen..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Bearbeitungen anzeigen..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "A_nhänge..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Einen Anhang zum Datensatz hinzufügen" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Notizen..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Eine Notiz zu einem Datensatz hinzufügen" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Aktion ausführen..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Beziehung öffnen..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Bericht öffnen..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_Bericht per E-Mail..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Bericht drucken..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Daten _exportieren..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Daten _importieren..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "_URL kopieren..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Registerkarte schließen" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Alle Felder" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Leeren" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Ausgewählte Felder" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV Parameter" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Feldtrenner:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Anführungszeichen:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Kodierung:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Feldname" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Als CSV exportieren" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Vordefinierte Exporte" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Name" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "Exportkonfiguration _speichern" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "Exportkonfiguration _löschen" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Öffnen" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Speichern" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Feldnamen _hinzufügen" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (string)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Wie soll der Name des Exports lauten?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Definition von '%s' nicht berücksichtigen?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "%d Datensatz gespeichert." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "%d Datensätze gespeichert." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Operation fehlgeschlagen.\n" "Fehlermeldung:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Verknüpfung" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Hinzufügen" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Entfernen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Neuen Datensatz erstellen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Ausgewählte Datensätze löschen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Löschung der ausgewählten Datensätze rückgängig machen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Vorheriger" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Nächster" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Ansicht wechseln" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Aus CSV Datei importieren" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "_Automatische Erkennung" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Importdatei:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Öffnen..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Zu überspringende Zeilen:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Zuerst muss eine Importdatei ausgewählt werden." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Fehler beim Öffnen der CSV-Datei" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Fehler bei der Verarbeitung der Datei in Feld %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "%d Datensatz importiert." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "%d Datensätze importiert." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Suche %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Wizard" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Erstellt von" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Erstellt am" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Zuletzt verändert von" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Zuletzt verändert am" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Kann Sicht für den Menübaum nicht anwenden." #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" liegt nicht im gültigen Wertebereich (Domain)." #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "In Feld \"%s\" ist ein Eintrag erforderlich." #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Die Werte von \"%s\" sind ungültig." #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Vorvalidierung" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Bildgröße" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Breite:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Höhe:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG Bild (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Speichern unter..." #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "Bild ist zu groß." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Filter öffnen" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Filterlesezeichen anzeigen" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Dieses Lesezeichen entfernen" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Diesen Filter als Lesezeichen hinzufügen" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Lesezeichenname:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Suchen" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Heute" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "Vorwärts bewegen" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "Rückwärts bewegen" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "Vorheriges Jahr" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "Nächstes Jahr" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Wochenansicht" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Monatsansicht" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Woche" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Auswählen..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Leeren" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Alle Dateien" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Auswählen" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Klartext anzeigen" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Wert hinzufügen" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "\"%s\" entfernen" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Bilder" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Bestehenden Datensatz hinzufügen" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Ausgewählten Datensatz löschen " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Datensatz öffnen " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Datensatz löschen " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Datensatz suchen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Ausgewählten Datensatz löschen " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Ausgewählten Datensatz bearbeiten " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Vordergrund" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Eine Farbe auswählen" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Übersetzung" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Bearbeiten" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Unscharf" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "" "Der Datensatz muss gespeichert werden, bevor eine Übersetzung hinzugefügt " "werden kann." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "Keine weiteren Sprachen verfügbar." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Aktuelle Sicht übersetzen" tryton-4.6.5/tryton/data/locale/de/LC_MESSAGES/tryton.mo0000644000175000017500000004616113260723565022176 0ustar cedced00000000000000a$ ,-)2\m -G->O_ fqu  #%:` o{ &-3 JT f s +2% =J]}  ! 3 =I fq  *0 GQW&n      "6F KV]ck " 4!Bdjq     . = J Y g s {       ! !!! #!0! E! S!_!q!!!#!!! !!"" $" /";"D"T"d" j"w"""" " """" "" # #%#<#Y#n# u# ## ### ##### ##$$4$C$J$Y$ k$ v$$ $$ $$$$$ %%#%*%IA%}% & &5&4&#''' -'8'I'\' k' w''''$'%''(4(T(s({( ( (( (( (( ( ())() 7)D)F)J)%i)7)) ) )) ))* * * %* 1*;*D* S* ^* j* u* ********* * ++++"+ (+2+ :+D+M+R+ b+ l+ z++ + ++ ++ + ++ +++, ,,,&, .,9, ;,\, ^, h,v,x,<,,,,,,~.4.*.../2/N/V/f/ w///////////t11 11 1 11)1&2!+2M2 ^2+k220212 33 !3 /3 ;3H3)Y3 333 3 3 333334%464 E4Q4 i4'v48434 5*5;5 W5x5555$5 6 6 6 )666 V6 a6(n6 6666 666 7 7 #7'D7 l7z777 77!7178 8&8=8N8d8 x88(8 888 89 999'9.9E9K9N9 R9^9q9x99 9999%9 :,:3: N:,[: ::::::: :;;*;H;Y;%l;;;;;;; < <</<#G<k< z< < <<<#<<<< = !=,=+E=+q== ==== = = >>$>6>>> N>Y>`>r>z> >'>!> >?4?G?V?'g?'???? ? ? @ @@/@B@Y@p@@@@@@@ @@A+A$;A`A oA$}AAAAAAABB )BOJBB9C"C;DMZDDDDDDD E E&E +E6E$QE%vEE-E.ECF ZF$dFF F F FFFF F%FGG@%GfGuGwG&zG0GXG +H 9HCH YHfH ~HHH H H H HH HI I'I >III _IiIxIIIIIII III I J"J *J6JEJJJ \JhJJ JJJ JJ JJK1K8KJKPKbK rK|K~KKKKKKKKK'K7LWLkLmLoL of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: de Language-Team: de Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 von "%s" liegt nicht im gültigen Wertebereich (Domain).In Feld "%s" ist ein Eintrag erforderlich.%d Datensatz importiert.%d Datensatz gespeichert.%d Datensätze importiert.%d Datensätze gespeichert.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:Alle FelderAusgewählte FelderVordefinierte ExporteAktualisierungskonflikt beim Schreiben des aktuellen Datensatzes: Dieser Datensatz wurde anderweitig geändert, während Sie ihn bearbeitet haben. Lösungsmöglichkeiten: - "Abbrechen" um den Speichervorgang abzubrechen, - "Vergleichen" um die geänderte Version des Datensatzes zu betrachten, - "Überschreiben" um die gespeicherte Version mit Ihrer Version zu überschreiben.Erstelle...Suche...A_nhänge...AktionAktionen...HinzufügenFeldnamen _hinzufügenEine Notiz zu einem Datensatz hinzufügenEinen Anhang zum Datensatz hinzufügenBestehenden Datensatz hinzufügenWert hinzufügenAlle DateienDiese Warnung künftig nicht mehr anzeigen.Anwendungsfehler.Möchten Sie diesen Datensatz wirklich löschen?Möchten Sie diese Datensätze wirklich löschen?Anhänge(%d)Anhang:Anhänge (%s)Anhänge...Textkörper:Lesezeichenname:Diesen Filter als Lesezeichen hinzufügenFehler meldenVon: CC:CSV Parameter_VerbindenAbbrechenSchnelltasten ändernLeerenDatensatz löschen Registerkarte schließenAlle Zeilen einklappenZeile einklappenKommandozeile:VergleichenAktualisierungskonfliktBestätigungVerbindung zum Tryton Server herstellenVerbindungsfehler. Anmeldename oder Passwort fehlerhaft.Verbindungsfehler. Kann nicht zum Server verbinden.URL in Zwischenablage kopieren_URL kopieren...Ausgewählten Text kopierenKann nicht zum Server verbinden!Neuen Datensatz erstellenNeuen Datensatz erstellen Neue Zeile erstellenNeue Beziehung erstellenNeuer Fehlerbericht angelegt mit ID Erstellt amErstellt amErstellt vonErstellt vonAusgewählten Text ausschneidenDatenbank:DatumsformatAusgewählte Datensätze löschen Feldtrenner:Angezeigtes FormatAngezeigtes DatumsformatAngezeigter WertFortfahren?E-MailBericht per E-Mail sendenE-Mail...BearbeitenBenutzereinstellungen bearbeitenAusgewählten Datensatz bearbeiten Bearbeiten...Widgets zur BearbeitungE-MailEinstellungen E-MailKodierung:FehlerFehler beim Öffnen der CSV-DateiFehler bei der Verarbeitung der Datei in Feld %s.Fehler:Ausnahme:Alle Zeilen ausklappenZeile ausklappenAusklappen/EinklappenAls CSV exportierenFa_voritenFalschSchneller Feldwechsel mit TabulatortasteDatenbankliste wird abgefragt...FeldnameDatei "%s" nicht gefundenImportdatei:SuchenVordergrundFormatUnscharfHöhe:Host-/DatenbankdetailsHost:IDID:BildgrößeBild ist zu groß.BilderAus CSV Datei importierenInkompatible ServerversionSchnelltastenZuletzt verändert amZuletzt verändert vonAktion ausführenLegende der verfügbaren Platzhalter:LimitierungLimit:Zu überspringende Zeilen:VerknüpfungSchnelltasten für Einträge in ListenfelderAnmeldungMFavoriten verwaltenZeile zum Löschen markierenModell:Zuletzt verändert amZuletzt verändert vonMonatsansichtCursor bewegenNach unten bewegenEine Seite nach unten bewegenZum Ende bewegenNach links bewegenZum übergeordneten Datensatz bewegenNach rechts bewegenAn den Anfang bewegenNach oben bewegenEine Seite nach oben bewegenNameNetzwerkfehler.NächsterNächster DatensatzNächstes WidgetKeine Aktion definiert.Keine weiteren Sprachen verfügbar.Kein Ergebnis.Notiz(%d)Notizen (%s)Notizen...ÖffnenFilter öffnenDatensätze einer Beziehung öffnenBeziehung öffnenBericht öffnenKalender öffnenDatensatz öffnen Öffnen...Beziehung suchen/öffnenOperation fehlgeschlagen. Fehlermeldung: %sDefinition von '%s' nicht berücksichtigen?PNG Bild (*.png)Passwort:Ausgewählten Text einfügenPort:VorvalidierungEinstellungEinstellungenVorherigerVorheriger DatensatzVorheriges WidgetDruckenBericht druckenDrucken...ProfilProfilbearbeitungProfil:Anführungszeichen:Der Datensatz wurde gespeichert.Die Datensätze wurden nicht gelöscht.Die Datensätze wurden gelöscht.BeziehungBeziehungen...Schnelltasten für Einträge in verknüpften Feldern"%s" entfernenEntfernen Ausgewählten Datensatz löschen Ausgewählten Datensatz löschen Dieses Lesezeichen entfernenBerichtFehler berichtenBerichte...BearbeitungBearbeitung:SpeichernSpeichern unter...Speichern unter...Menüansicht speichernBreite/Höhe speichernDiesen Datensatz speichernSuchenSuche %sEinstellung SuchlimitierungSuchlimitierung...Datensatz suchen Sicherheitsrisiko.AuswählenEine Farbe auswählenBearbeitung auswählenAlle auswählenÜbergeordneten Datensatz auswählenAktion wählenAuswählen...Aktuelle Zeile auswählen/aktivierenAuswahlServer:Filterlesezeichen anzeigenKlartext anzeigenBearbeitungen anzeigen...RechtschreibkorrekturBetreff:Ansicht wechselnSchnelltasten für TexteinträgeDie folgende Aktion erfordert die Schließung aller Registerkarten. Fortfahren?Derselbe Fehlerbericht wurde bereits von einem anderen Benutzer berichtet. Zu Ihrer Information wurde Ihr Benutzername auf der Interessentenliste eingetragen.Der Fingerabdruck des Servers hat sich seit der letzten Verbindung geändert. Der Client wird sich nicht mehr zu diesem Server verbinden bis der Fingerabdruck wieder dem des Servers entspricht.Die Werte von "%s" sind ungültig.Datensatz geändert. Soll der Datensatz gespeichert werden?Um Fehler online berichten zu können, benötigen Sie ein Konto auf %sAn:HeuteAuswahl für Zeile umkehrenAuswahl umkehrenZu viele ArgumenteAktuelle Sicht übersetzenÜbersetzungBaumansichtWahrVerbindungUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sKann locale %s nicht setzen.Kann Sicht für den Menübaum nicht anwenden.Kann Konfigurationsdatei '%s' nicht schreiben.Löschung der ausgewählten Datensätze rückgängig machen UnbekanntLöschmarkierung für Zeile aufhebenAuswahl aufhebenAnmeldename:Anmeldename:Anmeldename:Wert_Protokoll ansehen...WocheWochenansichtWie soll der Name des Exports lauten?Breite:WizardSie arbeiten nun an dem/den duplizierten Datensatz/Datensätzen.ÜberschreibenJJaEin Datensatz muss ausgewählt werden.Zuerst muss eine Importdatei ausgewählt werden.Der Datensatz muss gespeichert werden, bevor eine Übersetzung hinzugefügt werden kann.Ihre Auswahl:_Über..._Aktion ausführen..._Hinzufügen_Automatische Erkennung_Abbrechen_LeerenRegisterkarte schließen_Verbinden..._VerbindungURL kopieren_StandardExportkonfiguration _löschen_Löschen...Verbindung _trennen_Duplizieren_Bericht per E-Mail..._E-Mail...Daten _exportieren..._Formular_Globale Suche_Hilfe_SymboleDaten _importieren..._Schnelltasten..._Profile verwalten_Menü neu ladenMenü _umschalten_Menüleiste_Modus_Neu_Nächster_Nächste Registerkarte_Normal_Notizen..._Einstellungen_PDA_Einstellungen..._Vorheriger_Vorherige Registerkarte_Bericht drucken..._Beenden..._Beziehung öffnen...Neu laden/_Rückgängig_Entfernen_Bericht öffnen..._SpeichernExportkonfiguration _speichernEinstellungen _speichern_Suche_Ansicht wechseln_TextText _und Symbole_Werkzeugleiste_BenutzertEntwicklungsmodusVorwärts bewegenRückwärts bewegenhAllgemeiner Log-Level: INFOmNächstes JahrVorheriges JahrsAlternative Konfigurationsdatei angebenLoglevel angeben: DEBUG, INFO, WARNING, ERROR, CRITICALAnmeldename angebenwWJtryton-4.6.5/tryton/data/locale/bg/0000755000175000017500000000000013260723567016507 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/bg/LC_MESSAGES/0000755000175000017500000000000013260723567020274 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/bg/LC_MESSAGES/tryton.po0000644000175000017500000011560213255571102022166 0ustar cedced00000000000000# Bulgarian (Bulgaria) translations for tryton. # Copyright (C) 2010 B2CK # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2010. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "укажете друг конфигурационен файл" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "записване на всичко на ниво INFO " #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "укажете потребителското име" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "укажете адреса на сървъра" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Твърде много аргументи" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Файла \"%s\" не е намерен" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Не може да запише конфигурационен файл %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Не може да зададе локални настройки %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Изберете действие" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Не е зададено действие!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton връзка" #: tryton/common/common.py:250 msgid "Server:" msgstr "Сървър:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Порт:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Избор:" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Вашия избор" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Запис като ..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Винаги игнорирай това предупреждение." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Потвърждение" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Грешка при достъп" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Предупреждение при достъп за писане:\n" "\n" "Записът беше променен докато го редактирахте.\n" " Изберет:\n" " - \"Отказ\" за да откажете запис;\n" " - \"Сравняване\" за да видите променената версия;\n" " - \"Запис \" за да запишете вашата текуща версия." #: tryton/common/common.py:766 msgid "Compare" msgstr "Сравняване" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Запис" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Грешка" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Съобщаване за грешка" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Грешка в приложението!" #: tryton/common/common.py:832 msgid "Error: " msgstr "Грешка: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "За да съобщите за грешка трябва да имате сметка на %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "" #: tryton/common/common.py:899 msgid "User:" msgstr "Потребител: " #: tryton/common/common.py:907 msgid "Password:" msgstr "Парола:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Тази грешка е вече съобщена от друг потребител..\n" "За да бъдете информирани потребителя ви е добавен списъка за този проблем" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Създадена е нова грешка с ID" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Грешка при свързване!\n" "Грешно потребителско име или парола!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Грешка:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Идентификатора на сървъра е променен след последната връзка!\n" "Приложението ще спре да се връзва към сървъра докато не бъде оправен идентификатора му." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Риск за сигурността" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Грешка при свързване!\n" "Невъзможност да се свърже със сървъра!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Мрежова грешка!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "Лъжа" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "Нормален" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "Отваряне на календара" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "г" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Истина" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Лъжа" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "Изход..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Прикачен файл:" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Действия..." #: tryton/common/popup_menu.py:110 #, fuzzy msgid "Relate..." msgstr "Свързани..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Справки..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "Email..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Печат..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "Г" #: tryton/common/timedelta.py:27 msgid "M" msgstr "М" #: tryton/common/timedelta.py:28 msgid "w" msgstr "с" #: tryton/common/timedelta.py:29 msgid "d" msgstr "д" #: tryton/common/timedelta.py:30 msgid "h" msgstr "ч" #: tryton/common/timedelta.py:31 msgid "m" msgstr "м" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "Потребител" #: tryton/gui/main.py:236 msgid "_Options" msgstr "Настройки" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Помощ" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Търсене" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "Свързване..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Изключване" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Изход..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "Предпочитания..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "Презареждане" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Превключване на меню" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Лента с инструменти" #: tryton/gui/main.py:502 msgid "_Default" msgstr "По подразбиране" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Текс и икони" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "Икони" #: tryton/gui/main.py:532 msgid "_Text" msgstr "Текст" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "Лента с меню" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Смяна на бързи клавиши" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "Режим" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "Нормален" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Форма" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Запазване на ширина/височина" #: tryton/gui/main.py:602 #, fuzzy msgid "Save Tree State" msgstr "Запазване на състояние разгърнато дърво" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Проверка на правопис" #: tryton/gui/main.py:635 #, fuzzy msgid "_Previous Tab" msgstr "Предишен" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Ограничение при търсене..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "Email..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Запазване на опции" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Бързи клавиши..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "Относно..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 #, fuzzy msgid "Manage Favorites" msgstr "Управление на профили" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Следващите действия изискват затваряне на всички прозорци.\n" "Искате ли да продължите?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Затваряне на таб" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Прикачен файл(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Редактор на профили" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Профил" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "Добавяне" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "Изтриване" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Хост:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "База данни:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Вземане на списъка с бази данни:" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Потребителско име:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Несъвместима версия на сървъра!" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Не може да се свърже със сървъра!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Потребителско име" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "Отказ" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Отказ от свръзване с Tryton сървъра" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "Свързване" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Свързване с Tryton сървъра" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Профил:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "Управление на профили" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Информация за Хост / База данни" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Потребителско име:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Email" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Настройки на програма за email" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Команден ред:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Лагенда за налични контейнери:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "До" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Относно:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Тяло:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Прикачен файл:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Прикачен файл(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Трябва да изберете един запис!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Потребител създал:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Дата на създаване:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Последно променен от:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Дата на последна промяна:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Модел:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Наистина ли искате да изтриете този запис?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Наистина ли искате да изтриете тези записи?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Записа не е изтрит!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Записите изтрити!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Работите върху дублиран(и) запис(и)!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Записа съхранен!" #: tryton/gui/window/form.py:423 msgid " of " msgstr " от" #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Този запис е променен\n" "искате ли да го запишете ?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Действие" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Започване на действие" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Свързани" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Отваряне на свързани записи" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Справки" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Отваряне на справка" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Email" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Изращане на справка по Email" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Печат" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Отпечатване на справка" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Неизвестен" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Ограничение" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Настройки на органичения за търсене" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Ограничение:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Настройки" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Редактиране на потребителски настройки" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Настройки" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "Предишен" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "Избор:" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "Предишен" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Бързи клавиши" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Текстови бързи клавиши" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Изрязване на избрания текст" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Копиране на избрания текст" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Поставяне на копирания текст" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Следваща джаджа" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Предишенна джаджа" #: tryton/gui/window/shortcuts.py:33 #, fuzzy msgid "Relation Entries Shortcuts" msgstr "Текстови бързи клавиши" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Създаване на нова връзка" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Отваряне/Търсене на връзка" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Списък бързи клавиши" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Създаване на нов ред" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Отваряне на връзка" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Отбелязване на ред за изтриване" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Изчистване на ред за изтриване" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Превключване на изглед" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Превключване на изглед" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "Предишен" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Предишен запис" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Следващ" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Следващ запис" #: tryton/gui/window/tabcontent.py:59 #, fuzzy msgid "_Search" msgstr "Търсене" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "Нов" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Създаване на нов запис" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "Съхраняване" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Съхраняване на този запис" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Презареждане/Обратно" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Презареждане/Обратно" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "Дублиране" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Изтриване..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Преглед на логове" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 #, fuzzy msgid "A_ttachments..." msgstr "Прикачен файл:" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Добавяне на прикачен файл към записа" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "Действия..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "Свързани..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "Справки..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "Email..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "Печат..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Извличане на данни..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Вмъкване на данни..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Затваряне на таб" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Всички полета" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Изчистване" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV параметри" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Кодиране:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Име на поле" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Извличане в CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Предварително зададени извличания" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Име" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Запис на извличане" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Изтриване на извличане" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Отваряне" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Съхраняване" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Добавяне на имена на полета" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Какво е името на това извличане?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d заспис съхранен!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d записа съхранени!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Операцията неуспешна!\n" "Съобщение за грешка:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Връзка" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Добавяне" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Изтриване " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Създаване на нов запис " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Изтриване на избрания запис " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Възтановяване на избрания запис " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Предишен" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Следващ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Превключване" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Вмъкване от CSV" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Автоматично разпознаване" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Файл за вмъкване:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Отваряне..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Редове за пропускане:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Първо трябва да изберете файл за вмъкване!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Грешка при отваряне на CSV файл" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Грешка при обработка на файл при поле %s" #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d запис вмъкнат!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d записи вмъкнати!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Помощник" #: tryton/gui/window/view_form/screen/screen.py:194 #, fuzzy msgid "ID" msgstr "д" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "Потребител създал:" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "Дата на създаване:" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "Дата на последна промяна:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "Дата на последна промяна:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "Не може да зададе локални настройки %s" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "Не може да зададе локални настройки %s" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Размер на изображение" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Ширина:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Височина:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG изображение (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Запис като" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Размера на изображението е много голям!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Търсене" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "Тяло:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "Превключване на изглед" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "Превключване на изглед" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Изчистване" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Всички файлове" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Показване само на текст" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Изображения" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 #, fuzzy msgid "Add existing record" msgstr "Съхраняване на този запис" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 #, fuzzy msgid "Remove selected record " msgstr "Изтриване на избрания запис " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Отваряне на запис" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Тъсене на запис" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 #, fuzzy msgid "Remove selected record" msgstr "Изтриване на избрания запис " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Редактиране на избрания запис" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 #, fuzzy msgid "Translation" msgstr "Добавяне на превод" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Редактиране" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Неясно" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Трябва да съхраните записа преди да добавите преводи!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Няма наличен друг език!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Превод на изглед" tryton-4.6.5/tryton/data/locale/bg/LC_MESSAGES/tryton.mo0000644000175000017500000004253313260723565022175 0ustar cedced00000000000000%D lm)r /&7 >IM^w  #% ,;AP eqvz&   !) ?Lf ~(7F X bn   7GM dnt&       4?Sc hsy " 1!?agn}     $08LQ V bn     &0BH W bnw      &05 =HZk r|    )1K[m|I} k4     $ %? e }     ! ! '!4!6!:! J! T!`!e! m! x! ! !! ! ! ! ! !!!!!" ""3" D" Q"^"g"m"r" x"" """" " "" " "" "" # ##!#1#:#@#B#S# [#f# h## # ###<#$$$$$%)%%%%& &!&&&)& +&L&Gc&&E(V(g(x((2((C( -)7)FS)M)O)8*V*q* *** *****;*)5+_+t+++ +++ +,+1,], u,1,;,),.-%I--o-1-!-"-3.H. ].9i. ......//1/:/IQ/7///3/0 /06<0Gs00 00 001 1(1 11:>1y1&111 1 1182 G2Q2(U2~22:22.3'33([38333'3 4&!4!H4j4:m4 4 4 444 44 5 5%5-5A5H5W5q555 555 535"6$26W61k66"6 656 7(777J7]7n7!7 7*7 7 7$7 "8 08<8 M8Y8r88&8888859/H9x9 9B9/9:!:(: 7: B:!P: r:|: : ::+::& ;1;A;*Z;; < =e!== ==*== = = >>%8>D^>A>>8> 3?"@?c?"z? ??:? ? @ @(@+@/@E@W@k@ |@@@ @ @@@AA.A7A%@A fAqA A A#AA(AB&B@B WBbBiB xBB BBBBB B BB'C;CNC`C"wC*C CC$C D!D$D5D =DHD8KDD D DD?D<D4ESEUEXE of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationHost:ID:Image SizeImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:RelateRemove "%s"Remove Remove this bookmarkReportReport BugReport...SaveSave AsSave As...Save Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:Toggle rowToggle selectionToo much argumentsTranslate viewTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUndelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Options_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: bg Language-Team: bg Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 от"%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:Всички полетаFields selectedПредварително зададени извличанияПредупреждение при достъп за писане: Записът беше променен докато го редактирахте. Изберет: - "Отказ" за да откажете запис; - "Сравняване" за да видите променената версия; - "Запис " за да запишете вашата текуща версия.Create...Search...ДействиеДействия...ДобавянеДобавяне на имена на полетаAdd a note to the recordДобавяне на прикачен файл към записаAdd valueВсички файловеВинаги игнорирай това предупреждение.Наистина ли искате да изтриете този запис?Наистина ли искате да изтриете тези записи?Прикачен файл(%d)Прикачен файл:Прикачен файл:Тяло:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV параметриСвързванеОтказ от свръзване с Tryton сървъраСмяна на бързи клавишиИзчистванеClear the record Затваряне на табCollapse all rowsCollapse rowКоманден ред:СравняванеГрешка при достъпПотвърждениеСвързване с Tryton сървъраCopy URL into clipboardCopy _URL...Копиране на избрания текстНе може да се свърже със сървъра!Създаване на нов записСъздаване на нов запис Създаване на нов редСъздаване на нова връзкаСъздадена е нова грешка с IDДата на създаване:Потребител създал:Изрязване на избрания текстБаза данни:Date FormatИзтриване на избрания запис Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?EmailИзращане на справка по EmailEmail...РедактиранеРедактиране на потребителски настройкиРедактиране на избрания записEdition WidgetsEmailНастройки на програма за emailКодиране:ГрешкаГрешка при отваряне на CSV файлГрешка при обработка на файл при поле %sГрешка: Грешка:Expand all rowsExpand rowExpand/CollapseИзвличане в CSVFa_voritesЛъжаFast TabbingВземане на списъка с бази данни:Име на полеФайла "%s" не е намеренФайл за вмъкване:ТърсенеForegroundНеясноВисочина:Информация за Хост / База данниХост:ID:Размер на изображениеИзображенияВмъкване от CSVНесъвместима версия на сървъра!Бързи клавишиДата на последна промяна:Последно променен от:Започване на действиеЛагенда за налични контейнери:ОграничениеОграничение:Редове за пропускане:ВръзкаСписък бързи клавишиПотребителско имеМОтбелязване на ред за изтриванеМодел:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageИмеСледващСледващ записСледваща джаджаNo result found.Note(%d)Notes (%s)Notes...ОтварянеOpen filtersОтваряне на свързани записиОтваряне на връзкаОтваряне на справкаОтваряне...Отваряне/Търсене на връзкаOverride '%s' definition?PNG изображение (*.png)Парола:Поставяне на копирания текстПорт:Pre-validationНастройкиНастройкиПредишенПредишен записПредишенна джаджаПечатОтпечатване на справкаПечат...ПрофилРедактор на профилиПрофил:Quote char:СвързаниRemove "%s"Изтриване Remove this bookmarkСправкиСъобщаване за грешкаСправки...СъхраняванеЗапис катоЗапис като ...Запазване на ширина/височинаСъхраняване на този записТърсенеSearch %sНастройки на органичения за търсенеОграничение при търсене...Тъсене на записSelectSelect a colorSelect allSelect parentИзберете действиеSelect...Select/Activate current rowИзбор:Сървър:Show bookmarks of filtersПоказване само на текстShow revisions...Проверка на правописОтносно:ПревключванеТекстови бързи клавишиСледващите действия изискват затваряне на всички прозорци. Искате ли да продължите?Тази грешка е вече съобщена от друг потребител.. За да бъдете информирани потребителя ви е добавен списъка за този проблемThe values of "%s" are not validЗа да съобщите за грешка трябва да имате сметка на %sДоToggle rowToggle selectionТвърде много аргументиПревод на изгледTree viewИстинаTryton връзкаUnable to delete wizard %sUnable to search for completion of %sНе може да зададе локални настройки %sВъзтановяване на избрания запис НеизвестенИзчистване на ред за изтриванеUnselect allПотребителско име:Потребител: Потребителско име:Преглед на логовеWeekКакво е името на това извличане?Ширина:ПомощникЗаписГYesВашия изборОтносно...Действия...ДобавянеОтказЗатваряне на табСвързване..._Connection_Copy URLПо подразбиранеИзтриване...ИзключванеДублиранеEmail...Email...Извличане на данни...Форма_Global SearchПомощИкониВмъкване на данни...Бързи клавиши...Управление на профилиПрезарежданеПревключване на менюЛента с менюРежимНовСледващ_Next TabНормален_Notes...НастройкиPDAПредпочитания...ПредишенПечат...Изход...Свързани...Презареждане/ОбратноИзтриванеСправки...СъхраняванеЗапазване на опцииПревключване на изгледТекстТекс и икониЛента с инструментиПотребителдdevelopment modego backgo forwardчзаписване на всичко на ниво INFO мnext yearprevious yearsукажете друг конфигурационен файлspecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALукажете потребителското имеtсгtryton-4.6.5/tryton/data/locale/sl/0000755000175000017500000000000013260723567016535 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/sl/LC_MESSAGES/0000755000175000017500000000000013260723567020322 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/sl/LC_MESSAGES/tryton.po0000644000175000017500000010637413255571102022222 0ustar cedced00000000000000# Slovenian (Slovenia) translations for tryton. # Copyright (C) 2010 B2CK # This file is distributed under the same license as the tryton project. # Venceslav Vezjak , 2010. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "določi alterntivno konfiguracijsko datoteko" #: tryton/config.py:73 msgid "development mode" msgstr "Razvijalski način" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "beleženje vsega na INFO ravni" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "določi nivo beleženja: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "določi uporabniško ime" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "določi strežniškega gostitelja" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Preveč argumentov" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Datoteke \"%s\" ni moč najti" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "Ni možno zapisati konfiguracijske datoteke %s." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Ni možno nastaviti krajevnih nastavitev %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" # ? #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Izberi ukrep" #: tryton/action/main.py:197 msgid "No action defined." msgstr "Nobenega ukrepa ni določenega." #: tryton/common/button.py:56 msgid "By: " msgstr "Od: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton povezava" #: tryton/common/common.py:250 msgid "Server:" msgstr "Strežnik:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Vrata:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Izbira" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Vaša izbira:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Shrani kot..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Vedno prezri to opozorilo." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Ali želite nadaljevati?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Potrditev" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Izjema sočasnega izvajanja" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Opozorilo sočasnega zapisovanja:\n" "\n" "Ta zapis je bil spremenjen med vašim popravljanjem.\n" " Izberite:\n" " - \"Prekliči\" za preklic shranjevanja;\n" " - \"Primerjaj\" za vpogled v spremenjeno inačico;\n" " - \"Vseeno zapiši\" za shranitev vaše trenutne inačice." #: tryton/common/common.py:766 msgid "Compare" msgstr "Primerjaj" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Vseeno zapiši" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Napaka" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Prijava programske napake" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Napaka programa." #: tryton/common/common.py:832 msgid "Error: " msgstr "Napaka: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Za prijavo programskih napak morate imeti odprt račun pri %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Sledilnik programskih napak" #: tryton/common/common.py:899 msgid "User:" msgstr "Uporabnik:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Geslo:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Drugi uporabnik je že prijavil enako programsko napako.\n" "Zaradi obveščanja je vaše uporabniško ime dodano na seznam te programske napake" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Evidentirana je nova programska napaka z ID " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Napaka pri povezavovanju.\n" "Napačno uporabniško ime ali geslo." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Izjema:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Prstni odtis strežnika se je spremenil od zadnje povezave.\n" "Program bo ustavil povezovanje na ta strežnik, dokler ne bo njegov prstni odtis popravljen." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Varnostno tveganje." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Napaka pri povezovanju.\n" "Ni se možno povezati na strežnik." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Napaka mreže." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Išči..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Ustvari..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Vrednost" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Prikazana vrednost" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Oblika" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Oblika prikaza" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Odpri koledar" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Oblika datuma" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Prikazana oblika datuma" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "d" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Da" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Da" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "t" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Ne" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Uredi ..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Priponke..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Zabeležke ..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "_Ukrepi..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "_Veze..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Poročila..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "_Elektronska pošta..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "_Izpis..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "l" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "t" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "u" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "Po_vezava" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Uporabnik" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Možnosti" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "P_riljubljeno" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Pomoč" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Išči" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Brez rezultatov." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Poveži..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Pre_kini povezavo" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Izhod..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Nastavitve..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Ponovno naloži meni" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "_Preklopi meni" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "_Globalno iskanje" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Orodna vrstica" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Privzeto" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Bese_dilo in ikone" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Ikone" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Besedilo" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Menu vrstica" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Spremeni bližnjice" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Način" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Navaden" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "O_brazec" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Shrani širino/višino" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Shrani stanje drevesa" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Hitri premik" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Črkovanje" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "P_rejšnji zavihek" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_Naslednji zavihek" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Omejitev iskanja..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Epošta..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Shrani možnosti" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Bližnjice na tipkovnici..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Vizitka..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "_Upravljaj zaznamke" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Za naslednji ukrep morajo biti vsi zavihki zaprti.\n" "Ali želite nadaljevati?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Zapri zavihek" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Priponke (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Urejevalnik profilov" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Dodaj" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Odstrani" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Strežnik:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Podatkovna baza:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Pridobivanje seznama podatkovnih baz" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Uporabniško ime:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Nezdružljiva inačica strežnika" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Ni se možno povezati s strežnikom" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Prijava" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Prekliči" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Prekliči povezavo do Tryton strežnika" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "P_oveži" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Poveži se s Tryton strežnikom" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Upravljaj profile" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Strežnik in podatkovna baza" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Uporabnik:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Epošta" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Nastavitve poštnega odjemalca" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Ukazna vrstica:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Opis možnih prostornikov:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Za:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "Kp:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Zadeva:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Vsebina:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Priponka:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Priponka(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Zabeležka(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "En zapis mora biti izbran." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Ustvaril:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Ustvarjeno:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Nazadnje popravil:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Nazadnje popravljeno:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Model:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Ali res želiš izbrisati ta zapis?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Ali res želiš izbrisati te zapise?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Zapisi niso izbrisani." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Zapisi izbrisani." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Trenutno se dela na podvojenih zapisih." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Zapis shranjen." #: tryton/gui/window/form.py:423 msgid " of " msgstr " od " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Ta zapis je bil spremenjen,\n" "ga želiš shraniti?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Ukrep" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Zaženi ukrep" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Veza" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Odpri vezo" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Poročila" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Odpri poročilo" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Pošlji" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Pošlji poročilo" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Tisk" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Izpis poročila" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_Kopirak URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Kopiraj URL na odložišče" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Neznano" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Omejitev" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Nastavitev omejitev iskanja" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Omejitev:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Zabeležke (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Nastavitve" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Uredi uporabniške nastavitve" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Nastavitev" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Različica" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Izberi različico" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Različica:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Bližnjice" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Bližnjice za urejanje" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Izreži vsebino" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Kopiraj vsebino" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Prilepi vsebino" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Naslednje polje" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Prejšnje polje" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Bližnjice za veze" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Dodajanje nove veze" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Urejanje/iskanje veze" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Bližnjice za postavke" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Dodajanje postavke" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Urejenje postavke" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Postavka označena za brisanje" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Postavka neoznačena za brisanje" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Vnašanje podatkov" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Premiki" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Premik desno" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Premik levo" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Premik gor" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Premik dol" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Premik za eno stran gor" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Premik za eno stran dol" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Premik na začetek" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Premik na konec" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Premik na nadrejeno vejo" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Izberi vse" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Odznači vse" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Izberi nadrejeno vejo" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Izberi/Aktiviraj trenutno vrstico" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Vklopi/Izklopi izbor" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Razširi/Skrči" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Razširi vrstico" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Skrči vrstico" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Razširi/Skrči vrstico" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Skrči vse vrstice" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Razširi vse vrstice" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Drevesni pogled" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Preklopi po_gled" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Preklopi po_gled" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "P_rejšnji" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Prejšnji zapis" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Nas_lednji" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Naslednji zapis" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Išči" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nov" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Ustvari nov zapis" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Shrani" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Shrani ta zapis" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Ponovno naloži/Razvel_javi" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Ponovno naloži/Razvel_javi" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Podvoji" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Z_briši..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Poglej dnevni_k..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Prikaži različice ..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "P_riponke..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Dodaj priponko zapisu" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Zabeležke ..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "K zapisu dodaj zabeležko" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Ukrepi..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Veze..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "P_oročila..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_Elektronska pošta..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Tiskaj..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "I_zvozi podatke..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Uv_ozi podatke..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "_Kopiraj URL ..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Zapri zavi_hek" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Vsa polja" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Počisti" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Izbrana polja" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV parametri" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Ločilo:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Narekovaj:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Kodiranje:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Naziv polja" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Izvozi v CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Predefinirani izvozi" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Naziv" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_Shrani izvoz" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_Izbriši izvoz" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Odpri" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Shrani" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Dodaj imena _polj" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (niz)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Kako se imenuje ta izvoz?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Prepišem definicijo izvoza '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "%d zapis shranjen." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "%d zapisov shranjenih." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Operacija odpovedala.\n" "Sporočilo napake:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Povezava" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Dodaj" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Odstrani " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Ustvari nov zapis " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Zbriši izbran zapis " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Povrni izbran zapis " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Prejšnji" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Naslednji" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Preklopi" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Uvozi iz CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "_Samozaznava" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Datoteka za uvoz:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Odpri..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Izpuščene vrstice:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Najprej morate izbrati datoteke za uvažanje." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Napaka pri odpiranju CSV datoteke" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Napaka obdelave datoteke pri polju %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "%d zapis uvožen." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "%d zapisov uvoženih." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Išči %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Čarovnik" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Ustvaril" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Ustvarjeno" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Popravil" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Popravljeno" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Ni možno nastaviti stanja obrazca" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "Polje \"%s\" ni veljavno glede na svojo domeno" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "Polje \"%s\" je obvezno" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Vrednosti v polju \"%s\" niso veljavne" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Predpreverjanje" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Velikost slike" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Širina:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Velikost:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG slika (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Shrani kot" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "Slika je prevelika." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Odpri filtre" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Prikaži zaznamke filtrov" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Odstrani ta zaznamek" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Shrani ta filter" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Ime zaznamka:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Najdi" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Danes" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "pojdi nazaj" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "pojdi naprej" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "Prejšnje leto" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "naslednje leto" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Tedensko" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Mesečno" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Teden" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Izberi ..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Počisti" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Vse datoteke" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Izberi" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Prikaži navadno besedilo" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Dodaj vrednost" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Odstrani \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Slike" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Dodaj obstoječi zapis" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Odstrani izbran zapis " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Odpri zapis " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Počisti zapis " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Poišči zapis " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Odstrani izbran zapis" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Uredi izbran zapis " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Ospredje" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Izberi barvo" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Prevod" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Uredi" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Nejasno" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "Pred dodajanjem prevodov morate zapis shraniti." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "Drugih jezikov ni na voljo." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Prevedi pogled" tryton-4.6.5/tryton/data/locale/sl/LC_MESSAGES/tryton.mo0000644000175000017500000004376613260723565022234 0ustar cedced00000000000000a$ ,-)2\m -G->O_ fqu  #%:` o{ &-3 JT f s +2% =J]}  ! 3 =I fq  *0 GQW&n      "6F KV]ck " 4!Bdjq     . = J Y g s {       ! !!! #!0! E! S!_!q!!!#!!! !!"" $" /";"D"T"d" j"w"""" " """" "" # #%#<#Y#n# u# ## ### ##### ##$$4$C$J$Y$ k$ v$$ $$ $$$$$ %%#%*%IA%}% & &5&4&#''' -'8'I'\' k' w''''$'%''(4(T(s({( ( (( (( (( ( ())() 7)D)F)J)%i)7)) ) )) ))* * * %* 1*;*D* S* ^* j* u* ********* * ++++"+ (+2+ :+D+M+R+ b+ l+ z++ + ++ ++ + ++ +++, ,,,&, .,9, ;,\, ^, h,v,x,<,,,,,,.,... //5/L/T/d/u/~//////////00 1 1 11$161P1f1}1 111#1$1 2 2 %2 32?2 H2V2g222 22'2222 2 33-3 =3G3 c3m3>3;34$454#E4i4{444,4 4 44 55 5 15?5Z5c5r55555555 6 #6-6@6H6 g6r6!y6&666666 7 7$7 '7$47 Y7e777777 77 77777 8 8! 8 B8M8c8 v888 88888889$9 +979@9I9 Q9\9t9 99 99 9999 : ::+:K:g:x:::: : ::: ::;;+$;!P;r;;;;; ; ; ;;;;; <<<-< 5<@<P<g<y<~<< <<<<< <= "= /= :=F= M= X=f=|=== ===== > > > 2>=> S> `>!k>> >>>> >>>?K?j??$@0@D@+A/A5AMAbAuAAAAAA$A%A+B"@B/cBBB B B B BB CC'C-C6CPC YC'cCCCCC-C/C D &D 2D=D DD QD \DfD uD D D DD DDDD DDEE*E2E9EKEhE{EE EEE EEEE EEF FF /F :FDFMF iF sFF FFFF FFF FFF G G(G*GIGKGZGiG,kG>GGGGG of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: sl Language-Team: sl Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 od Polje "%s" ni veljavno glede na svojo domenoPolje "%s" je obvezno%d zapis uvožen.%d zapis shranjen.%d zapisov uvoženih.%d zapisov shranjenih.%s (%s)%s (model name)%s (record name)%s (niz)%s%%, ,….....:Vsa poljaIzbrana poljaPredefinirani izvoziOpozorilo sočasnega zapisovanja: Ta zapis je bil spremenjen med vašim popravljanjem. Izberite: - "Prekliči" za preklic shranjevanja; - "Primerjaj" za vpogled v spremenjeno inačico; - "Vseeno zapiši" za shranitev vaše trenutne inačice.Ustvari...Išči...P_riponke...Ukrep_Ukrepi...DodajDodaj imena _poljK zapisu dodaj zabeležkoDodaj priponko zapisuDodaj obstoječi zapisDodaj vrednostVse datotekeVedno prezri to opozorilo.Napaka programa.Ali res želiš izbrisati ta zapis?Ali res želiš izbrisati te zapise?Priponka(%d)Priponka:Priponke (%s)Priponke...Vsebina:Ime zaznamka:Shrani ta filterSledilnik programskih napakOd: Kp:CSV parametriP_ovežiPrekliči povezavo do Tryton strežnikaSpremeni bližnjicePočistiPočisti zapis Zapri zavihekSkrči vse vrsticeSkrči vrsticoUkazna vrstica:PrimerjajIzjema sočasnega izvajanjaPotrditevPoveži se s Tryton strežnikomNapaka pri povezavovanju. Napačno uporabniško ime ali geslo.Napaka pri povezovanju. Ni se možno povezati na strežnik.Kopiraj URL na odložišče_Kopiraj URL ...Kopiraj vsebinoNi se možno povezati s strežnikomUstvari nov zapisUstvari nov zapis Dodajanje postavkeDodajanje nove vezeEvidentirana je nova programska napaka z ID UstvarjenoUstvarjeno:UstvarilUstvaril:Izreži vsebinoPodatkovna baza:Oblika datumaZbriši izbran zapis Ločilo:Oblika prikazaPrikazana oblika datumaPrikazana vrednostAli želite nadaljevati?PošljiPošlji poročilo_Elektronska pošta...UrediUredi uporabniške nastavitveUredi izbran zapis Uredi ...Vnašanje podatkovEpoštaNastavitve poštnega odjemalcaKodiranje:NapakaNapaka pri odpiranju CSV datotekeNapaka obdelave datoteke pri polju %s.Napaka: Izjema:Razširi vse vrsticeRazširi vrsticoRazširi/SkrčiIzvozi v CSVP_riljubljenoNeHitri premikPridobivanje seznama podatkovnih bazNaziv poljaDatoteke "%s" ni moč najtiDatoteka za uvoz:NajdiOspredjeOblikaNejasnoVelikost:Strežnik in podatkovna bazaStrežnik:IDID:Velikost slikeSlika je prevelika.SlikeUvozi iz CSVNezdružljiva inačica strežnikaBližnjiceNazadnje popravljeno:Nazadnje popravil:Zaženi ukrepOpis možnih prostornikov:OmejitevOmejitev:Izpuščene vrstice:PovezavaBližnjice za postavkePrijavaM_Upravljaj zaznamkePostavka označena za brisanjeModel:PopravljenoPopravilMesečnoPremikiPremik dolPremik za eno stran dolPremik na konecPremik levoPremik na nadrejeno vejoPremik desnoPremik na začetekPremik gorPremik za eno stran gorNazivNapaka mreže.NaslednjiNaslednji zapisNaslednje poljeNobenega ukrepa ni določenega.Drugih jezikov ni na voljo.Brez rezultatov.Zabeležka(%d)Zabeležke (%s)Zabeležke ...OdpriOdpri filtreOdpri vezoUrejenje postavkeOdpri poročiloOdpri koledarOdpri zapis Odpri...Urejanje/iskanje vezeOperacija odpovedala. Sporočilo napake: %sPrepišem definicijo izvoza '%s'?PNG slika (*.png)Geslo:Prilepi vsebinoVrata:PredpreverjanjeNastavitevNastavitvePrejšnjiPrejšnji zapisPrejšnje poljeTiskIzpis poročila_Izpis...ProfilUrejevalnik profilovProfil:Narekovaj:Zapis shranjen.Zapisi niso izbrisani.Zapisi izbrisani.Veza_Veze...Bližnjice za vezeOdstrani "%s"Odstrani Odstrani izbran zapisOdstrani izbran zapis Odstrani ta zaznamekPoročilaPrijava programske napakePoročila...RazličicaRazličica:ShraniShrani kotShrani kot...Shrani stanje drevesaShrani širino/višinoShrani ta zapisIščiIšči %sNastavitev omejitev iskanjaOmejitev iskanja...Poišči zapis Varnostno tveganje.IzberiIzberi barvoIzberi različicoIzberi vseIzberi nadrejeno vejoIzberi ukrepIzberi ...Izberi/Aktiviraj trenutno vrsticoIzbiraStrežnik:Prikaži zaznamke filtrovPrikaži navadno besediloPrikaži različice ...ČrkovanjeZadeva:PreklopiBližnjice za urejanjeZa naslednji ukrep morajo biti vsi zavihki zaprti. Ali želite nadaljevati?Drugi uporabnik je že prijavil enako programsko napako. Zaradi obveščanja je vaše uporabniško ime dodano na seznam te programske napakePrstni odtis strežnika se je spremenil od zadnje povezave. Program bo ustavil povezovanje na ta strežnik, dokler ne bo njegov prstni odtis popravljen.Vrednosti v polju "%s" niso veljavneTa zapis je bil spremenjen, ga želiš shraniti?Za prijavo programskih napak morate imeti odprt račun pri %sZa:DanesRazširi/Skrči vrsticoVklopi/Izklopi izborPreveč argumentovPrevedi pogledPrevodDrevesni pogledDaTryton povezavaUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sNi možno nastaviti krajevnih nastavitev %sNi možno nastaviti stanja obrazcaNi možno zapisati konfiguracijske datoteke %s.Povrni izbran zapis NeznanoPostavka neoznačena za brisanjeOdznači vseUporabnik:Uporabnik:Uporabniško ime:VrednostPoglej dnevni_k...TedenTedenskoKako se imenuje ta izvoz?Širina:ČarovnikTrenutno se dela na podvojenih zapisih.Vseeno zapišilDaEn zapis mora biti izbran.Najprej morate izbrati datoteke za uvažanje.Pred dodajanjem prevodov morate zapis shraniti.Vaša izbira:_Vizitka..._Ukrepi..._Dodaj_Samozaznava_Prekliči_PočistiZapri zavi_hek_Poveži...Po_vezava_Kopirak URL_Privzeto_Izbriši izvozZ_briši...Pre_kini povezavo_Podvoji_Elektronska pošta..._Epošta...I_zvozi podatke...O_brazec_Globalno iskanje_Pomoč_IkoneUv_ozi podatke..._Bližnjice na tipkovnici..._Upravljaj profile_Ponovno naloži meni_Preklopi meni_Menu vrstica_Način_NovNas_lednji_Naslednji zavihek_Navaden_Zabeležke ..._Možnosti_PDA_Nastavitve...P_rejšnjiP_rejšnji zavihek_Tiskaj..._Izhod..._Veze...Ponovno naloži/Razvel_javi_OdstraniP_oročila..._Shrani_Shrani izvoz_Shrani možnosti_IščiPreklopi po_gled_BesediloBese_dilo in ikone_Orodna vrstica_UporabnikdRazvijalski načinpojdi nazajpojdi naprejubeleženje vsega na INFO ravnimnaslednje letoPrejšnje letosdoloči alterntivno konfiguracijsko datotekodoloči nivo beleženja: DEBUG, INFO, WARNING, ERROR, CRITICALdoloči uporabniško imettdtryton-4.6.5/tryton/data/locale/ca/0000755000175000017500000000000013260723567016502 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ca/LC_MESSAGES/0000755000175000017500000000000013260723567020267 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ca/LC_MESSAGES/tryton.po0000644000175000017500000011011013255571102022146 0ustar cedced00000000000000# Catalan translations for tryton. # Copyright (C) 2012 Zikzakmedia SL # This file is distributed under the same license as the tryton project. # Sergi Almacellas Abellana 2012. # Jordi Esteve Cusiné 2012. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "Indica un fitxer de configuració alternatiu" #: tryton/config.py:73 msgid "development mode" msgstr "mode desenvolupament" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "Registra tota la informació amb nivell INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "indica el nivell de log: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "Indica l'usuari" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "Indica el nom:port del servidor" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Massa arguments" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "No s'ha trobat el fitxer \"%s\"" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "No s'ha pogut escriure el fitxer configuració %s" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "No s'ha pogut establir l'idioma %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Seleccioneu la vostra acció" #: tryton/action/main.py:197 msgid "No action defined." msgstr "No s'ha definit cap acció." #: tryton/common/button.py:56 msgid "By: " msgstr "Per: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Connexió a Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Servidor:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Selecció" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "La vostra selecció:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Desa com..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Ignora sempre aquest advertiment." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Voleu continuar?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Confirmació" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Excepció de concurrència" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Avís de concurrència d'escriptura:\n" "\n" "Aquest registre ha estat modificat mentre l'editàveu.\n" " Trieu:\n" " - \"Cancel·la\" per no desar;\n" " - \"Compara\" per veure la versió modificada;\n" " - \"Desa de totes formes\" per desar els vostres canvis." #: tryton/common/common.py:766 msgid "Compare" msgstr "Compara" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Desa de totes formes" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Error" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Informa de l'error" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Error d'aplicació." #: tryton/common/common.py:832 msgid "Error: " msgstr "Error: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Per informar d'errors heu de tenir un compte a %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Seguiment d'errors" #: tryton/common/common.py:899 msgid "User:" msgstr "Usuari:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Contrasenya:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "El mateix error ja ha estat notificat per un altre usuari.\n" "Per mantenir-vos informat afegirem el vostre usuari a la llista d'interessats en aquest assumpte." #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "S'ha creat una nou informe d'error amb l'identificador " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Error de connexió.\n" "Nom d'usuari o contrasenya incorrectes." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Excepció:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "L'empremta digital del servidor ha canviat des de l'última connexió.\n" "L'aplicació no es podrà connectar amb aquest servidor fins que es corregeixi l'empremta digital del servidor." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Risc de seguretat." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Error de connexió.\n" "No ha estat possible connectar amb el servidor." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Error de xarxa." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Cerca..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Crea..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "No es pot buscar l'autocompletat de %s" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Valor" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Valor a mostrar" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Format" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Format a mostrar" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Obre el calendari" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Format dates" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Format dates a mostrar" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "a" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Si" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Verdader" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "v" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Fals" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Edita..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Adjunts..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notes..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Accions..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Relacionat..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Informe..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "Correu electrònic..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Imprimeix..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "A" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "S" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_Conexió" #: tryton/gui/main.py:222 msgid "_User" msgstr "U_suari" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Opcions" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "_Preferits" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Aj_uda" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Cerca" #: tryton/gui/main.py:372 msgid "No result found." msgstr "No s'han trobat resultats." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Connecta..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Desconnecta" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Surt..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Preferències..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Recarrega el menú" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Commuta el _menú" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Cerca _Global" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Barra d'_eines" #: tryton/gui/main.py:502 msgid "_Default" msgstr "Per _defecte" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Text _i icones" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Icones" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Text" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "Barra de _menú" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Canvia tecles ràpides" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Mode" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Formulari" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Desa ample/alt" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Desa l'estat de l'arbre" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Tabulació ràpida" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Correcció ortogràfica" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Anterior" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_Següent" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "_Límit de cerca..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Correu electrònic..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Desa opcions" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Com_binacions de tecles..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Quant a..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "_Gestiona els favorits" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "L'acció seleccionada requereix tancar totes les pestanyes.\n" "Voleu continuar?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Tanca pestanya" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Adjunts (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Editor de perfils" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Perfil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Afegeix" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Elimina" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Servidor:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Base de dades:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Recuperant llista de bases de dades" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Nom d'usuari:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "El client no és compatible amb la versió del servidor" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "No ha estat possible connectar amb el servidor" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Usuari" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Cancel·la" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Cancel·la connexió amb el servidor Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "C_onnecta" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Connecta amb el servidor Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Perfil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Administra perfils" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Informació del Servidor / Base de dades" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Nom d'usuari:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Correu electrònic" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Configuració del programa de correu electrònic" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Línia de comandes:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Llegenda de paraules clau disponibles:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "A:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Assumpte:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Missatge:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Adjunt:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Adjunt(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Nota(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Heu de triar un registre." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "Identificador:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Creat per:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Data creació:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Última modificació per:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Última data de modificació:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Model:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Esteu segur que voleu eliminar aquest registre?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Esteu segur que voleu eliminar aquests registres?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Els registres no s'han eliminat." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Registres eliminats." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Ara esteu treballant en el registre duplicat." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Registre desat." #: tryton/gui/window/form.py:423 msgid " of " msgstr " de " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Aquest registre ha estat modificat.\n" "Voleu desar-lo?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Acció" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Executa acció" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "_Relacionat" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Obre registres relacionats" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Informes" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Obre informe" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Correu electrònic" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Informe per email" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Imprimeix" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Imprimeix informe" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_Copia l'URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Copia l'URL al porta-retalls" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Desconegut" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Límit" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Preferències del límit de cerca" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Límit:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notes (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Preferències" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Edita preferències d'usuari" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Preferències" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Revisió" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Seleccioneu una revisió" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Revisió:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Combinacions de tecles" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Dreceres en camps de text" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Talla el text seleccionat" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Copia el text seleccionat" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Enganxa el text seleccionat" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Camp següent" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Camp anterior" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Dreceres en relacions" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Crea una nova relació" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Obre/Cerca una relació" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Dreceres en llistes" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Crea una nova línia" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Obre una relació" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Marca la línia per ser eliminada" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Desmarca la línia per ser eliminada" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Controls en l'edició" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Mou cursor" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Mou a la dreta" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Mou a l'esquerra" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Mou amunt" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Mou avall" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Mou amunt una pàgina" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Mou avall una pàgina" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Mou al principi" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Mou al final" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Mou al pare" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Selecciona tot" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Deselecciona tot" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Selecciona pare" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Selecciona/Activa fila actual" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Commuta selecció" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Expandeix/Contrau" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Expandeix fila" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Contrau fila" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Commuta fila" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Contrau totes les files" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Expandeix totes les files" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Vista d'arbre" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Canvia la vi_sta" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "Canvia la vista" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Anterior" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Registre anterior" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Seg_üent" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Registre següent" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Cerca" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nou" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Crea un nou registre" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Desa" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Desa aquest registre" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_Recarrega/Desfés" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "Recarrega/Desfés" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplica" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Elimina..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Veure _registre..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Mostra revisions..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "Adjun_ts..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Afegeix un adjunt al registre" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Notes..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Afegeix una nota al registre" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Accions..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Relacionat..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Informes..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_Correu electrònic..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "Im_primeix..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Exporta dades..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importa dades..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "Copia l'_URL..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Tanca la pestanya" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Tots els camps" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Neteja" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Camps seleccionats" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Paràmetres CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Separador:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Delimitador de text:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codificació:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nom del camp" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exporta a CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Exportacions predeterminades" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nom" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_Desa exportació" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_Elimina exportació" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Obre" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Desa" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Afegeix noms de _camp" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (text)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "%s (nom del model)" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "%s (nom del registre)" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Quin és el nom d'aquesta exportació?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Voleu sobreescriure la definició de '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "S'ha desat %d registre." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "S'han desat %d registres." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Ha fallat l'operació.\n" "Missatge d'error:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Enllaç" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Afegeix" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Elimina " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Crea un nou registre " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Elimina el registre seleccionat " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Recupera el registre seleccionat " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Anterior" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Següent" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Canvia la vista" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importa des de CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "Detecta _automàticament " #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Fitxer a importar:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Obre..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Línies a ometre:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Primer heu de seleccionar un fitxer a importar." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Error a l'obrir el fitxer CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "S'ha produït un error en processar el fitxer en el camp %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "S'ha importat %d registre." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "S'han importat %d registres." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Cerca %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "No s'ha pogut eliminar l'assistent %s" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Assistent" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Creat per" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Data de creació" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Modificat per" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Data de modificació" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, python-format msgid "Unable to get view tree state for %s" msgstr "No s'ha pogut obtenir l'estat de la vista d'arbre de %s" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "No s'ha pogut desar l'estat de la vista d'arbre" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" no és vàlid segons el seu domini." #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "\"%s\" és obligatori." #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Els valors de \"%s\" no són vàlids." #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Prevalidació" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Mida de la imatge" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Amplada:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Altura:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "Imatge PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Anomena i desa" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "La mida de la imatge és massa gran." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Obre filtres" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Mostra les cerques preferides" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Elimina de les cerques preferides" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Desa com a cerca preferida" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Nom de la cerca preferida:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Cerca" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Avui" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "vés enrere" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "vés endavant" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "any anterior" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "l'any següent" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Vista setmanal" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Vista mensual" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Setmana" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Selecciona..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Neteja" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Tots els fitxers" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Selecciona" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Mostra com a text pla" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Afegeix un valor" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Eliminar \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Imatges" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Afegeix un registre existent" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Elimina el registre seleccionat " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Obre el registre " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Eliminar el registe " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Cerca un registre " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Elimina el registre seleccionat" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Edita registre seleccionat " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Primer pla" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Seleccioneu un color" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Traducció" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Edita" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Dubtosa" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "Heu de desar el registre abans d'afegir traduccions." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "No hi ha cap altre idioma disponible." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Tradueix la vista" tryton-4.6.5/tryton/data/locale/ca/LC_MESSAGES/tryton.mo0000644000175000017500000004543113260723565022170 0ustar cedced00000000000000d< \])b #&+.24F]w]n   3#F%j   &"I]c z   +2"U mz % 4BQ c my    (BJZ` w&     "/ GRfv { "2L d!r  ' 2 > H ^ m z       ! !1! :!E!N! S!`! u! !!!!!#!!" #"-"?"E" T" _"k"t""" """"" " """# #!# <# H# T#a#x### # ## ### ##$$$$ +$5$K$[$p$$$$ $ $$ $$ $% %%%5%G%V%_% f%r%I%}%Q& &5'46'k'o' u'''' ' ''''$'% (F(^(|(((( ( (( () )) ) ')H)O)(V) ))))%)7)* * )*5* :*G*O* V* a* m* y*** * * * * ******++++ <+ I+V+_+e+j+ p+z+ ++++ + + ++ + ++ +, , ,!, ),6,<,L,U,[,],n, v,, ,, , ,,,<,- 2-S-U-W-Y-.(./*/E/]/z//// /////////#09001?1 O1[1 b1m1u111111!2'2/;21k2 22 2 2 22233!3%3 53+?3k33333 3333 44;;4Cw4444.515F5`5u57555 5 556 "6&/6 V6a6r666666667(717G70Z7 777<77 8 8'868 H8 V8a8f8#y8 8888 8888(9 ,96999H9$Z9997999:!:&0:W:^:f:x:::::!::: : ; ; ;#; 9;F; W;c;r; ;;;;;; ;;%;!<<< E<P<Y< ^<k<< <<<<<+<*=D= W=d== = = === = == => >>#>8> H>i> ~> >>> >>>&>!$?F?O? b?m? v??? ??????!? @!@8@ K@V@k@@@@ @@ @ @AA4AHA `AjAzAALAAB#EC3iC8CCC CCC D D *D8DAD%TD7zD&D"D/D1,E&^E E$EE EE EEEF F&FAF JF-TFFFFF/F4FG 0G ILIUIdIwI III IIIIIIIII J J(J,*JWJYJ hJuJ,wJ>JJJKKK of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: ca Language-Team: ca Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 de "%s" no és vàlid segons el seu domini."%s" és obligatori.S'ha importat %d registre.S'ha desat %d registre.S'han importat %d registres.S'han desat %d registres.%s (%s)%s (nom del model)%s (nom del registre)%s (text)%s%%, ,….....:Tots els campsCamps seleccionatsExportacions predeterminadesAvís de concurrència d'escriptura: Aquest registre ha estat modificat mentre l'editàveu. Trieu: - "Cancel·la" per no desar; - "Compara" per veure la versió modificada; - "Desa de totes formes" per desar els vostres canvis.Crea...Cerca...Adjun_ts...AccióAccions...AfegeixAfegeix noms de _campAfegeix una nota al registreAfegeix un adjunt al registreAfegeix un registre existentAfegeix un valorTots els fitxersIgnora sempre aquest advertiment.Error d'aplicació.Esteu segur que voleu eliminar aquest registre?Esteu segur que voleu eliminar aquests registres?Adjunt(%d)Adjunt:Adjunts (%s)Adjunts...Missatge:Nom de la cerca preferida:Desa com a cerca preferidaSeguiment d'errorsPer: CC:Paràmetres CSVC_onnectaCancel·la connexió amb el servidor TrytonCanvia tecles ràpidesNetejaEliminar el registe Tanca pestanyaContrau totes les filesContrau filaLínia de comandes:ComparaExcepció de concurrènciaConfirmacióConnecta amb el servidor TrytonError de connexió. Nom d'usuari o contrasenya incorrectes.Error de connexió. No ha estat possible connectar amb el servidor.Copia l'URL al porta-retallsCopia l'_URL...Copia el text seleccionatNo ha estat possible connectar amb el servidorCrea un nou registreCrea un nou registre Crea una nova líniaCrea una nova relacióS'ha creat una nou informe d'error amb l'identificador Data de creacióData creació:Creat perCreat per:Talla el text seleccionatBase de dades:Format datesElimina el registre seleccionat Separador:Format a mostrarFormat dates a mostrarValor a mostrarVoleu continuar?Correu electrònicInforme per emailCorreu electrònic...EditaEdita preferències d'usuariEdita registre seleccionat Edita...Controls en l'edicióCorreu electrònicConfiguració del programa de correu electrònicCodificació:ErrorError a l'obrir el fitxer CSVS'ha produït un error en processar el fitxer en el camp %s.Error: Excepció:Expandeix totes les filesExpandeix filaExpandeix/ContrauExporta a CSV_PreferitsFalsTabulació ràpidaRecuperant llista de bases de dadesNom del campNo s'ha trobat el fitxer "%s"Fitxer a importar:CercaPrimer plaFormatDubtosaAltura:Informació del Servidor / Base de dadesServidor:IDIdentificador:Mida de la imatgeLa mida de la imatge és massa gran.ImatgesImporta des de CSVEl client no és compatible amb la versió del servidorCombinacions de teclesÚltima data de modificació:Última modificació per:Executa accióLlegenda de paraules clau disponibles:LímitLímit:Línies a ometre:EnllaçDreceres en llistesUsuariM_Gestiona els favoritsMarca la línia per ser eliminadaModel:Data de modificacióModificat perVista mensualMou cursorMou avallMou avall una pàginaMou al finalMou a l'esquerraMou al pareMou a la dretaMou al principiMou amuntMou amunt una pàginaNomError de xarxa.SegüentRegistre següentCamp següentNo s'ha definit cap acció.No hi ha cap altre idioma disponible.No s'han trobat resultats.Nota(%d)Notes (%s)Notes...ObreObre filtresObre registres relacionatsObre una relacióObre informeObre el calendariObre el registre Obre...Obre/Cerca una relacióHa fallat l'operació. Missatge d'error: %sVoleu sobreescriure la definició de '%s'?Imatge PNG (*.png)Contrasenya:Enganxa el text seleccionatPort:PrevalidacióPreferènciesPreferènciesAnteriorRegistre anteriorCamp anteriorImprimeixImprimeix informeImprimeix...PerfilEditor de perfilsPerfil:Delimitador de text:Registre desat.Els registres no s'han eliminat.Registres eliminats._RelacionatRelacionat...Dreceres en relacionsRecarrega/DesfésEliminar "%s"Elimina Elimina el registre seleccionatElimina el registre seleccionat Elimina de les cerques preferidesInformesInforma de l'errorInforme...RevisióRevisió:DesaAnomena i desaDesa com...Desa l'estat de l'arbreDesa ample/altDesa aquest registreCercaCerca %sPreferències del límit de cerca_Límit de cerca...Cerca un registre Risc de seguretat.SeleccionaSeleccioneu un colorSeleccioneu una revisióSelecciona totSelecciona pareSeleccioneu la vostra accióSelecciona...Selecciona/Activa fila actualSeleccióServidor:Mostra les cerques preferidesMostra com a text plaMostra revisions...Correcció ortogràficaAssumpte:Canvia la vistaCanvia la vistaDreceres en camps de textL'acció seleccionada requereix tancar totes les pestanyes. Voleu continuar?El mateix error ja ha estat notificat per un altre usuari. Per mantenir-vos informat afegirem el vostre usuari a la llista d'interessats en aquest assumpte.L'empremta digital del servidor ha canviat des de l'última connexió. L'aplicació no es podrà connectar amb aquest servidor fins que es corregeixi l'empremta digital del servidor.Els valors de "%s" no són vàlids.Aquest registre ha estat modificat. Voleu desar-lo?Per informar d'errors heu de tenir un compte a %sA:AvuiCommuta filaCommuta seleccióMassa argumentsTradueix la vistaTraduccióVista d'arbreVerdaderConnexió a TrytonNo s'ha pogut eliminar l'assistent %sNo s'ha pogut obtenir l'estat de la vista d'arbre de %sNo es pot buscar l'autocompletat de %sNo s'ha pogut establir l'idioma %sNo s'ha pogut desar l'estat de la vista d'arbreNo s'ha pogut escriure el fitxer configuració %sRecupera el registre seleccionat DesconegutDesmarca la línia per ser eliminadaDeselecciona totNom d'usuari:Usuari:Nom d'usuari:ValorVeure _registre...SetmanaVista setmanalQuin és el nom d'aquesta exportació?Amplada:AssistentAra esteu treballant en el registre duplicat.Desa de totes formesASiHeu de triar un registre.Primer heu de seleccionar un fitxer a importar.Heu de desar el registre abans d'afegir traduccions.La vostra selecció:_Quant a..._Accions..._AfegeixDetecta _automàticament _Cancel·la_Neteja_Tanca la pestanya_Connecta..._Conexió_Copia l'URLPer _defecte_Elimina exportació_Elimina..._Desconnecta_Duplica_Correu electrònic..._Correu electrònic..._Exporta dades..._FormulariCerca _GlobalAj_uda_Icones_Importa dades...Com_binacions de tecles..._Administra perfils_Recarrega el menúCommuta el _menúBarra de _menú_Mode_NouSeg_üent_Següent_Normal_Notes..._Opcions_PDA_Preferències..._Anterior_AnteriorIm_primeix..._Surt..._Relacionat..._Recarrega/Desfés_Elimina_Informes..._Desa_Desa exportació_Desa opcions_CercaCanvia la vi_sta_TextText _i iconesBarra d'_einesU_suaridmode desenvolupamentvés enrerevés endavanthRegistra tota la informació amb nivell INFOml'any següentany anteriorsIndica un fitxer de configuració alternatiuindica el nivell de log: DEBUG, INFO, WARNING, ERROR, CRITICALIndica l'usuariIndica el nom:port del servidorvSatryton-4.6.5/tryton/data/locale/cs/0000755000175000017500000000000013260723567016524 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/cs/LC_MESSAGES/0000755000175000017500000000000013260723567020311 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/cs/LC_MESSAGES/tryton.po0000644000175000017500000010422613255571102022203 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "zadejte alternativní konfigurační soubor" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "zadejte uživatelské jméno" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "zadejte název hostitele pro server" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Nelze zapsat konfigurační soubor %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Nemohu nastavit lokalizaci %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Vyberte akci" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Žádná akce není definována!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton spojení" #: tryton/common/common.py:250 msgid "Server:" msgstr "Server:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Výběr" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Váš výběr:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Uložit jako..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "zadejte alternativní konfigurační soubor" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Potvrzení" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Výjimka při souběhu" #: tryton/common/common.py:757 #, fuzzy msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Varování při souběhu zápisů:\n" "\n" "Tento záznam byl změněn zatímco jste ho upravovali.\n" " Vyberte:\n" " - \"Zrušit\" pro zrušení ukládání,\n" " - \"Porovnat\" pro zobrazení změněné verze,\n" " - \"Přesto zapsat\" pro zapsání vaší verze." #: tryton/common/common.py:766 msgid "Compare" msgstr "Porovnat" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Přesto zapsat" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Chyba" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Nahlásit chybu" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Chyba aplikace!" #: tryton/common/common.py:832 msgid "Error: " msgstr "Chyba:" #: tryton/common/common.py:852 #, python-format, python-format, fuzzy, python-format msgid "To report bugs you must have an account on %s" msgstr "Pro hlášení chyb musíte mít účet na %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Sledování chyb" #: tryton/common/common.py:899 msgid "User:" msgstr "Uživatel:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Heslo:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Ta samá chyba již byla nahlášena jiným uživatelem.\n" "Vaše uživatelské jméno bylo přidáno na její seznam." #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Založena nová chyba s ID" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Chyba při spojení!\n" "Špatné uživatelské jméno nebo heslo!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Výjimka:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" #: tryton/common/common.py:1005 msgid "Security risk." msgstr "" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Chyba spojení!\n" "Nelze se připojit k serveru!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Chyba sítě!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "Nepravda" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "_Normální" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "Otevřít kalendář" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Pravda" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Nepravda" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "Konec..." #: tryton/common/popup_menu.py:89 #, fuzzy msgid "Attachments..." msgstr "Příloha:" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 #, fuzzy msgid "Actions..." msgstr "Akce..." #: tryton/common/popup_menu.py:110 #, fuzzy msgid "Relate..." msgstr "_Odstranit..." #: tryton/common/popup_menu.py:111 #, fuzzy msgid "Report..." msgstr "Importovat data..." #: tryton/common/popup_menu.py:112 #, fuzzy msgid "E-Mail..." msgstr "_Email..." #: tryton/common/popup_menu.py:113 #, fuzzy msgid "Print..." msgstr "_Tisk..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "" #: tryton/common/timedelta.py:27 msgid "M" msgstr "" #: tryton/common/timedelta.py:28 msgid "w" msgstr "" #: tryton/common/timedelta.py:29 msgid "d" msgstr "" #: tryton/common/timedelta.py:30 msgid "h" msgstr "" #: tryton/common/timedelta.py:31 msgid "m" msgstr "" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Uživatel" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Volby" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Nápo_věda" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Hledat" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Připojit..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Odpojit" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Konec..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Vlastnosti..." #: tryton/gui/main.py:460 #, fuzzy msgid "_Menu Reload" msgstr "_Obnovit" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 #, fuzzy msgid "_Toolbar" msgstr "Nástrojová lišta" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Výchozí" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Text a ikony" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Ikony" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Text" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "Hlavní nabídka" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Režim" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normální" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Formulář" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Kontrola pravopisu" #: tryton/gui/main.py:635 #, fuzzy msgid "_Previous Tab" msgstr "_Předchozí" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "" #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Email..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Uložit nastavení" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Klávesové zkratky..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_O programu..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Zavřít záložku" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Příloha(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Přidat" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Odstranit" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 #, fuzzy msgid "Host:" msgstr "Port:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Databáze:" #: tryton/gui/window/dblogin.py:98 #, fuzzy msgid "Fetching databases list" msgstr "Nastavení nové databáze:" #: tryton/gui/window/dblogin.py:114 #, fuzzy msgid "Username:" msgstr "Uživatelské jméno:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 #, fuzzy msgid "Incompatible version of the server" msgstr "Verze serveru není kompatibilní!" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 #, fuzzy msgid "Could not connect to the server" msgstr "Nelze se spojit se serverem!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Přihlášení" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Zrušit" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Zrušit spojení k Tryton serveru." #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "_Připojit" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Připojit k Tryton serveru" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Uživatelské jméno:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Email" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Poslat nastavení programu emailem" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Příkazový řádek:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Seznam dostupných náhrad:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Komu:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Předmět: " #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Tělo:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Příloha:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Příloha(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Musíte vybrat právě jeden záznam!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Vytvořeno uživatelem:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Datum vytvoření:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Poslední úpravu provedl:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Datum poslední úpravy:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Model:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Opravdu chcete odstranit tento záznam?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Opravdu chcete odstranit tyto záznamy?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Záznamy neodstraněny!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Záznamy odstraněny!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Nyní pracujete s duplicitním záznamem!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Záznam uložen!" #: tryton/gui/window/form.py:423 msgid " of " msgstr " z " #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Tento záznam byl upraven\n" "chcete ho uložit?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Akce" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Relate" msgstr "_Vytvořit" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Open related records" msgstr "Otevřít záznam" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Report" msgstr "Sestavy" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Open report" msgstr "Otevřít záznam" #: tryton/gui/window/form.py:501 #, fuzzy msgid "E-Mail" msgstr "Email" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Tisk" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Neznámý" #: tryton/gui/window/limit.py:17 #, fuzzy msgid "Limit" msgstr "Omezit:" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "" #: tryton/gui/window/limit.py:28 #, fuzzy msgid "Limit:" msgstr "Omezit:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Nastavení" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Upravit uživatelské nastavení" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Nastavení" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "Předchozí" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "Výběr" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "Předchozí" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Klávesové zkratky" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Zkratky pro texty" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Vyjmout vybraný text" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Kopírovat vybraný text" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Vložit vybraný text" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Další prvek" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Předchozí prvek" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Zkratky pro relace" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Vytvořit novou relaci" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Otevřít/prohledat relaci" #: tryton/gui/window/shortcuts.py:36 #, fuzzy msgid "List Entries Shortcuts" msgstr "Zkratky pro texty" #: tryton/gui/window/shortcuts.py:37 #, fuzzy msgid "Create new line" msgstr "Vytvořit novou relaci" #: tryton/gui/window/shortcuts.py:38 #, fuzzy msgid "Open relation" msgstr "Otevřít/prohledat relaci" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Editovací prvky" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Přepnout pohled" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Přepnout pohled" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Předchozí" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Předchozí záznam" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Následující" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Následující záznam" #: tryton/gui/window/tabcontent.py:59 #, fuzzy msgid "_Search" msgstr "Hledat" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nový" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Vytvořit nový záznam" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Uložit" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Uložit tento záznam" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Obnovit/Zpět" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Obnovit/Zpět" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplikovat" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Odstranit..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Zobrazit záznamy..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 #, fuzzy msgid "A_ttachments..." msgstr "Příloha:" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Přidat přílohu k záznamu" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "Akce..." #: tryton/gui/window/tabcontent.py:119 #, fuzzy msgid "_Relate..." msgstr "_Odstranit..." #: tryton/gui/window/tabcontent.py:125 #, fuzzy msgid "_Report..." msgstr "Importovat data..." #: tryton/gui/window/tabcontent.py:130 #, fuzzy msgid "_E-Mail..." msgstr "_Email..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Tisk..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Exportovat data" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Importovat data..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Zavřít kartu" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Všechna pole" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Vymazat" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Parametry CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Kódování:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Jméno pole" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exportovat do CSV souboru" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Předdefinované exporty" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Uložit exportu" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Smazat exportu" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Otevřít" #: tryton/gui/window/win_export.py:86 #, fuzzy msgid "Save" msgstr "_Uložit" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Přidat jména polí" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d záznam uložen!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d záznamů uloženo!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Operace selhala.\n" "Chybová zpráva:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Odkaz" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Přidat" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 #, fuzzy msgid "Create a new record " msgstr "Vytvořit nový záznam" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 #, fuzzy msgid "Delete selected record " msgstr "Smazat vybraný záznam" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 #, fuzzy msgid "Undelete selected record " msgstr "Smazat vybraný záznam" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Předchozí" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Další" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Přepnout" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Import CSV souboru" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Automatická detekce" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Soubor k importu:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Otevřít..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Vynechané řádky:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Nejprve je nutné vybrat soubor pro import!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Chyba při otevírání CSV souboru" #: tryton/gui/window/win_import.py:141 #, python-format, python-format, fuzzy, python-format msgid "Error processing the file at field %s." msgstr "Chyba při zpracování souboru u pole %s.\n" #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d záznam načten!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d záznamů načteno!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Průvodce" #: tryton/gui/window/view_form/screen/screen.py:194 #, fuzzy msgid "ID" msgstr "Najít" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "Vytvořeno uživatelem:" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "Datum vytvoření:" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "Datum poslední úpravy:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "Datum poslední úpravy:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "Nemohu nastavit lokalizaci %s" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "Nemohu nastavit lokalizaci %s" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Velikost obrázku" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Šířka:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Výška:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "Obrázek PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Uložit jako" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Rozměry obrázku jsou příliš velké!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Najít" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "Tělo:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "Přepnout pohled" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "Přepnout pohled" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Vymazat" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Všechny soubory" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Obrázky" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 #, fuzzy msgid "Add existing record" msgstr "Uložit tento záznam" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 #, fuzzy msgid "Remove selected record " msgstr "Smazat vybraný záznam" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Otevřít záznam" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 #, fuzzy msgid "Search a record " msgstr "Hledat záznam" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 #, fuzzy msgid "Remove selected record" msgstr "Smazat vybraný záznam" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 #, fuzzy msgid "Edit selected record " msgstr "Upravit vybraný záznam" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 #, fuzzy msgid "Translation" msgstr "Přidat překlad" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Musíte uložit záznam před přidáváním překladů!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Jiný jazyk není k dispozici!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Přeložit pohled" tryton-4.6.5/tryton/data/locale/cs/LC_MESSAGES/tryton.mo0000644000175000017500000003120713260723565022206 0ustar cedced00000000000000\) .E_p  #%*P _kq & $ 6 CQY o| - ? I U`o   * 2= MX h v     #6P h!v   + : HT\pu z     %7= L Wcl|      '2BTe lv    %?OapyI}_  .A PZ_q%    =D KXZ^ n x         %5L ]jsy~       '-/@ HS Uv x <    !)!!!! " ")"."1"3"H"_"""""""" "#+#'@#'h# # ####### # #"$*$>$F$]$p$ $$$$ $$$ %%)%A%X%s%%% % % %%%% & #&1& 6&W&h&"n& &&#&& && &&' ')' 2' ?'K'_'q' x'''''''''' ( ((6(R(f(l({(}((( ( ((( (( ) ))%)9)>)F) ])k)|) )) ) ) ))))**$*** 9* D* O*[*o** **** ** * **+ ++-+=+O+e+ l+v+++++ + + + ++ ,,,7,G,Y, l, x,,I,s,R- -. ..#.6. H.R.Y.i.%.. .. .. //./ 3/ T/ ^/h/w/y/}////// / / / / /0 0 0!0 10<0 K0W0^0q00 00000 0 0 0001 11(1 11 ?1J1S1f1w1 }1 1111 11 11 1 11+1<'2d2222 of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsCreate...Search...ActionAddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCreate a new recordCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEditEdit User PreferencesEdition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationID:Image SizeImagesImport from CSVKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:Lines to Skip:LinkLoginMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportProfileProfile EditorProfile:Quote char:Relation Entries ShortcutsRemove "%s"Remove Remove this bookmarkReport BugSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Security risk.SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validTo:Toggle rowToggle selectionToo much argumentsTranslate viewTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUnknownUnmark line for deletionUnselect allUser name:User:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Print..._Quit..._Reload/Undo_Remove_Save_Save Options_Switch View_Text_Text and Icons_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: cs Language-Team: cs Plural-Forms: nplurals=3; plural=((n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 z "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:Všechna poleFields selectedPředdefinované exportyCreate...Search...AkcePřidatPřidat jména políAdd a note to the recordPřidat přílohu k záznamuAdd valueVšechny souboryzadejte alternativní konfigurační souborOpravdu chcete odstranit tento záznam?Opravdu chcete odstranit tyto záznamy?Příloha(%d)Příloha:Tělo:Bookmark Name:Bookmark this filterSledování chybBy: CC:Parametry CSV_PřipojitZrušit spojení k Tryton serveru.Change AcceleratorsVymazatClear the record Zavřít záložkuCollapse all rowsCollapse rowPříkazový řádek:PorovnatVýjimka při souběhuPotvrzeníPřipojit k Tryton serveruCopy URL into clipboardCopy _URL...Kopírovat vybraný textVytvořit nový záznamVytvořit novou relaciZaložena nová chyba s IDDatum vytvoření:Vytvořeno uživatelem:Vyjmout vybraný textDatabáze:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEditUpravit uživatelské nastaveníEditovací prvkyEmailPoslat nastavení programu emailemKódování:ChybaChyba při otevírání CSV souboruChyba:Výjimka:Expand all rowsExpand rowExpand/CollapseExportovat do CSV souboruFa_voritesNepravdaFast TabbingJméno poleFile "%s" not foundSoubor k importu:NajítForegroundFuzzyVýška:Host / Database informationID:Velikost obrázkuObrázkyImport CSV souboruKlávesové zkratkyDatum poslední úpravy:Poslední úpravu provedl:Launch actionSeznam dostupných náhrad:Vynechané řádky:OdkazPřihlášeníMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameDalšíNásledující záznamDalší prvekNo result found.Note(%d)Notes (%s)Notes...OtevřítOpen filtersOtevřít...Otevřít/prohledat relaciOverride '%s' definition?Obrázek PNG (*.png)Heslo:Vložit vybraný textPort:Pre-validationNastaveníNastaveníPředchozíPředchozí záznamPředchozí prvekTiskPrint reportProfileProfile EditorProfile:Quote char:Zkratky pro relaceRemove "%s"Remove Remove this bookmarkNahlásit chybuUložit jakoUložit jako...Save Tree StateSave Width/HeightUložit tento záznamHledatSearch %sSearch Limit SettingsSearch Limit...Security risk.SelectSelect a colorSelect allSelect parentVyberte akciSelect...Select/Activate current rowVýběrServer:Show bookmarks of filtersShow plain textShow revisions...Kontrola pravopisuPředmět: PřepnoutZkratky pro textyThe following action requires to close all tabs. Do you want to continue?Ta samá chyba již byla nahlášena jiným uživatelem. Vaše uživatelské jméno bylo přidáno na její seznam.The server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validKomu:Toggle rowToggle selectionToo much argumentsPřeložit pohledTree viewPravdaTryton spojeníUnable to delete wizard %sUnable to search for completion of %sNemohu nastavit lokalizaci %sNeznámýUnmark line for deletionUnselect allUživatelské jméno:Uživatel:Zobrazit záznamy...WeekWhat is the name of this export?Šířka:PrůvodcePřesto zapsatYYesVáš výběr:_O programu...Akce..._Přidat_Zrušit_Zavřít kartu_Připojit..._Connection_Copy URL_Výchozí_Odstranit..._Odpojit_Duplikovat_Email...Exportovat dataFormulář_Global SearchNápo_věda_IkonyImportovat data..._Klávesové zkratky..._Manage profiles_Menu ToggleHlavní nabídka_Režim_Nový_Následující_Next Tab_Normální_Notes..._Volby_PDA_Vlastnosti..._Předchozí_Tisk...Konec...Obnovit/Zpět_Odstranit_UložitUložit nastaveníPřepnout pohled_Text_Text a ikony_Uživatelddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearszadejte alternativní konfigurační souborspecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALzadejte uživatelské jménotwytryton-4.6.5/tryton/data/locale/es/0000755000175000017500000000000013260723567016526 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/es/LC_MESSAGES/0000755000175000017500000000000013260723567020313 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/es/LC_MESSAGES/tryton.po0000644000175000017500000011106613255571102022205 0ustar cedced00000000000000# Spanish (Spain) translations for tryton. # Copyright (C) 2008 igor@tamarapatino.org # Copyright (C) 2009 PEMAS Servicios Profesionales, S.L. # Copyright (C) 2012 Zikzakmedia SL # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2008. # Carlos Perelló Marín , 2008-2009. # Sergi Almacellas Abellana 2012. # Jordi Esteve Cusiné 2012. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "Indica un archivo de configuración alternativo" #: tryton/config.py:73 msgid "development mode" msgstr "Modo desarrollo" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "Registra toda la información con nivel INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "Indica el nivel de log: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "Indica el usuario" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "Indica el nombre:puerto del servidor" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Demasiados argumentos" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "El archivo «%s» no se ha encontrado" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "No se ha podido escribir el archivo de configuración %s." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "No se ha podido establecer el idioma %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Seleccione su acción" #: tryton/action/main.py:197 msgid "No action defined." msgstr "No se ha definido ninguna acción." #: tryton/common/button.py:56 msgid "By: " msgstr "Por: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Conexión a Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Servidor:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Puerto:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Selección" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Su selección:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Guardar como..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Ignorar siempre esta advertencia." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "¿Desea continuar?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Confirmación" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Excepción de concurrencia" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Aviso de concurrencia de escritura:\n" "\n" "Este registro ha sido modificado mientras lo editaba.\n" " Elija:\n" " - \"Cancelar\" para no guardar;\n" " - \"Comparar\" para ver la versión modificada;\n" " - \"Guardar de todas formas\" para guardar sus cambios." #: tryton/common/common.py:766 msgid "Compare" msgstr "Comparar" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Guardar de todas formas" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Error" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Informar del error" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Error de aplicación." #: tryton/common/common.py:832 msgid "Error: " msgstr "Error: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Para informar de errores debe tener una cuenta en %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Seguimiento de errores" #: tryton/common/common.py:899 msgid "User:" msgstr "Usuario:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Contraseña:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "El mismo error ya fue notificado por otro usuario.\n" "Para mantenerle informado añadiremos su usuario a la lista de interesados en esta incidencia." #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Se creó un nuevo error con identificador " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Error de conexión.\n" "Nombre de usuario o contraseña incorrectos." #: tryton/common/common.py:986 msgid "Exception:" msgstr "Excepción:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "La huella de seguridad del servidor ha cambiado desde la última conexión. \n" "La aplicación no se podrá conectar con este servidor hasta que se corrija la huella de seguridad del servidor." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Riesgo de seguridad." #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Error de conexión.\n" "No se ha podido conectar con el servidor." #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Error de red." #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Buscar..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Crear..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "No se ha podido buscar el autocompletado de %s" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Valor" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Valor a mostrar" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Format" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Format a mostrar" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Abrir el calendario" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Formato fecha" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Formato fecha actual" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "a" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Sí" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Verdadero" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "v" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Falso" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Editar..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Adjuntos..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notas..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Acciones..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Relacionado..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Informe..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "Correo electrónico..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Imprimir..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "A" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "S" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_Conexión" #: tryton/gui/main.py:222 msgid "_User" msgstr "U_suario" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Opciones" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_voritos" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Ay_uda" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Buscar" #: tryton/gui/main.py:372 msgid "No result found." msgstr "No se han encontrado resultados." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Conectar..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Desconectar" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Salir..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Preferencias..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Recargar menú" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Conmutar _menú" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Búsqueda _global" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Barra de herramien_tas" #: tryton/gui/main.py:502 msgid "_Default" msgstr "Por _defecto" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Texto _e iconos" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Iconos" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Texto" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "Barra de _menú" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Cambiar teclas rápidas" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Modo" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Formulario" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Guardar ancho/alto" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Guardar estado de expansión del árbol" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Tabulación rápida" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Corrección ortográfica" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Anterior" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Siguiente" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "_Límite de búsqueda..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Correo electrónico..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Guardar opciones" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Com_binaciones de teclas..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_Acerca de..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "_Administrar menús favoritos" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "La acción seleccionada requiere cerrar todas las pestañas.\n" "¿Desea continuar?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Cerrar pestaña" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "Adjuntos (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Editor de perfiles" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Perfil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Añadir" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Eliminar" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Servidor:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Base de datos:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Recuperando lista de bases de datos" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Nombre de usuario:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "El cliente no es compatible con la versión del servidor" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "No se ha podido conectar con el servidor" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Usuario" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Cancelar" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Cancelar conexión con el servidor Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "C_onectar" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Conectar con el servidor Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Perfil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Administrar perfiles" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Información del Servidor / Base de datos" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Nombre de usuario:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Correo electrónico" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Configuración del programa de correo electrónico" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Línea de comando:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Leyenda de palabras clave disponibles:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Para:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Asunto:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Mensaje:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Adjunto:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Adjunto(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Nota(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Debe elegir un registro." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Creado por:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Fecha creación:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Última modificación por:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Última fecha de modificación:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modelo:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "¿Está seguro que quiere eliminar este registro?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "¿Está seguro que quiere eliminar estos registros?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Los registros no se han eliminado." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Registros eliminados." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Ahora está trabajando en el registro duplicado." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Registro guardado." #: tryton/gui/window/form.py:423 msgid " of " msgstr " de " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Este registro ha sido modificado.\n" "¿Desea guardarlo?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Acción" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Ejecutar acción" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "_Relacionado" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Abrir registros relacionados" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Informes" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Abrir informe" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Email" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Informe por email" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Imprimir" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Imprimir informe" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_Copiar la URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Copiar la URL al portapapeles" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Desconocido" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Límite" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Preferencias del límite de búsqueda" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Límite:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notas (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Preferencias" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Editar preferencias de usuario" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Preferencias" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Versión" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Seleccionar una versión" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Versión:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Combinaciones de teclas" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Atajos en campos de texto" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Cortar texto seleccionado" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Copiar texto seleccionado" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Pegar texto seleccionado" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Campo siguiente" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Campo anterior" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Atajos en relaciones" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Crear nueva relación" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Abrir/Buscar relación" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Atajos en listas" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Crear nueva línea" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Abrir relación" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Marcar para eliminación" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Desmarcar para eliminación" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Controles de edición" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Mover cursor" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Mover a la derecha" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Mover a la izquierda" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Mover arriba" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Mover abajo" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Mover arriba una página" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Mover abajo una página" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Mover al principio" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Mover al final" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Mover al padre" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Seleccionar todo" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Deseleccionar todo" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Seleccionar padre" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Seleccionar/Activar fila actual" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Conmutar selección" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Expandir/Contraer" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Expandir fila" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Contraer fila" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Conmutar fila" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Contraer todas las filas" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Expandir todas las filas" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Vista de árbol" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Cambiar vi_sta" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "Cambiar vista" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Anterior" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Registro anterior" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Sig_uiente" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Registro siguiente" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Buscar" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nuevo" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Crear un nuevo registro" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Guardar" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Guardar este registro" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_Recargar/Deshacer" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "Recargar/Deshacer" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplicar" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Eliminar..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Ver _registro..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Mostrar versiones..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "Adjun_tos..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Añadir un adjunto al registro" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_Notas..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Añadir una nota al registro" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Acciones..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_Relacionado..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Informes..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_Correo electrónico..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "Im_primir..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Exportar datos..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importar datos..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "Copiar _URL..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Cerrar pestaña" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Todos los campos" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_Limpiar" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Campos seleccionados" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Parámetros CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Separador de campo:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Delimitador de texto:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codificación:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nombre del campo" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exportar a CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Exportaciones predeterminadas" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nombre" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_Guardar exportación" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_Eliminar exportación" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Abrir" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Guardar" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Añadir nombres de _campo" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (cadena)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "%s (nombre del modelo)" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "%s (nombre del registro)" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "¿Cuál es el nombre de esta exportación?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Sobrescribir la definición de '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "Se ha guardado %d registro." #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "Se han guardado %d registros." #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Ha fallado la operación.\n" "Mensaje de error:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Enlace" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Añadir" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Eliminar " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Crear un nuevo registro " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Eliminar registro seleccionado " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Recuperar registro seleccionado " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Anterior" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Siguiente" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Cambiar vista" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importar desde CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "_Auto-detectar" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Archivo a importar:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Abrir..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Líneas a omitir:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Primero debe elegir un archivo a importar." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Error al abrir el archivo CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Se ha producido un error al procesar el archivo en el campo %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "Se ha importado %d registro." #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "Se han importado %d registros." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Buscar %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "No se ha podido eliminar el asistente %s" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Asistente" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Creado por:" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Fecha creación:" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Última modificación por:" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Última fecha de modificación:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, python-format msgid "Unable to get view tree state for %s" msgstr "No se ha podido obtener el estado de expansión del árbol de %s" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "No se ha podido establecer el estado de expansión del árbol" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" no es válido según su dominio." #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "\"%s\" es obligatorio." #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Los valores de \"%s\" no son válidos." #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Prevalidación" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Tamaño de la imagen" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Anchura:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Altura:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "Imagen PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Guardar como" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "El tamaño de la imagen es muy grande." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Abrir filtros" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Muestra las búsquedas favoritas" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Eliminar de las búsquedas favoritas" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Guardar como búsqueda favorita" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Nombre de la búsqueda favorita:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Buscar" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Hoy:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "retroceder" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "ir adelante" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "año anterior" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "año próximo" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Vista semanal" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Vista mensual" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Semana" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Seleccionar…" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Limpiar" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Todos los archivos" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Seleccionar" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Mostrar como texto plano" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Añadir un valor" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Eliminar \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Imágenes" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Añadir un registro existente" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Eliminar registro seleccionado " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Abrir registro " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Eliminar el registro " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Buscar registro " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Eliminar registro seleccionado" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Editar registro seleccionado " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Primer plano" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Seleccione un color" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Traducción" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Editar" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Confuso" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "Debe guardar el registro antes de añadir traducciones." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "No hay otro idioma disponible." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Traducir vista" tryton-4.6.5/tryton/data/locale/es/LC_MESSAGES/tryton.mo0000644000175000017500000004607013260723565022214 0ustar cedced00000000000000d< \])b #&+.24F]w]n   3#F%j   &"I]c z   +2"U mz % 4BQ c my    (BJZ` w&     "/ GRfv { "2L d!r  ' 2 > H ^ m z       ! !1! :!E!N! S!`! u! !!!!!#!!" #"-"?"E" T" _"k"t""" """"" " """# #!# <# H# T#a#x### # ## ### ##$$$$ +$5$K$[$p$$$$ $ $$ $$ $% %%%5%G%V%_% f%r%I%}%Q& &5'46'k'o' u'''' ' ''''$'% (F(^(|(((( ( (( () )) ) ')H)O)(V) ))))%)7)* * )*5* :*G*O* V* a* m* y*** * * * * ******++++ <+ I+V+_+e+j+ p+z+ ++++ + + ++ + ++ +, , ,!, ),6,<,L,U,[,],n, v,, ,, , ,,,<,- 2-S-U-W-Y-.%./'/D/`///// ////////0$+0P0F1V1 g1t1 |11111122!(2J21`232 22 2 22 23?3V3\3`3 p3)z333333 44)424 M4[4@{4=445'5(A5j5555*556 6 !6-6G6 V6%d66666666677!<7 ^7h7~727777?788 @8L8 e8s88 888#88%89(9 /9<9C9K9)S9 }9999&9 9989 :8:X:s:&:::::::::;';/;O; j; x; ;;;;;;; <<(< /< =<G<Z<"j<< << <<< <<= +=9=M=a=j=.=$== ==>> %> 2>?>H>Z>i>r> >>>>>>">> ? ?/?D? V?d?t?%?$??? ?@ @@ @-@'=@e@x@@ @%@@@@ AA(AAARAdAzAA A A AAA B&B .B K,@KmK oK }KK/K=KK$ L2L4L6L of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: es Language-Team: es Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 de "%s" no es válido según su dominio."%s" es obligatorio.Se ha importado %d registro.Se ha guardado %d registro.Se han importado %d registros.Se han guardado %d registros.%s (%s)%s (nombre del modelo)%s (nombre del registro)%s (cadena)%s%%, ,….....:Todos los camposCampos seleccionadosExportaciones predeterminadasAviso de concurrencia de escritura: Este registro ha sido modificado mientras lo editaba. Elija: - "Cancelar" para no guardar; - "Comparar" para ver la versión modificada; - "Guardar de todas formas" para guardar sus cambios.Crear...Buscar...Adjun_tos...AcciónAcciones...AñadirAñadir nombres de _campoAñadir una nota al registroAñadir un adjunto al registroAñadir un registro existenteAñadir un valorTodos los archivosIgnorar siempre esta advertencia.Error de aplicación.¿Está seguro que quiere eliminar este registro?¿Está seguro que quiere eliminar estos registros?Adjunto(%d)Adjunto:Adjuntos (%s)Adjuntos...Mensaje:Nombre de la búsqueda favorita:Guardar como búsqueda favoritaSeguimiento de erroresPor: CC:Parámetros CSVC_onectarCancelar conexión con el servidor TrytonCambiar teclas rápidasLimpiarEliminar el registro Cerrar pestañaContraer todas las filasContraer filaLínea de comando:CompararExcepción de concurrenciaConfirmaciónConectar con el servidor TrytonError de conexión. Nombre de usuario o contraseña incorrectos.Error de conexión. No se ha podido conectar con el servidor.Copiar la URL al portapapelesCopiar _URL...Copiar texto seleccionadoNo se ha podido conectar con el servidorCrear un nuevo registroCrear un nuevo registro Crear nueva líneaCrear nueva relaciónSe creó un nuevo error con identificador Fecha creación:Fecha creación:Creado por:Creado por:Cortar texto seleccionadoBase de datos:Formato fechaEliminar registro seleccionado Separador de campo:Format a mostrarFormato fecha actualValor a mostrar¿Desea continuar?EmailInforme por emailCorreo electrónico...EditarEditar preferencias de usuarioEditar registro seleccionado Editar...Controles de ediciónCorreo electrónicoConfiguración del programa de correo electrónicoCodificación:ErrorError al abrir el archivo CSVSe ha producido un error al procesar el archivo en el campo %s.Error: Excepción:Expandir todas las filasExpandir filaExpandir/ContraerExportar a CSVFa_voritosFalsoTabulación rápidaRecuperando lista de bases de datosNombre del campoEl archivo «%s» no se ha encontradoArchivo a importar:BuscarPrimer planoFormatConfusoAltura:Información del Servidor / Base de datosServidor:IDID:Tamaño de la imagenEl tamaño de la imagen es muy grande.ImágenesImportar desde CSVEl cliente no es compatible con la versión del servidorCombinaciones de teclasÚltima fecha de modificación:Última modificación por:Ejecutar acciónLeyenda de palabras clave disponibles:LímiteLímite:Líneas a omitir:EnlaceAtajos en listasUsuarioM_Administrar menús favoritosMarcar para eliminaciónModelo:Última fecha de modificación:Última modificación por:Vista mensualMover cursorMover abajoMover abajo una páginaMover al finalMover a la izquierdaMover al padreMover a la derechaMover al principioMover arribaMover arriba una páginaNombreError de red.SiguienteRegistro siguienteCampo siguienteNo se ha definido ninguna acción.No hay otro idioma disponible.No se han encontrado resultados.Nota(%d)Notas (%s)Notas...AbrirAbrir filtrosAbrir registros relacionadosAbrir relaciónAbrir informeAbrir el calendarioAbrir registro Abrir...Abrir/Buscar relaciónHa fallado la operación. Mensaje de error: %sSobrescribir la definición de '%s'?Imagen PNG (*.png)Contraseña:Pegar texto seleccionadoPuerto:PrevalidaciónPreferenciasPreferenciasAnteriorRegistro anteriorCampo anteriorImprimirImprimir informeImprimir...PerfilEditor de perfilesPerfil:Delimitador de texto:Registro guardado.Los registros no se han eliminado.Registros eliminados._RelacionadoRelacionado...Atajos en relacionesRecargar/DeshacerEliminar "%s"Eliminar Eliminar registro seleccionadoEliminar registro seleccionado Eliminar de las búsquedas favoritasInformesInformar del errorInforme...VersiónVersión:GuardarGuardar comoGuardar como...Guardar estado de expansión del árbolGuardar ancho/altoGuardar este registroBuscarBuscar %sPreferencias del límite de búsqueda_Límite de búsqueda...Buscar registro Riesgo de seguridad.SeleccionarSeleccione un colorSeleccionar una versiónSeleccionar todoSeleccionar padreSeleccione su acciónSeleccionar…Seleccionar/Activar fila actualSelecciónServidor:Muestra las búsquedas favoritasMostrar como texto planoMostrar versiones...Corrección ortográficaAsunto:Cambiar vistaCambiar vistaAtajos en campos de textoLa acción seleccionada requiere cerrar todas las pestañas. ¿Desea continuar?El mismo error ya fue notificado por otro usuario. Para mantenerle informado añadiremos su usuario a la lista de interesados en esta incidencia.La huella de seguridad del servidor ha cambiado desde la última conexión. La aplicación no se podrá conectar con este servidor hasta que se corrija la huella de seguridad del servidor.Los valores de "%s" no son válidos.Este registro ha sido modificado. ¿Desea guardarlo?Para informar de errores debe tener una cuenta en %sPara:Hoy:Conmutar filaConmutar selecciónDemasiados argumentosTraducir vistaTraducciónVista de árbolVerdaderoConexión a TrytonNo se ha podido eliminar el asistente %sNo se ha podido obtener el estado de expansión del árbol de %sNo se ha podido buscar el autocompletado de %sNo se ha podido establecer el idioma %sNo se ha podido establecer el estado de expansión del árbolNo se ha podido escribir el archivo de configuración %s.Recuperar registro seleccionado DesconocidoDesmarcar para eliminaciónDeseleccionar todoNombre de usuario:Usuario:Nombre de usuario:ValorVer _registro...SemanaVista semanal¿Cuál es el nombre de esta exportación?Anchura:AsistenteAhora está trabajando en el registro duplicado.Guardar de todas formasASíDebe elegir un registro.Primero debe elegir un archivo a importar.Debe guardar el registro antes de añadir traducciones.Su selección:_Acerca de..._Acciones..._Añadir_Auto-detectar_Cancelar_Limpiar_Cerrar pestaña_Conectar..._Conexión_Copiar la URLPor _defecto_Eliminar exportación_Eliminar..._Desconectar_Duplicar_Correo electrónico..._Correo electrónico..._Exportar datos..._FormularioBúsqueda _globalAy_uda_Iconos_Importar datos...Com_binaciones de teclas..._Administrar perfiles_Recargar menúConmutar _menúBarra de _menú_Modo_NuevoSig_uienteSiguiente_Normal_Notas..._Opciones_PDA_Preferencias..._Anterior_AnteriorIm_primir..._Salir..._Relacionado..._Recargar/Deshacer_Eliminar_Informes..._Guardar_Guardar exportación_Guardar opciones_BuscarCambiar vi_sta_TextoTexto _e iconosBarra de herramien_tasU_suariodModo desarrolloretrocederir adelantehRegistra toda la información con nivel INFOmaño próximoaño anteriorsIndica un archivo de configuración alternativoIndica el nivel de log: DEBUG, INFO, WARNING, ERROR, CRITICALIndica el usuarioIndica el nombre:puerto del servidorvSatryton-4.6.5/tryton/data/locale/ru/0000755000175000017500000000000013260723567016545 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ru/LC_MESSAGES/0000755000175000017500000000000013260723567020332 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/ru/LC_MESSAGES/tryton.po0000644000175000017500000011716013255571102022225 0ustar cedced00000000000000# Russian (Russia) translations for tryton. # Copyright (C) 2009 B2CK # This file is distributed under the same license as the tryton project. # Dmitry Klimanov , 2010. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "указать альтернативный конфигурационный файл" #: tryton/config.py:73 msgid "development mode" msgstr "режим разработки" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "все сообщения на уровне INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" "указать уровень вывода сообщений: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "указать имя пользователя" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "укажите имя сервера" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Слишком много аргументов" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Файл \"%s\" не найден" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Невозможно записать файл конфигурации %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Не удается установить локализацию %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Выберите действие" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Не определены действия!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton соединение" #: tryton/common/common.py:250 msgid "Server:" msgstr "Сервер:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Порт:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Выбор" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Ваш выбор:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Сохранить как..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Всегда игнорировать это предупреждение." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Вы хотите продолжить?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Подтвердите" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Прерывание конкурентных записей" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" " Внимание сохранена другая копия этой записи: \n" "\n" "Эта запись была изменена, пока вы её редактирование.\n" "Выбирате:\n" "- \" Отмена \", чтобы отменить ваше изменение;\n" "- \" Сравнить \", чтобы увидеть модифицированный вариант;\n" "- \" Переписать \", чтобы сохранить вашу текущую версию." #: tryton/common/common.py:766 msgid "Compare" msgstr "Сравнить" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Записать все равно" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Ошибка" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Сообщить об ошибке" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Ошибка приложения!" #: tryton/common/common.py:832 msgid "Error: " msgstr "Ошибка: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "" "Вы можете отправить отчет об ошибке если вы зарегистрированны на %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Система сбора ошибок" #: tryton/common/common.py:899 msgid "User:" msgstr "Пользователь:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Пароль:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Эта же ошибка была уже сообщена от другого пользователя.\n" "Чтобы держать вас в курсе ваше имя пользователя будет добавлен в список перечень по этому вопросу" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Создан новый отчет об ошибке с идентификатором" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Ошибка соединения!\n" "Неверное имя пользователя или пароль!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Исключительная ситуация:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Цифровой сертификат сервера изменился с момента последнего подключения!\n" "Подключение к серверу приостановлено до тех пор пока сертификат не будет исправлен." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Угроза безопасности!" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Ошибка соединения!\n" "Невозможно соединиться с сервером!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Сетевая ошибка!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Поиск..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Создать..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "Добавить значение" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 #, fuzzy msgid "Displayed value" msgstr "Добавить значение" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "Нормальный" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "Открыть календарь " #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Истинный" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Ложный" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "_Выход..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Вложения..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Действия..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Связанные..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Отчет..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "Эл.почта..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Печать..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "Г" #: tryton/common/timedelta.py:27 msgid "M" msgstr "М" #: tryton/common/timedelta.py:28 msgid "w" msgstr "н" #: tryton/common/timedelta.py:29 msgid "d" msgstr "д" #: tryton/common/timedelta.py:30 msgid "h" msgstr "ч" #: tryton/common/timedelta.py:31 msgid "m" msgstr "м" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Пользователь" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Параметры" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Избранное" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Помощь" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Поиск" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Ничего не найдено." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "Подключение..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Отключение" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Выход..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "Настройки..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "Обновить меню" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Показать/скрыть меню" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Глобальный поиск" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Панель инструментов" #: tryton/gui/main.py:502 msgid "_Default" msgstr "По умолчанию" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Текст и Значки" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "Значки" #: tryton/gui/main.py:532 msgid "_Text" msgstr "Текст" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Меню" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Режим изменения быстрых клавиш" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "Режим" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "Нормальный" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "Упрощенный" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Форма" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Сохранить размеры" #: tryton/gui/main.py:602 #, fuzzy msgid "Save Tree State" msgstr "Запомнить состояние дерева" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Проверка орфографии" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "Предыдущая вкладка" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Следующая вкладка" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Максимальное количество строк..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "Настройки _Эл.почты" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Сохранить настройки" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Быстрые клавиши" #: tryton/gui/main.py:687 msgid "_About..." msgstr "О программе" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Управление закладками" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Данное действие приведет к закрытию всех вкладок.\n" "Продолжить?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Закрыть вкладку" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Вложений (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Редактор профилей" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Профиль" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Добавить" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Удалить" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Сервер:порт" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "База данных:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Получение списка баз данных" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Имя пользователя:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Несовместимая версия сервера" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Не удается подключиться к серверу!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Логин" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "Отмена" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Отмена подключения к серверу" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "Соединение" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Соединение с сервером" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Профиль:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "Управление профилями" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Сервер / база данных" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Имя пользователя:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Эл.почта" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Настройки программы электронной почты" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Командная строка:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Переменные доступные для подстановки:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Кому:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "Скрытая копия:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Тема:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Сообщение:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Вложение:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Вложений (%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Вы должны выбрать одну запись!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "Номер строки" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Создано пользователем" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Дата создания" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Изменена пользователем:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Дата изменения:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Модель:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Вы уверены что хотите удалить эту запись?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Вы уверены что хотите удалить эти записи?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Записи не удалены!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Записи удалены!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Сейчас работает на дублирующихся записях!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Запись сохранена!" #: tryton/gui/window/form.py:423 msgid " of " msgstr "из" #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Эта запись была изменена\n" "Вы хотите её сохранить?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Действие" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Выполнить действие" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Связанные" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Открыть связанные записи" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Отчет" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Открыть отчет" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "Эл.почта" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Отправить отчет по Эл.почте" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Печать" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Печать отчета" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Неизвестно" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Ограничение" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Настройки ограничения поиска" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Кол-во записей" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Настройки" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Изменить настройки пользователя" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Настройка" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "Предыдущий" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "Выбор" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "Предыдущий" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Сочетания клавиш быстрого доступа" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Горячие клавиши в текстовых полях" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Вырезать выделенный текст" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Скопировать выделенный текст" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Вставить скопированный текст" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Следующий Widget" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Предыдущий Widget" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Связи записей \"быстрого доступа\"" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Создать новую связь" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Открыть / Поиск связей" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Список горячих клавиш" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Создать новую строку" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Открыть связь" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Отметить линию на удаление" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Убрать отметку на удаление" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Редактируемые поля" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Сменить просмотр" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Сменить просмотр" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "Предыдущая" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Предыдущая запись" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Следующая" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Следующая запись" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "Поиск" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "Новый" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Создать новую запись" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "Сохранить" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Сохранить эту запись" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Обновить/Отменить" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "Обновить/Отменить" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "Копировать" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Удалить..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Просмотр изменений" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "Вложения..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Добавить вложение для этой записи" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "Действия" #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "Связанные..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "Отчет..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "Эл.почта..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "печать" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Экспорт данных" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Импорт данных" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Закрыть вкладку" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Все поля" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Очистить" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Параметры CVS" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Кодировка:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Наименование поля" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Экспорт в CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Предопределенные экспорты" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Имя" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Сохранить настройку экспорта" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Удалить настройку экспорта" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Открыть" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Сохранить" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Добавить имя поля" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Укажите имя для экспорта." #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d запись сохранена!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d записей сохранено!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Не удалось выполнить операцию!\n" "Сообщение об ошибке:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Ссылка" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Добавить" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Удалить " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Создать новую запись " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Удалить выбраную запись " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Восстановить выбраную запись " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Предыдущий" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Следующий" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Переключить" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Импорт из файла CSV" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Авто-обнаружение" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Файл для импорта:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Открыть..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Строки для пропуска:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Вы должны сначала выбрать файл для импорта!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Ошибка открытия файла CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Ошибка при обработке файла на поле %s." #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d запись импортирована!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d записей импортировано!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Мастер" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "Создано пользователем" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "Дата создания" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "Дата изменения:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "Дата изменения:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "Не удается установить локализацию %s" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "Не удается установить локализацию %s" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Размер изображения" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Ширина:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Ввысота:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG изображение (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Сохранить как" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Размер изображения слишком большой!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Показать сохраненные фильтры" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Удалить эту закладку" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Запомнить этот фильтр" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Имя закладки:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Найти" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "Сообщение:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "Переключить вид" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "Переключить вид" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Очистить" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Все фалы" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Показать в виде текста" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Добавить значение" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Удалить \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Изображения" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Добавить существующую запись" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Удалить выбраную запись " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Открыть запись " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Поиск записи " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Удалить выбраную запись" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Изменить выбранную запись " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Перевод" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Редактировать" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Неточный" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Необходимо сохранить запись перед добавлением перевода!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Отсутствуют другие доступные языки!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Перевод текущего окна" tryton-4.6.5/tryton/data/locale/ru/LC_MESSAGES/tryton.mo0000644000175000017500000004504413260723565022233 0ustar cedced00000000000000/  )<MUe v 'G [ eo#%  )5:>M&V}    * BOb   &2 OZi   "(&?f ny      '-5QWZ ^ip" !%49PVXi       *6G P[d iv      *6?O_ er{     5 < GQV ^i{    $ @JRl|I} 4   !! $! 0!:!?!Q!%l!!!!! ! !" " " " %"F"M" T"a"c"g" w" """ " " " "" " " " " "###,#2#9#I#`# q# ~##### ## #### # # #$ $ $"$ *$5$ ;$I$ Q$^$d$t$}$$$$ $$ $$ $ $$$<%C%Z%\%^%`%8')='g'x''' ''''''8'()*+*?*P*d* u**>*6*!%+G+JW+K+K+:,P,b,v,,(,&,,,-*-5?-9u----- . .5.<F..(.. .6.?/&_/+/&/$/V/U0)o0100 020 !1,1;1'Q1y12111<15'2#]22G22 2,2C'3k3.z33 3333 3 434!K4m44 4 444$4 55"5#:5^5 u565?5 6,*6#W6F{666%6 7('7 P7[7)^717 7 7 777 88 8 -898A8U8\8o88!88 888 8.939M9g9(y99"9 969 $:.:=:P:c:!x:: ::::!:; .;:;M;;c;;;,;2;&(< O<"Z< }<<<<!<&< = )=63=;j==== = =!= >> :> E>6S>)>>%> >>> ?qL?? @@ }A AA.A(AA BB%BAB%\BBB<BC1C IC VCwC C#CC.C D D"%DHDKDODbDxDD DDD D DDE E5EJE#]EE EE E EEE'FCF&]F F F FF!FF FF G!G7G#LG pG}GG!GG GG%G H&H FHQH%lHHHHH HH0HI I #I1IU3IdI.IJJ"J of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationHost:IDID:Image SizeImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...SaveSave AsSave As...Save Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:Toggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUndelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: ru Language-Team: ru Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 из"%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:Все поляFields selectedПредопределенные экспорты Внимание сохранена другая копия этой записи: Эта запись была изменена, пока вы её редактирование. Выбирате: - " Отмена ", чтобы отменить ваше изменение; - " Сравнить ", чтобы увидеть модифицированный вариант; - " Переписать ", чтобы сохранить вашу текущую версию.Создать...Поиск...Вложения...ДействиеДействия...ДобавитьДобавить имя поляAdd a note to the recordДобавить вложение для этой записиДобавить существующую записьДобавить значениеВсе фалыВсегда игнорировать это предупреждение.Вы уверены что хотите удалить эту запись?Вы уверены что хотите удалить эти записи?Вложений (%d)Вложение:Вложения...Сообщение:Имя закладки:Запомнить этот фильтрСистема сбора ошибокBy: Скрытая копия:Параметры CVSСоединениеОтмена подключения к серверуРежим изменения быстрых клавишОчиститьClear the record Закрыть вкладкуCollapse all rowsCollapse rowКомандная строка:СравнитьПрерывание конкурентных записейПодтвердитеСоединение с серверомCopy URL into clipboardCopy _URL...Скопировать выделенный текстНе удается подключиться к серверу!Создать новую записьСоздать новую запись Создать новую строкуСоздать новую связьСоздан новый отчет об ошибке с идентификаторомДата созданияСоздано пользователемВырезать выделенный текстБаза данных:Date FormatУдалить выбраную запись Delimiter:Display formatDisplayed date formatВы хотите продолжить?Эл.почтаОтправить отчет по Эл.почтеЭл.почта...РедактироватьИзменить настройки пользователяИзменить выбранную запись Редактируемые поляЭл.почтаНастройки программы электронной почтыКодировка:ОшибкаОшибка открытия файла CSVОшибка при обработке файла на поле %s.Ошибка: Исключительная ситуация:Expand all rowsExpand rowExpand/CollapseЭкспорт в CSVИзбранноеЛожныйFast TabbingПолучение списка баз данныхНаименование поляФайл "%s" не найденФайл для импорта:НайтиForegroundНеточныйВвысота:Сервер / база данныхСервер:портIDНомер строкиРазмер изображенияИзображенияИмпорт из файла CSVНесовместимая версия сервераСочетания клавиш быстрого доступаДата изменения:Изменена пользователем:Выполнить действиеПеременные доступные для подстановки:ОграничениеКол-во записейСтроки для пропуска:СсылкаСписок горячих клавишЛогинМУправление закладкамиОтметить линию на удалениеМодель:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageИмяСледующийСледующая записьСледующий WidgetНичего не найдено.Note(%d)Notes (%s)Notes...ОткрытьOpen filtersОткрыть связанные записиОткрыть связьОткрыть отчетОткрыть...Открыть / Поиск связейOverride '%s' definition?PNG изображение (*.png)Пароль:Вставить скопированный текстПорт:Pre-validationНастройкаНастройкиПредыдущийПредыдущая записьПредыдущий WidgetПечатьПечать отчетаПечать...ПрофильРедактор профилейПрофиль:Quote char:СвязанныеСвязанные...Связи записей "быстрого доступа"Удалить "%s"Удалить Удалить выбраную записьУдалить выбраную запись Удалить эту закладкуОтчетСообщить об ошибкеОтчет...СохранитьСохранить какСохранить как...Сохранить размерыСохранить эту записьПоискSearch %sНастройки ограничения поискаМаксимальное количество строк...Поиск записи SelectSelect a colorSelect allSelect parentВыберите действиеSelect...Select/Activate current rowВыборСервер:Показать сохраненные фильтрыПоказать в виде текстаShow revisions...Проверка орфографииТема:ПереключитьГорячие клавиши в текстовых поляхДанное действие приведет к закрытию всех вкладок. Продолжить?Эта же ошибка была уже сообщена от другого пользователя. Чтобы держать вас в курсе ваше имя пользователя будет добавлен в список перечень по этому вопросуThe values of "%s" are not validВы можете отправить отчет об ошибке если вы зарегистрированны на %sКому:Toggle rowToggle selectionСлишком много аргументовПеревод текущего окнаПереводTree viewИстинныйTryton соединениеUnable to delete wizard %sUnable to search for completion of %sНе удается установить локализацию %sВосстановить выбраную запись НеизвестноУбрать отметку на удалениеUnselect allИмя пользователя:Пользователь:Имя пользователя:Просмотр измененийWeekУкажите имя для экспорта.Ширина:МастерЗаписать все равноГYesВаш выбор:О программеДействия_ДобавитьОтменаЗакрыть вкладкуПодключение..._Connection_Copy URLПо умолчаниюУдалить...ОтключениеКопироватьЭл.почта...Настройки _Эл.почтыЭкспорт данныхФормаГлобальный поискПомощьЗначкиИмпорт данных_Быстрые клавишиУправление профилямиОбновить менюПоказать/скрыть меню_МенюРежимНовыйСледующаяСледующая вкладкаНормальный_Notes..._ПараметрыУпрощенныйНастройки...ПредыдущаяПредыдущая вкладкапечать_Выход...Связанные...Обновить/Отменить_УдалитьОтчет...СохранитьСохранить настройкиПоискСменить просмотрТекстТекст и ЗначкиПанель инструментов_Пользовательдрежим разработкиgo backgo forwardчвсе сообщения на уровне INFOмnext yearprevious yearsуказать альтернативный конфигурационный файлуказать уровень вывода сообщений: DEBUG, INFO, WARNING, ERROR, CRITICALуказать имя пользователяtнytryton-4.6.5/tryton/data/locale/pl/0000755000175000017500000000000013260723567016532 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/pl/LC_MESSAGES/0000755000175000017500000000000013260723567020317 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/pl/LC_MESSAGES/tryton.po0000644000175000017500000010710513255571102022210 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "podaj alternatywny plik konfiguracyjny" #: tryton/config.py:73 msgid "development mode" msgstr "tryb dewelopera" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "rejestrowanie wszystkiego na poziomie INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "podaj poziom rejestrowania: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "podaj login użytkownika" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "podaj nazwę:port serwera" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Zbyt wiele argumentów" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Nie znaleziono pliku \"%s\"" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "Nie można zapisać pliku konfiguracyjnego %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Nie można ustawić lokalizacji %s" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr ", " #: tryton/action/main.py:95 msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Wybierz akcję" #: tryton/action/main.py:197 msgid "No action defined." msgstr "Brak zdefiniowanej akcji." #: tryton/common/button.py:56 msgid "By: " msgstr "Przez: " #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Łączenie z systemem Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Serwer:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Port:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Zaznaczenie" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Twoje zaznaczenie:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Zapisz jako..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Zawsze ignoruj takie ostrzeżenie." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Czy chcesz kontynuować?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Potwierdzenie" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Wyjątek równoczesnego zapisu danych" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Ostrzeżenie o równoczesnym zapisie danych:\n" "\n" "Dane zostały zmienione w trakcie twojej pracy nad nimi.\n" " Wybierz:\n" " - \"Anuluj\" jeśli chcesz anulować zapis danych;\n" " - \"Porównaj\" jeśli chcesz zobaczyć zmienioną wersję danych;\n" " - \"Zapisz\" jeśli chcesz zapisać aktualną wersję danych." #: tryton/common/common.py:766 msgid "Compare" msgstr "Porównaj" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Zapisz" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Błąd" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Zgłoś błąd" #: tryton/common/common.py:809 msgid "Application Error." msgstr "Błąd aplikacji." #: tryton/common/common.py:832 msgid "Error: " msgstr "Błąd: " #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Aby zgłosić błędy musisz posiadać konto w %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Bug Tracker" #: tryton/common/common.py:899 msgid "User:" msgstr "Użytkownik:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Hasło:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Taki sam błąd został już zgłoszony przez innego użytkownika.\n" "Abyś był na bieżąco z informacjami o błędzie zostałeś dopisany do właściwej listy" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Nowe zgłoszenie o błędzie otrzymało ID " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "Błędna nazwa użytkownika lub hasło!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Wyjątek:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "Odcisk palca serwera uległ zmianie od ostatniego połączenia!\n" "Aplikacja zostanie rozłączona z serwerem do momentu ustalenia właściwego odcisku palca." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "Zagrożenie bezpieczeństwa!" #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Błąd połączenia!\n" "Nie można połączyć się z serwerem!" #: tryton/common/common.py:1077 msgid "Network Error." msgstr "Problem z siecią!" #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Szukaj..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Utwórz..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "Brak możliwości wyszukania uzupełnienia dla %s" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Wartość" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Wyświetlana wartość" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Format" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Wyświetl format" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Otwórz kalendarz" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Format daty" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Wyświetlany format daty" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "t" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "Tak" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Tak" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "p" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Nie" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Edycja..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Załączniki..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "Notatki..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Akcje..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Dotyczy..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Raport..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "E-mail..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Wydruk..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "R" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "t" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "g" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "Połączenie" #: tryton/gui/main.py:222 msgid "_User" msgstr "Użytkownik" #: tryton/gui/main.py:236 msgid "_Options" msgstr "Opcje" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Ulubione" #: tryton/gui/main.py:260 msgid "_Help" msgstr "Pomoc" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Szukaj" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Nie znaleziono wyniku." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "Połącz..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Rozłącz" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Wyjście..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "Preferencje..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "Odśwież menu" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "Zwiń/rozwiń menu" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "Wyszukiwanie globalne" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "Pasek narzędzi" #: tryton/gui/main.py:502 msgid "_Default" msgstr "Domyślnie" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "Tekst i ikony" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "Ikony" #: tryton/gui/main.py:532 msgid "_Text" msgstr "Tekst" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "Pasek menu" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Zmień klawisze skrótów" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "Tryb" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "Normalny" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Formularz" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Zapamiętaj szerokość/wysokość" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Zapamiętaj stan drzewa" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "Szybki tabulator" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Sprawdzanie pisowni" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "Poprzednia karta" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "Następna karta" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Ograniczenie wyszukiwania..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "E-mail..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "Zapisz opcje" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Skróty klawiszowe..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "O programie..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Zarządzaj ulubionymi" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "Wykonanie polecenia wymaga zamknięcia wszystkich kart.\n" "Czy chcesz kontynuować?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Zamknij kartę" #: tryton/gui/window/attachment.py:22 #, python-format msgid "Attachments (%s)" msgstr "Załączniki (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Edytor profili" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profil" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "Dodaj" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "Usuń" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Host:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Baza danych:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Pobieranie listy baz danych" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Użytkownik:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Niewłaściwa wersja serwera" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Nie można połączyć się z serwerem" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Login" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "Anuluj" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Anuluj połączenie z serwerem Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "Połącz" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Połącz z serwerem Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profil:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "Zarządzanie profilami" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Informacje o hoście / bazie danych" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Użytkownik:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "E-mail" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Ustawienia czytnika poczty" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Linia poleceń:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Lista dostępnych symboli zastępczych:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Do:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "DW:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Temat:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Treść:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Załącznik:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Załącznik(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "Notatka(%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "Musisz wybrać jeden rekord." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Utworzył:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Data utworzenia:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Autor ostatniej modyfikacji:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Data ostatniej modyfikacji:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Model:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Czy na pewno usunąć wybrany rekord?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Czy na pewno usunąć wybrane rekordy?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "Rekordy nie zostały usunięte." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "Rekordy zostały usunięte." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "Pracujesz na zduplikowanym(ch) rekordzie(ch)." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "Rekord został zapisany." #: tryton/gui/window/form.py:423 msgid " of " msgstr " z " #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Rekord został zmodyfikowany.\n" "Czy chcesz go zapisać?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Akcja" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Uruchom akcję" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Odnośnik" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Otwórz powiązane rekordy" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Raport" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Otwórz raport" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "E-mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "Wyślij raport" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Wydruk" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Drukuj raport" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "Skopiuj adres URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "Skopiuj adres URL do schowka" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Nieznany" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limit" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Ustawienia limitu wyszukiwania" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Limit:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "Notatki (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Preferencje" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Edytuj preferencje użytkownika" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Preferencje" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Rewizja" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Wybierz rewizję" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Rewizja:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Skróty klawiszowe" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Skróty dotyczące tekstu" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Wytnij zaznaczony tekst" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Skopiuj zaznaczony tekst" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Wklej zaznaczony tekst" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Następny widżet" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Poprzedni widżet" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Skróty dotyczące odnośników" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Utwórz nowy odnośnik" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Otwórz/Szukaj odnośnik" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Skróty dotyczące list" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Utwórz nowy wiersz" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Utwórz odnośnik" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Zaznacz wiersz do usunięcia" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Odznacz wiersz do usunięcia" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Widżety edycji" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "Przesuń kursor" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "Przesuń w prawo" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "Przesuń w lewo" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "Przesuń w górę" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "Przesuń w dół" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "Przesuń w górę o jedną stronę" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "Przesuń w dół o jedną stronę" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "Przesuń do góry" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "Przesuń do dołu" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "Przesuń do elementu nadrzędnego" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "Zaznacz wszystko" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "Odznacz wszystko" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "Zaznacz element nadrzędny" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "Zaznacz/Aktywuj bieżący wiersz" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "Przełącz zaznaczenie" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "Rozwiń/Zwiń" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "Rozwiń wiersz" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "Zwiń wiersz" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "Przełącz wiersz" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "Zwiń wszystkie wiersze" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "Rozwiń wszystkie wiersze" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "Widok drzewa" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Przełącz widok" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "Przełącz widok" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "Poprzedni" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Poprzedni rekord" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "Następny" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Następny rekord" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "Szukaj" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "Nowy" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Utwórz nowy rekord" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "Zapisz" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Zapisz rekord" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "Odśwież/Przywróć" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "Odśwież/Przywróć" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "Duplikuj" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Usuń..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Przeglądaj dziennik..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Pokaż rewizje..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "Załączniki..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Dodaj załącznik do rekordu" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "Notatki..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "Dodaj notatkę do rekordu" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "Akcje..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "Odnośnik..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "Raport..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "E-mail..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "Wydruk..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "Eksportuj dane..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "Importuj dane..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "Skopiuj adres URL..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Zamknij kartę" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Wszystkie pola" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "Wyczyść" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "Pola wybrane" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Parametry CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "Separator:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "Symbol dziesiętny:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Kodowanie:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nazwa pola" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Eksport do CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Predefiniowane eksporty" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nazwa" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "Zapisz eksport" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "Usuń eksport" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Otwórz" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Zapisz" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Dodaj nazwy pól" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (string)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "%s (model name)" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "%s (record name)" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Jaka jest nazwa tego eksportu?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Czy nadpisać definicję '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format msgid "%d record saved." msgstr "%d rekord został zapisany." #: tryton/gui/window/win_export.py:333 #, python-format msgid "%d records saved." msgstr "%d rekordy zostały zapisane." #: tryton/gui/window/win_export.py:336 #, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Operacja nie powiodła się.\n" "Komunikat błędu:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Link" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Dodaj" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "Usuń " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "Utwórz nowy rekord " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Usuń zaznaczony rekord " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Przywróć zaznaczony rekord " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Poprzedni" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Następny" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Przełącz" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importuj z CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "Rozpoznaj" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Plik do zaimportowania:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Otwórz..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Wiersze do ominięcia:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "Najpierw wybierz plik do zaimportowania." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Błąd otwarcia pliku CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Błąd przetwarzania pliku w polu %s." #: tryton/gui/window/win_import.py:201 #, python-format msgid "%d record imported." msgstr "Rekord %d został zaimportowany." #: tryton/gui/window/win_import.py:203 #, python-format msgid "%d records imported." msgstr "Rekordy %d zostały zaimportowane." #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "Szukaj %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "Brak możliwości usunięcia kreatora %s" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Kreator" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ID" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Utworzył" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Data utworzenia" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Zmodyfikował" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Data modyfikacji" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, python-format msgid "Unable to get view tree state for %s" msgstr "Brak możliwości uzyskania stanu widoku drzewa dla %s" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Brak możliwości ustawienia stanu widoku drzewa" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" jest nieprawidłowy pod względem swojej domeny" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "\"%s\" jest wymagany" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "Wartości \"%s\" nie są prawidłowe" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "Wstępna walidacja" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Rozmiar obrazka" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Szerokość:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Wysokość:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "Obrazek w formacie PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Zapisz jako" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "Za duży rozmiar obrazka." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "Otwórz filtry" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Pokaż zakładki filtrów" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Usuń zakładkę" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Dodaj filtr do zakładek" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Dodaj do zakładek nazwę:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Znajdź" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Dzisiaj" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "wstecz" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "dalej" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "poprzedni rok" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "następny rok" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Widok tygodnia" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Widok miesiąca" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Tydzień" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "Wybierz..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Wyczyść" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Wszystkie pliki" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "Wybierz" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Pokaż tekst" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Dodaj wartość" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Usuń \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Obrazki" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Dodaj istniejący rekord" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "Usuń wybrany rekored " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "Otwórz rekord " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "Wyczyść record " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "Szukaj rekord " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Usuń wybrany rekord" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Edytuj wybrany rekord " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "Przód" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "Wybierz kolor" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "Tłumaczenie" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Edycja" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Niejasne" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "Musisz zapisać rekord przed dodaniem tłumaczeń." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "Brak innych języków." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Widok tłumaczenia" tryton-4.6.5/tryton/data/locale/pl/LC_MESSAGES/tryton.mo0000644000175000017500000004513013260723565022214 0ustar cedced00000000000000d< \])b #&+.24F]w]n   3#F%j   &"I]c z   +2"U mz % 4BQ c my    (BJZ` w&     "/ GRfv { "2L d!r  ' 2 > H ^ m z       ! !1! :!E!N! S!`! u! !!!!!#!!" #"-"?"E" T" _"k"t""" """"" " """# #!# <# H# T#a#x### # ## ### ##$$$$ +$5$K$[$p$$$$ $ $$ $$ $% %%%5%G%V%_% f%r%I%}%Q& &5'46'k'o' u'''' ' ''''$'% (F(^(|(((( ( (( () )) ) ')H)O)(V) ))))%)7)* * )*5* :*G*O* V* a* m* y*** * * * * ******++++ <+ I+V+_+e+j+ p+z+ ++++ + + ++ + ++ +, , ,!, ),6,<,L,U,[,],n, v,, ,, , ,,,<,- 2-S-U-W-Y-!/4%/Z/ m//"////0 0 0%0(0-0004060L0`0101111111 2$2A2Z2j2"z22%2&22 33+3;3D3_3 x333 33%33 3344 /4<4 L4%V4 |44'4<4 5'5<5&U5|5555+566 !6 +666 N6 [6g6 6666666 7 7717 L7V7f7m7 777%77 778 8$838<8@8Q8 m8x888888 8#8889990989G9d9w999'9999 ::(:.:0:F:c:j: {::::!:::!: ;1;C;"U;x;~; ;;;;;; < < <*<2<A<\<n<}<< <<2<<=8=@=W=]= p= |= ==== = =====>>?> [> e>p>> > >>>>>? ??&?/? 6?B?Q?"i? ?? ?????@ @-@>@O@j@ y@ @ @@@ @@@A AA)APCAA3B"B5B8(CaCeCmCCCC C CCC(C6$D1[D"D0D.D"E3EIJILI\IcIiI*kII I II&IAIJ8JRJTJVJ of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: pl Language-Team: pl Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 z "%s" jest nieprawidłowy pod względem swojej domeny"%s" jest wymaganyRekord %d został zaimportowany.%d rekord został zapisany.Rekordy %d zostały zaimportowane.%d rekordy zostały zapisane.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:Wszystkie polaPola wybranePredefiniowane eksportyOstrzeżenie o równoczesnym zapisie danych: Dane zostały zmienione w trakcie twojej pracy nad nimi. Wybierz: - "Anuluj" jeśli chcesz anulować zapis danych; - "Porównaj" jeśli chcesz zobaczyć zmienioną wersję danych; - "Zapisz" jeśli chcesz zapisać aktualną wersję danych.Utwórz...Szukaj...Załączniki...AkcjaAkcje...DodajDodaj nazwy pólDodaj notatkę do rekorduDodaj załącznik do rekorduDodaj istniejący rekordDodaj wartośćWszystkie plikiZawsze ignoruj takie ostrzeżenie.Błąd aplikacji.Czy na pewno usunąć wybrany rekord?Czy na pewno usunąć wybrane rekordy?Załącznik(%d)Załącznik:Załączniki (%s)Załączniki...Treść:Dodaj do zakładek nazwę:Dodaj filtr do zakładekBug TrackerPrzez: DW:Parametry CSVPołączAnuluj połączenie z serwerem TrytonZmień klawisze skrótówWyczyśćWyczyść record Zamknij kartęZwiń wszystkie wierszeZwiń wierszLinia poleceń:PorównajWyjątek równoczesnego zapisu danychPotwierdzeniePołącz z serwerem TrytonBłędna nazwa użytkownika lub hasło!Błąd połączenia! Nie można połączyć się z serwerem!Skopiuj adres URL do schowkaSkopiuj adres URL...Skopiuj zaznaczony tekstNie można połączyć się z serweremUtwórz nowy rekordUtwórz nowy rekord Utwórz nowy wierszUtwórz nowy odnośnikNowe zgłoszenie o błędzie otrzymało ID Data utworzeniaData utworzenia:UtworzyłUtworzył:Wytnij zaznaczony tekstBaza danych:Format datyUsuń zaznaczony rekord Separator:Wyświetl formatWyświetlany format datyWyświetlana wartośćCzy chcesz kontynuować?E-mailWyślij raportE-mail...EdycjaEdytuj preferencje użytkownikaEdytuj wybrany rekord Edycja...Widżety edycjiE-mailUstawienia czytnika pocztyKodowanie:BłądBłąd otwarcia pliku CSVBłąd przetwarzania pliku w polu %s.Błąd: Wyjątek:Rozwiń wszystkie wierszeRozwiń wierszRozwiń/ZwińEksport do CSVUlubioneNieSzybki tabulatorPobieranie listy baz danychNazwa polaNie znaleziono pliku "%s"Plik do zaimportowania:ZnajdźPrzódFormatNiejasneWysokość:Informacje o hoście / bazie danychHost:IDID:Rozmiar obrazkaZa duży rozmiar obrazka.ObrazkiImportuj z CSVNiewłaściwa wersja serweraSkróty klawiszoweData ostatniej modyfikacji:Autor ostatniej modyfikacji:Uruchom akcjęLista dostępnych symboli zastępczych:LimitLimit:Wiersze do ominięcia:LinkSkróty dotyczące listLoginMZarządzaj ulubionymiZaznacz wiersz do usunięciaModel:Data modyfikacjiZmodyfikowałWidok miesiącaPrzesuń kursorPrzesuń w dółPrzesuń w dół o jedną stronęPrzesuń do dołuPrzesuń w lewoPrzesuń do elementu nadrzędnegoPrzesuń w prawoPrzesuń do góryPrzesuń w góręPrzesuń w górę o jedną stronęNazwaProblem z siecią!NastępnyNastępny rekordNastępny widżetBrak zdefiniowanej akcji.Brak innych języków.Nie znaleziono wyniku.Notatka(%d)Notatki (%s)Notatki...OtwórzOtwórz filtryOtwórz powiązane rekordyUtwórz odnośnikOtwórz raportOtwórz kalendarzOtwórz rekord Otwórz...Otwórz/Szukaj odnośnikOperacja nie powiodła się. Komunikat błędu: %sCzy nadpisać definicję '%s'?Obrazek w formacie PNG (*.png)Hasło:Wklej zaznaczony tekstPort:Wstępna walidacjaPreferencjePreferencjePoprzedniPoprzedni rekordPoprzedni widżetWydrukDrukuj raportWydruk...ProfilEdytor profiliProfil:Symbol dziesiętny:Rekord został zapisany.Rekordy nie zostały usunięte.Rekordy zostały usunięte.OdnośnikDotyczy...Skróty dotyczące odnośnikówOdśwież/PrzywróćUsuń "%s"Usuń Usuń wybrany rekordUsuń wybrany rekored Usuń zakładkęRaportZgłoś błądRaport...RewizjaRewizja:ZapiszZapisz jakoZapisz jako...Zapamiętaj stan drzewaZapamiętaj szerokość/wysokośćZapisz rekordSzukajSzukaj %sUstawienia limitu wyszukiwaniaOgraniczenie wyszukiwania...Szukaj rekord Zagrożenie bezpieczeństwa!WybierzWybierz kolorWybierz rewizjęZaznacz wszystkoZaznacz element nadrzędnyWybierz akcjęWybierz...Zaznacz/Aktywuj bieżący wierszZaznaczenieSerwer:Pokaż zakładki filtrówPokaż tekstPokaż rewizje...Sprawdzanie pisowniTemat:PrzełączPrzełącz widokSkróty dotyczące tekstuWykonanie polecenia wymaga zamknięcia wszystkich kart. Czy chcesz kontynuować?Taki sam błąd został już zgłoszony przez innego użytkownika. Abyś był na bieżąco z informacjami o błędzie zostałeś dopisany do właściwej listyOdcisk palca serwera uległ zmianie od ostatniego połączenia! Aplikacja zostanie rozłączona z serwerem do momentu ustalenia właściwego odcisku palca.Wartości "%s" nie są prawidłoweRekord został zmodyfikowany. Czy chcesz go zapisać?Aby zgłosić błędy musisz posiadać konto w %sDo:DzisiajPrzełącz wierszPrzełącz zaznaczenieZbyt wiele argumentówWidok tłumaczeniaTłumaczenieWidok drzewaTakŁączenie z systemem TrytonBrak możliwości usunięcia kreatora %sBrak możliwości uzyskania stanu widoku drzewa dla %sBrak możliwości wyszukania uzupełnienia dla %sNie można ustawić lokalizacji %sBrak możliwości ustawienia stanu widoku drzewaNie można zapisać pliku konfiguracyjnego %s!Przywróć zaznaczony rekord NieznanyOdznacz wiersz do usunięciaOdznacz wszystkoUżytkownik:Użytkownik:Użytkownik:WartośćPrzeglądaj dziennik...TydzieńWidok tygodniaJaka jest nazwa tego eksportu?Szerokość:KreatorPracujesz na zduplikowanym(ch) rekordzie(ch).ZapiszRTakMusisz wybrać jeden rekord.Najpierw wybierz plik do zaimportowania.Musisz zapisać rekord przed dodaniem tłumaczeń.Twoje zaznaczenie:O programie...Akcje...DodajRozpoznajAnulujWyczyśćZamknij kartęPołącz...PołączenieSkopiuj adres URLDomyślnieUsuń eksportUsuń...RozłączDuplikujE-mail...E-mail...Eksportuj dane...FormularzWyszukiwanie globalnePomocIkonyImportuj dane...Skróty klawiszowe...Zarządzanie profilamiOdśwież menuZwiń/rozwiń menuPasek menuTrybNowyNastępnyNastępna kartaNormalnyNotatki...OpcjePDAPreferencje...PoprzedniPoprzednia kartaWydruk...Wyjście...Odnośnik...Odśwież/PrzywróćUsuńRaport...ZapiszZapisz eksportZapisz opcjeSzukajPrzełącz widokTekstTekst i ikonyPasek narzędziUżytkownikdtryb deweloperawsteczdalejgrejestrowanie wszystkiego na poziomie INFOmnastępny rokpoprzedni rokspodaj alternatywny plik konfiguracyjnypodaj poziom rejestrowania: DEBUG, INFO, WARNING, ERROR, CRITICALpodaj login użytkownikapodaj nazwę:port serweraptttryton-4.6.5/tryton/data/locale/lo/0000755000175000017500000000000013260723567016531 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/lo/LC_MESSAGES/0000755000175000017500000000000013260723567020316 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/lo/LC_MESSAGES/tryton.po0000644000175000017500000013254213255571102022212 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "ລະບຸ config file ທີ່ສະຫຼັບກັນ" #: tryton/config.py:73 msgid "development mode" msgstr "ຮູບແບບການພັດທະນາ" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "ເຂົ້າໃຊ້ທຸກຢ່າງໃນລະດັບຂໍ້ມູນ" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" "ລະບຸ ລະດັບ ການບັນທຶກ: ແກ້ໄຂຂໍ້ຜິດພາດ, ຂໍ້ມູນ, ຄຳເຕືອນ, ຂໍ້ຜິດພາດ, ທີ່ສຳຄັນ" #: tryton/config.py:81 msgid "specify the login user" msgstr "ລະບຸ ຜູ້ເຂົ້າໃຊ້ງານ" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "ລະບຸ ທີ່ຢູ່ ຂອງ ເຄື່ອງແມ່ຂ່າຍ" #: tryton/config.py:87 msgid "Too much arguments" msgstr "ມີຂໍ້ໂຕ້ແຍ່ງຫຼາຍເກີນໄປ" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "ບໍ່ພໍ້ ຟາຍລ໌ \"%s\" ນີ້" #: tryton/config.py:128 #, python-format, python-format, python-format msgid "Unable to write config file %s." msgstr "ບໍ່ສາມາດ ຂຽນ ຟາຍລ໌ ຕັ້ງຄ່າ (config file) %s ນີ້ໄດ້." #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "ບໍ່ສາມາດຕັ້ງຄ່າ ທ້ອງຖິ່ນ %s ໄດ້." #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr "," #: tryton/action/main.py:95 msgid ",…" msgstr ",..." #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "%s (%s)" #: tryton/action/main.py:191 msgid "Select your action" msgstr "ເລືອກການດຳເນີນການຂອງທ່ານ" #: tryton/action/main.py:197 msgid "No action defined." msgstr "ບໍ່ມີ ການດຳເນີນການ ທີ່ລະບຸໄວ້!" #: tryton/common/button.py:56 msgid "By: " msgstr "ໂດຍ:" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "ການເຊື່ອມຕໍ່ເຂົ້າ ໄຕຣຕັອນ" #: tryton/common/common.py:250 msgid "Server:" msgstr "ແມ່ຂ່າຍ:" #: tryton/common/common.py:268 msgid "Port:" msgstr "ປະຕູເຊື່ອມຕໍ່:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "ການເລືອກ" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "ການເລືອກຂອງທ່ານ:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "ບັນທຶກເປັນ..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "ບໍ່ສົນກັບຄຳເຕືອນນີ້ເລີຍ." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "ທ່ານຕ້ອງການດຳເນີນການຕໍ່ໄປບໍ່?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "ການຢືນຢັນ" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "ຍົກເວັ້ນການເຂົ້າເຖິງພ້ອມກັນ" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "ຂຽນຄຳເຕືອນການເຂົ້າພ້ອມກັນ:\n" "\n" "ແຖວຂໍ້ມູນນີ້ຖືກປ່ຽນແປງໃນເວລາທີ່ທ່ານແກ້ໄຂມັນແລ້ວ.\n" " ໃຫ້ເລືອກ:\n" " - \"ຍົກເລີກ\" ເພື່ອຍົກເລີກການບັນທຶກ;\n" " - \"ສົມທຽບ\" ເພື່ອເບິ່ງສະບັບທີ່ປ່ຽນແປງ;\n" " - \"ຂຽນລົງເລີຍ\" ເພື່ອບັນທຶກ ສະບັບປັດຈຸບັນຂອງທ່ານ." #: tryton/common/common.py:766 msgid "Compare" msgstr "ສົມທຽບ" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "ຂຽນລົງເລີຍ" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "ຜິດພາດ" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "ລາຍງານຂໍ້ຜິດພາດ" #: tryton/common/common.py:809 msgid "Application Error." msgstr "ໂປຣແກຣມ ມີຂໍ້ຜິດພາດ!" #: tryton/common/common.py:832 msgid "Error: " msgstr "ຂໍ້ຜິດພາດ:" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "ທ່ານຕ້ອງມີບັນຊີໃຊ້ຈຶ່ງຈະສາມາດລາຍງານຂໍ້ຜິດພາດ %s ນີ້ໄດ້" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "ໂຕຕິດຕາມ ຂໍ້ຜິດພາດ" #: tryton/common/common.py:899 msgid "User:" msgstr "ຜູ້ໃຊ້:" #: tryton/common/common.py:907 msgid "Password:" msgstr "ລະຫັດຜ່ານ:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "ຂໍ້ຜິດພາດອັນດຽວກັນນີ້ ຖືກລາຍງານ ໂດຍຜູ້ໃຊ້ງານຄົນອື່ນແລ້ວ.\n" "ເພື່ອໃຫ້ທ່ານໄດ້ຮັບຂໍ້ມູນການແກ້ໄຂ ຊື່ເຂົ້າໃຊ້ງານຂອງທ່ານ ໄດ້ຖືກເພີ່ມ ເຂົ້າໃນ ບັນຊີລາຍຊື່ຂອງບັນຫານີ້້" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "ສ້າງ ລາຍການຂໍ້ຜິດພາດ ໃໝ່ ດ້ວຍ ເລກກຳກັບ " #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" "ການເຊື່ອມຕໍ່ ຜິດພາດ!\n" "ຊື່ຜູໃຊ້ ຫຼື ລະຫັດຜ່ານ ບໍ່ຖືກຕ້ອງ!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "ຂໍ້ຍົກເວັ້ນ:" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "ແມ່ຂ່າຍລາຍພິມນີ້ວມື ຖືກປ່ຽນແປງ ຕັ້ງແຕ່ ການເຊື່ອມຕໍ່ເຂົ້າໃຊ້ ຄັ້ງລ້າສຸດ!\n" "ໂປຣແກຣມ ຈະຢຸດ ການເຊື່ອມຕໍ່ເຂົ້າແມ່ຂ່າຍນີ້ ຈົນກວ່າ ການພິມລາຍນີ້ວມຶ ຈະຖືກແກ້ໄຂ." #: tryton/common/common.py:1005 msgid "Security risk." msgstr "ຄວາມປອດໄພ ມີຄວາມສ່ຽງ!" #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "ການເຊື່ອມຕໍ່ຜິດພາດ!\n" "ບໍ່ສາມາດ ເຊື່ອມຕໍ່ເຂົ້າຫາແມ່ຂ່າຍໄດ້!" #: tryton/common/common.py:1077 msgid "Network Error." msgstr "ເຄືອຂ່າຍ ຜິດພາດ!" #: tryton/common/common.py:1410 msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "ຊອກຫາ..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "ສ້າງ..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "ຄ່າ" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "ຄ່າສະແດງອອກ" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "ຮູບແບບ" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "ຮູບແບບສະແດງອອກ" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "ໄຂປະຕິທິນ" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "ຮູບແບບວັນທີ" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "ຮູບແບບວັນທີທີ່ສະແດງອອກ" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "ມ" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "ແມ່ນ" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "ຈິງ" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "ຈ" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "ຜິດ" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "ແກ້ໄຂ..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "ຄັດຕິດ..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "ໝາຍເຫດ..." #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "ດຳເນີນການ..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "ທີ່ກ່ຽວພັນ..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "ລາຍງານ..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "ອີ-ເມວລ໌..." #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "ພິມອອກ..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "ປ" #: tryton/common/timedelta.py:27 msgid "M" msgstr "ດ" #: tryton/common/timedelta.py:28 msgid "w" msgstr "ອ" #: tryton/common/timedelta.py:29 msgid "d" msgstr "ມ" #: tryton/common/timedelta.py:30 msgid "h" msgstr "ມ." #: tryton/common/timedelta.py:31 msgid "m" msgstr "ນ" #: tryton/common/timedelta.py:32 msgid "s" msgstr "ວ" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "_ການເຊື່ອມຕໍ່" #: tryton/gui/main.py:222 msgid "_User" msgstr "_ຜູ້ໃຊ້" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_ທາງເລືອກ" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "ທີ່_ມັກຫຼາຍ" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_ຊ່ອຍເຫຼືອ" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "ຊອກຫາ" #: tryton/gui/main.py:372 msgid "No result found." msgstr "ບໍ່ພົບຜົນຊອກຫາ" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_ເຊື່ອມຕໍ່..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_ຕັດການເຊື່ອມຕໍ່" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_ອອກ..." #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_ການຕັ້ງຄ່າຂອງ..." #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_ໂຫຼດ ລາຍການຄຳສັ່ງໃໝ່" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "_ສະຫຼັບລາຍການຄຳສັ່ງ" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "_ຊອກຫາໂດຍລວມ" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_ແຖບເຄື່ອງມື" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_ຄ່າເດີມ" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_ຂໍ້ຄວາມ ແລະ ປຸ່ມລັດ" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_ປຸ່ມລັດ" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_ຂໍ້ຄວາມ" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_ແຖບຄຳສັ່ງງານ" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "ປ່ຽນໂຕເລັ່ງ" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_ແບບສະແດງ" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_ທຳມະດາ" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_ພີດີເອ (PDA)" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_ແບບຟອມ" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "ບັນທຶກ ຄວາມກວ້າງ/ຄວາມສູງ" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "ບັນທຶກ ສະຖານະ ໂຄງສ້າງ" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "ຍ້າຍແບບໄວ" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "ກວດສອບການສະກົດຄຳ" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_ແຖບງານກ່ອນໜ້າ" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_ແຖບງານ ຕໍ່ໄປ" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "ຈຳກັດການຊອກຫາ..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_ອີເມວລ໌..." #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_ບັນທຶກ ທາງເລືອກ" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_ປຸ່ມລັດທາງແປ້ນພິມ..." #: tryton/gui/main.py:687 msgid "_About..." msgstr "_ກ່ຽວກັບ..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "ຈັດການລາຍການທີ່ມັກ" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "ການດຳເນີນການດັ່ງຕໍ່ໄປນີ້ ຕ້ອງການໃຫ້ ອັດແຖບງານທັງໝົດລົງ\n" "ທ່ານຕ້ອງການສືບຕໍ່ບໍ່?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "ອັດແຖບງານ" #: tryton/gui/window/attachment.py:22 #, python-format, python-format, python-format msgid "Attachments (%s)" msgstr "ເອກະສານຄັດຕິດ (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "ຂໍ້ມູນລາຍລະອຽດບັນນາທິການ" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "ຂໍ້ມູນລາຍລະອຽດ" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_ເພີ່ມເຂົ້າ" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_ເອົາອອກ" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "ແມ່ຂ່າຍ:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "ຖານຂໍ້ມູນ:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "ລາຍການດຶງເອົາຖານຂໍ້ມູນ" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "ຜູ້ໃຊ້:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "ບໍ່ຖືກລຸ່ນກັບແມ່ຂ່າຍ" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "ບໍ່ສາມາດເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍໄດ້" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "ເຂົ້າສູ່ລະບົບ" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_ຍົກເລີກ" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "ຍົກເລີກການເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍ ໄຕຣຕັອນ" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "ເ_ຊື່ອມຕໍ່" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "ເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍ ໄຕຣຕັອນ" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "ຂໍ້ມູນລາຍລະອຽດ:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_ບໍລິຫານລາຍລະອຽດ" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "ແມ່ຂ່າຍ / ຂໍ້ມູນກ່ຽວກັບຖານຂໍ້ມູນ" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "ຊື່ຜູ້ໃຊ້:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "ອີເມວລ໌" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "ການຕັ້ງຄ່າໂປຣແກຣມອີເມວລ໌" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "ຄຳສັ່ງງານ:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "ເລື່ອງຂອງ ທີ່ຢູ່ ທີ່ມີປັດຈຸບັນ:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "ເຖິງ:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "ຫົວເລື່ອງ:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "ເນື້ອຄວາມ:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "ເອກະສານຄັດຕິດ:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "ຄັດຕິດ(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "ບັນທຶກ (%d)" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "ທ່ານຕ້ອງໄດ້ເລືອກ ໜຶ່ງແຖວຂໍ້ມູນ." #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ເລກລໍາດັບ:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "ຜູ້ສ້າງ:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "ວັນທີສ້າງ:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "ປັບປ່ຽນລ້າສຸດ ໂດຍ:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "ວັນທີປັບປ່ຽນລ້າສຸດ:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "ແບບ:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "ທ່ານແນ່ໃຈບໍ່ທີ່ຈະລຶບແຖວຂໍ້ມູນນີ້?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "ທ່ານແນ່ໃຈບໍ່ທີ່ຈະລຶບແຖວຂໍ້ມູນເຫຼົ່ານີ້?" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "ແຖວຂໍ້ມູນບໍ່ທັນຖືກເອົາອອກ." #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "ແຖວຂໍ້ມູນຖືກເອົາອອກແລ້ວ." #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "ດຽວນີ້ກຳລັງເຮັດວຽກກັບແຖວຂໍ້ມູນທີ່ສ້າງຂຶ້ນຊ້ອນກັນ." #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "ແຖວຂໍ້ມູນບັນທຶກແລ້ວ" #: tryton/gui/window/form.py:423 msgid " of " msgstr "ຂອງ" #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "ແຖວຂໍ້ມູນນີ້ ຖືກແກ້ໄຂແລ້ວ ທ່ານຕ້ອງການບັນທຶກໄວ້ບໍ່?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "ການດຳເນີນການ" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "ເປີດການດຳເນີນການ" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "ທີ່ກ່ຽວພັນ" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "ໄຂແຖວຂໍ້ມູນທີ່ກ່ຽວພັນ" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "ລາຍງານ..." #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "ໄຂບົດລາຍງານ" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "ອີ-ເມວລ໌" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "ລາຍງານທາງອີເມວລ໌" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "ພິມອອກ" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "ພິມລາຍງານອອກ" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "_ກ່າຍ URL" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "ກ່າຍເອົາ URL ໃສ່ ຄລິບບອດ" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "ບໍ່ຮູ້" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "ຂີດຈຳກັດ:" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "ການຕັ້ງຄ່າຂີດຈຳກັດການຊອກຫາ" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "ຂີດຈຳກັດ:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "ບັນທຶກ (%s)" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "ການຕັ້ງຄ່າ" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "ແກ້ໄຂການຕັ້ງຄ່າຜູ້ໃຊ້ງານ" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "ການຕັ້ງຄ່າ" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "ການກວດແກ້ຄືນ" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "ເລືອກໜຶ່ງການກວດແກ້ຄືນ" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "ການກວດແກ້ຄືນ:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "ປຸ່ມລັດແປ້ນພິມ" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "ປຸ່ມລັດການປ້ອນຂໍ້ຄວາມ" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "ຕັດຂໍ້ຄວາມທີ່ເລືອກໄວ້" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "ກ່າຍເອົາຂໍ້ຄວາມທີ່ເລືອກໄວ້" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "ວາງຂໍ້ຄວາມທີ່ກ່າຍເອົາໃສ່" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "ເຄື່ອງມື ຕໍ່ໄປ" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "ເຄື່ອງມືກ່ອນໜ້ານີ້" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "ປຸ່ມລັດລາຍການສາຍພົວພັນ" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "ສ້າງການກ່ຽວພັນໃໝ່" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "ໄຂ/ຊອກຫາການກ່ຽວພັນ" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "ປຸ່ມລັດການປ້ອນລາຍການ" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "ສ້າງແຖວໃໝ່" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "ໄຂການກ່ຽວພັນ" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "ໝາຍແຖວເພື່ອລຶບອອກ" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "ບໍ່ໝາຍແຖວທີ່ຈະລຶບ" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "ເຄື່ອງມືການແກ້ໄຂ" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "ຍ້າຍ ເຄິກເຊີຣ໌" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "ຍ້າຍໄປຂວາ" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "ຍ້າຍໄປຊ້າຍ" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "ຍ້າຍຂຶ້ນ" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "ຍ້າຍລົງ" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "ຫຍັບຂຶ້ນໜຶ່ງໜ້າ" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "ຍ້າຍລົງລຸ່ມໜຶ່ງໜ້າ" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "ຍ້າຍຂຶ້ນເທິງສຸດ" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "ຍ້າຍລົງລຸ່ມ" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "ຍ້າຍໄປຫາບັນຊີແມ່" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "ເລືອກທັງໝົດ" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "ບໍ່ເລືອກທັງໝົດ" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "ເລືອກ ບັນຊີແມ່" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "ເລືອກ/ໃຊ້ງານແຖວປັດຈຸບັນ" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "ສະຫຼັບການເລືອກ" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "ຂະຫຽາຍອອກ/ຍຸບເຂົ້າກັນ" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "ຂະຫຽາຍແຖວອອກ" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "ຍຸບແຖວເຂົ້າກັນ" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "ສະຫຼັບແຖວ" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "ຍຸບແຖວທັງໝົດ" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "ຂະຫຽາຍແຖວທັງໝົດ" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "ມູມມອງແບບຕົ້ນໄມ້" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_ສະຫຼັບໜ້າເບິ່ງ" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "_ສະຫຼັບໜ້າເບິ່ງ" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_ກ່ອນໜ້າ" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "ແຖວຂໍ້ມູນກ່ອນນີ້" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_ຕໍ່ໄປ" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "ແຖວຂໍ້ມູນ ຕໍ່ໄປ" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_ຊອກຫາ" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_ສ້າງໃໝ່" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "ສ້າງແຖວຂໍ້ມູນໃໝ່" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_ບັນທຶກ" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "ບັນທຶກແຖວຂໍ້ມູນນີ້" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_ໂຫຼດຄືນໃໝ່/ຍົກເລີກ" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "_ໂຫຼດຄືນໃໝ່/ຍົກເລີກ" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_ເຮັດຊໍ້າກັນ" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_ລຶບ..." #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "ເບິ່ງ_ບັນທຶກ..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "ສະແດງການກວດແກ້ຄືນ..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "ຄ_ັດຕິດ..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "ເພີ່ມເອກະສານຄັດຕິດໃສ່ແຖວຂໍ້ມູນ" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "_ຈົດບັນທຶກ..." #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "ເພີ່ມບັນທຶກຂໍ້ຄວາມໃສ່ແຖວຂໍ້ມູນ" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_ດຳເນີນການ..." #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "_ທີ່ກ່ຽວພັນ..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_ລາຍງານ..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_ອີ-ແມວລ໌.." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_ພິມອອກ..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_ສົ່ງອອກຂໍ້ມູນ..." #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_ນໍາເຂົ້າຂໍ້ມູນ..." #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "ກ່າຍ_URL..." #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_ອັດແຖບງານ" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "ຊ່ອງຂໍ້ມູນທັງໝົດ" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "_ໃຫ້ເປົາ" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "ຊ່ອງຂໍ້ມູນທີ່ເລືອກໄວ້" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "ຂອບເຂດການໃຊ້ (parameters) ຂອງ ຟາຍລ໌ CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "ຕົວຂັ້ນ:" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "ຂໍ້ຄວາມອ້າງອີງ:" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "ເຂົ້າລະຫັດ:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "ຊື່ຊ່ອງຂໍ້ມູນ" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "ສົ່ງອອກເປັນຟາຍລ໌ CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "ການສົ່ງອອກທີ່ຈັດຕຽມໄວ້ກ່ອນ" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "ຊື່" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "_ບັນທຶກການສົ່ງອອກ" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "_ລຶບການສົ່ງອອກ" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "ໄຂ" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "ບັນທຶກ" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "ເພີ່ມ_ຊ່ອງຂໍ້ມູນ" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (ສະຕຣິງ)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "ຊື່ຂອງການສົ່ງອອກນີ້ແມ່ນຫຍັງ?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "ຂຽນທັບ ຄຳອະທິບາຍ '%s' ນີ້ບໍ່?" #: tryton/gui/window/win_export.py:331 #, python-format, python-format, python-format msgid "%d record saved." msgstr "ແຖວຂໍ້ມູນ %d ຖືກບັນທຶກແລ້ວ!" #: tryton/gui/window/win_export.py:333 #, python-format, python-format, python-format msgid "%d records saved." msgstr "ບັນດາແຖວຂໍ້ມູນ %d ຖືກບັນທຶກແລ້ວ!" #: tryton/gui/window/win_export.py:336 #, python-format, python-format, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "ການດຳເນີນການລົ້ມເຫຼວ!\n" "ຂໍ້ຄວາມເຕືອນຂໍ້ຜິດພາດ:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "ເຊື່ອມໂຍງ" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "ເພີ່ມ" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "ເອົາອອກ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "ສ້າງແຖວຂໍ້ມູນໃໝ່ " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "ລຶບແຖວຂໍ້ມູນທີ່ເລືອກ " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "ຍົກເລີກການລຶບແຖວທີ່ເລືອກ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "ກ່ອນໜ້າ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "ຕໍ່ໄປ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "ສະຫຼັບ" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "ນໍາເຂົ້າຈາກ ຟາຍລ໌ CSV" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "_ກວດຫາ-ອັດຕະໂນມັດ" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "ຟາຍລ໌ທີ່ຈະນໍາເຂົ້າ:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "ໄຂ..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "ແຖວທີ່ຈະຂວ້າມ:" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "ກ່ອນອື່ນ ທ່ານຕ້ອງໄດ້ເລືອກ ຟາຍລ໌ ທີ່ຈະນໍາເຂົ້າກ່ອນ." #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "ຜິດພາດໃນການໄຂ ຟາຍລ໌ CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "ປະມວນຜົນ ຟາຍລ໌ ຜິດພາດ ໃນຊ່ອງຂໍ້ມູນ %s." #: tryton/gui/window/win_import.py:201 #, python-format, python-format, python-format msgid "%d record imported." msgstr "ແຖວຂໍ້ມູນ %d ຖືກນໍາເຂົ້າແລ້ວ!" #: tryton/gui/window/win_import.py:203 #, python-format, python-format, python-format msgid "%d records imported." msgstr "ບັນດາແຖວຂໍ້ມູນ %d ຖືກນໍາເຂົ້າແລ້ວ!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "ຊອກຫາ %s" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "ໂຕນໍາພາສ້າງ" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "ເລກລໍາດັບ" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "ຜູ້ສ້າງ" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "ວັນທີສ້າງ" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "ຜູ້ປັບປ່ຽນ" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "ວັນທີປັບປ່ຽນ" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "ບໍ່ສາມາດຕັ້ງຄ່າສະຖານະມູມມອງແບບຕົ້ນໄມ້ໄດ້" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "\"%s\" ບໍ່ຖືກຕ້ອງ ກັບ ໂດເມນຂອງມັນ" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "ຕ້ອງໃຫ້ມີ \"%s\"" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "ຄ່າຂອງ \"%s\" ນີ້ ບໍ່ຖືກຕ້ອງ" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "ກ່ອນ-ການກວດສອບ" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "ຂະໜາດຮູບ" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "ຄວາມກວ້າງ:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "ຄວາມສູງ:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "ຮູບແບບ PNG (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "ບັນທຶກເປັນ" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "ຂະໜາດຮູບ ໃຫຍ່ໂພດ." #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr ".." #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "ໄຂໂຕກັ່ນຕອງ" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "ສະແດງໝາຍໜ້າຂອງການກັ່ນຕອງ" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "ເອົາໝາຍໜ້ານີ້ອອກ" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "ໝາຍໜ້າກັ່ນຕອງນີ້" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "ຊື່ໝາຍໜ້າ:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "ຊອກພົບ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "ມື້ນີ້" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "ກັບຄືນ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "ໄປໜ້າ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "ປີກ່ອນ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "ປີຕໍ່ໄປ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "ເບິ່ງເປັນລາຍອາທິດ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "ເບິ່ງເປັນເດືອນ" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "ອາທິດ" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "ເລືອກ..." #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "ໃຫ້ເປົ່າ" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "ຟາຍລ໌ ທັງໝົດ" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "ເລືອກ..." #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "ສະແດງເປັນຂໍ້ຄວາມທຳມະດາ" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "ເພີ່ມຄ່າ" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "ເອົາ \"%s\" ອອກ" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "ຮູບ" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "ເພີ່ມແຖວຂໍ້ມູນທີ່ມີຢູ່" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "ເອົາແຖວຂໍ້ມູນທີ່ເລືອກນີ້ອອກ " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "ໄຂແຖວຂໍ້ມູນ " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "ອະນາໄມແຖວຂໍ້ມູນ " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "ຊອກຫາແຖວຂໍ້ມູນໜຶ່ງ " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "ເອົາແຖວຂໍ້ມູນທີ່ເລືອກນີ້ອອກ" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "ແກ້ໄຂ ແຖວຂໍ້ມູນ ທີ່ເລືອກ " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "%s%%" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "ພື້ນໜ້າ" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "ເລືອກສີ" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "ການແປ" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "ແກ້ໄຂ" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "ເລືອນລາງ" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "ທ່ານຕ້ອງບັນທຶກຂໍ້ມູນໄວ້ກ່ອນຈຶ່ງເພີ່ມການແປເຂົ້າໄປໄດ້." #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "ບໍ່ມີພາສາອື່ນໃຫ້ໃຊ້." #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "ມູມມອງການແປ" tryton-4.6.5/tryton/data/locale/lo/LC_MESSAGES/tryton.mo0000644000175000017500000006772413260723565022230 0ustar cedced00000000000000a$ ,-)2\m -G->O_ fqu  #%:` o{ &-3 JT f s +2% =J]}  ! 3 =I fq  *0 GQW&n      "6F KV]ck " 4!Bdjq     . = J Y g s {       ! !!! #!0! E! S!_!q!!!#!!! !!"" $" /";"D"T"d" j"w"""" " """" "" # #%#<#Y#n# u# ## ### ##### ##$$4$C$J$Y$ k$ v$$ $$ $$$$$ %%#%*%IA%}% & &5&4&#''' -'8'I'\' k' w''''$'%''(4(T(s({( ( (( (( (( ( ())() 7)D)F)J)%i)7)) ) )) ))* * * %* 1*;*D* S* ^* j* u* ********* * ++++"+ (+2+ :+D+M+R+ b+ l+ z++ + ++ ++ + ++ +++, ,,,&, .,9, ;,\, ^, h,v,x,<,,,,,, w.O. .M.G@/\/V/<0D0T0e0}00000070F0U1Lg1333$3!4@4.P4Z4Z4B55x5"5F585a46s6 7(!7,J7w7770747 -888O<88m8!9993R99$9*99:Q":t:O::x;<<V<Nj<Z<0=5E={=3=k=:>V>s>>?>>!>B?b?*y?B?!?U @_@0v@@@H@IAdA0wAAHAB'B;:BdvBB"B-C$IC=nC4CC D DB'D'jD1D7DDE%E8EQEZhEEEEF/,F \F5fF<F*F7G2M!cMM&M M4MNGNNNH O(VO(OOOO0O6-PdP$wPP*PHP+&Q+RQ9~QLQFRLR!kRBRRRQSWTS0SS-S!T$7T%\TTT!T;TDU6WUUUNU*V;+V;gVVV?V! W(.WHWWWCWWXH'XBpX6X0XY8Y?KYYhZ*\@]^^ F_T_g_*_B_!_`0#` T`I^``$`%`TaxcamaHJbb3b*bc"c6c Jc%Tczc3cRcd!.dPdde eYelee.ffff/gOgfg}gg%ggg( h 2h.@h"ohhh+hh"i)iFi.]i7i.i;i7/j%gjjjj#jjk'kAk+[kk(kk k"k5lEl\lsl1l,ll+l#m6:m"qmmm0mmmnTnZn^ntnn=nn7oooo of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%, ,….....:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: lo Language-Team: lo Plural-Forms: nplurals=1; plural=0 MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 ຂອງ"%s" ບໍ່ຖືກຕ້ອງ ກັບ ໂດເມນຂອງມັນຕ້ອງໃຫ້ມີ "%s"ແຖວຂໍ້ມູນ %d ຖືກນໍາເຂົ້າແລ້ວ!ແຖວຂໍ້ມູນ %d ຖືກບັນທຶກແລ້ວ!ບັນດາແຖວຂໍ້ມູນ %d ຖືກນໍາເຂົ້າແລ້ວ!ບັນດາແຖວຂໍ້ມູນ %d ຖືກບັນທຶກແລ້ວ!%s (%s)%s (model name)%s (record name)%s (ສະຕຣິງ)%s%%,,........:ຊ່ອງຂໍ້ມູນທັງໝົດຊ່ອງຂໍ້ມູນທີ່ເລືອກໄວ້ການສົ່ງອອກທີ່ຈັດຕຽມໄວ້ກ່ອນຂຽນຄຳເຕືອນການເຂົ້າພ້ອມກັນ: ແຖວຂໍ້ມູນນີ້ຖືກປ່ຽນແປງໃນເວລາທີ່ທ່ານແກ້ໄຂມັນແລ້ວ. ໃຫ້ເລືອກ: - "ຍົກເລີກ" ເພື່ອຍົກເລີກການບັນທຶກ; - "ສົມທຽບ" ເພື່ອເບິ່ງສະບັບທີ່ປ່ຽນແປງ; - "ຂຽນລົງເລີຍ" ເພື່ອບັນທຶກ ສະບັບປັດຈຸບັນຂອງທ່ານ.ສ້າງ...ຊອກຫາ...ຄ_ັດຕິດ...ການດຳເນີນການດຳເນີນການ...ເພີ່ມເພີ່ມ_ຊ່ອງຂໍ້ມູນເພີ່ມບັນທຶກຂໍ້ຄວາມໃສ່ແຖວຂໍ້ມູນເພີ່ມເອກະສານຄັດຕິດໃສ່ແຖວຂໍ້ມູນເພີ່ມແຖວຂໍ້ມູນທີ່ມີຢູ່ເພີ່ມຄ່າຟາຍລ໌ ທັງໝົດບໍ່ສົນກັບຄຳເຕືອນນີ້ເລີຍ.ໂປຣແກຣມ ມີຂໍ້ຜິດພາດ!ທ່ານແນ່ໃຈບໍ່ທີ່ຈະລຶບແຖວຂໍ້ມູນນີ້?ທ່ານແນ່ໃຈບໍ່ທີ່ຈະລຶບແຖວຂໍ້ມູນເຫຼົ່ານີ້?ຄັດຕິດ(%d)ເອກະສານຄັດຕິດ:ເອກະສານຄັດຕິດ (%s)ຄັດຕິດ...ເນື້ອຄວາມ:ຊື່ໝາຍໜ້າ:ໝາຍໜ້າກັ່ນຕອງນີ້ໂຕຕິດຕາມ ຂໍ້ຜິດພາດໂດຍ:CC:ຂອບເຂດການໃຊ້ (parameters) ຂອງ ຟາຍລ໌ CSVເ_ຊື່ອມຕໍ່ຍົກເລີກການເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍ ໄຕຣຕັອນປ່ຽນໂຕເລັ່ງໃຫ້ເປົ່າອະນາໄມແຖວຂໍ້ມູນ ອັດແຖບງານຍຸບແຖວທັງໝົດຍຸບແຖວເຂົ້າກັນຄຳສັ່ງງານ:ສົມທຽບຍົກເວັ້ນການເຂົ້າເຖິງພ້ອມກັນການຢືນຢັນເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍ ໄຕຣຕັອນການເຊື່ອມຕໍ່ ຜິດພາດ! ຊື່ຜູໃຊ້ ຫຼື ລະຫັດຜ່ານ ບໍ່ຖືກຕ້ອງ!ການເຊື່ອມຕໍ່ຜິດພາດ! ບໍ່ສາມາດ ເຊື່ອມຕໍ່ເຂົ້າຫາແມ່ຂ່າຍໄດ້!ກ່າຍເອົາ URL ໃສ່ ຄລິບບອດກ່າຍ_URL...ກ່າຍເອົາຂໍ້ຄວາມທີ່ເລືອກໄວ້ບໍ່ສາມາດເຊື່ອມຕໍ່ກັບແມ່ຂ່າຍໄດ້ສ້າງແຖວຂໍ້ມູນໃໝ່ສ້າງແຖວຂໍ້ມູນໃໝ່ ສ້າງແຖວໃໝ່ສ້າງການກ່ຽວພັນໃໝ່ສ້າງ ລາຍການຂໍ້ຜິດພາດ ໃໝ່ ດ້ວຍ ເລກກຳກັບ ວັນທີສ້າງວັນທີສ້າງ:ຜູ້ສ້າງຜູ້ສ້າງ:ຕັດຂໍ້ຄວາມທີ່ເລືອກໄວ້ຖານຂໍ້ມູນ:ຮູບແບບວັນທີລຶບແຖວຂໍ້ມູນທີ່ເລືອກ ຕົວຂັ້ນ:ຮູບແບບສະແດງອອກຮູບແບບວັນທີທີ່ສະແດງອອກຄ່າສະແດງອອກທ່ານຕ້ອງການດຳເນີນການຕໍ່ໄປບໍ່?ອີ-ເມວລ໌ລາຍງານທາງອີເມວລ໌ອີ-ເມວລ໌...ແກ້ໄຂແກ້ໄຂການຕັ້ງຄ່າຜູ້ໃຊ້ງານແກ້ໄຂ ແຖວຂໍ້ມູນ ທີ່ເລືອກ ແກ້ໄຂ...ເຄື່ອງມືການແກ້ໄຂອີເມວລ໌ການຕັ້ງຄ່າໂປຣແກຣມອີເມວລ໌ເຂົ້າລະຫັດ:ຜິດພາດຜິດພາດໃນການໄຂ ຟາຍລ໌ CSVປະມວນຜົນ ຟາຍລ໌ ຜິດພາດ ໃນຊ່ອງຂໍ້ມູນ %s.ຂໍ້ຜິດພາດ:ຂໍ້ຍົກເວັ້ນ:ຂະຫຽາຍແຖວທັງໝົດຂະຫຽາຍແຖວອອກຂະຫຽາຍອອກ/ຍຸບເຂົ້າກັນສົ່ງອອກເປັນຟາຍລ໌ CSVທີ່_ມັກຫຼາຍຜິດຍ້າຍແບບໄວລາຍການດຶງເອົາຖານຂໍ້ມູນຊື່ຊ່ອງຂໍ້ມູນບໍ່ພໍ້ ຟາຍລ໌ "%s" ນີ້ຟາຍລ໌ທີ່ຈະນໍາເຂົ້າ:ຊອກພົບພື້ນໜ້າຮູບແບບເລືອນລາງຄວາມສູງ:ແມ່ຂ່າຍ / ຂໍ້ມູນກ່ຽວກັບຖານຂໍ້ມູນແມ່ຂ່າຍ:ເລກລໍາດັບເລກລໍາດັບ:ຂະໜາດຮູບຂະໜາດຮູບ ໃຫຍ່ໂພດ.ຮູບນໍາເຂົ້າຈາກ ຟາຍລ໌ CSVບໍ່ຖືກລຸ່ນກັບແມ່ຂ່າຍປຸ່ມລັດແປ້ນພິມວັນທີປັບປ່ຽນລ້າສຸດ:ປັບປ່ຽນລ້າສຸດ ໂດຍ:ເປີດການດຳເນີນການເລື່ອງຂອງ ທີ່ຢູ່ ທີ່ມີປັດຈຸບັນ:ຂີດຈຳກັດ:ຂີດຈຳກັດ:ແຖວທີ່ຈະຂວ້າມ:ເຊື່ອມໂຍງປຸ່ມລັດການປ້ອນລາຍການເຂົ້າສູ່ລະບົບດຈັດການລາຍການທີ່ມັກໝາຍແຖວເພື່ອລຶບອອກແບບ:ວັນທີປັບປ່ຽນຜູ້ປັບປ່ຽນເບິ່ງເປັນເດືອນຍ້າຍ ເຄິກເຊີຣ໌ຍ້າຍລົງຍ້າຍລົງລຸ່ມໜຶ່ງໜ້າຍ້າຍລົງລຸ່ມຍ້າຍໄປຊ້າຍຍ້າຍໄປຫາບັນຊີແມ່ຍ້າຍໄປຂວາຍ້າຍຂຶ້ນເທິງສຸດຍ້າຍຂຶ້ນຫຍັບຂຶ້ນໜຶ່ງໜ້າຊື່ເຄືອຂ່າຍ ຜິດພາດ!ຕໍ່ໄປແຖວຂໍ້ມູນ ຕໍ່ໄປເຄື່ອງມື ຕໍ່ໄປບໍ່ມີ ການດຳເນີນການ ທີ່ລະບຸໄວ້!ບໍ່ມີພາສາອື່ນໃຫ້ໃຊ້.ບໍ່ພົບຜົນຊອກຫາບັນທຶກ (%d)ບັນທຶກ (%s)ໝາຍເຫດ...ໄຂໄຂໂຕກັ່ນຕອງໄຂແຖວຂໍ້ມູນທີ່ກ່ຽວພັນໄຂການກ່ຽວພັນໄຂບົດລາຍງານໄຂປະຕິທິນໄຂແຖວຂໍ້ມູນ ໄຂ...ໄຂ/ຊອກຫາການກ່ຽວພັນການດຳເນີນການລົ້ມເຫຼວ! ຂໍ້ຄວາມເຕືອນຂໍ້ຜິດພາດ: %sຂຽນທັບ ຄຳອະທິບາຍ '%s' ນີ້ບໍ່?ຮູບແບບ PNG (*.png)ລະຫັດຜ່ານ:ວາງຂໍ້ຄວາມທີ່ກ່າຍເອົາໃສ່ປະຕູເຊື່ອມຕໍ່:ກ່ອນ-ການກວດສອບການຕັ້ງຄ່າການຕັ້ງຄ່າກ່ອນໜ້າແຖວຂໍ້ມູນກ່ອນນີ້ເຄື່ອງມືກ່ອນໜ້ານີ້ພິມອອກພິມລາຍງານອອກພິມອອກ...ຂໍ້ມູນລາຍລະອຽດຂໍ້ມູນລາຍລະອຽດບັນນາທິການຂໍ້ມູນລາຍລະອຽດ:ຂໍ້ຄວາມອ້າງອີງ:ແຖວຂໍ້ມູນບັນທຶກແລ້ວແຖວຂໍ້ມູນບໍ່ທັນຖືກເອົາອອກ.ແຖວຂໍ້ມູນຖືກເອົາອອກແລ້ວ.ທີ່ກ່ຽວພັນທີ່ກ່ຽວພັນ...ປຸ່ມລັດລາຍການສາຍພົວພັນເອົາ "%s" ອອກເອົາອອກເອົາແຖວຂໍ້ມູນທີ່ເລືອກນີ້ອອກເອົາແຖວຂໍ້ມູນທີ່ເລືອກນີ້ອອກ ເອົາໝາຍໜ້ານີ້ອອກລາຍງານ...ລາຍງານຂໍ້ຜິດພາດລາຍງານ...ການກວດແກ້ຄືນການກວດແກ້ຄືນ:ບັນທຶກບັນທຶກເປັນບັນທຶກເປັນ...ບັນທຶກ ສະຖານະ ໂຄງສ້າງບັນທຶກ ຄວາມກວ້າງ/ຄວາມສູງບັນທຶກແຖວຂໍ້ມູນນີ້ຊອກຫາຊອກຫາ %sການຕັ້ງຄ່າຂີດຈຳກັດການຊອກຫາຈຳກັດການຊອກຫາ...ຊອກຫາແຖວຂໍ້ມູນໜຶ່ງ ຄວາມປອດໄພ ມີຄວາມສ່ຽງ!ເລືອກ...ເລືອກສີເລືອກໜຶ່ງການກວດແກ້ຄືນເລືອກທັງໝົດເລືອກ ບັນຊີແມ່ເລືອກການດຳເນີນການຂອງທ່ານເລືອກ...ເລືອກ/ໃຊ້ງານແຖວປັດຈຸບັນການເລືອກແມ່ຂ່າຍ:ສະແດງໝາຍໜ້າຂອງການກັ່ນຕອງສະແດງເປັນຂໍ້ຄວາມທຳມະດາສະແດງການກວດແກ້ຄືນ...ກວດສອບການສະກົດຄຳຫົວເລື່ອງ:ສະຫຼັບປຸ່ມລັດການປ້ອນຂໍ້ຄວາມການດຳເນີນການດັ່ງຕໍ່ໄປນີ້ ຕ້ອງການໃຫ້ ອັດແຖບງານທັງໝົດລົງ ທ່ານຕ້ອງການສືບຕໍ່ບໍ່?ຂໍ້ຜິດພາດອັນດຽວກັນນີ້ ຖືກລາຍງານ ໂດຍຜູ້ໃຊ້ງານຄົນອື່ນແລ້ວ. ເພື່ອໃຫ້ທ່ານໄດ້ຮັບຂໍ້ມູນການແກ້ໄຂ ຊື່ເຂົ້າໃຊ້ງານຂອງທ່ານ ໄດ້ຖືກເພີ່ມ ເຂົ້າໃນ ບັນຊີລາຍຊື່ຂອງບັນຫານີ້້ແມ່ຂ່າຍລາຍພິມນີ້ວມື ຖືກປ່ຽນແປງ ຕັ້ງແຕ່ ການເຊື່ອມຕໍ່ເຂົ້າໃຊ້ ຄັ້ງລ້າສຸດ! ໂປຣແກຣມ ຈະຢຸດ ການເຊື່ອມຕໍ່ເຂົ້າແມ່ຂ່າຍນີ້ ຈົນກວ່າ ການພິມລາຍນີ້ວມຶ ຈະຖືກແກ້ໄຂ.ຄ່າຂອງ "%s" ນີ້ ບໍ່ຖືກຕ້ອງແຖວຂໍ້ມູນນີ້ ຖືກແກ້ໄຂແລ້ວ ທ່ານຕ້ອງການບັນທຶກໄວ້ບໍ່?ທ່ານຕ້ອງມີບັນຊີໃຊ້ຈຶ່ງຈະສາມາດລາຍງານຂໍ້ຜິດພາດ %s ນີ້ໄດ້ເຖິງ:ມື້ນີ້ສະຫຼັບແຖວສະຫຼັບການເລືອກມີຂໍ້ໂຕ້ແຍ່ງຫຼາຍເກີນໄປມູມມອງການແປການແປມູມມອງແບບຕົ້ນໄມ້ຈິງການເຊື່ອມຕໍ່ເຂົ້າ ໄຕຣຕັອນUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sບໍ່ສາມາດຕັ້ງຄ່າ ທ້ອງຖິ່ນ %s ໄດ້.ບໍ່ສາມາດຕັ້ງຄ່າສະຖານະມູມມອງແບບຕົ້ນໄມ້ໄດ້ບໍ່ສາມາດ ຂຽນ ຟາຍລ໌ ຕັ້ງຄ່າ (config file) %s ນີ້ໄດ້.ຍົກເລີກການລຶບແຖວທີ່ເລືອກບໍ່ຮູ້ບໍ່ໝາຍແຖວທີ່ຈະລຶບບໍ່ເລືອກທັງໝົດຊື່ຜູ້ໃຊ້:ຜູ້ໃຊ້:ຜູ້ໃຊ້:ຄ່າເບິ່ງ_ບັນທຶກ...ອາທິດເບິ່ງເປັນລາຍອາທິດຊື່ຂອງການສົ່ງອອກນີ້ແມ່ນຫຍັງ?ຄວາມກວ້າງ:ໂຕນໍາພາສ້າງດຽວນີ້ກຳລັງເຮັດວຽກກັບແຖວຂໍ້ມູນທີ່ສ້າງຂຶ້ນຊ້ອນກັນ.ຂຽນລົງເລີຍປແມ່ນທ່ານຕ້ອງໄດ້ເລືອກ ໜຶ່ງແຖວຂໍ້ມູນ.ກ່ອນອື່ນ ທ່ານຕ້ອງໄດ້ເລືອກ ຟາຍລ໌ ທີ່ຈະນໍາເຂົ້າກ່ອນ.ທ່ານຕ້ອງບັນທຶກຂໍ້ມູນໄວ້ກ່ອນຈຶ່ງເພີ່ມການແປເຂົ້າໄປໄດ້.ການເລືອກຂອງທ່ານ:_ກ່ຽວກັບ..._ດຳເນີນການ..._ເພີ່ມເຂົ້າ_ກວດຫາ-ອັດຕະໂນມັດ_ຍົກເລີກ_ໃຫ້ເປົາ_ອັດແຖບງານ_ເຊື່ອມຕໍ່..._ການເຊື່ອມຕໍ່_ກ່າຍ URL_ຄ່າເດີມ_ລຶບການສົ່ງອອກ_ລຶບ..._ຕັດການເຊື່ອມຕໍ່_ເຮັດຊໍ້າກັນ_ອີ-ແມວລ໌.._ອີເມວລ໌..._ສົ່ງອອກຂໍ້ມູນ..._ແບບຟອມ_ຊອກຫາໂດຍລວມ_ຊ່ອຍເຫຼືອ_ປຸ່ມລັດ_ນໍາເຂົ້າຂໍ້ມູນ..._ປຸ່ມລັດທາງແປ້ນພິມ..._ບໍລິຫານລາຍລະອຽດ_ໂຫຼດ ລາຍການຄຳສັ່ງໃໝ່_ສະຫຼັບລາຍການຄຳສັ່ງ_ແຖບຄຳສັ່ງງານ_ແບບສະແດງ_ສ້າງໃໝ່_ຕໍ່ໄປ_ແຖບງານ ຕໍ່ໄປ_ທຳມະດາ_ຈົດບັນທຶກ..._ທາງເລືອກ_ພີດີເອ (PDA)_ການຕັ້ງຄ່າຂອງ..._ກ່ອນໜ້າ_ແຖບງານກ່ອນໜ້າ_ພິມອອກ..._ອອກ..._ທີ່ກ່ຽວພັນ..._ໂຫຼດຄືນໃໝ່/ຍົກເລີກ_ເອົາອອກ_ລາຍງານ..._ບັນທຶກ_ບັນທຶກການສົ່ງອອກ_ບັນທຶກ ທາງເລືອກ_ຊອກຫາ_ສະຫຼັບໜ້າເບິ່ງ_ຂໍ້ຄວາມ_ຂໍ້ຄວາມ ແລະ ປຸ່ມລັດ_ແຖບເຄື່ອງມື_ຜູ້ໃຊ້ມຮູບແບບການພັດທະນາກັບຄືນໄປໜ້າມ.ເຂົ້າໃຊ້ທຸກຢ່າງໃນລະດັບຂໍ້ມູນນປີຕໍ່ໄປປີກ່ອນວລະບຸ config file ທີ່ສະຫຼັບກັນລະບຸ ລະດັບ ການບັນທຶກ: ແກ້ໄຂຂໍ້ຜິດພາດ, ຂໍ້ມູນ, ຄຳເຕືອນ, ຂໍ້ຜິດພາດ, ທີ່ສຳຄັນລະບຸ ຜູ້ເຂົ້າໃຊ້ງານຈອມtryton-4.6.5/tryton/data/locale/it_IT/0000755000175000017500000000000013260723567017127 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/it_IT/LC_MESSAGES/0000755000175000017500000000000013260723567020714 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/it_IT/LC_MESSAGES/tryton.po0000644000175000017500000010475213255571102022612 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "indica un altro file di configurazione" #: tryton/config.py:73 msgid "development mode" msgstr "modo sviluppatore" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "registrare tutto a livello INFO" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" "specifica il livello di registrazione: DEBUG, INFO, WARNING, ERROR, CRITICAL" #: tryton/config.py:81 msgid "specify the login user" msgstr "specifica l'utente di accesso" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "specifica l'hostname" #: tryton/config.py:87 msgid "Too much arguments" msgstr "Troppi argomenti" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "File \"%s\" non trovato" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Impossibile scrivere il file di configurazione %s!" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Impossibile impostare la localizzazione %s" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Scegliere un'azione" #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Nessuna azione definita!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Connessione Tryton" #: tryton/common/common.py:250 msgid "Server:" msgstr "Server:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Porta:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Selezione" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Selezione:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Salva come..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Ignorare sempre l'avviso" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "Procedere?" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Conferma" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Eccezione di concorrenza" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Write Concurrency Warning:\n" "\n" "Il record veniva modificato durante l'edit.\n" "Scegliere:\n" "- \"Cancel\" per rinunciare a salvarlo;\n" "- \"Compare\" per vedere la versione modificata;\n" "- \"Write Anyway\" per salvare la versione attuale." #: tryton/common/common.py:766 msgid "Compare" msgstr "Confrontare" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Scrivere comunque" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Errore" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Segnala un bug" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Errore di applicazione!" #: tryton/common/common.py:832 msgid "Error: " msgstr "Errore:" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "Per segnalare bugs è necessario avere un account in %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Bug Tracker" #: tryton/common/common.py:899 msgid "User:" msgstr "Utente:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Password:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Lo stesso bug è stato già segnalato da altro utente.\n" "Per tua informazione il tuo nome utente è aggiunto alla nosy-list di questo problema" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Creato nuovo bug con ID" #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Errore di connessione!\n" "Nome utente o password errati!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Eccezione:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "La fingerprint del server è cambiata dall'ultima connessione!\n" "L'applicazione terminerà la connessione a questo server finché il fingerprint non sia corretto." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Rischio di sicurezza!" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Errore di connessione!\n" "Impossibile connettersi al server!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Errore di rete!" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "Cerca..." #: tryton/common/completion.py:27 msgid "Create..." msgstr "Crea..." #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "Valore" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "Valore visualizzato" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "Formato" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "Formato di visualizzazione" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "Apertura calendario" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "Formato data" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "Formato data visualizzato" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "a" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "True" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "o" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "False" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "Modifica..." #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "Allegati..." #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "Azioni..." #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "Riferire..." #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "Segnala..." #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "E-Mail" #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "Stampa..." #: tryton/common/timedelta.py:26 msgid "Y" msgstr "A" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "S" #: tryton/common/timedelta.py:29 msgid "d" msgstr "g" #: tryton/common/timedelta.py:30 msgid "h" msgstr "h" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "s" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_User" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Options" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "Fa_vorites" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Help" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Ricerca" #: tryton/gui/main.py:372 msgid "No result found." msgstr "Nessun risultato trovato." #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Connect" #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "_Disconnect" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "_Esci" #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Preferenze" #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "_Ricarica menu" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "_Menu Toggle" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "_Global Search" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Toolbar" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Default" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Testo e Icone" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "_Icone" #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Testo" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Barra dei Menu" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Cambia acceleratori" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Modalità" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normale" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "_Modulo" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Salva larghezza/altezza" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "Salva diagramma ad albero" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Controllo ortogbrafico" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "_Scheda precedente" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "_Scheda Successiva" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Limite di ricerca..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "_Email" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Salva opzioni" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "_Scorciatoie da tastiera" #: tryton/gui/main.py:687 msgid "_About..." msgstr "_About" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "Gestione Preferiti" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" "L'azione seguente richiede la chiusura di tutte le finestre.\n" "Vuoi continuare?" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Chiudere la scheda" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Allegato(%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "Editor del profilo" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "Profilo" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "Profilo" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Rimuovi" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "Host:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Database:" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "Preleva la lista dei database" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "Nome utente:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "Versione del server incompatibile" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "Impossibile connettersi al server" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Accedi" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "_Cancella" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Cancella la connessione al server Tryton" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "C_onnetti" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Connetti il server Tryton" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "Profilo:" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "_Gestisci profili" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "Informazione su Host/ database" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "nome utente" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "Email" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "Impostazioni programma Email" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Riga di comando:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Leggenda dei segnaposto disponibili:" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "a:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr ".CC" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Oggetto:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Corpo:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Allegato:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Allegato(%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Devi selezionare un record!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Utente di creazione:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Data di creazione:" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Ultima modifica a:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Ultima data di modifica:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Modello:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Sei sicuro di rimuovere questo record?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Sei sicuro di rimuovere questi records?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Record non rimossi!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Records rimossi!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Attivo ora nel (nei) record duplicato!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Record salvato!" #: tryton/gui/window/form.py:423 msgid " of " msgstr "di" #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Il record è stato modificato\n" " intendi salvarlo?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Azione" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "Lanciare l'azione" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "Collegato" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "Apri record relazionati" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "Rapporto" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "Apri rapporto" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "E-Mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "report E-Mail" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Stampa" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "Stampa report" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Sconosciuto" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limite" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Impostazione dei limiti di ricerca" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "Limite:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Preferenze" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Modifica le preferenze dell'utente" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Preferenza" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "Revisione" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "Scegli una revisione" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "Revisione:" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Scorciatoie da tastiera" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Scorciatoie imputazioni di testo" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Taglia testo selezionato" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Copia il testo selezionato" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Incolla il testo copiato" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Prossimo oggetto" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Oggetto precedente" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Scorciatoie imputazioni relazionate" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Crea nuova relazione" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Apri/Cerca relazione" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "Lista scorciatoie registrazioni" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "Crea nuova riga" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "Apri relazione" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "Seleziona riga da eliminare" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "Deseleziona riga da eliminare" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Widget di modifica" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "_Cambia vista" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "_Cambia vista" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "_Precedente" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Record Precedente" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Successivo" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Prossimo Record" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "_Cerca" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nuovo" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Crea nuovo record" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "_Salva" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Salva questo record." #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Duplicato" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "_Eliimina" #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Visualizza_Log..." #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "Mostra revisioni..." #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "A_llegati..." #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Aggiungi un allegato al record" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Azioni..." #: tryton/gui/window/tabcontent.py:119 #, fuzzy msgid "_Relate..." msgstr "Riferire..." #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "_Rapporto..." #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "_E-Mail..." #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "_Stampa..." #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Esporta dati" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importa dati" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "_Chiudi scheda" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Tutti i campi" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Pulisci" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "Parametri CSV" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codifica:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Nome di campo" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "esportazioni predefinite" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Nome" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Salva esportazione" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Elimina Esportazione" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Apri" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Salva" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Aggiungi_nomi di campo" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "%s (stringa)" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Qual è il nome di questa esportazione?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "Sostituisci definizione '%s'?" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d record salvato!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d record salvato!" #: tryton/gui/window/win_export.py:336 #, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "" #: tryton/gui/window/win_form.py:125 #, fuzzy msgid "Add" msgstr "Profilo" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 #, fuzzy msgid "Create a new record " msgstr "Crea nuovo record" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "Elimina il record selezionato " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "Non eliminare il record selezionato " #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Precedente" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Prossimo" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Cambia" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importa da CSV" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Autorilevamento" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "File da importare:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Apri..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Righe da saltare." #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "Devi prima selezionare un file di import!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Errore nell'apertura del file CSV" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "Errore nel processare il file nel campo %s." #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr " %d record importati" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr " %d record importati!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "Creazione utente" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "Data di creazione" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "Utente di modifica" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "Data di modifica" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "Impossibile configurare la vista ad albero" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr "" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Dimensione immagine" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Salva come" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "Mostra segnalibri dei filtri" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "Rimuovi questo segnalibro" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "Memorizza questo filtro" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "Nome segnalibro:" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Trova" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "Oggi" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "Vista settimanale" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "Vista mensile" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "Settimana" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Pulisci" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Tutti i files" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "Mostra testo semplice" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "Aggiungi valore" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "Rimuovi \"%s\"" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Immagini" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "Aggiungi un record esistente" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 #, fuzzy msgid "Remove selected record " msgstr "Elimina il record selezionato " #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "Rimuovi i record selezionati" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "Modifica il record selezionato " #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 #, fuzzy msgid "Translation" msgstr "Traduzione" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "Modifica" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "Vago" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "E' necessario salvare il record prima di aggiungere le traduzioni!" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Nessun altra lingua disponibile!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Traduci vista" tryton-4.6.5/tryton/data/locale/it_IT/LC_MESSAGES/tryton.mo0000644000175000017500000003724313260723565022617 0ustar cedced00000000000000@ )"L]eu   3S g q{#%    5AFJY&b    6 N[n    + 5A ^ix   "( ?IO&f      .> CNU[c " ,!:\bix}   & 5B Q _ks      *?G#\     #09AP Ye lv          ) 9 K \ c m       ! "!,!4!N!^!p!!!!I!}! n"4""" """" ###-#$H#%m###### $ $!$ '$1$ 7$E$ J$ T$u$|$ $$$$ $ $$$ $ $ $ $$ $ % % !% ,%6%F%L%[%a%h%x%% % %%%%% %% %%%% & & &&0& 9&F& N&Y& _&m& u&&&&&&&& && && & & ' '<*'g'~'''')))E)V)^)n) ))))))))** ** *++0+O+l+ |++&+'+ + + ,,,-, E,Q,V, Z, h,(r,,,,,, ,- --6-?-Y- q-~-!----- ../.@.U. n. x.#. .... ./ //$/"-/#P/ t//// //!/+/0 0(0 80C0 S0 a0l0 r00 0000 0000011"1&1:1P1Y1!h11111$12 22&2+2K2R2T2g2222 2 2 222 23 3 #3/373K3P3Y3i3z33 333 333 33 4!4)4#>4b44 4444 4 4 4445 5 &50585K5 T5 `5 j5#v5 5 5 55556 6 6 $6/6 56 @6N6h666 6"66666 7 7 *787 L7V7 r7|7777777 7M8a8 8?9O9R9 W9b9s9 9 9999$9%9*:*E:)p: :: : :: ::: ;;'';O;V;];o;q; u;; ;; ;;; ; ;; ; ; ; ;< <<$<3<9< @<N<g<y< << << <<< <<< < == "=-= 3=@= I=V=]=l= s======== ==== = = >& >L2>>>>> of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...Add _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUndelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Reload/Undo_Remove_Report..._Save_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: it_IT Language-Team: it_IT Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 di"%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (stringa)%s%%..:Tutti i campiFields selectedesportazioni predefiniteWrite Concurrency Warning: Il record veniva modificato durante l'edit. Scegliere: - "Cancel" per rinunciare a salvarlo; - "Compare" per vedere la versione modificata; - "Write Anyway" per salvare la versione attuale.Crea...Cerca...A_llegati...AzioneAzioni...Aggiungi_nomi di campoAdd a note to the recordAggiungi un allegato al recordAggiungi un record esistenteAggiungi valoreTutti i filesIgnorare sempre l'avvisoSei sicuro di rimuovere questo record?Sei sicuro di rimuovere questi records?Allegato(%d)Allegato:Allegati...Corpo:Nome segnalibro:Memorizza questo filtroBug TrackerBy: .CCParametri CSVC_onnettiCancella la connessione al server TrytonCambia acceleratoriPulisciClear the record Chiudere la schedaCollapse all rowsCollapse rowRiga di comando:ConfrontareEccezione di concorrenzaConfermaConnetti il server TrytonCopy URL into clipboardCopy _URL...Copia il testo selezionatoImpossibile connettersi al serverCrea nuovo recordCrea nuova rigaCrea nuova relazioneCreato nuovo bug con IDData di creazioneData di creazione:Creazione utenteUtente di creazione:Taglia testo selezionatoDatabase:Formato dataElimina il record selezionato Delimiter:Formato di visualizzazioneFormato data visualizzatoValore visualizzatoProcedere?E-Mailreport E-MailE-MailModificaModifica le preferenze dell'utenteModifica il record selezionato Modifica...Widget di modificaEmailImpostazioni programma EmailCodifica:ErroreErrore nell'apertura del file CSVErrore nel processare il file nel campo %s.Errore:Eccezione:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingPreleva la lista dei databaseNome di campoFile "%s" non trovatoFile da importare:TrovaForegroundFormatoVagoHeight:Informazione su Host/ databaseHost:IDID:Dimensione immagineImage size too large.ImmaginiImporta da CSVVersione del server incompatibileScorciatoie da tastieraUltima data di modifica:Ultima modifica a:Lanciare l'azioneLeggenda dei segnaposto disponibili:LimiteLimite:Righe da saltare.LinkLista scorciatoie registrazioniAccediMGestione PreferitiSeleziona riga da eliminareModello:Data di modificaUtente di modificaVista mensileMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNomeProssimoProssimo RecordProssimo oggettoNessun risultato trovato.Note(%d)Notes (%s)Notes...ApriOpen filtersApri record relazionatiApri relazioneApri rapportoApertura calendarioOpen the record Apri...Apri/Cerca relazioneOperation failed. Error message: %sSostituisci definizione '%s'?PNG image (*.png)Password:Incolla il testo copiatoPorta:Pre-validationPreferenzaPreferenzePrecedenteRecord PrecedenteOggetto precedenteStampaStampa reportStampa...ProfiloEditor del profiloProfilo:Quote char:CollegatoRiferire...Scorciatoie imputazioni relazionateReload/UndoRimuovi "%s"Remove Rimuovi i record selezionatiRimuovi questo segnalibroRapportoSegnala un bugSegnala...RevisioneRevisione:SalvaSalva comeSalva come...Salva diagramma ad alberoSalva larghezza/altezzaSalva questo record.RicercaSearch %sImpostazione dei limiti di ricercaLimite di ricerca...Search a record SelectSelect a colorScegli una revisioneSelect allSelect parentScegliere un'azioneSelect...Select/Activate current rowSelezioneServer:Mostra segnalibri dei filtriMostra testo sempliceMostra revisioni...Controllo ortogbraficoOggetto:CambiaScorciatoie imputazioni di testoL'azione seguente richiede la chiusura di tutte le finestre. Vuoi continuare?Lo stesso bug è stato già segnalato da altro utente. Per tua informazione il tuo nome utente è aggiunto alla nosy-list di questo problemaThe values of "%s" are not validPer segnalare bugs è necessario avere un account in %sa:OggiToggle rowToggle selectionTroppi argomentiTraduci vistaTree viewTrueConnessione TrytonUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sImpossibile impostare la localizzazione %sImpossibile configurare la vista ad alberoNon eliminare il record selezionato SconosciutoDeseleziona riga da eliminareUnselect allnome utenteUtente:Nome utente:ValoreVisualizza_Log...SettimanaVista settimanaleQual è il nome di questa esportazione?Width:WizardScrivere comunqueAYesSelezione:_About_Azioni...Profilo_Cancella_Chiudi scheda_Connect_Connection_Copy URL_Default_Eliimina_Disconnect_Duplicato_E-Mail..._Email_Esporta dati_Modulo_Global Search_Help_Icone_Importa dati_Scorciatoie da tastiera_Gestisci profili_Ricarica menu_Menu Toggle_Barra dei Menu_Modalità_Nuovo_Successivo_Scheda Successiva_Normale_Notes..._Options_PDA_Preferenze_Precedente_Scheda precedente_Stampa..._Esci_Reload/Undo_Rimuovi_Rapporto..._Salva_Salva opzioni_Cerca_Cambia vista_Testo_Testo e Icone_Toolbar_Usergmodo sviluppatorego backgo forwardhregistrare tutto a livello INFOmnext yearprevious yearsindica un altro file di configurazionespecifica il livello di registrazione: DEBUG, INFO, WARNING, ERROR, CRITICALspecifica l'utente di accessooSatryton-4.6.5/tryton/data/locale/tryton.pot0000644000175000017500000007254013255571102020200 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2017 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2017. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: tryton 4.5.dev0\n" "Report-Msgid-Bugs-To: issue_tracker@tryton.org\n" "POT-Creation-Date: 2017-10-09 19:30+0200\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=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.5.0\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "" #: tryton/config.py:128 #, python-format msgid "Unable to write config file %s." msgstr "" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "" #: tryton/action/main.py:93 tryton/common/button.py:56 msgid ", " msgstr "" #: tryton/action/main.py:95 msgid ",…" msgstr "" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "" #: tryton/action/main.py:197 msgid "No action defined." msgstr "" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "" #: tryton/common/common.py:250 msgid "Server:" msgstr "" #: tryton/common/common.py:268 msgid "Port:" msgstr "" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "" #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" #: tryton/common/common.py:766 msgid "Compare" msgstr "" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "" #: tryton/common/common.py:809 msgid "Application Error." msgstr "" #: tryton/common/common.py:832 msgid "Error: " msgstr "" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "" #: tryton/common/common.py:899 msgid "User:" msgstr "" #: tryton/common/common.py:907 msgid "Password:" msgstr "" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "" #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" #: tryton/common/common.py:986 msgid "Exception:" msgstr "" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint" " is fixed." msgstr "" #: tryton/common/common.py:1005 msgid "Security risk." msgstr "" #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" #: tryton/common/common.py:1077 msgid "Network Error." msgstr "" #: tryton/common/common.py:1410 msgid "..." msgstr "" #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "" #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "" #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "" #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "" #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "" #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "" #: tryton/common/timedelta.py:26 msgid "Y" msgstr "" #: tryton/common/timedelta.py:27 msgid "M" msgstr "" #: tryton/common/timedelta.py:28 msgid "w" msgstr "" #: tryton/common/timedelta.py:29 msgid "d" msgstr "" #: tryton/common/timedelta.py:30 msgid "h" msgstr "" #: tryton/common/timedelta.py:31 msgid "m" msgstr "" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "" #: tryton/gui/main.py:236 msgid "_Options" msgstr "" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "" #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "" #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "" #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "" #: tryton/gui/main.py:502 msgid "_Default" msgstr "" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "" #: tryton/gui/main.py:532 msgid "_Text" msgstr "" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "" #: tryton/gui/main.py:582 msgid "_Form" msgstr "" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "" #: tryton/gui/main.py:655 msgid "_Email..." msgstr "" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "" #: tryton/gui/main.py:687 msgid "_About..." msgstr "" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "" #: tryton/gui/window/attachment.py:22 #, python-format msgid "Attachments (%s)" msgstr "" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "" #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "" #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "" #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "" #: tryton/gui/window/form.py:423 msgid " of " msgstr "" #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "" #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "" #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "" #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "" #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "" #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format msgid "%d record saved." msgstr "" #: tryton/gui/window/win_export.py:333 #, python-format msgid "%d records saved." msgstr "" #: tryton/gui/window/win_export.py:336 #, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "" #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "" #: tryton/gui/window/win_import.py:201 #, python-format msgid "%d record imported." msgstr "" #: tryton/gui/window/win_import.py:203 #, python-format msgid "%d records imported." msgstr "" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr "" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "" tryton-4.6.5/tryton/data/locale/es_419/0000755000175000017500000000000013260723567017123 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/es_419/LC_MESSAGES/0000755000175000017500000000000013260723567020710 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/es_419/LC_MESSAGES/tryton.po0000644000175000017500000007201713255571102022604 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "" #: tryton/config.py:83 msgid "specify the server hostname:port" msgstr "" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "" #: tryton/config.py:128 #, python-format msgid "Unable to write config file %s." msgstr "" #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "" #: tryton/action/main.py:197 msgid "No action defined." msgstr "" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "" #: tryton/common/common.py:250 msgid "Server:" msgstr "" #: tryton/common/common.py:268 msgid "Port:" msgstr "" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "" #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "" #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "" #: tryton/common/common.py:757 msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" #: tryton/common/common.py:766 msgid "Compare" msgstr "" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "" #: tryton/common/common.py:809 msgid "Application Error." msgstr "" #: tryton/common/common.py:832 msgid "Error: " msgstr "" #: tryton/common/common.py:852 #, python-format msgid "To report bugs you must have an account on %s" msgstr "" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "" #: tryton/common/common.py:899 msgid "User:" msgstr "" #: tryton/common/common.py:907 msgid "Password:" msgstr "" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "" #: tryton/common/common.py:981 msgid "" "Connection error.\n" "Bad username or password." msgstr "" #: tryton/common/common.py:986 msgid "Exception:" msgstr "" #: tryton/common/common.py:1003 msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" #: tryton/common/common.py:1005 msgid "Security risk." msgstr "" #: tryton/common/common.py:1010 msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" #: tryton/common/common.py:1077 msgid "Network Error." msgstr "" #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 msgid "Value" msgstr "" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 msgid "Format" msgstr "" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 msgid "Open the calendar" msgstr "" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "" #: tryton/common/popup_menu.py:84 msgid "Edit..." msgstr "" #: tryton/common/popup_menu.py:89 msgid "Attachments..." msgstr "" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 msgid "Actions..." msgstr "" #: tryton/common/popup_menu.py:110 msgid "Relate..." msgstr "" #: tryton/common/popup_menu.py:111 msgid "Report..." msgstr "" #: tryton/common/popup_menu.py:112 msgid "E-Mail..." msgstr "" #: tryton/common/popup_menu.py:113 msgid "Print..." msgstr "" #: tryton/common/timedelta.py:26 msgid "Y" msgstr "" #: tryton/common/timedelta.py:27 msgid "M" msgstr "" #: tryton/common/timedelta.py:28 msgid "w" msgstr "" #: tryton/common/timedelta.py:29 msgid "d" msgstr "" #: tryton/common/timedelta.py:30 msgid "h" msgstr "" #: tryton/common/timedelta.py:31 msgid "m" msgstr "" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "" #: tryton/gui/main.py:236 msgid "_Options" msgstr "" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "" #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "" #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "" #: tryton/gui/main.py:460 msgid "_Menu Reload" msgstr "" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "" #: tryton/gui/main.py:502 msgid "_Default" msgstr "" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "" #: tryton/gui/main.py:532 msgid "_Text" msgstr "" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "" #: tryton/gui/main.py:582 msgid "_Form" msgstr "" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "" #: tryton/gui/main.py:635 msgid "_Previous Tab" msgstr "" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "" #: tryton/gui/main.py:655 msgid "_Email..." msgstr "" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "" #: tryton/gui/main.py:687 msgid "_About..." msgstr "" #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "" #: tryton/gui/window/attachment.py:22 #, python-format msgid "Attachments (%s)" msgstr "" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 msgid "Host:" msgstr "" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "" #: tryton/gui/window/dblogin.py:98 msgid "Fetching databases list" msgstr "" #: tryton/gui/window/dblogin.py:114 msgid "Username:" msgstr "" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 msgid "Incompatible version of the server" msgstr "" #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 msgid "Could not connect to the server" msgstr "" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr "" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "" #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "" #: tryton/gui/window/email.py:44 msgid "To:" msgstr "" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 msgid "You have to select one record." msgstr "" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "" #: tryton/gui/window/form.py:270 msgid "Records not removed." msgstr "" #: tryton/gui/window/form.py:272 msgid "Records removed." msgstr "" #: tryton/gui/window/form.py:301 msgid "Working now on the duplicated record(s)." msgstr "" #: tryton/gui/window/form.py:313 msgid "Record saved." msgstr "" #: tryton/gui/window/form.py:423 msgid " of " msgstr "" #: tryton/gui/window/form.py:443 msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "" #: tryton/gui/window/form.py:498 msgid "Relate" msgstr "" #: tryton/gui/window/form.py:498 msgid "Open related records" msgstr "" #: tryton/gui/window/form.py:500 msgid "Report" msgstr "" #: tryton/gui/window/form.py:500 msgid "Open report" msgstr "" #: tryton/gui/window/form.py:501 msgid "E-Mail" msgstr "" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr "" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "" #: tryton/gui/window/revision.py:19 msgid "Revision" msgstr "" #: tryton/gui/window/revision.py:27 msgid "Select a revision" msgstr "" #: tryton/gui/window/revision.py:30 msgid "Revision:" msgstr "" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "" #: tryton/gui/window/shortcuts.py:36 msgid "List Entries Shortcuts" msgstr "" #: tryton/gui/window/shortcuts.py:37 msgid "Create new line" msgstr "" #: tryton/gui/window/shortcuts.py:38 msgid "Open relation" msgstr "" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "" #: tryton/gui/window/tabcontent.py:42 msgid "Switch View" msgstr "" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "" #: tryton/gui/window/tabcontent.py:59 msgid "_Search" msgstr "" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:78 msgid "Reload/Undo" msgstr "" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "" #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 msgid "A_ttachments..." msgstr "" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "" #: tryton/gui/window/tabcontent.py:119 msgid "_Relate..." msgstr "" #: tryton/gui/window/tabcontent.py:125 msgid "_Report..." msgstr "" #: tryton/gui/window/tabcontent.py:130 msgid "_E-Mail..." msgstr "" #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "" #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "" #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "" #: tryton/gui/window/win_csv.py:86 msgid "_Clear" msgstr "" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "" #: tryton/gui/window/win_export.py:60 msgid "_Save Export" msgstr "" #: tryton/gui/window/win_export.py:69 msgid "_Delete Export" msgstr "" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format msgid "%d record saved." msgstr "" #: tryton/gui/window/win_export.py:333 #, python-format msgid "%d records saved." msgstr "" #: tryton/gui/window/win_export.py:336 #, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 msgid "Create a new record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 msgid "Delete selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 msgid "Undelete selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "" #: tryton/gui/window/win_import.py:32 msgid "_Auto-Detect" msgstr "" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "" #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "" #: tryton/gui/window/win_import.py:103 msgid "You must select an import file first." msgstr "" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "" #: tryton/gui/window/win_import.py:141 #, python-format msgid "Error processing the file at field %s." msgstr "" #: tryton/gui/window/win_import.py:201 #, python-format msgid "%d record imported." msgstr "" #: tryton/gui/window/win_import.py:203 #, python-format msgid "%d records imported." msgstr "" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:194 msgid "ID" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:195 msgid "Creation User" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:196 msgid "Creation Date" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:197 msgid "Modification User" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:198 msgid "Modification Date" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format msgid "Unable to get view tree state for %s" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:826 msgid "Unable to set view tree state" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr "" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "" #: tryton/gui/window/view_form/view/graph.py:149 msgid "Image size too large." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 msgid "Today" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 msgid "Week View" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 msgid "Month View" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 msgid "Add existing record" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 msgid "Remove selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 msgid "Open the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 msgid "Search a record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 msgid "Remove selected record" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 msgid "Edit selected record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 msgid "Translation" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 msgid "You need to save the record before adding translations." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 msgid "No other language available." msgstr "" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "" tryton-4.6.5/tryton/data/locale/es_419/LC_MESSAGES/tryton.mo0000644000175000017500000004264313260723565022613 0ustar cedced00000000000000a$ ,-)2\m  !;!2CS Zeiz  # %.T co & !' >H Z gu} +2 1>Qq   ' 1= Zet  $ ;EK&b      *: ?JQW_{ " (!6X^ety     " 1 > M [ g o         !! !$! 9! G!S!e!z!!#!!! !!" " " #"/"8"H"X" ^"k"t"|"" " """" "" # # #%#<#Y#n# u# ## ### ##### ##$$4$C$J$Y$ k$ v$$ $$ $$$$$ %%#% *%6%IM%}%& &5&4&/'3' 9'D'U'h' w' ''''$'%' ("(@(`((( ( (( (( (( ( ( ))() C)P)R)V)%u)7)) ) )) ) ** * %* 1* =*G*P* _* j* v* * ********* + ++#+)+.+ 4+>+ F+P+Y+^+ n+ x+ ++ + ++ ++ + ++ ++,,,,!,2, :,E, G,h, j, t,,,<,, ,----.)...//-/?/G/W/ h/t/y/|/~////0000 0001191 M1 W1a1}1#1%11 11222*2 ?2K2P2T2c2&l2222 22 2 223 3&3+@32l33 3333 4$444H4 a4o4 ~444 4 44 4445 585 ?5 M5W5\5r55555 555&56 6"6 26=6 M6 [6f6 l6y6 6666 6666677 7 77/767"F7i7|77 7!777777888/8F8M8_8 q8 |8 888 88 8 888 999 "9 .9:9M9j9{9 999 99 9 999::#:A:[: m:w::: : ::::: :::;; ; &;4;I;Z; a;k; ; ; ;;;;; ; << <#<(< 0<;<K<]<n< u<<<<<<<< < < = ='= C=M=U=o===== ==I=}>> )?5J?4??? ???? ? @@@*@$E@%j@@@@@A A &A 3A>A DANA TAbA gA qAAA(A AAAA%A7!BYB iB sBB BBB B B B BBB B B B C CC,C2CACGCNC^CuC C CCCCC CC CCCC C C DD D *D7D ?DJD PD ]DkD sDDDDDDDD DD DD D DE E<(EeE |EEEE of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: es_419 Language-Team: es_419 Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 of "%s" is not valid according to its domain"%s" is required%d record imported.%d record saved.%d records imported.%d records saved.%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsWrite Concurrency Warning: This record has been modified while you were editing it. Choose: - "Cancel" to cancel saving; - "Compare" to see the modified version; - "Write Anyway" to save your current version.Create...Search...A_ttachments...ActionActions...AddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd existing recordAdd valueAll filesAlways ignore this warning.Application Error.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Attachments (%s)Attachments...Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverConnection error. Bad username or password.Connection error. Unable to connect to the server.Copy URL into clipboardCopy _URL...Copy selected textCould not connect to the serverCreate a new recordCreate a new record Create new lineCreate new relationCreated new bug with ID Creation DateCreation Date:Creation UserCreation User:Cut selected textDatabase:Date FormatDelete selected record Delimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-MailE-Mail reportE-Mail...EditEdit User PreferencesEdit selected record Edit...Edition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError processing the file at field %s.Error: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingFetching databases listField nameFile "%s" not foundFile to Import:FindForegroundFormatFuzzyHeight:Host / Database informationHost:IDID:Image SizeImage size too large.ImagesImport from CSVIncompatible version of the serverKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkList Entries ShortcutsLoginMManage FavoritesMark line for deletionModel:Modification DateModification UserMonth ViewMove CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNetwork Error.NextNext RecordNext widgetNo action defined.No other language available.No result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen related recordsOpen relationOpen reportOpen the calendarOpen the record Open...Open/Search relationOperation failed. Error message: %sOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportPrint...ProfileProfile EditorProfile:Quote char:Record saved.Records not removed.Records removed.RelateRelate...Relation Entries ShortcutsReload/UndoRemove "%s"Remove Remove selected recordRemove selected record Remove this bookmarkReportReport BugReport...RevisionRevision:SaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...Search a record Security risk.SelectSelect a colorSelect a revisionSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchSwitch ViewText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe server fingerprint has changed since last connection. The application will stop connecting to this server until its fingerprint is fixed.The values of "%s" are not validThis record has been modified do you want to save it?To report bugs you must have an account on %sTo:TodayToggle rowToggle selectionToo much argumentsTranslate viewTranslationTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to get view tree state for %sUnable to search for completion of %sUnable to set locale %sUnable to set view tree stateUnable to write config file %s.Undelete selected record UnknownUnmark line for deletionUnselect allUser name:User:Username:ValueView _Logs...WeekWeek ViewWhat is the name of this export?Width:WizardWorking now on the duplicated record(s).Write AnywayYYesYou have to select one record.You must select an import file first.You need to save the record before adding translations.Your selection:_About..._Actions..._Add_Auto-Detect_Cancel_Clear_Close Tab_Connect..._Connection_Copy URL_Default_Delete Export_Delete..._Disconnect_Duplicate_E-Mail..._Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Reload_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Previous Tab_Print..._Quit..._Relate..._Reload/Undo_Remove_Report..._Save_Save Export_Save Options_Search_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login userspecify the server hostname:porttwytryton-4.6.5/tryton/data/locale/nl/0000755000175000017500000000000013260723567016530 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/nl/LC_MESSAGES/0000755000175000017500000000000013260723567020315 5ustar cedced00000000000000tryton-4.6.5/tryton/data/locale/nl/LC_MESSAGES/tryton.po0000644000175000017500000010472213255571102022210 0ustar cedced00000000000000# Translations template for tryton. # Copyright (C) 2016 Tryton # This file is distributed under the same license as the tryton project. # FIRST AUTHOR , 2016. # msgid "" msgstr "Content-Type: text/plain; charset=utf-8\n" #: tryton/config.py:70 msgid "specify alternate config file" msgstr "specificeer een vervangend configuratiebestand" #: tryton/config.py:73 msgid "development mode" msgstr "" #: tryton/config.py:76 msgid "logging everything at INFO level" msgstr "logboek bijhouden op INFO niveau" #: tryton/config.py:78 msgid "specify the log level: DEBUG, INFO, WARNING, ERROR, CRITICAL" msgstr "" #: tryton/config.py:81 msgid "specify the login user" msgstr "specificeer de inlog gebruiker" #: tryton/config.py:83 #, fuzzy msgid "specify the server hostname:port" msgstr "Stel de servernaam in" #: tryton/config.py:87 msgid "Too much arguments" msgstr "" #: tryton/config.py:90 #, python-format msgid "File \"%s\" not found" msgstr "Bestand \"%s\" niet gevonden" #: tryton/config.py:128 #, python-format, fuzzy, python-format msgid "Unable to write config file %s." msgstr "Kan configuratiebestand %s niet opslaan! " #: tryton/translate.py:185 #, python-format msgid "Unable to set locale %s" msgstr "Kan omgeving %s niet instellen" #: tryton/action/main.py:93 tryton/common/button.py:56 #, fuzzy msgid ", " msgstr ", " #: tryton/action/main.py:95 #, fuzzy msgid ",…" msgstr ",…" #: tryton/action/main.py:96 #, python-format msgid "%s (%s)" msgstr "" #: tryton/action/main.py:191 msgid "Select your action" msgstr "Selecteer je handeling." #: tryton/action/main.py:197 #, fuzzy msgid "No action defined." msgstr "Geen handeling gedefinieerd!" #: tryton/common/button.py:56 msgid "By: " msgstr "" #: tryton/common/common.py:240 msgid "Tryton Connection" msgstr "Tryton verbinding" #: tryton/common/common.py:250 msgid "Server:" msgstr "Server:" #: tryton/common/common.py:268 msgid "Port:" msgstr "Poort:" #: tryton/common/common.py:340 tryton/gui/window/shortcuts.py:56 msgid "Selection" msgstr "Selectie" #: tryton/common/common.py:348 msgid "Your selection:" msgstr "Uw selectie:" #: tryton/common/common.py:471 #: tryton/gui/window/view_form/view/form_gtk/binary.py:35 #: tryton/gui/window/view_form/view/form_gtk/binary.py:121 #: tryton/gui/window/view_form/view/graph.py:159 #: tryton/gui/window/view_form/view/list_gtk/widget.py:497 #: tryton/gui/window/win_export.py:305 msgid "Save As..." msgstr "Opslaan als..." #: tryton/common/common.py:618 msgid "Always ignore this warning." msgstr "Altijd deze waarschuwing negeren." #: tryton/common/common.py:623 msgid "Do you want to proceed?" msgstr "" #: tryton/common/common.py:642 msgid "Confirmation" msgstr "Bevestiging" #: tryton/common/common.py:744 tryton/common/common.py:1051 msgid "Concurrency Exception" msgstr "Simultaan gebruik" #: tryton/common/common.py:757 #, fuzzy msgid "" "Write Concurrency Warning:\n" "\n" "This record has been modified while you were editing it.\n" " Choose:\n" " - \"Cancel\" to cancel saving;\n" " - \"Compare\" to see the modified version;\n" " - \"Write Anyway\" to save your current version." msgstr "" "Waarschuwing voor gelijktijdig gebruik:\n" "\n" "Deze boeking is gewijzigd tijdens uw bewerking.\n" " Kies:\n" " - \"Annuleren\" om opslaan te annuleren;\n" " - \"Vergelijk\" om de verschillen te vergelijken;\n" " - \"Toch opslaan\" om deze versie op te slaan. " #: tryton/common/common.py:766 msgid "Compare" msgstr "Vergelijk" #: tryton/common/common.py:771 msgid "Write Anyway" msgstr "Overschrijven" #: tryton/common/common.py:799 tryton/gui/window/win_export.py:337 #: tryton/gui/window/win_import.py:113 tryton/gui/window/win_import.py:142 msgid "Error" msgstr "Fout" #: tryton/common/common.py:802 msgid "Report Bug" msgstr "Programmafout melden" #: tryton/common/common.py:809 #, fuzzy msgid "Application Error." msgstr "Programmafout" #: tryton/common/common.py:832 msgid "Error: " msgstr "Fout: " #: tryton/common/common.py:852 #, python-format, python-format, fuzzy, python-format msgid "To report bugs you must have an account on %s" msgstr "" "Om programmafouten aan te melden moet je een account hebben bij %s" #: tryton/common/common.py:882 msgid "Bug Tracker" msgstr "Foutrapportage" #: tryton/common/common.py:899 msgid "User:" msgstr "Gebruiker:" #: tryton/common/common.py:907 msgid "Password:" msgstr "Wachtwoord:" #: tryton/common/common.py:962 msgid "" "The same bug was already reported by another user.\n" "To keep you informed your username is added to the nosy-list of this issue" msgstr "" "Dezelfde programmafout was al gemeld door een andere gebruiker.\n" "Om je op de hoogte te houden is je gebuikersnaam toegevoegd aan de lijst van belangstellenden" #: tryton/common/common.py:973 msgid "Created new bug with ID " msgstr "Nieuwe foutmelding gemaakt met ID " #: tryton/common/common.py:981 #, fuzzy msgid "" "Connection error.\n" "Bad username or password." msgstr "" "Geen verbinding!\n" "Verkeerde gebruikersnaam of wachtwoord!" #: tryton/common/common.py:986 msgid "Exception:" msgstr "Uitzondering:" #: tryton/common/common.py:1003 #, fuzzy msgid "" "The server fingerprint has changed since last connection.\n" "The application will stop connecting to this server until its fingerprint is fixed." msgstr "" "De identificatiecode van de server is gewijzigd sinds de laatste verbinding!\n" "Het programma maakt geen verbinding meer met de server totdat de identificatiecode is hersteld." #: tryton/common/common.py:1005 #, fuzzy msgid "Security risk." msgstr "Beveiligingsrisico!" #: tryton/common/common.py:1010 #, fuzzy msgid "" "Connection error.\n" "Unable to connect to the server." msgstr "" "Verbinding mislukt!\n" "Verbinden met de server niet mogelijk!" #: tryton/common/common.py:1077 #, fuzzy msgid "Network Error." msgstr "Netwerkfout." #: tryton/common/common.py:1410 #, fuzzy msgid "..." msgstr "..." #: tryton/common/completion.py:25 msgid "Search..." msgstr "" #: tryton/common/completion.py:27 msgid "Create..." msgstr "" #: tryton/common/completion.py:69 #, python-format msgid "Unable to search for completion of %s" msgstr "" #: tryton/common/datetime_.py:35 tryton/common/datetime_.py:235 #: tryton/common/datetime_.py:385 #, fuzzy msgid "Value" msgstr "Niet waar" #: tryton/common/datetime_.py:36 tryton/common/datetime_.py:236 #: tryton/common/datetime_.py:386 msgid "Displayed value" msgstr "" #: tryton/common/datetime_.py:40 tryton/common/datetime_.py:193 #: tryton/common/datetime_.py:239 tryton/common/datetime_.py:342 #, fuzzy msgid "Format" msgstr "_Normaal" #: tryton/common/datetime_.py:41 tryton/common/datetime_.py:194 #: tryton/common/datetime_.py:240 tryton/common/datetime_.py:343 msgid "Display format" msgstr "" #: tryton/common/datetime_.py:63 #, fuzzy msgid "Open the calendar" msgstr "Open de kalender" #: tryton/common/datetime_.py:390 tryton/common/datetime_.py:395 msgid "Date Format" msgstr "" #: tryton/common/datetime_.py:391 tryton/common/datetime_.py:396 msgid "Displayed date format" msgstr "" #: tryton/common/domain_parser.py:236 msgid "y" msgstr "" #: tryton/common/domain_parser.py:236 msgid "Yes" msgstr "" #: tryton/common/domain_parser.py:236 tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "True" msgstr "Waar" #: tryton/common/domain_parser.py:236 msgid "t" msgstr "" #: tryton/common/domain_parser.py:461 #: tryton/gui/window/view_form/view/screen_container.py:551 msgid "False" msgstr "Niet waar" #: tryton/common/popup_menu.py:84 #, fuzzy msgid "Edit..." msgstr "Afsluiten" #: tryton/common/popup_menu.py:89 #, fuzzy msgid "Attachments..." msgstr "Bijlage:" #: tryton/common/popup_menu.py:96 msgid "Notes..." msgstr "" #: tryton/common/popup_menu.py:109 #, fuzzy msgid "Actions..." msgstr "_Acties.." #: tryton/common/popup_menu.py:110 #, fuzzy msgid "Relate..." msgstr "Verwijderen... " #: tryton/common/popup_menu.py:111 #, fuzzy msgid "Report..." msgstr "_Importeer gegevens... " #: tryton/common/popup_menu.py:112 #, fuzzy msgid "E-Mail..." msgstr "E-mail" #: tryton/common/popup_menu.py:113 #, fuzzy msgid "Print..." msgstr "Afdrukken" #: tryton/common/timedelta.py:26 msgid "Y" msgstr "J" #: tryton/common/timedelta.py:27 msgid "M" msgstr "M" #: tryton/common/timedelta.py:28 msgid "w" msgstr "w" #: tryton/common/timedelta.py:29 msgid "d" msgstr "d" #: tryton/common/timedelta.py:30 msgid "h" msgstr "u" #: tryton/common/timedelta.py:31 msgid "m" msgstr "m" #: tryton/common/timedelta.py:32 msgid "s" msgstr "" #: tryton/gui/main.py:214 msgid "_Connection" msgstr "" #: tryton/gui/main.py:222 msgid "_User" msgstr "_Gebruiker" #: tryton/gui/main.py:236 msgid "_Options" msgstr "_Opties" #: tryton/gui/main.py:244 msgid "Fa_vorites" msgstr "" #: tryton/gui/main.py:260 msgid "_Help" msgstr "_Help" #: tryton/gui/main.py:282 tryton/gui/main.py:844 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:341 #: tryton/gui/window/view_form/view/form_gtk/many2many.py:46 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:89 #: tryton/gui/window/view_form/view/screen_container.py:144 #: tryton/gui/window/win_search.py:32 msgid "Search" msgstr "Zoeken" #: tryton/gui/main.py:372 msgid "No result found." msgstr "" #: tryton/gui/main.py:412 msgid "_Connect..." msgstr "_Verbinden..." #: tryton/gui/main.py:422 msgid "_Disconnect" msgstr "Verbinding verbreken" #: tryton/gui/main.py:432 msgid "_Quit..." msgstr "Afsluiten" #: tryton/gui/main.py:448 msgid "_Preferences..." msgstr "_Voorkeuren..." #: tryton/gui/main.py:460 #, fuzzy msgid "_Menu Reload" msgstr "He_rladen" #: tryton/gui/main.py:470 msgid "_Menu Toggle" msgstr "" #: tryton/gui/main.py:478 msgid "_Global Search" msgstr "" #: tryton/gui/main.py:494 msgid "_Toolbar" msgstr "_Werkbalk" #: tryton/gui/main.py:502 msgid "_Default" msgstr "_Standaard" #: tryton/gui/main.py:513 msgid "_Text and Icons" msgstr "_Tekst en pictogrammen" #: tryton/gui/main.py:523 msgid "_Icons" msgstr "Pictogrammen..." #: tryton/gui/main.py:532 msgid "_Text" msgstr "_Tekst" #: tryton/gui/main.py:541 msgid "_Menubar" msgstr "_Menubalk" #: tryton/gui/main.py:549 msgid "Change Accelerators" msgstr "Versnellers aanpassen" #: tryton/gui/main.py:558 msgid "_Mode" msgstr "_Modus" #: tryton/gui/main.py:566 msgid "_Normal" msgstr "_Normaal" #: tryton/gui/main.py:575 msgid "_PDA" msgstr "_PDA" #: tryton/gui/main.py:582 msgid "_Form" msgstr "Formulier" #: tryton/gui/main.py:591 msgid "Save Width/Height" msgstr "Bewaar breedte/hoogte" #: tryton/gui/main.py:602 msgid "Save Tree State" msgstr "" #: tryton/gui/main.py:614 msgid "Fast Tabbing" msgstr "" #: tryton/gui/main.py:624 msgid "Spell Checking" msgstr "Spellingscontrole uitvoeren" #: tryton/gui/main.py:635 #, fuzzy msgid "_Previous Tab" msgstr "V_orige" #: tryton/gui/main.py:642 msgid "_Next Tab" msgstr "" #: tryton/gui/main.py:649 msgid "Search Limit..." msgstr "Zoek limiet..." #: tryton/gui/main.py:655 msgid "_Email..." msgstr "E-mail" #: tryton/gui/main.py:663 msgid "_Save Options" msgstr "_Sla opties op" #: tryton/gui/main.py:677 msgid "_Keyboard Shortcuts..." msgstr "Sneltoetsen" #: tryton/gui/main.py:687 msgid "_About..." msgstr "I_nfo..." #: tryton/gui/main.py:723 tryton/gui/main.py:745 msgid "Manage Favorites" msgstr "" #: tryton/gui/main.py:898 msgid "" "The following action requires to close all tabs.\n" "Do you want to continue?" msgstr "" #: tryton/gui/main.py:1143 msgid "Close Tab" msgstr "Tabblad sluiten" #: tryton/gui/window/attachment.py:22 #, python-format, fuzzy, python-format msgid "Attachments (%s)" msgstr "Bijlage (%s)" #: tryton/gui/window/dblogin.py:31 msgid "Profile Editor" msgstr "" #: tryton/gui/window/dblogin.py:45 msgid "Profile" msgstr "" #: tryton/gui/window/dblogin.py:51 tryton/gui/window/win_csv.py:68 msgid "_Add" msgstr "_Toevoegen" #: tryton/gui/window/dblogin.py:56 tryton/gui/window/win_csv.py:77 msgid "_Remove" msgstr "_Verwijderen" #: tryton/gui/window/dblogin.py:69 tryton/gui/window/dblogin.py:446 #, fuzzy msgid "Host:" msgstr "Poort:" #: tryton/gui/window/dblogin.py:79 tryton/gui/window/dblogin.py:457 msgid "Database:" msgstr "Database:" #: tryton/gui/window/dblogin.py:98 #, fuzzy msgid "Fetching databases list" msgstr "Maak een nieuwe database:" #: tryton/gui/window/dblogin.py:114 #, fuzzy msgid "Username:" msgstr "Gebruikersnaam:" #: tryton/gui/window/dblogin.py:300 tryton/gui/window/dblogin.py:613 #, fuzzy msgid "Incompatible version of the server" msgstr "Deze versie is onverenigbaar met de server! " #: tryton/gui/window/dblogin.py:302 tryton/gui/window/dblogin.py:616 #, fuzzy msgid "Could not connect to the server" msgstr "Geen verbinding met de server!" #: tryton/gui/window/dblogin.py:381 msgid "Login" msgstr "Inlognaam" #: tryton/gui/window/dblogin.py:387 msgid "_Cancel" msgstr " _Annuleren" #: tryton/gui/window/dblogin.py:392 msgid "Cancel connection to the Tryton server" msgstr "Verbreek verbinding met Tryton server" #: tryton/gui/window/dblogin.py:394 msgid "C_onnect" msgstr "_Verbinden" #: tryton/gui/window/dblogin.py:399 msgid "Connect the Tryton server" msgstr "Verbind met Tryton server" #: tryton/gui/window/dblogin.py:427 msgid "Profile:" msgstr "" #: tryton/gui/window/dblogin.py:431 msgid "_Manage profiles" msgstr "" #: tryton/gui/window/dblogin.py:443 msgid "Host / Database information" msgstr "" #: tryton/gui/window/dblogin.py:472 msgid "User name:" msgstr "Gebruikersnaam:" #: tryton/gui/window/email.py:16 msgid "Email" msgstr "E-mail" #: tryton/gui/window/email.py:24 msgid "Email Program Settings" msgstr "E-mail instellingen " #: tryton/gui/window/email.py:27 msgid "Command Line:" msgstr "Opdrachtregel:" #: tryton/gui/window/email.py:37 msgid "Legend of Available Placeholders:" msgstr "Legenda van beschikbare sjablonen: " #: tryton/gui/window/email.py:44 msgid "To:" msgstr "Aan:" #: tryton/gui/window/email.py:48 msgid "CC:" msgstr "CC:" #: tryton/gui/window/email.py:52 msgid "Subject:" msgstr "Onderwerp:" #: tryton/gui/window/email.py:56 msgid "Body:" msgstr "Bericht:" #: tryton/gui/window/email.py:60 msgid "Attachment:" msgstr "Bijlage:" #: tryton/gui/window/form.py:118 #, python-format msgid "Attachment(%d)" msgstr "Bijlage (%d)" #: tryton/gui/window/form.py:144 #, python-format msgid "Note(%d)" msgstr "" #: tryton/gui/window/form.py:166 #, fuzzy msgid "You have to select one record." msgstr "Je moet één item selecteren!" #: tryton/gui/window/form.py:170 msgid "ID:" msgstr "ID:" #: tryton/gui/window/form.py:171 msgid "Creation User:" msgstr "Aangemaakt door:" #: tryton/gui/window/form.py:172 msgid "Creation Date:" msgstr "Aanmaakdatum" #: tryton/gui/window/form.py:173 msgid "Latest Modification by:" msgstr "Laatste wijziging door:" #: tryton/gui/window/form.py:174 msgid "Latest Modification Date:" msgstr "Laatste wijzigingsdatum:" #: tryton/gui/window/form.py:193 msgid "Model:" msgstr "Model:" #: tryton/gui/window/form.py:265 msgid "Are you sure to remove this record?" msgstr "Weet je zeker dat je dit item wilt verwijderen?" #: tryton/gui/window/form.py:267 msgid "Are you sure to remove those records?" msgstr "Weet je zeker dat je deze items wilt verwijderen?" #: tryton/gui/window/form.py:270 #, fuzzy msgid "Records not removed." msgstr "Items niet verwijderd!" #: tryton/gui/window/form.py:272 #, fuzzy msgid "Records removed." msgstr "Items verwijderd!" #: tryton/gui/window/form.py:301 #, fuzzy msgid "Working now on the duplicated record(s)." msgstr "Je werkt nu met het gekopieerde item!" #: tryton/gui/window/form.py:313 #, fuzzy msgid "Record saved." msgstr "Item opgeslagen!" #: tryton/gui/window/form.py:423 msgid " of " msgstr " van " #: tryton/gui/window/form.py:443 #, fuzzy msgid "" "This record has been modified\n" "do you want to save it?" msgstr "" "Item is aangepast.\n" "Wil je de wijzigingen opslaan?" #: tryton/gui/window/form.py:497 msgid "Action" msgstr "Actie" #: tryton/gui/window/form.py:497 msgid "Launch action" msgstr "" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Relate" msgstr "Aan_maken" #: tryton/gui/window/form.py:498 #, fuzzy msgid "Open related records" msgstr "Item openen" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Report" msgstr "Rapporten" #: tryton/gui/window/form.py:500 #, fuzzy msgid "Open report" msgstr "Item openen" #: tryton/gui/window/form.py:501 #, fuzzy msgid "E-Mail" msgstr "E-mail" #: tryton/gui/window/form.py:501 msgid "E-Mail report" msgstr "" #: tryton/gui/window/form.py:502 msgid "Print" msgstr "Afdrukken" #: tryton/gui/window/form.py:502 msgid "Print report" msgstr "" #: tryton/gui/window/form.py:522 msgid "_Copy URL" msgstr "" #: tryton/gui/window/form.py:525 msgid "Copy URL into clipboard" msgstr "" #: tryton/gui/window/form.py:585 #: tryton/gui/window/view_form/view/list_gtk/widget.py:888 msgid "Unknown" msgstr "Onbekend" #: tryton/gui/window/limit.py:17 msgid "Limit" msgstr "Limiet:" #: tryton/gui/window/limit.py:25 msgid "Search Limit Settings" msgstr "Zoek limiet instellen" #: tryton/gui/window/limit.py:28 msgid "Limit:" msgstr " Limiet:" #: tryton/gui/window/note.py:17 #, python-format msgid "Notes (%s)" msgstr "" #: tryton/gui/window/preference.py:23 msgid "Preferences" msgstr "Voorkeuren" #: tryton/gui/window/preference.py:48 msgid "Edit User Preferences" msgstr "Voorkeuren gebruiker aanpassen" #: tryton/gui/window/preference.py:75 msgid "Preference" msgstr "Voorkeur" #: tryton/gui/window/revision.py:19 #, fuzzy msgid "Revision" msgstr "Vorige" #: tryton/gui/window/revision.py:27 #, fuzzy msgid "Select a revision" msgstr "Selectie" #: tryton/gui/window/revision.py:30 #, fuzzy msgid "Revision:" msgstr "Vorige" #: tryton/gui/window/shortcuts.py:17 msgid "Keyboard Shortcuts" msgstr "Sneltoetsen" #: tryton/gui/window/shortcuts.py:27 msgid "Text Entries Shortcuts" msgstr "Sneltoetsen in tekstvakken" #: tryton/gui/window/shortcuts.py:28 msgid "Cut selected text" msgstr "Knip geselecteerde tekst" #: tryton/gui/window/shortcuts.py:29 msgid "Copy selected text" msgstr "Kopieer geselecteerde tekst" #: tryton/gui/window/shortcuts.py:30 msgid "Paste copied text" msgstr "Plak geselecteerde tekst" #: tryton/gui/window/shortcuts.py:31 msgid "Next widget" msgstr "Volgend element" #: tryton/gui/window/shortcuts.py:32 msgid "Previous widget" msgstr "Vorig element" #: tryton/gui/window/shortcuts.py:33 msgid "Relation Entries Shortcuts" msgstr "Relatie sneltoetsen" #: tryton/gui/window/shortcuts.py:34 msgid "Create new relation" msgstr "Nieuwe relatie aanmaken" #: tryton/gui/window/shortcuts.py:35 msgid "Open/Search relation" msgstr "Zoek / open relatie" #: tryton/gui/window/shortcuts.py:36 #, fuzzy msgid "List Entries Shortcuts" msgstr "Sneltoetsen in tekstvakken" #: tryton/gui/window/shortcuts.py:37 #, fuzzy msgid "Create new line" msgstr "Nieuwe relatie aanmaken" #: tryton/gui/window/shortcuts.py:38 #, fuzzy msgid "Open relation" msgstr "Zoek / open relatie" #: tryton/gui/window/shortcuts.py:39 msgid "Mark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:40 msgid "Unmark line for deletion" msgstr "" #: tryton/gui/window/shortcuts.py:43 msgid "Edition Widgets" msgstr "Versies widgets" #: tryton/gui/window/shortcuts.py:46 msgid "Move Cursor" msgstr "" #: tryton/gui/window/shortcuts.py:47 msgid "Move to right" msgstr "" #: tryton/gui/window/shortcuts.py:48 msgid "Move to left" msgstr "" #: tryton/gui/window/shortcuts.py:49 msgid "Move up" msgstr "" #: tryton/gui/window/shortcuts.py:50 msgid "Move down" msgstr "" #: tryton/gui/window/shortcuts.py:51 msgid "Move up of one page" msgstr "" #: tryton/gui/window/shortcuts.py:52 msgid "Move down of one page" msgstr "" #: tryton/gui/window/shortcuts.py:53 msgid "Move to top" msgstr "" #: tryton/gui/window/shortcuts.py:54 msgid "Move to bottom" msgstr "" #: tryton/gui/window/shortcuts.py:55 msgid "Move to parent" msgstr "" #: tryton/gui/window/shortcuts.py:57 tryton/gui/window/shortcuts.py:58 msgid "Select all" msgstr "" #: tryton/gui/window/shortcuts.py:59 tryton/gui/window/shortcuts.py:60 msgid "Unselect all" msgstr "" #: tryton/gui/window/shortcuts.py:61 msgid "Select parent" msgstr "" #: tryton/gui/window/shortcuts.py:62 tryton/gui/window/shortcuts.py:63 #: tryton/gui/window/shortcuts.py:64 tryton/gui/window/shortcuts.py:65 msgid "Select/Activate current row" msgstr "" #: tryton/gui/window/shortcuts.py:66 msgid "Toggle selection" msgstr "" #: tryton/gui/window/shortcuts.py:67 msgid "Expand/Collapse" msgstr "" #: tryton/gui/window/shortcuts.py:68 msgid "Expand row" msgstr "" #: tryton/gui/window/shortcuts.py:69 msgid "Collapse row" msgstr "" #: tryton/gui/window/shortcuts.py:70 msgid "Toggle row" msgstr "" #: tryton/gui/window/shortcuts.py:71 msgid "Collapse all rows" msgstr "" #: tryton/gui/window/shortcuts.py:72 msgid "Expand all rows" msgstr "" #: tryton/gui/window/shortcuts.py:75 msgid "Tree view" msgstr "" #: tryton/gui/window/tabcontent.py:41 msgid "_Switch View" msgstr "Wijzig beeld" #: tryton/gui/window/tabcontent.py:42 #, fuzzy msgid "Switch View" msgstr "Wijzig beeld" #: tryton/gui/window/tabcontent.py:47 msgid "_Previous" msgstr "V_orige" #: tryton/gui/window/tabcontent.py:48 msgid "Previous Record" msgstr "Vorige item" #: tryton/gui/window/tabcontent.py:53 msgid "_Next" msgstr "_Volgende" #: tryton/gui/window/tabcontent.py:54 msgid "Next Record" msgstr "Volgende item" #: tryton/gui/window/tabcontent.py:59 #, fuzzy msgid "_Search" msgstr "Zoeken" #: tryton/gui/window/tabcontent.py:65 msgid "_New" msgstr "_Nieuw" #: tryton/gui/window/tabcontent.py:66 msgid "Create a new record" msgstr "Maak een nieuw item" #: tryton/gui/window/tabcontent.py:71 tryton/gui/window/win_form.py:68 msgid "_Save" msgstr "Op_slaan" #: tryton/gui/window/tabcontent.py:72 msgid "Save this record" msgstr "Bewaar dit item" #: tryton/gui/window/tabcontent.py:77 msgid "_Reload/Undo" msgstr "_Ongedaan maken" #: tryton/gui/window/tabcontent.py:78 #, fuzzy msgid "Reload/Undo" msgstr "_Ongedaan maken" #: tryton/gui/window/tabcontent.py:83 msgid "_Duplicate" msgstr "_Dupliceren" #: tryton/gui/window/tabcontent.py:88 msgid "_Delete..." msgstr "Verwijderen... " #: tryton/gui/window/tabcontent.py:94 msgid "View _Logs..." msgstr "Bekijk logregister" #: tryton/gui/window/tabcontent.py:97 msgid "Show revisions..." msgstr "" #: tryton/gui/window/tabcontent.py:102 #, fuzzy msgid "A_ttachments..." msgstr "Bijlage:" #: tryton/gui/window/tabcontent.py:103 msgid "Add an attachment to the record" msgstr "Voeg een bijlage aan dit item toe" #: tryton/gui/window/tabcontent.py:108 msgid "_Notes..." msgstr "" #: tryton/gui/window/tabcontent.py:109 msgid "Add a note to the record" msgstr "" #: tryton/gui/window/tabcontent.py:114 msgid "_Actions..." msgstr "_Acties.." #: tryton/gui/window/tabcontent.py:119 #, fuzzy msgid "_Relate..." msgstr "Verwijderen... " #: tryton/gui/window/tabcontent.py:125 #, fuzzy msgid "_Report..." msgstr "_Importeer gegevens... " #: tryton/gui/window/tabcontent.py:130 #, fuzzy msgid "_E-Mail..." msgstr "E-mail" #: tryton/gui/window/tabcontent.py:135 msgid "_Print..." msgstr "Afdrukken" #: tryton/gui/window/tabcontent.py:141 msgid "_Export Data..." msgstr "_Exporteer gegevens... " #: tryton/gui/window/tabcontent.py:146 msgid "_Import Data..." msgstr "_Importeer gegevens... " #: tryton/gui/window/tabcontent.py:150 msgid "Copy _URL..." msgstr "" #: tryton/gui/window/tabcontent.py:156 msgid "_Close Tab" msgstr "Tabblad sluiten" #: tryton/gui/window/win_csv.py:59 msgid "All fields" msgstr "Alle velden" #: tryton/gui/window/win_csv.py:86 #, fuzzy msgid "_Clear" msgstr "Wissen" #: tryton/gui/window/win_csv.py:107 msgid "Fields selected" msgstr "" #: tryton/gui/window/win_csv.py:126 msgid "CSV Parameters" msgstr "CSV parameters" #: tryton/gui/window/win_csv.py:134 msgid "Delimiter:" msgstr "" #: tryton/gui/window/win_csv.py:148 msgid "Quote char:" msgstr "" #: tryton/gui/window/win_csv.py:157 msgid "Encoding:" msgstr "Codering:" #: tryton/gui/window/win_csv.py:193 tryton/gui/window/win_csv.py:197 msgid "Field name" msgstr "Veldnaam" #: tryton/gui/window/win_export.py:28 msgid "Export to CSV" msgstr "Exporteer naar CSV" #: tryton/gui/window/win_export.py:39 msgid "Predefined exports" msgstr "Voorgedefinieerde exportinstellingen" #: tryton/gui/window/win_export.py:46 msgid "Name" msgstr "Naam" #: tryton/gui/window/win_export.py:60 #, fuzzy msgid "_Save Export" msgstr "Exportgegevens opslaan" #: tryton/gui/window/win_export.py:69 #, fuzzy msgid "_Delete Export" msgstr "Exportgegevens verwijderen" #: tryton/gui/window/win_export.py:85 msgid "Open" msgstr "Open" #: tryton/gui/window/win_export.py:86 msgid "Save" msgstr "Opslaan" #: tryton/gui/window/win_export.py:90 msgid "Add _field names" msgstr "Voeg veldnamen toe" #: tryton/gui/window/win_export.py:104 #, python-format msgid "%s (string)" msgstr "" #: tryton/gui/window/win_export.py:107 #, python-format msgid "%s (model name)" msgstr "" #: tryton/gui/window/win_export.py:109 #, python-format msgid "%s (record name)" msgstr "" #: tryton/gui/window/win_export.py:208 msgid "What is the name of this export?" msgstr "Wat is de naam voor deze export?" #: tryton/gui/window/win_export.py:214 #, python-format msgid "Override '%s' definition?" msgstr "" #: tryton/gui/window/win_export.py:331 #, python-format, fuzzy, python-format msgid "%d record saved." msgstr "%d item opgeslagen!" #: tryton/gui/window/win_export.py:333 #, python-format, fuzzy, python-format msgid "%d records saved." msgstr "%d items opgeslagen!" #: tryton/gui/window/win_export.py:336 #, python-format, fuzzy, python-format msgid "" "Operation failed.\n" "Error message:\n" "%s" msgstr "" "Handeling mislukt!\n" "Foutmelding:\n" "%s" #: tryton/gui/window/win_form.py:37 msgid "Link" msgstr "Koppeling" #: tryton/gui/window/win_form.py:125 msgid "Add" msgstr "Toevoegen" #: tryton/gui/window/win_form.py:138 msgid "Remove " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:133 #: tryton/gui/window/win_form.py:153 #, fuzzy msgid "Create a new record " msgstr "Maak een nieuw item" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:153 #: tryton/gui/window/win_form.py:165 #, fuzzy msgid "Delete selected record " msgstr "Geselecteerd item verwijderen" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:163 #: tryton/gui/window/win_form.py:179 #, fuzzy msgid "Undelete selected record " msgstr "Geselecteerd item verwijderen" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:59 #: tryton/gui/window/view_form/view/screen_container.py:213 #: tryton/gui/window/win_form.py:194 msgid "Previous" msgstr "Vorige" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:73 #: tryton/gui/window/view_form/view/screen_container.py:225 #: tryton/gui/window/win_form.py:208 msgid "Next" msgstr "Volgende" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:48 #: tryton/gui/window/win_form.py:221 msgid "Switch" msgstr "Omschakelen" #: tryton/gui/window/win_import.py:25 msgid "Import from CSV" msgstr "Importeer uit CSV" #: tryton/gui/window/win_import.py:32 #, fuzzy msgid "_Auto-Detect" msgstr "Automatisch" #: tryton/gui/window/win_import.py:43 msgid "File to Import:" msgstr "Bestand om te importeren:" #: tryton/gui/window/view_form/view/form_gtk/binary.py:209 #: tryton/gui/window/view_form/view/list_gtk/widget.py:462 #: tryton/gui/window/win_import.py:45 msgid "Open..." msgstr "Openen..." #: tryton/gui/window/win_import.py:50 msgid "Lines to Skip:" msgstr "Regels overslaan:" #: tryton/gui/window/win_import.py:103 #, fuzzy msgid "You must select an import file first." msgstr "U moet eerst een import bestand selecteren!" #: tryton/gui/window/win_import.py:113 msgid "Error opening CSV file" msgstr "Fout bij openen CSV-bestand" #: tryton/gui/window/win_import.py:141 #, python-format, python-format, fuzzy, python-format msgid "Error processing the file at field %s." msgstr "Fout bij inlezen van bestand bij veld%s" #: tryton/gui/window/win_import.py:201 #, python-format, fuzzy, python-format msgid "%d record imported." msgstr "%d item geïmporteerd!" #: tryton/gui/window/win_import.py:203 #, python-format, fuzzy, python-format msgid "%d records imported." msgstr "%d items geïmporteerd!" #: tryton/gui/window/win_search.py:68 #, python-format msgid "Search %s" msgstr "" #: tryton/gui/window/wizard.py:143 #, python-format msgid "Unable to delete wizard %s" msgstr "" #: tryton/gui/window/wizard.py:297 msgid "Wizard" msgstr "Assistent" #: tryton/gui/window/view_form/screen/screen.py:194 #, fuzzy msgid "ID" msgstr " d" #: tryton/gui/window/view_form/screen/screen.py:195 #, fuzzy msgid "Creation User" msgstr "Aangemaakt door:" #: tryton/gui/window/view_form/screen/screen.py:196 #, fuzzy msgid "Creation Date" msgstr "Aanmaakdatum" #: tryton/gui/window/view_form/screen/screen.py:197 #, fuzzy msgid "Modification User" msgstr "Laatste wijzigingsdatum:" #: tryton/gui/window/view_form/screen/screen.py:198 #, fuzzy msgid "Modification Date" msgstr "Laatste wijzigingsdatum:" #: tryton/gui/window/view_form/screen/screen.py:765 #, python-format, fuzzy msgid "Unable to get view tree state for %s" msgstr "Kan omgeving %s niet instellen" #: tryton/gui/window/view_form/screen/screen.py:826 #, fuzzy msgid "Unable to set view tree state" msgstr "Kan omgeving %s niet instellen" #: tryton/gui/window/view_form/screen/screen.py:1003 #, python-format msgid "\"%s\" is not valid according to its domain" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1010 #, python-format msgid "\"%s\" is required" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1014 #, python-format msgid "The values of \"%s\" are not valid" msgstr "" #: tryton/gui/window/view_form/screen/screen.py:1063 msgid "Pre-validation" msgstr "" #: tryton/gui/window/view_form/view/form.py:207 #: tryton/gui/window/view_form/view/form.py:209 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:478 #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:480 #: tryton/gui/window/view_form/view/form_gtk/widget.py:150 #: tryton/gui/window/view_form/view/form_gtk/widget.py:152 #: tryton/gui/window/view_form/view/list.py:534 #: tryton/gui/window/view_form/view/list.py:536 msgid ":" msgstr ":" #: tryton/gui/window/view_form/view/graph.py:100 msgid "Image Size" msgstr "Afbeeldingsgrootte" #: tryton/gui/window/view_form/view/graph.py:110 msgid "Width:" msgstr "Breedte:" #: tryton/gui/window/view_form/view/graph.py:118 msgid "Height:" msgstr "Hoogte:" #: tryton/gui/window/view_form/view/graph.py:128 msgid "PNG image (*.png)" msgstr "PNG afbeelding (*.png)" #: tryton/gui/window/view_form/view/graph.py:137 msgid "Save As" msgstr "Opslaan als" #: tryton/gui/window/view_form/view/graph.py:149 #, fuzzy msgid "Image size too large." msgstr "Afbeelding te groot!" #: tryton/gui/window/view_form/view/screen_container.py:23 msgid ".." msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:149 msgid "Open filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:197 msgid "Show bookmarks of filters" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:368 msgid "Remove this bookmark" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:375 msgid "Bookmark this filter" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:463 msgid "Bookmark Name:" msgstr "" #: tryton/gui/window/view_form/view/screen_container.py:582 msgid "Find" msgstr "Vind" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:22 #, fuzzy msgid "Today" msgstr "Bericht:" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:32 msgid "go back" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:73 msgid "go forward" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:82 msgid "previous year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:96 msgid "next year" msgstr "" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:107 #, fuzzy msgid "Week View" msgstr "Wijzig beeld" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:117 #, fuzzy msgid "Month View" msgstr "Wijzig beeld" #: tryton/gui/window/view_form/view/calendar_gtk/toolbar.py:142 msgid "Week" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:44 msgid "Select..." msgstr "" #: tryton/gui/window/view_form/view/form_gtk/binary.py:53 msgid "Clear" msgstr "Wissen" #: tryton/gui/window/view_form/view/form_gtk/binary.py:66 msgid "All files" msgstr "Alle bestanden" #: tryton/gui/window/view_form/view/form_gtk/binary.py:89 msgid "Select" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/char.py:165 msgid "Show plain text" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:367 msgid "Add value" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/dictionary.py:491 #, python-format msgid "Remove \"%s\"" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/image.py:49 msgid "Images" msgstr "Afbeeldingen" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:66 #: tryton/gui/window/view_form/view/form_gtk/one2many.py:108 #, fuzzy msgid "Add existing record" msgstr "Bewaar dit item" #: tryton/gui/window/view_form/view/form_gtk/many2many.py:77 #, fuzzy msgid "Remove selected record " msgstr "Geselecteerd item verwijderen" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:305 #, fuzzy msgid "Open the record " msgstr "Item openen" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:306 msgid "Clear the record " msgstr "" #: tryton/gui/window/view_form/view/form_gtk/many2one.py:309 #, fuzzy msgid "Search a record " msgstr "Item zoeken" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:120 #, fuzzy msgid "Remove selected record" msgstr "Geselecteerd item verwijderen" #: tryton/gui/window/view_form/view/form_gtk/one2many.py:143 #, fuzzy msgid "Edit selected record " msgstr "Geselecteerd item aanpassen" #: tryton/gui/window/view_form/view/form_gtk/progressbar.py:35 #: tryton/gui/window/view_form/view/list_gtk/widget.py:864 #, python-format msgid "%s%%" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:99 msgid "Foreground" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/richtextbox.py:304 msgid "Select a color" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:126 #, fuzzy msgid "Translation" msgstr "Voeg vertaling toe" #: tryton/gui/window/view_form/view/form_gtk/widget.py:187 msgid "Edit" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:192 msgid "Fuzzy" msgstr "" #: tryton/gui/window/view_form/view/form_gtk/widget.py:262 #, fuzzy msgid "You need to save the record before adding translations." msgstr "Gegevens eerst opslaan voordat u een vertaling toevoegt! " #: tryton/gui/window/view_form/view/form_gtk/widget.py:273 #, fuzzy msgid "No other language available." msgstr "Geen andere taal beschikbaar!" #: tryton/plugins/translation/__init__.py:23 msgid "Translate view" msgstr "Vertaal aanzicht" tryton-4.6.5/tryton/data/locale/nl/LC_MESSAGES/tryton.mo0000644000175000017500000003065313260723565022216 0ustar cedced00000000000000 l) &27:<Ne   #&%Jp  & # :D V cqy  />M _ i u   #-3J R] mx      !,3CVp !   &< KX g u    6 HRdj y     , ALQ Ydt     6@HbrI}   %!G_g        & 1 = IS \ g s ~  # +5>C S ]g p}      .0<N6!)"Q"!j" ""!"/"1" )#6#?#H#W#l#{### #%#####$ $'$ 6$@$ R$^$x$ $$$$"$ %%&% ?% I% U%`%o%%% %%%%%% &&&6& =&K& [&f&v& & & &&&&& &&&'#''' :'G' Y'e'~' '#'''' ' ''(()( 0( <(F(\( k(x( ( ((((( (((( ))) ) ))3)G)a) x))))) )) ) ) ) ))** *+* ?* K*X*m** ****** **+++ '+ 2+@+ X+b+~++++++ + ++I,c, -"- '-2-C-V- g-q-v--%---- .. '.2.E. J.k. t. ~... .. . . .. . . . .// -/9/@/ X/b/q/w// // / /// / // /000$0 ,0 60@0 P0]0f0 u000 0 0000 00 00 1 11.1<I11111 of "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:All fieldsFields selectedPredefined exportsCreate...Search...ActionAddAdd _field namesAdd a note to the recordAdd an attachment to the recordAdd valueAll filesAlways ignore this warning.Are you sure to remove this record?Are you sure to remove those records?Attachment(%d)Attachment:Body:Bookmark Name:Bookmark this filterBug TrackerBy: CC:CSV ParametersC_onnectCancel connection to the Tryton serverChange AcceleratorsClearClear the record Close TabCollapse all rowsCollapse rowCommand Line:CompareConcurrency ExceptionConfirmationConnect the Tryton serverCopy URL into clipboardCopy _URL...Copy selected textCreate a new recordCreate new relationCreated new bug with ID Creation Date:Creation User:Cut selected textDatabase:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEditEdit User PreferencesEdition WidgetsEmailEmail Program SettingsEncoding:ErrorError opening CSV fileError: Exception:Expand all rowsExpand rowExpand/CollapseExport to CSVFa_voritesFalseFast TabbingField nameFile "%s" not foundFile to Import:FindForegroundFuzzyHeight:Host / Database informationID:Image SizeImagesImport from CSVKeyboard ShortcutsLatest Modification Date:Latest Modification by:Launch actionLegend of Available Placeholders:LimitLimit:Lines to Skip:LinkLoginMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNameNextNext RecordNext widgetNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpen...Open/Search relationOverride '%s' definition?PNG image (*.png)Password:Paste copied textPort:Pre-validationPreferencePreferencesPreviousPrevious RecordPrevious widgetPrintPrint reportProfileProfile EditorProfile:Quote char:Relation Entries ShortcutsRemove "%s"Remove Remove this bookmarkReport BugSaveSave AsSave As...Save Tree StateSave Width/HeightSave this recordSearchSearch %sSearch Limit SettingsSearch Limit...SelectSelect a colorSelect allSelect parentSelect your actionSelect...Select/Activate current rowSelectionServer:Show bookmarks of filtersShow plain textShow revisions...Spell CheckingSubject:SwitchText Entries ShortcutsThe following action requires to close all tabs. Do you want to continue?The same bug was already reported by another user. To keep you informed your username is added to the nosy-list of this issueThe values of "%s" are not validTo:Toggle rowToggle selectionToo much argumentsTranslate viewTree viewTrueTryton ConnectionUnable to delete wizard %sUnable to search for completion of %sUnable to set locale %sUnknownUnmark line for deletionUnselect allUser name:User:View _Logs...WeekWhat is the name of this export?Width:WizardWrite AnywayYYesYour selection:_About..._Actions..._Add_Cancel_Close Tab_Connect..._Connection_Copy URL_Default_Delete..._Disconnect_Duplicate_Email..._Export Data..._Form_Global Search_Help_Icons_Import Data..._Keyboard Shortcuts..._Manage profiles_Menu Toggle_Menubar_Mode_New_Next_Next Tab_Normal_Notes..._Options_PDA_Preferences..._Previous_Print..._Quit..._Reload/Undo_Remove_Save_Save Options_Switch View_Text_Text and Icons_Toolbar_Userddevelopment modego backgo forwardhlogging everything at INFO levelmnext yearprevious yearsspecify alternate config filespecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecify the login usertwyProject-Id-Version: PROJECT VERSION Report-Msgid-Bugs-To: EMAIL@ADDRESS POT-Creation-Date: 2018-04-03 18:10+0200 PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE Last-Translator: FULL NAME Language: nl Language-Team: nl Plural-Forms: nplurals=2; plural=(n != 1) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit Generated-By: Babel 2.5.0 van "%s" is not valid according to its domain"%s" is required%s (%s)%s (model name)%s (record name)%s (string)%s%%..:Alle veldenFields selectedVoorgedefinieerde exportinstellingenCreate...Search...ActieToevoegenVoeg veldnamen toeAdd a note to the recordVoeg een bijlage aan dit item toeAdd valueAlle bestandenAltijd deze waarschuwing negeren.Weet je zeker dat je dit item wilt verwijderen?Weet je zeker dat je deze items wilt verwijderen?Bijlage (%d)Bijlage:Bericht:Bookmark Name:Bookmark this filterFoutrapportageBy: CC:CSV parameters_VerbindenVerbreek verbinding met Tryton serverVersnellers aanpassenWissenClear the record Tabblad sluitenCollapse all rowsCollapse rowOpdrachtregel:VergelijkSimultaan gebruikBevestigingVerbind met Tryton serverCopy URL into clipboardCopy _URL...Kopieer geselecteerde tekstMaak een nieuw itemNieuwe relatie aanmakenNieuwe foutmelding gemaakt met ID AanmaakdatumAangemaakt door:Knip geselecteerde tekstDatabase:Date FormatDelimiter:Display formatDisplayed date formatDisplayed valueDo you want to proceed?E-Mail reportEditVoorkeuren gebruiker aanpassenVersies widgetsE-mailE-mail instellingen Codering:FoutFout bij openen CSV-bestandFout: Uitzondering:Expand all rowsExpand rowExpand/CollapseExporteer naar CSVFa_voritesNiet waarFast TabbingVeldnaamBestand "%s" niet gevondenBestand om te importeren:VindForegroundFuzzyHoogte:Host / Database informationID:AfbeeldingsgrootteAfbeeldingenImporteer uit CSVSneltoetsenLaatste wijzigingsdatum:Laatste wijziging door:Launch actionLegenda van beschikbare sjablonen: Limiet: Limiet:Regels overslaan:KoppelingInlognaamMManage FavoritesMark line for deletionModel:Move CursorMove downMove down of one pageMove to bottomMove to leftMove to parentMove to rightMove to topMove upMove up of one pageNaamVolgendeVolgende itemVolgend elementNo result found.Note(%d)Notes (%s)Notes...OpenOpen filtersOpenen...Zoek / open relatieOverride '%s' definition?PNG afbeelding (*.png)Wachtwoord:Plak geselecteerde tekstPoort:Pre-validationVoorkeurVoorkeurenVorigeVorige itemVorig elementAfdrukkenPrint reportProfileProfile EditorProfile:Quote char:Relatie sneltoetsenRemove "%s"Remove Remove this bookmarkProgrammafout meldenOpslaanOpslaan alsOpslaan als...Save Tree StateBewaar breedte/hoogteBewaar dit itemZoekenSearch %sZoek limiet instellenZoek limiet...SelectSelect a colorSelect allSelect parentSelecteer je handeling.Select...Select/Activate current rowSelectieServer:Show bookmarks of filtersShow plain textShow revisions...Spellingscontrole uitvoerenOnderwerp:OmschakelenSneltoetsen in tekstvakkenThe following action requires to close all tabs. Do you want to continue?Dezelfde programmafout was al gemeld door een andere gebruiker. Om je op de hoogte te houden is je gebuikersnaam toegevoegd aan de lijst van belangstellendenThe values of "%s" are not validAan:Toggle rowToggle selectionToo much argumentsVertaal aanzichtTree viewWaarTryton verbindingUnable to delete wizard %sUnable to search for completion of %sKan omgeving %s niet instellenOnbekendUnmark line for deletionUnselect allGebruikersnaam:Gebruiker:Bekijk logregisterWeekWat is de naam voor deze export?Breedte:AssistentOverschrijvenJYesUw selectie:I_nfo..._Acties.._Toevoegen _AnnulerenTabblad sluiten_Verbinden..._Connection_Copy URL_StandaardVerwijderen... Verbinding verbreken_DuplicerenE-mail_Exporteer gegevens... Formulier_Global Search_HelpPictogrammen..._Importeer gegevens... Sneltoetsen_Manage profiles_Menu Toggle_Menubalk_Modus_Nieuw_Volgende_Next Tab_Normaal_Notes..._Opties_PDA_Voorkeuren...V_origeAfdrukkenAfsluiten_Ongedaan maken_VerwijderenOp_slaan_Sla opties opWijzig beeld_Tekst_Tekst en pictogrammen_Werkbalk_Gebruikerddevelopment modego backgo forwardulogboek bijhouden op INFO niveaumnext yearprevious yearsspecificeer een vervangend configuratiebestandspecify the log level: DEBUG, INFO, WARNING, ERROR, CRITICALspecificeer de inlog gebruikertwytryton-4.6.5/tryton/data/pixmaps/0000755000175000017500000000000013260723567016341 5ustar cedced00000000000000tryton-4.6.5/tryton/data/pixmaps/tryton/0000755000175000017500000000000013260723567017700 5ustar cedced00000000000000tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-print.svg0000644000175000017500000005352313175640533023116 0ustar cedced00000000000000 image/svg+xml Printer Jakub Steiner http://jimmac.musichall.cz printer local laser bubblejet inkjet print output cups lpd tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-open.svg0000644000175000017500000007412513175640533022724 0ustar cedced00000000000000 image/svg+xml Folder Icon Accept 2005-01-31 Jakub Steiner http://jimmac.musichall.cz Active state - when files are being dragged to. Novell, Inc. tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-save.svg0000644000175000017500000007230613175640533022720 0ustar cedced00000000000000 image/svg+xml Save Jakub Steiner hdd hard drive save io store http://jimmac.musichall.cz tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-print-open.svg0000644000175000017500000010372013175640533024050 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-copy.svg0000644000175000017500000003635313175640533022736 0ustar cedced00000000000000 image/svg+xml Edit Copy 2005-10-15 Andreas Nilsson edit copy Jakub Steiner tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-log-out.svg0000644000175000017500000004526713175640533023356 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz System Log Out log out logout exit tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-preferences.svg0000644000175000017500000007330213175640533024260 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Desktop Preferences preferences system category tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-folder-new.svg0000644000175000017500000005707613175640533024033 0ustar cedced00000000000000 image/svg+xml New Folder Jakub Steiner http://jimmac.musichall.cz folder directory create new Tuomas Kuosmanen tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-connect.svg0000644000175000017500000017124113175640533023411 0ustar cedced00000000000000 image/svg+xml Computer 2005-03-08 Jakub Steiner workstation computer node client http://jimmac.musichall.cz/ tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-attachment-hi.svg0000644000175000017500000002177213175640533024511 0ustar cedced00000000000000 image/svg+xml Mail Attachment 2005-11-04 Andreas Nilsson http://tango-project.org attachment file Garrett LeSage, Cédric Krier tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-text-foreground.svg0000644000175000017500000007670213175640533025122 0ustar cedced00000000000000 image/svg+xml Jakub Steiner graphics category pixel vector editor draw paint http://tango-project.org tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-new.svg0000644000175000017500000004177613175640533022562 0ustar cedced00000000000000 image/svg+xml New Document Jakub Steiner http://jimmac.musichall.cz tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-icon.png0000644000175000017500000000142213175640533022666 0ustar cedced00000000000000PNG  IHDR DsRGB8PLTE !"## %!&"' $)"'+%',&).'*/(,0*-1+.3-05.16/4827<68<68=7:>8BF@GKFKOIMPKNQLOSNPTOSVQVZUY]X\_Z]a\_c^`c_beacfaehceidmpknqmpsoqtptvruxtz}y|~{}tRNS@fbKGDH pHYs@ tIME 1NFIDAT8˅V@T wFAE% -lMcgw=" QSB. HyZvYG=jXmEP 8Y` .lcAЫ=l% image/svg+xml Edit Find edit find locate search Steven Garrity Jakub Steiner tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-dialog-information.svg0000644000175000017500000013153413175640533025543 0ustar cedced00000000000000 image/svg+xml Info Jakub Steiner dialog info http://jimmac.musichall.cz Garrett LeSage tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-dialog-warning.svg0000644000175000017500000003352513175640533024664 0ustar cedced00000000000000 image/svg+xml Dialog Warning 2005-10-14 Andreas Nilsson Jakub Steiner, Garrett LeSage dialog warning tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-text-markup.svg0000644000175000017500000006152013175640533024237 0ustar cedced00000000000000 image/svg+xml Document Properties document settings preferences properties tweak Jakub Steiner http://jimmac.musichall.cz tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-start-here.svg0000644000175000017500000004765113175640533024045 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Start Here To be replaced by vendor/distribution branding. start applications launchers Garrett LeSage tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-star.svg0000644000175000017500000001117013175640533022723 0ustar cedced00000000000000 image/svg+xml tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-disconnect.svg0000644000175000017500000022047413175640533024114 0ustar cedced00000000000000 image/svg+xml Computer 2005-03-08 Jakub Steiner workstation computer node client http://jimmac.musichall.cz/ tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-mail-message-new.svg0000644000175000017500000004747113175640533025122 0ustar cedced00000000000000 image/svg+xml Mail New Jakub Steiner Andreas Nilsson, Steven Garrity mail e-mail MUA tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-mail-message.svg0000644000175000017500000005115113175640533024321 0ustar cedced00000000000000 image/svg+xml Mail New Jakub Steiner Andreas Nilsson, Steven Garrity, Cédric Krier mail e-mail MUA tryton-4.6.5/tryton/data/pixmaps/tryton/tryton.ico0000644000175000017500000017233613175640533021743 0ustar cedced00000000000000  -00 %.  8T(d00  F&00 6PNG  IHDR\rfsRGBgAMA a-IDATx XM1U\D2Oi5dL  2e.RDd!u%4 ) q}y=λY.(_|wVNFjFvFvVf,g^degeD zmyye>}T7!OT*@(ʔX|wtJJUUQɁ% ʕ-VړꪪTU՟>PxRj LEHn8 C%Rz{SSS޾sMӟץ.MpJ]7tu_oNC-[VrlHIIx S'Oo킂uABVWhobblrج !(ٕO>ĩOt|.u+B^V+䰉iE3xEI>v2ϼOyeF%ooһgϝ:)u^̙fwtܷ+R!G J~֥{ND"/_ݵ+rPՓoiI]Pviջ7jԘÇ(w )e׍Y=#+6=vjիe9v^4v*tBGtXt7mSSMd)jYO d*.3^~ECzQ<5k~E__\ x_{ކu/A $|AEOO ^^7vm?=>`-W- ;-H~0yh gϜ3cqd ƍ/n-=&-zzX>.Orus%#z4 ڶ9%<Ǐk fw4^֭͑ι<|!IէGAQ555q&iiiuLNK{M Sw2]vO z Am۱g %%w.r];wYnU-b ϢkCR BLj[p` 66zR/p*`nn(Coo>|I$z?|E%>J$ ZA$dƍ9 [rR^}hݪ5QT\M^$.^Q䀪U+H9|A_K<N aWNH#14S&M6yw 77fV>|P§C|k׾X+(( (tܺ})@kǴEo$  \8BԩkBւfmzq/X /s^RP$'Q+SпE/_IaS|ʕ+[v@ Xi/;; <}< |x9m{wۺLt)f`!ӂkC!du0wBX>tNBJ*A:" ϟgZ'J.-cx4g @/a6m Z ˿UV`3ڵՃ?WCy&$J#Ikzyv#k$>S ??3ʔxouLM77ש -?~zM(<}tF ud~0s;M@\XrSR0y<C' Wi\;sı..LΝ _OSeZI>:Ԃ=3Spthή'O)|~[)?qv Aжu[VŅ'~'z!`m`5/x|?:c۝*†A~uW- @C FGF;]5kw`ѱͻ7&p| 4C tM=oG=˵GuC-Zo?(Pnqag柳Co^ ug.d7DEo}.noj5eam">M@"?z7 o ^\k%y' µ7y#fx ίVUgPOeѤPL<ҺU".WSSom\6iJ V,[f2kONsx{Mow|L-Zux<*A`t yy= 'V{V-dgfi0=8,d ggmX8ϮxCѦmLf-G"fs^ͭ"BWn q{ `M6j޾^( *URՠΧ/_K [ݻvuR',RS2^ /ʗ+FYOCpLmsk+ P 9)а&cwnƬiOD6sJ|2i0l=BPUUGXkw2RpIN wLڎ;!~&?Z{ǒad , @p 짋)ȯA&tmb`[V ,  )b7U5&H$M6>,qajb($3 :5ƆJ[XO^T""[vvCVv6 M_Ç`4W * 4k6oa%U ;S@! S'Oc-<~ Vp6 a-+~p=?:a2p`Pc;*UTQmI@*3>^~ЯO?V"5ӫ/ `<?r*07`~05 nZ$𵛘Aix8 zNGaQ['`ƺ8YJLt`iy5XQ@Id|УtAγUO * lQ\~ L=_<typ@A% C.$I:۝`&Aph @n6J!,҂UA soeK 6`񏄃-#=-;Ł=;w|NcVڢQ gQvUJ[Z;#'rʬ5x ~e$`3fϜ#糳[Jv짏e=Ld J. {@MMM6yC]J0jڳLT$^ )܇VJ%hbBV",5~ 6Q*IS&G3 o ^Gho܎0q6&O<s0bu, S:v7{p1+>6U&qC+J}A}Xi M@ QNaD?,(Wΰ>lkJ[W^C #JxJcC)(} \`ȱԉD"8"X K$I7 P5Up{;;vE_/a$ڸ-)'Nq*|GhѼ%lݸf ~*@R ~C`Ŭ|RXq=a$8&H^0e Ũ `(_<3 ^m(z{9s7}T8H^$KcqIE@Qa3AjԨ)q'@dOb!^j- 0v0̜>KIv!??_RL8{Uʺ//@P}LHמ鳧 [k;p-籀H~=;VƊl56 '19-?57%233Q#ܾsKMLu^R. g{ {1՝6aVX" z:uW^A̾=qK8deenwᶗٯ;*DC[639[Eַ¢% !zO `۽:>|,_L! Xk͛`lNexf҂밌 `H Z^K!Nl1E@e{LE6^ȝ$lwzԓq1]PdIf cTZF2 Nl[7IG0oğ/((a#yC1MMs(̙ d{`F H_"A[mcf#&dm^xG9(ˏɇArdvEK歛H˟]a%R1kL'׊MO[u c;Q999$R@$b b4ґ LwGtQge6v^KsK\R67o˗w @ܧf1g'iK9/{R; ز6<do wRwg +#AyJ۟&HU8,\lL -fbt0iDSΰz Qf?@+,x6g]|3 ؾ96i&U;脋@&M(`B&VqIpH êAR}ϳ}q &84Bׄ(ebc=ˏ"@6mZH{AP4eQ2"m1I̟$RWH5{6sShG=$쁵?` aAllTM?<$;ү(ElU~ X_T-  Z-u;芋,4aܦ*Y5y !!<͕-mJNؾcྟ!%` 6&0h [uH:[o a/˂^76F00u2ϒ& [wJ4ylX; 4ѭLv=+M?QQdT}8Me,IX͂B!U3gI0r(^A$ o"%gժ[pC JGt֍YuTз`6;w,Iuq0 2a%&\ Cƺylz uG ;dU`N]Rp.I (cQXkT4+<CfP\JfӨf?,$2q8{ $uܯ>~L=QCظn#'h>vh_APDf{v,0{kՆe[`ϖxKAob|,cUhby{,]u*  k(a 5mZYks~@pHS;>|e+2B.F$DV.:_JC#KIZs/&I˃c$ӂce-_<ӧ0@ٜPA2}ܿ>2;0UOt8+T#*U~C' WZuNA)ǏAPfX{l7Əui_a=5jBP/^dHпί8L40djphS+7cj5ѬpI|!cCc p0=PY<^cvl~E!hE0g#:\D )U4ILf5qq-;A|N"pG EIG(QsLpو rO[ v0` D!? H/ޓJZ@JCx?.DpOSN:\\(ur0)qZ)K B-W,[Y~㼟>~ ('d>/_5"m'|F$RS A?i+ we{mf/THX`8ҪK(y/}@=?Y;vE_ VBO=K-Z|ot~>>;{ u!5jÁD /#F;|Kнoo~}=!zO\<@@! gUJ[Zf7nѮ_>ӟ1 Z^ `9570fLz[ 8Ç όr&/?g|WgϜvwõ3 K_V1l wW]Ȟ]{A <{wyxC(ϩkҀ͚3+c#ZKA!`U˃򈖭*9)nIh9ۀH(>׆BP:MACm$hJ(.?d`KsK\lٶ.Q(iצlX\/.Tb\!No, r%fc;B,.v7IQ?`Ƕ]X=rLsw1@&9C\op<#%WGOAɒ%鍒3mOjj0^|>s$AVIPƅ?o~ͯєdXxSYx%g(Ÿ B(;&֬ ujbAEQr.I-HL>_ . H۷۷8>S"B2ypr \\\qCx̯׿2/"5kBbA(U p8s #IkVG3,W2nʾNJ R 7sȥKr 4hjي&9d8'8s BZ^ bıf ™ ;kp=x)3,,۰lٲ{=}cg/!(7/5ǎW2o$;3K @Vm@aNO`ݻ`77h7о#jo}3ZZuWcCcoO; < }a:_{MdjjB1.lժ5BD)Es1=zzOzz^Z D,Ɔ&JO(,):QLI9{\yqI#ch۶`= nC\V³g"0jfKZ 1#:xzB*^T\]D>֭__ Z4oĔ%8y'c, [:k"~AZ435g9:~SzfCoQ\\(g'7kXbP[6alٷQLb]z]>].]JY@'N6#'”)pUQnnn&-g)s Ҽ#XPYy H ?Pbwoܯ5m*N2n%3Us @c 024Lے>{p{0]v⑁%3] "(֮b2isNa`̠M[Ý),7XZt&Mh݀'%D CBV-[9j6oٶeԌY(,Ek" nPti +=)IG4ѭ{Ԧ]oPX$_7062 ,)S-`|m$ U`0PPP jѺyW/jRx̜Y@BzbӸ c9*%-FG#-:su >n]P:Zt3 nٚ<% Θ5%P0X`^n|[GNwJ˪2&f`anLp@E|X$f>#== @VVV6tB${0 c.&jҠ?QD`#TKֻk׮0qn+)F sKb'1"l×/Yen}SSQ @_|nӧ ;w-Tp֠uڗ/_ȀO |GD$#Cc@O9 ;;>˨TιuV-qX 8zXW 0A###c`ԁ1MQC1vnWphl޺L=dİ!&$5W LD}ڵc T <Գ{O4Я͛7[oIҟץp>ހTz A+ݷ/lÓ1[=?fO ]j^~$/6O0~-Ɇ6իW&%ǏqDP۾(||md?ϬES,RCCوHcs}?[o;?oי}[iջwIݯ{)5'{/)8*PWj5UԬQ ?޾y ߼f^W9O=e ! -\hc3(i>$567HBHIڷ%K#Ǎ0|֪gIÐ#ɇS( B073Kض) @ZZZ; ReJ}L;ҢaÆwd[f|1yˢwE?q={Ph BؠOTDT¶$ ֧ݻیBL¤ZjY ijj)Xwmhկɗ/^R BX,Y2ˆm]̒b~?nM+P B8xLrr8(]F ۛOEB7~gs''J=j.ہ6,Z$ 8رc9~]%z =v6v/X: |Hy]zA1&#+6=+}'IϚ %4f.0LW==渍1&PڶX;=}<o\?j lV˃---/#GNu@f".ڶ9r]Q|x$''ς;"Fh Ls=~܄ſ:/(ʩ:xyyqzzQ|0FݐE2u.7/-==RojkJ>gUiVyotH+fF gTfprZ8D|||M[;?y?ν#G\0tѻ)P6p?f/]0}E6R\7F)&FƇeO ? B .蝻pÙgM]8!'':u+B+W c#dcm۶=@aكԛ׽zRu{Y3M~sOڍ4nsQc uo4l𦎎] !";;5srUddj<jϳ^R9LǏ|yj~AӇO?~XT*ſW,[]re+T-]՚53k֨fY93U՚5j?K^^_ ܑW/dIENDB`(0` %9?9(.2.i$,' &! ' %!                       ! $" & #*#'-)4<8?484?#*$"#"!  !!!!!!!!!!!!!!!!!!!!!!!!   !#$ )$282V).+%!                                    !$(-(&-($                                   #%-(-50_$                       !             $.4.bUjj $!                   joly}z&-(                &!fff -30Y$             &-(Y^[MSO !            $.41R%*'"         284kolFLH  !           "$+& &!!       ?EA{}$+&           ! &!'    '-)UZW             !%"!! CIEZ_[ !          ! !  ptq"         !  9?:jnkFKG9?9,+2-o$*&% !(#!                        !&# &!$+'*1,r:      lpm#)%         !  !          X\Y.50         ! !!!  X]Z"       OTPkol           !!# 283$       #*%         #$!  V[X       .40         !$!(!#w{yy}{     5;7OTQ          #!(#.4.,#    !      afc>D@  !         #.44,$*&}$              !         $$*$}%+'u!#!! !!!!!!!!!!!!!!!!  !#"$*&w6=6!$*&x%!$#                 %&!#)%z4<4"PNG  IHDR\rfsRGBgAMA a(hIDATxxM} H F$JcA!!]"AB.H""$Z)ea(cQAyYxO {)ysgw/h13q܅{2^=uVy^|[Ϟ{(X . TX?+U<  CYr0eFX@`w!\2&$x`hhF a*3;tyO8@BуƍaI W"4 +5̟PE z;'{}BīHۓKL /_7-} nxB穦_ = 01kݹ{:A|Bҥ*3Fmķ+WN9 hؖ zG֭IU)&pˣ?CO *AA*k{+ڵ?#C{U)^h ؃[ׯP)RےAL6aQbbS[ T$`۴ G!=5U}d&IL AK[ ? I%VCM[8p) BCcHL{L ݿz F- r h\SOB#U@8"傦#7f&uPAS1ڹk,Ah;v0\" BȸvK7n߹MIFj72NO=IZ: YN zuٿ jPD W8yn޼A*UΞʳEEGQ>Ӷu;ճ71fM؞ 7$f䈑5J'00{:Br!(060/d_8O@s/3fs! Ct*U’PRe%¦-`9CT >]PBjT{2G V8ʕо;zd&. -EaTY᳀s܁)U TV=QTP@&f޼!X%gPFeN ^ ~j]I#Tg? uG*JgϞ#Cz;޾}K.3 k׿.rO7>իWD۷I kVڢ_'9% r@ˀG#Ǐ^#Fk^ׯ_C(ʍ T+_F/3͛e7 T䘪83x3iڟwh~@LZa}\d_^`Ͼ2 ,rL1`^(0mOS!>a=Z-51?S!m1+e3f$&V/RHQXtpDF-@Rwl~׼Ȁ~aDG`̆td_מf;ѯ KCP 6'r~=dOƐ9czoЀ0?NDz?8r(|sB^.+ }\xcr 6A%i!ݷX kr!#yáoWG^ C=O?YgDA 0x`nӦ] Me%Â0r9zl+ڸlަdff҃^n. ފz..UZNde6UuɒɁ`dw@^.xy'iSd;{8=xTIG0Oᄇ<Zoɟ]udܸq:(c@ r2kLYAoA6?X@d>Y7 6MleytuMo)Щc'ɯkegIGuQpVTR|Ӵ=KR af(}iI EFcdӡM붲uCw: 6f]drp]J, &@ٲz\rU4 lLUJr)SW0n$ך3o6D\N.斠jն9wY1ŹE*_1&|IE : ع&j~AnŲcI ^1l @ȇam#PY62nɟ[|[V(4FJc) mL4 '䥚~5P52UK$;lR1?Yg3omFz)TXTF Ϟ(K+hoi8e1f$ڤ)ɣQA(YTU2%1}Lhݲ .]N7HN{1Оr@Ju^Ǭ`eN`&%>V )[ƌ)RsJ@ j .,J'O}] ===HۺY{xǮ <: mvdx9X4t[vf޻{ %;|[Wd eЭ ]X<3Vǭ%;@ZLE/ >u]k@-7Q{ će cԱ$3{a2VVI[XS;Ta`51k&r39 mIJ ?փQ1LRqkʢ@oW7Ť-<~ &.=HXUS}=5mT[KJŋUm˔.#-< HC?'`b 8vpdٮ0C8yvb׬-=tk2$쾴JQKA!ܼytlMo¸2 ЈG#K!Љ4`LӧOޒ:@΀6BC4!ށ;,Gc?}ԩ$'7(hpӭ ǠOwT4 Zh1UUpmz]5MxIJ 5 j f |q V,] AӧRKȜ`3ʀ[]U6@,%4HŸ1DGjcp׃:B,҂UA :1Q:B(ض}+2i QY߼u3/+ E*`QvaXlNw%J0iGpie$ܥWeB-u6uY{@ $(PR6orʩIaz|0jMڳVT$^.W^:䖠U_=:D 9Xj|kb #=te&ȤW^Ac+Sa$ӧw_~ G>:2`Ip, 4m@#@z0 /mOҩaj4h߶@Y1 C=x942m̤S^}z#bŊöTCP]tm;yS TG!~ l 4~7^ܼ*;tJeǒ l-f ([Vvncv B#@^0mu9pp? 6P_~U+V3kmn 7Pl%KYWhټ Ŭy@Ha$ѧ~}P P g/v^~ؙY{|`k*y(,-%?2ΜEȞ)SV6{ {wke& +0kr P ݻc<o߾ժ~)X 9pLpԵ#_ ^M)P\yۘ06'hU@ZmnߢF,uuqj slUܱ0Vf ڀ'Ns.׫?+U?Lϟ=w׳O6uN0us|"27d,֞=]a/6M-F;) nݡ]Pr\}ǰiKLVvn{ >ɓ'Z~cAwF7`bސF3q~jYx3gπ $,ʷ: -6MlSl&OBuXƎh|ꂖWiE q=  :[,kőįKj?TS;nFC|-@Vǀr(Ulސe .lʹHҦu[9}]yM&|9]\uZƏ];\μ_6ŃAM@ zC1DaI2m?q wwB vsfU$BisK5}6Ǝ-y+V,E?iբ%50w=zD T* fZn70 OGuش)A~ذy@ dAmD\sָ{ @ܧfMabx}-=Z !wQYݵ\LQ =kVCЌi:>I'&E^1{:Ĭ^I {[{?WX><yҘhrha]d]a[ٔ[vM, veXv q5|X UX%%>#`4yl{_ Ta5a$\'!񤼂Ec^@ tR:hf_"BѨ7q 5~?Slg=$ x_jvְ `m\ 89;w{S#}A:nν7zzz=9yP57@VpvYi¸MUbĚB^H۹Fy"jY4n'hT]0KIoRgϝ\HX z_8_L`s&z_z|& kV4y֣+oШM6?St=)V8Q^H[֓0eL80 1C!?Ç~}=IXx~ȴS!N7m?S ;;bdhV2uTR&!5;"=Q@gXnS.Vb8 :nܸSV]vꂳ-u @.+Vh{>1+V˖DRJ"oU@KVʟfaz:YtaoOp.50Κ#cȿ[a}:fIr/(kpk- k), @*sgQRA!͛36ڊb1U!1!Y~Z懆h }K6;! S'E @d )]FeQ1*cM 6%'7̝?J1#$#b+ yx2K[:qɁh|$%1ڑF?5 HS9 0a{IX+"aET::fS=~髱zh$Y8<³$W53)=9p"v7>t CB%+Tk"Ŋ!N>5!O% K"bnc0dPQr},m5)SDH >OO I'cgɯq\c~ S:58 ~ҥ&rPA8/Qz:?LF]\)x _v57&+{6uhAS:R}q$@@pHJ$6xd3&Q[ lBhHuD?G&L6Jz]uw(ٱWsJv?Hz97`?dvOye{Z*ڣ"1$K|J-](Y~\_>idptx2P `V_)ރ5"{t2HR\9ؑ:"9#y,ۣޣGBdZU:"p\gd%](0`)Щc'HٖcJ_3{̜ +TG+m}05`uDeg'rdD1; :U@TlMLxwѷ1˛5iO׈gC"g-~MZժziК #f͒4R )9y](?٦q_Gc1+'L,5 J*{YԸgAʕ*D̸!6a^BqEd XG "|q{Ν?ρ_zǸ~?}J#! 7C5#ݱڟ׀^SWPխ/,EbWM/BBV7Wg*9hצ%Eh?Ss$ q;~-p!`[/wr/C^͛7$AP4 %tSps9 #+alq"`iCSXtu׭#x\B;9ۣUDtٖ:B ٶ}+_C`.%JzuC9==|ǏBy+WE*=$PD< AK0dP_7n FwfaÚx9ZBĒp{T[Cf>lx;ghD@ I'D93Ŗs;J#I}ӤDgdɒsnќYv ޣ4NCtd  'u6.Hq3Fyj4А0A Putjw!B"y!nm,L>Uc:M6{;~70 g? ~j@I?9L!T* LA$Yp8}4\*\rn߾ůs6xƍcf޲2 ܑq;#;1n-ELTN>} NΎ:oIе<[lRJh 'æ- $v`gkی꫙H#G{QGOr)g f%jǡ׭GJQEBVMN2nTs @c׾䩓j`ia @'W> LMMgr<XIXե<~;cWoF1po uP@&v ǿ{u=W& pq PH{d^@P:{fMlj{pw鬘H>z@#:@;[;~g}`ŦA‘TK(&c7ȃKIIa @Sf`-?Geݘ!u6  -6ֶ`og/p@|8LTa id#2GLX"uJ3`ͺ8 f?B% 9 @-ӧ^VSvŘׯa̸ѐs ڹ̛=/ge2d9E+?GZ2G ?": YZXx!7a,ܻI1ŋ /~]zvCP X6MS˔)gQ"Bah2ޮuefhSF&z6&Cp՗xE0leʠ00p>`؜TtE~W<»%i3ĮY o\'2 M 1!)w@O0/Ɇ\~?hݽ=-^zEH_ @F {j^:| o-"#ݸy_8/f=gΞ _~58Pf ʗAl'|jK>7Mx9<}q6:ϙMrw A( ~fƴZ_5jp/Du`@~Yʢ^'0d;_:  eЭ3̙X|vݚ) 8sL5ܥ!%}@i0Ta AhOVDA>sq+<{LML`s|1+ZQcص4 `=-6Ξ=CO /yXX7ndܤ'JRŊp ǧk'L9WFN]q)[J]P νZ) 7nJ$"t ϷdA=χKM$Sn=HMڮ"Cfs '~;NFSp07Uo*MHw7czRpahlj1q_*Ml??Kp}6}dϟ/Ykծ #5n                       Y]Z           ;A=                                 &!              !                                                                      #                                                                                        GLH                                                                       "            FKG                                         픗                           !                                                                                                                     173             fjg                                    )0+                       4:6                              =C@                  PUQ                 INJ                                                              062BHD                                                               AFB                                          KPLgkh                                        fjg                                                                      ( @                                                 +2-                                           LQN;A=                                  psp                         173           =C>                                                              퐓                 6<8                                                                                                                                             ink                                                    mqn                                  JPL                                                                                               퇊                        퍐                     _c`               fjg                                          &                           &                       RWRPNG  IHDR\rfsRGBgAMA a&JIDATx]}վ6KئVBm@qvkкQ[QcRl}kK1JBuS@GЀ@-)$bjT4jJj FLs׻wg~3s܏97!粻HxZ{wyG3'O|裏ĩS{O|ⓟdg?ˎ7N?^,[,=~0W_?Dr>ψ;OL8QG WoookϞ=/* ?/:;;# /7|}3EB@1cFVBPj{ytUn ɳēO>1(o7$ͤ|p++#2*xݭ<}g-5:;;[y"Toz,HsU/ؿTK8D4,mMp ɜ9sZӟ,K]SN[n* (yGDY"褭nZ1aSYY5"PHN8hӳdikn}BJϊϒeq 5kY=K\a %Kկ$Xd,#Jd2ڰ DTf?d/8h(zzzZjQK,L~{?N=,Y/ ,dvvȑ#ЮRdIE svm%ʯdx@DaϒeW 21m+dɊO;E*#?KJ&Mj%%{ ĨQgtqq!?9)l_=* ~ aKPU:?ázr=zTlٲEڵkhx ߿0 P$bC'_zŗ{mo3Di.@@U?2S)Ds=L[o{a3hr1˂?},sNkv@5ĭ2G&?NAKƍ+|>wrko9< ĒWˀ}Yg'w3aAs9sP3x"qL]rVk*b;Qh`je`,_t eUW]%Ԧ3V~wTc"@*kSkFȹMg4-[AE~'_$ݪU{kEe~3@ `wK2*Q_ H4? zy &s2x%8@d,j48P~5Y3~js.ڹuwiR/K9$@Ռ (vi twws&Ў"{+W'Ν $ud !5ݟ8q",:H:>PM7?k}gW'% cG* s|~ߊ{キP^?& `OB9s$qF30ݣ5uһ{ӞGj;vL̞={ˑ?]Q*@ ShW :@kiREfɒ%@ n?F̀,ui{?NMEYm޾}{K3HT,'y\.B<.C+Wr7ӂEn>5  @}5aRQB i ڎ04TrY0w\?XKÇ)SˀM;.jKV|E,W|!좟3k\x{"9w-k VѣG̙3sUJ],X@ IM9'05X@3.^!A^`2#Z%((t@V~Xӧ|$"c߮v\R3p :ӷZe {Al`,pJdۢꫯ.<4`T+\sc8UJ% ʗjY R1nT%eH̛7/w7P)HEE 5w2| .62TT~{zzgY /25UEa{3TVO[\ Ow*gQB 57 l(Pʀ Xd"n VElC[/@ʒ^d Ai7a/5\Thl*?<&yZ+Y5V~W^yt _p:1ڶ\=F^C=lf:o78IimU@z>H0vjC3f+W$Թʕ P3m'5kBa-fed I,@P|gSS,Y2 Au[E݀,ઃ@YB ƕK#`zV#PVbܛǓz- )V}X@@V>R&/^\ H~|۵kW@<zd k PK֠  L6-@3uxĉŸq?yB:uB>|88pՖWfYT9<|Aח:Tu'7tS%ᪿ-}rUX-cY [Eoٳg'Xw}w|0NTs$ `au]#*O8!z衡 ^K az'JuaXRאA@x`,WcGQLZ*kYP䰩3LʃӆVlcgr@STXR@m,QWIE Hvl@e*>bԨ\&*6:DԒ ,x 9&g-vIOTl" "K)isuY+@y͛QXo.m"E@6ʦt&Qm6rJJ߯Z+PKN@S+@m5B.VGl 6X*X)bZz]wu$/AMR6'X`W;w5W3QET,LV+L̲TacM!MtVT֣4f2՞!#`BscLHu}2M/ d ![4`h4M}p>\dME!t*ATXӫ$]@y6մ+Py*J@S_t2e Pb Ij)꺅ЬU떤 314٪@@Baʟ-Y'K +bZgDI-H1P6q^^_r+  sXNB 2,dt;v8SN"d cuuuXp7 yXe-_V(v|*ni C}vCA(+BSӔ\"T  B$W`>A $ MH; "% $˴G@Wz+惓%!ZN},m g?$}&{֭ "}NAu+)=R lYuKKܫEw TOR2VxcxKA.\0LK2)2!! &OM~}yI-r3|>`r=UMXj#Z%UP~1ZLͱA @E)킀u˗_!:*)?PyT FX }0lWPQG7 ^(zI@Ք E3=z4)m\P4"F]@h0KqÆ ʏsucjK1**ct_OfHE4+7,{ !}P5pjٛPeƒgFLL ȞۺNL=^_L@Օ_C%uL R u/lZ*P^oG(z6^~T7 :XAٲeB!jrV3j p=+FTNÕ҇}rlL)Az-T~,NWM5 NʟƢc G&CG~jcǎNNQ<4Е߶ο/`oGJF0PP,K@E8V4K*)mw˽``>h_U3^Az϶`Da*ʶ.*dZ/_j d=)SćY[N[ĩuVJ&QdH-(=2h;œ 3)+*LAݚkmާ.A$$e#>}y={$￧ts=\uZp~g,n^ 4W)R H-Ozլv-dw pb$i <.~@S_6ըm.\QЂ=pDw-&+xfͺқ›H1Ph킸CƲ(O7E{4h \J:<ܻ+QЬ#fΜieq#k~^}7y7N6#dKfGKof  T \Rvϛ70IYE*u>bA [+sBGMū)[Ai@Vb& +|nuX+V/^x TPSMrHY 5d{  cƌ?O6\_$z)єg`,}Cާ؊|G}۟oM`x5pH+%fթX?lzf̚ `.Qܬ~ڵqFഽf~ q f]K@Rd;}EԷ"[D7-ba& ,I=> I,.Ah VNJi(ozdp:9cX˓-"MĊG\@w o'qn_ouM@Ccf+ysdF}6@DžE!S46IYg r#ӑI=z4Yg%."q饗f2gڪR9@cI*iVr&i֯5duQژv(ǵr Gg.ʙYdž5YC|ZyPw__+rڜuwɹqtjnrUCq H ce>'o/$a'cP=j':[S~ّ2WVz1C@,Ur`Vlt]^mwr s/wމ&VgtLZ=$Ɲ\mw81\l ,Q/m6wrR2JT:e^xdUg`.ǨfQftfpBEe`ѓ-_` شiS0{rUn@DEEU_wyg"T1)?+ 5 T=ڔN?J*P]h7{ƍmq,ܲe + SI>PVmHLE0V Dޣh?d DOŶTJ4UV>裬D5 H9\0WRUotRο(G( @ (CzՑ| 2yd'Er4U2bE,oH @ :s@;v,~($ 1* 5vx}Խ.ᒡV+UL6?N%|H/Rbz0h*ӂ'gd MAR>w +Tz/f 7 -2&b { r"VU~KR~c wKmW^-~ >k֕\ϔ6^tܹ3v#Vz/b۶MbԨZ኿:}n{!(ƍСCΑUwX'F F1,$ !?r:E E$R:ԙX+ Fr %^|Eo?JD<:u*5A3_ $9r$ƍ]v7_^ķ~^}"J Vɳ=m_z+Vp +ZZ}]1uh\U0$>|xH2>u^\|x_V&n /xt_^E,@F1P9JȺaG?q>??;48qbHs:XN%]_&:@ &Mj*Z%G_r%1藿;Vۚw-Ľ!Y4_M,dVPPY7iS;/I^A@УH5l)~;@]@# ӧ_Ι1lҲSP?c -}m%l!=v`>~ҥC$ќ9sZ䓢8m!0mڴ`p dF)G]A 3Ђ…^<'m#}.Dv[- T`ڴa3E1̣. -[gb8 '̙3/὿=XUDIYȑ#QMV5`(n!8c q饗fM<%y?$cGM. F@U& r5M"S) ,UYVǏo[4(rM@+9@WB_@y>| @;q+"v/WLnS__U *py}D09x`i:.CR܀S}n&n7T(sL  ;&nF!WM. Pl|"8 LxY$;/|$1(iAKN@໓<7 8hK,w&SҪxbP@BP~ƥٳgVFKki%@J?vJ)Rå5k*WuAd T~jD=|'7jRArdHՈ2T~D2b3@P!oQG{_ˍ'jUAO緊] ;ǏC=߯%@%oVlٲP$6.(vZ'zpZ1(3@%P'姶$ DKBg֭bӦM䬙Uj F; R(̀" ?|qH(ݻwx=y}ow $Z"IݕV#~n„ sύy[ u_o'^{Ԩ>UVGAq}AD.芇qŮ%A?_W(.w}i{:_ϖ@sr ru!* &488hm” `ڽs v %/ͷ=6O.6lPtPT +@;@iUpP*Y e[ ^A@e!֛oiMX|Η}QQ11cƈB*dg.W /zP*ri U~cyXYR?}gJ KXCeF ,C*XyYt?Юs8˺XTFa>b!X&?uZrd3K)v в]$tAt NWءh^XV1&Om; Z-D|޺ @.. 2[{U"U0]暑|\">, Y}VZzcFYv X.i2ij z#j %KBH^xꫯ|pY:o"Tދ/뛾r@Kwx ,CUV~|x" Yrf/.XrTyd| k'O|?SNgW3 8㌡Ƨ>xhqYgn6**IENDB`(0` ʦ @ ` @@ @@@`@@@@`` `@`````` @` @` @` @`@@ @@@`@@@@@ @ @ @@ `@ @ @ @ @@@@ @@@@@`@@@@@@@@@`@` @`@@``@`@`@`@`@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@ @` @ ` @@ @@@`@@@@`` `@`````` @` @` @` @` @` @ ` @@ @@@`@@@@`` `@`````` @` @` @`IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII[IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII[IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII[IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIII[[IIIIIIIIIIIIII[IIIIII[IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIII[IIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIII[IIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII( @ʦ @ ` @@ @@@`@@@@`` `@`````` @` @` @` @`@@ @@@`@@@@@ @ @ @@ `@ @ @ @ @@@@ @@@@@`@@@@@@@@@`@` @`@@``@`@`@`@`@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@@@ @@@`@@@@ @` @ ` @@ @@@`@@@@`` `@`````` @` @` @` @` @` @ ` @@ @@@`@@@@`` `@`````` @` @` @`IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIRIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII[IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII[tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-go-jump.svg0000644000175000017500000001766213175640533023344 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Go Jump go jump seek arrow pointer tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-help.svg0000644000175000017500000003224013175640533022703 0ustar cedced00000000000000 image/svg+xml Help Browser 2005-11-06 Tuomas Kuosmanen help browser documentation docs man info Jakub Steiner, Andreas Nilsson http://tigert.com tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-web-browser.svg0000644000175000017500000014256013175640533024220 0ustar cedced00000000000000 image/svg+xml Globe Jakub Steiner Tuomas Kuosmanen http://jimmac.musichall.cz globe international web www internet network tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-noimage.png0000644000175000017500000000025413175640533023357 0ustar cedced00000000000000PNG  IHDRo pHYs  tIME8ȠtEXtCommentCreated with The GIMPd%n"IDAT8c?5A4jШA-IiIENDB`tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-close.svg0000644000175000017500000003301013175640533023054 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Unreadable emblem access denied unreadable tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-find-replace.svg0000644000175000017500000013147013175640533024311 0ustar cedced00000000000000 image/svg+xml Edit Find Replace edit find locate search Garrett LeSage Jakub Steiner, Steven Garrity tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-list-remove.svg0000644000175000017500000003273613175640533024233 0ustar cedced00000000000000 image/svg+xml Remove 2006-01-04 Andreas Nilsson http://tango-project.org remove delete tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-go-home.svg0000644000175000017500000005167513175640533023323 0ustar cedced00000000000000 image/svg+xmlGo HomeJakub Steinerhttp://jimmac.musichall.czhomereturngodefaultuserdirectoryTuomas Kuosmanen tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-save-as.svg0000644000175000017500000007625113175640533023324 0ustar cedced00000000000000 image/svg+xml Save As Jakub Steiner hdd hard drive save as io store http://jimmac.musichall.cz tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-refresh.svg0000644000175000017500000004074413175640533023421 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz View Refresh reload refresh view tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-print-email.svg0000644000175000017500000011102613175640533024174 0ustar cedced00000000000000 image/svg+xml Jakub Steiner Andreas Nilsson, Steven Garrity mail e-mail MUA tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-locale.svg0000644000175000017500000007450413175640533023223 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Locale Preferences locale preferences tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-delete.svg0000644000175000017500000015321613175640533023224 0ustar cedced00000000000000 image/svg+xml Delete Jakub Steiner edit delete shredder Novell, Inc. tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-icon.svg0000644000175000017500000001221213175640533022700 0ustar cedced00000000000000 Tryton image/svg+xml Tryton Bertrand Chenal tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-undo.svg0000644000175000017500000002202313175640533022716 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Edit Undo edit undo revert tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-note.svg0000644000175000017500000004323413251060075022715 0ustar cedced00000000000000 image/svg+xml Jakub Steiner group chat IRC internet network tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-preferences-system-session.svg0000644000175000017500000005521213175640533027263 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Preferences Session session restart tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-preferences-system.svg0000644000175000017500000004537613175640533025614 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Preferences System preferences settings control panel tweaks system tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-go-previous.svg0000644000175000017500000006742313175640533024245 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Go Previous go previous left arrow pointer < tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-dialog-error.svg0000644000175000017500000002560513175640533024350 0ustar cedced00000000000000 image/svg+xml Rodney Dawes Jakub Steiner, Garrett LeSage Dialog Error tryton-4.6.5/tryton/data/pixmaps/tryton/tryton.icns0000644000175000017500000006411213175640533022115 0ustar cedced00000000000000icnshJICN#????il32@ 7O  2zZ-+ "8 !1 K;`v{5b1Wx%c >dFD L$kf g6 !Q@$ tu -=4ﭔ8.T Y1*tc ލo +$ ; яdk 1! 'OQ9k(Rށ 4MTG/"!    "!! !!$!!  !$ !  ;S% " 6}] 1/ !' = ! &6 $ ! O? cy  ~9 f6 $Z z* g $ #B   h  JH $P ) ni j$ : $ &U D) wx 2A 8ﯖ = 3X   \5 #. wf !ޏ! r 0)@ ёgo 5& !+ST !  =n ! -Uބ  " "9QWK3 " !!  " " !! !! " 5M 0yX+)  6 0I9^uz3a/Uv$b<cEC J"ie e4 O?# st +<2ﭓ6,S X/(sa ތn *": Ўbj} / %MO7j&P݀ 3KRE-l8mkMߦN " ki}s*' I[it32 1LN)Cp CU&І8Nj;U|"G,')"SHR_$ދJ}ЬʌQ$ڊvsЉ2݊UWasB(57}5fpJl_p&ׅrZlΟIɅ08Xc'ŅI0مJ 0fDLYKmLrSbNQ\φ@O 0f>'#CQ^J"P_ '݁+qQ0ݜ"]R_֜Lʦ(0Ϝ}KYQǜŅQq'a"HF̅LhFԇMR҅+2 ʌ0q"gv!؆^Ј̗Rr%5!EؖHU*?߉*mfmGۉ 'a1 C)^&=y/Yy9ܟ&G,9ȋgxl_M)%1RʠnݍhUɎ"uԦ͏BZ{SL>FArY#@#m)9Zdc3ˇ43JrC{`ZTqMiKUk.N ز*Ŏu(jhg>,Г~~<Aa"ES$cL-0lnNǽ1m?Qʵ4p S̬.5rL"Vѣi;xf%\֚b@~<(b֐n.WԅҿA!0>NXI7$              6OR.  Gs%  GX  "* !ц!  <ȍ? Y  ' K  1 +  .  & WL  Vb )ߋ  N$ Ѭ  ʌT )ۊ!  x v$  # $щ  7݊ Y  [ dv  F  $ˆ -9 ; : is N o bs *ׅ u] oΟ M "ʅ4 < [g , ƅ M5 څ " N% 4 i H O \ O p P u W e R™ T ` ІD S" %4 i B, (GTaN' S# b% ,݁0 t $# U4 †ޜ &` Vb ֜ P˦ - 4Ϝ O \ TȜ ƅU t #+ d' LJ "ͅ O lJ Շ QV #҅/ 7 %ˌ4 t& j y &؆" ˜ a" ! ш͗ Vu* 9& Iٖ LY . C߉. pi! p" Kۉ% +d6 %G. a* A |3 \| "> #ܟ *K 1 >ɋj {o c Q" #. * 6V ˠ$ "qݍ k# Yʎ& xըΏF ]~ W" PB J Eu\( D( p. >] hf 7 !̇ 87 Nu G} d^ W# tQ lO Yn 2R %ز. Ǝx- m ljC" 1 $ѓš@ E d& IW  )f  "O2  4oq  #RȽ!  6pC  $Tʵ  8s"  %Wͬ2  :uP  &Zңl  ?{i  *`֚e  D@  -e֐q!  2[ՅE  &4CR[M;)              /JM'AoBS$І6NJ9T{ F*%' RGQ]"ދH|ЬɌO"ڊtrЉ0܊TV`r@&35|4eoHj]o$ׅqXj͟Hȅ.6Wb%ąH/مH.eCJWIlKqR`MO[φ>M.e<%!BO\H N]%܁*p~P.ݜ \Q]֜Kʦ&.Μ|IWOǜŅPp%` GD̅JgDԇLQ҅)0ʌ.o eu׆\Ј̗Qq#3CؖGT(>߉(kekEۉ%`/B'\$;x-Wx8ܟ$E*8ȋewj^L'#/Qʠm܍fTȎ tԦ͏@XzRK<D?qW!>!l'8Xca1ˇ21HqBy_YRoLhITj,Mײ(Ŏt&ige=*Г}}:?` CR"aJ+.jmMǽ/l>Oɵ2oR̬,4qK Uѣh9we#[֚`>}:&`֐m,VԅҾ?.=MWH5" t8mk@(^̽g/RREIqt} $[`mlJE+&818-TMUQ¹|kG+ |j8*x` ghPa} t'`s%lE6 J|굀IDv˾V tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-list-add.svg0000644000175000017500000003473013175640533023462 0ustar cedced00000000000000 image/svg+xml Add 2006-01-04 Andreas Nilsson http://tango-project.org add plus tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-bookmark.svg0000644000175000017500000005010113175640533023554 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz address contact book office tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-go-next.svg0000644000175000017500000001734013175640533023340 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz Go Next go next right arrow pointer > tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-clear.svg0000644000175000017500000004605313175640533023050 0ustar cedced00000000000000 image/svg+xml Edit Clear Andreas Nilsson http://www.tango-project.org clear reset blank edit Jakub Steiner (although minimally ;) tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-unstar.svg0000644000175000017500000001066113175640533023272 0ustar cedced00000000000000 image/svg+xml tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-attachment.svg0000644000175000017500000001610213175640533024102 0ustar cedced00000000000000 image/svg+xml Mail Attachment 2005-11-04 Andreas Nilsson http://tango-project.org attachment file Garrett LeSage tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-note-hi.svg0000644000175000017500000004117513251060075023315 0ustar cedced00000000000000 image/svg+xml Jakub Steiner group chat IRC internet network tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-executable.svg0000644000175000017500000002312613175640533024077 0ustar cedced00000000000000 image/svg+xml Executable Jakub Steiner http://jimmac.musichall.cz/ executable program binary bin script shell tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-system.svg0000644000175000017500000011005113175640533023274 0ustar cedced00000000000000 image/svg+xml Computer 2005-03-08 Jakub Steiner workstation computer node client http://jimmac.musichall.cz/ tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-fullscreen.svg0000644000175000017500000004750713175640533024131 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz View Fullscreen tryton-4.6.5/tryton/data/pixmaps/tryton/tryton.png0000644000175000017500000010726713175640533021756 0ustar cedced00000000000000PNG  IHDR;sRGBbKGD pHYs B(xtIME 19: IDATxymgY5ΜCZB<9T|T jXZGVkS[)-jJZQ(B"|gӚ^:B y5gu_~?qÁ=zѣǣ =zѣǣ=zB=.lZ>=z=z<ѣG}ѣG=zG=z=zѣ=zѣG>ѣG=ޣG=z|>ѣGcZIZT ![u4Z󖺮x=zxX}!$ix}|IR,#scc!!P5MP5 er`;w}mBV =z,M8vqi\s!B@"{O DJR{ fBk-IfHӴ !,|?g­%$ ѧw#ѣGoԕ%O\~J'sWd8h$AkR%%u`@ BR59$AD)kb`VesAhJ#2~-%EOyǏ#M2RJFDC Zњr:{? C@iE3 qj޵Yv떒 $-Z8p#Kv D|/bޣG've"o}sWԧ^1 w!IvlZ*lmm)iRx𝋽-lmNyraGkM%ix:iS%TU&RJ={O}Syh4b߾} $cbt%w[R| $R@UV8>Dr )Ep>xѣGuk5W?'>L&8,# GJV 99֚$I3Ϲ;;vht:E+J)8i)zR"OK!!HVG*$ i\ʵָmMgH);_e!/p=zx\U<𒗼#/Ah4چ4KHAJeZk!xlUZu]{/ RJVZkF1@`kk m E]4 Ob I2xS748Z,9G4n,KVeRF#&) &Ih,`l[h0FG>v {=zq#_z9_%G.(}++"),84ZsTr!2xe@>H!M]Sבe)BI|HRubw!$ u]w94N(w>b}m}pl6CJ ؝Zh-9u$??}&"Mj6~KѣG0nѣGɈ{g? uD86] +$Q5O]U[꺎er%;[,.xhyYH%iZZ(1e m74@ P5 Z+8EJQ4;R"B(%۱H3&IO|"Ox8oޣG=~4cOpɑ #dc667@i"2U I>tu-BYܾ-mɢz1&R7|Ii\CZQ,ц`HfFUThKLUbZPIb0F2wdYJb F3\eIM5F+㢔m,p6`LolE4%ZIwL&cmux4y/ nXWYx/ѣEa6+:g3ɲbyG|d<4Mb6#M&) i}nڄ,Mc@=ilC}{>Ǚ31k]鷥u9](Uآ 8y48kY\[r۞Ùhu]6%8*fJb}TQ9b1h{Mz?e]x=zx>0ʦO~Ip8auxLb IPB-&1EA$$(˒Xe)[\Rt4M0&n\X8lFSQe[>PU%mTUR,t kł%E5ӕ̸D]TJRy Qom)ԍvt10L|ӟbZx=z88yߺe_p%yEQlF4\zH7W]wA`0@JIQeEb"K}8$ eY\-"3?.R*=Vhm]|x#3<Ύ朏DnM +L& />,I /Ew,q!ek9*@( ." oھ<`k~~£g=zq`s\+^1$diRxp0 ;[ },O;X__Ckӧގv[%.XXg9}=IbB B rBDᗦiH<1ten=>8`6Ɛ9{,'sʲ v>k:j65ibPJHS ٌ|٣ǮwHѣGG:og$kuRt<CU~6 w@@*FsRJ110Lp6f{Yx<&xѣG/dL|7'=,Xķ.a{#Y{A6RlƁ: x6K672oZxu5۬mo}X$ Œq%4CiN$EU-ϣш$IY.VlwZt2AIr{OYK_oZ"ֺc˖$ $Ak,gMijԀ8AD=w=$yJ%Aju"ox)Uѣ\1/,Jԍɇg8S2ɭ,K<$ix2Ulw'51Cʪy-Qg&Hh0)BR)ٳEq,<R. Sl3, b>ߥn dmcJYBsO}VΜ9luSۇ@60N9u4D6\zɥtMZg %8}$0OHa>;Nd:x3NiCffޡ!E:ᝧjJTV4Jk|jUZG=i|@E-;;@hE&(>YVQ-jkI4`OEqv޹Vv 8Iyd돣޻Xطo~k_h=z >xB oYQg=M+q4uC~\VH(ܜs(!m|dZ6mM;nEeB@Кxe]HCo&mtkbX45 dg>'AD{<;.njIwS AQ6H4@ .P HTh{& JDQ\yc!%I*e[6߳>fA*s-B7}?>_X[[ {<^z! ݿ7r~ëPH7;$)_>}|t^}̓CC8yRra=ѣ1><ҼuSs]wrmλև$++"M> pIn9ydTot־X,floos!Ҕ-ۼ\BCQdih2f6eY7Fя|Gv}c6a8ߪ3g΢d{k\r 3$a0weEYPU%!xVU#W $eYZwYW;;k?0_t׾Z~?gu^|=q~?P._x {okj;O|7 {v;' ^ӮyW\~ET|`ggo|?Gˋ ×=+ykaHkkJ)DJɓ'XߠkN:&4傃wiu]uƩSIӄrIUVlllf4t6(V$PUQE "fEU$$yZ粺V%M"@4"JFekk4KI҄@1Գ4n* M\0cDR\z{$IlXֹMZ:hQU mnއ.Tg dG 3:U{^_~g~7菿?B=H/^z`7}|/r ;v_r~?mb%_y3DA|Ƴx3ō~'o(>r^$xeW??f1L 8*؈!b>'IAa rFG2SVłgGpe4)^xԍX DS|9}uC (8!xmĐfYn,ˎ^܊1n(y DK簥籕Nѱ:pzuK`l=8֔UI-֭`۶!fy@s}ϙs 12.΢J5W_%r;.}ρWN^o|؃7o9syW#?s^uUn%Eu ׽1_{a4oοv:^_y7sem:A=Y5s:UYy=/mctg1F`Bgr)JH$a4qinVDi]G!fժ*+(ZӤU[rnj`\rkغJDYRe^1Bjnڬ8GЎuAV0ˣh@(jkIh M R* yCAeUO7Z3nqhR()¹8oxu/$^/y܃u/!TR\{/P|scoo}X=}y_=%/O7颸wg¯|QE/ :ʳLswIh>]֚|?) ]3i±+rYbwwwmghrتAzQ[;,lrb}cM!yeQ uUAbTM|>.KHPYk!Y\gmsh_I{s~|9zyyރ*-|c p b?[?#?47׿{|+~o{=kk=S#<Wa:@KM&ƾM[ I4ilMxHy=TUɓ'llQ h67>lw.ȡ(ռ7lح=f06;ۻآA:)RzÌEbQE%~`38>>!%R.r& "bU"D;ĠG+Vh۹\.Y%i2 L&YFTeGĔ؏0P5咝]nm3)2Iّ꺎gδ4 Zs1pfiq;jkc!V dvc5&MDTZkT!ےF)ݕnj1$A' "MiJoBb>ɱ,EXkIZi'Ηkmxs4{}ݝ狟%:/x U]{{.%˿ |=jƕEw6d F0N Csh%ަjnFoP;|gXr!\c Fـp6=\z2w`>p"Ǫ*=vם~]:KX'Oa6_,˒9<$>D }8ry>@)$Զv5&SSRaCr$)I",7s,_cZEbk{,J|j0_,ٝY 4QVru,c-ۇQUu-uӐѮs(}h?bY|O9Af!. %mMC]U8kqF]uk C:p}fPJ!jTUTHkzܛ&;sRJ&Bm_!_#\;_{a%|k7^@k?L3gN? -%q?IOIO|#G.KpWQđCGrٚ4у[klcYLɒ'f40G:pIHЉa<rwri>OSNrf,gΞeg6c\LB:}epTe=N, dYN8͝w Rb]t+ż%n9,+y6` ]Y8HLxOOO&gǟp^Ǿ뮻 (ڬO{Fӿ=gNǙ+._d$(ccz<2pq gcm-vKkK6< 6'Or]wT5ij9gss_d uSSU[[g"eS5k?iblی*xrU'S4Ŷlw$Y6[,e4eUSVU4 sʪbZ* vvwY8[E6I/~pd'QnUmS ! !H H6ir9p8JNiVUUaC*Պxb1MbMts("$tA{ﱷ@>gQvv/V*s(%Iӄ߾//R~gzCzxC7?_l6,ZxX!{ywɄ,ZJhlgjגvwwQJ1LIIk++c<6HSR08?`c}%egEQ* VqK)1vLKi"ʈ%nm >lk*+# LkqRD@UU4u*Byniub3BsoΩӉ4z,pit26UKNi]v BT+w:Ekڔ4,z9t#WߒOi~X,vE~o:/s^|?og J){xg¿~ww=v꼎~+_|m?OO~mO߫̾q(nϸ]\+o6ov"8|0(ʳ$H u98x J)Q>r5ْUQa.lsT][?GF6!pKY[[pxrUӸH']VAN0,Yj4XPT%J),fӨ a:ښ@`[q%w2.."a-M'8 3˰!49|QfLHr5o+x$d"na ( 8$%x_Ϻ\%}{ϑ#pS{{V*矓WWA>qǹw*_ }n>s)>?=~/kӾzp!M\~.CXլu%߽&s 1kwDZ XszLu]b шMkl-f{5RVU0kKLvgѐ,&1ۑ@ u+84Qj\cbe%5uC4IȒjESD.=u==W E12'cҕ4C+AV/ViBBRὸMe0QU " j+#Nk"I+B+uM_B0? WFkB1 !soϸݟeBAU ~wym?>"Džg?YVԘH&e,7֢,V3] IRRVMSh8Op4"MS$%њp3`@2}YkN8-"(ɺ6f84U;eVQރX6$IN˒N:VuSo)\IY>s$Cflg(;Erc ]EV%UXiѡ-m6xO}6Za$iRt=w%%κhb9:ǸEzL zReYU>Tty?n>?峯_խ2}Bկ| ixg rvC7*lgΞỿfMa rj^q',";Gt4(˒Y6cs>| B,;K,UU\X8׬αZ.qւKNӧcl?mx2+.ȑ>|pRjp0`-+4ŅXP:f6 hakȑìV+@ɸ`V-%ŒbD҂c]w3%$eY\X.V]]Y*,KB CmF4!`h0D)E"\}ڎ gXY-{,8{wkc6 蜡n kksOzf//+?Eu7-^B|ݯG>r.?9?]\ɱˎ%4UY(PV%uU3rr603ee\O|9<yeGPXl/NkkLGS5&)R8%K ,р ANhdj0lwR%jISv)Vs;KS7x먊hXVͲ&)kO^Z|$l=|wFYxQҰFe$iJY5$Ud O Ֆ_@},UQT>7(pv}ʞ UU7>? M6}6ɪbޯum?$I80X[[Gf|iY4g8n5dcc mUYe\X)ٌZra1kc66oLI3u5RI!x&s!0)PFr%9~Q4*+l;zy\bb\E)NȒbYpel U]"{b9=n6yŊb& Yשm=Y,I*wX۴t,O0YH~Tk"TWnrFt{l׀m LcWkg>쿗VOoŌg<y;ˡ{k"Uߔ= 0;v윣tNZC;8uoR`Q8e-=c7iV)TۆloZru4ͺclFb <ØfaFo8z|(KX{a?m(mH2s"-EP:MkP2Vz{V}oڹs)[R s.)Ι/Ѫ)-6~%+9=rc.a>ޛ}ѥ\?kr oyYms=[h$ X+K,XT, N*P6v*WEa0`@F0IH3I3͢^n{wm=Is{Fyo{=ݿS1II/zQ_NБ|yi ZSUCOM{}r:ZnΙFbfSu{Bθl,1T˴]6)+6c94M*fְA@SU J ٪$> ,Nu=a[kqvk'x"I3-)k|h%?8=7M3GiE"Hu8kewg{|}@Cq$HD“&a"\E]5(m Beڀq mW71N"$n9U~M'ePdGV=,_W \?p3ʜ`bj={ӯa1_L_?ЃO y#0|/{a~_7⶞Tּ^K {zZOc9p9cZq|don]ڶ#B(ehfw] XΝ;`>_uEH H2Ϙ͚)|cww٬I8+i]]߲<>f{MeYPr;; c۰L n4+9z՚IxZQ9+TRCqsu-#F-Y.t]_Ho\`u7(Nʒ8Í0ċ YleqC[i.fhGϤ,fD7Fd{|7|ӳo)Ϳ73_/⮻.9o{뙍TnZs٧ݯW^5~!}|髿t֧/x׼F[Xד3LڧĜcY'*փVz&L\|PvUee^Crwж):Z}uLSg%!hBlp]:i}!1B$%kҙDKy Q]ڢ4spp@xD%dIm~2ɚgѤ:ַhXHJb%J8gH!#x$XR oW i-b<l.&wʘ& h9n+_;…;| .|RGGOEWn|3kJH)٬Iu]Kjuݮ-愋98Ur7._‡(~;/| 1αZY\|!$f}8g55ͼ'Xqﹺ${6+u*4峡3gAdTUUIjQX9zBs|D:hn`n{s)X8gk-IH,i9âIwJt ucQ@0 hB92dKI~c CNɴnpZhBFHbb"+ FARYE|_jПut|o毟{-ou_}6G虃T>O=Jf IDATw~}ROO'mm{wmN h<^,1EUݦQt+XJ3K.se^J 3C ٴt_VS814n5;hXY~QҠ5TZ͆C_čIY#'H}bƬc [t5_HE0|]yaMHj'A"JKNx@ C1IZU0Х&(D;/ef(8-OU$ftvZ_[y7[ퟚU7nH<أ_o=75/}w/{MOC ?OHXbfwwWu%^)q>1Q vv888} ?wh%<>$2 mwxxȣ!]BTuN 9^.R5{$"9/fVYE{C:C6mGYr Xg-X#ׂ(d nbѨkj9g$aE,ri]Oe\%Z*ș=bLxߓSf60ƒEH)ڊbb:sSU5]XI(VkLi }.9D/hewBr[IF&US3ꢁIKR.))L}+l Q_ȒsPUr aTIdQFY3YuT,S7HI !)s7Yyͫw; \ =r7vۧ,M,uճ#1~^!7~裏Ly^F۶Eb[z1򗽂*|*\\(j649uca`ny+xߎZvvCS7s]6rH Jm{OL"cҮV;՞} }lWĐd2`݌>(^ Kʉ~h -:>]e[0P; գ#Wt풅EŊZϥB KŘ%KL)nEdcm,kR ӵq")\eY{ F#9(uͪV(elY"E4}9]3 .ӼҐc5ϒe{+rut뺎?]|Xoּ}7Mga]yG}uu6}}2 wOD+qMbv;։A}Yg9:Q8:>Gn1Ũ!yZmf b|$+t /zыH)c+c8wpʵ!a'@>vww"H,1eϬi0b\; rG[MU~A)LɫVg)A( I|Zِ3b\=aeC }7~6ȑkih w +ч{y i’QL IMyιi]3a`Bΐg=+di4^iZ;bJL,giF mt@ z C(d.IJMżś>7~g0vʳ>g/{M3{<iLvםwy?m}׻w2]Qeo…pn_>y衇Z>ZMIn.@G7cb}ku]{44u=Aܪ{}!ٌYm,!DаX찿#h|ְYmlFAы~b6V;}G{SW9vsd/|x;`ZS$D+ᦜ2 Nq1+kd(1 @J`m%5{ '9֓UT4&Sc;1 fMLLI;9LVFq>PI_*#~X2Jw8'4!(c8JZ ^NCTI6xH V;.D4ƐKϯ> ͆fͦݰٴ}Ow7L1bc?Sg~c}͹ o >WkYPx_+_.qE>GyyG?ి׽λ3pb[m]œX3^[gQBPM,)4Ci֫a&`3]߱b>7rn*r,J1a F*EK& Бˢ2}2yu)NWB $2 ?Zrާn*ߗMy^nόR–_QnPrֽ<"뇞n#2$̔+' J0ؕjY+EJvUwq~|76moQ9G}\\Hs|O>W\}n<CM.;+LK?M~=kgr u_:r^=ʕ+(X,yǝEF6둿}lvMӟϚh|K^Z^rC6֫}mKTuD.XbL {!1t-~ph99ue=vwwAXHֽb~כDYvC$d(TRE(Px@ r4 $W!e^sx*9ff u]]OF;4B4͌"%DctӤe'+k(;rg-՚9꺡k;?;G̉9a0Pv2D!xW6d;+55:gb,.Sz e܍1d)%|Om}#S*9!oݙ{__47x_￾7L*MO7ԩSiRwy|fuvm{oOzAz('>7u]hiG];䭒jՔz M3#F9WqHbꇌm9\.98l`S8T&bLd$zJ:Y֊nX,a@~L)lzy?h G/ncY,%*kơh\CfJi]6/Di*L$>⤦5: u ɋ-mH^ 2埠8ݙ ʥ)Tclh3L/ ͚(0ZM17t,oJ50ԉ"'O!KKo{jY=sZE_3#>Ce7lۖfu}['3;㖺ǘ8z ݙgyޗ? `Ɣ iȠj3>ƉyZ|sEmOZ\7F)цnkX7:b\"//xӮ >S]=z]Ԯ{^pQ$1k~Nno; .#p}/^_^ju=.rغr#{ZŹݝ=꺦<1ueq֊X }QwHUTN/_qNK10aƏܶƔ;N)v-ˣcZ+njdBWmE"_4ƞ,W+s\$<ɡ]re@f'2ϥf> _Rd[ʖKꦖ lRlPS1tQigǐAh#p_\f-sANgF4͌fuީT3϶^|ݽh﹡p_1`TOY RbO0\:bd>a|b$e&ҟBO9O5#>ГT1r7ybꋃ[ꑱֲO޴-8?;[Bwoow7/yɳ }Wɫs'>| ` zhvu=LHz"YpU~`ZbggG$\IڵH]+I DP:b˗1pb,Mj="T(v{bN,M%Ҳ"1lr$tj ZU9AdpLۮj0۝G~Z\:,3!%\%kZ㲃pLqƜ4d5/lٌ6lD&g M-Y2rbw %qjSd+EUW&wdy''L2 r)ERT򚗕Vs*r9NNDL0Sve=yI>/zՙo< <ӟ_M=a<=-w@},x_> }:kSUs2 uh, 躡L_*I5 Jx)À}mCVz;F|?`U @v YQUuYd:L*f IZO*dr)b)68d;D}@)a+*|K8|6si$9k!@BQi0P7}bS=ڔ=F}k2GRKOOyɟ+AnM ik3Zn|^B`^xMݿ.6Myb4H>yqEOb~{?nn͙X~s{T!ӷ-<8sw_Q|;`Czrmh.~4;DzX3/rTz62ᙤ)/fvO6@ 0t%f-I# 1@8]g{JD/^w뎡V vYTo~%H#eĞr -MjcrSG׶ !LZ[A-$pKW05& @JE530j*P G@kT"HWe _+Yw䂈,$:0ɠh*qʎxM. /u]\wyΝ;T9ln?O^rsnvo1Oc#'n1&^ҥ|x"Lkc+|%]~BOOo7y'3._;/Y/_˗ow77Mnh)4Mى1~wgY.hYVh xY,D{bb6_@u+lcR9b~f&􁝝9 f.}mQH"3]94 wu)8P8RF13I9S73.(#_2Vkݶ6ȼb \ql6k=`o E` >EКDm˪1J1k 9.'uidZk FR DۖfV3oFq'cI%粫vV5Ti$K$8N6 l_TeTJo[ۺ \vž HHHwww|B^d'S[c@YS׎z-зhr1[%;u1`J[SyL(ЏY%Y) lr.v4 k\mm{\S〰@IHf!rzzN*q4 k@g"Dp$ehq]O ԝ#à IDATuӐ *Hb9$y_kp!e0ҼItLڲBؘK֔3Y&\36齣>P {MP3\tqmk[7P#Lmewo5#LY[,ͨ;n8Z^F51+1()Z18@( ,ňbJaLbHWd#]ZI#Tiw20jSVT#D,+m|/-E"9m1*%YNF"]YMڗ=s\n13Y+2eG_A?CFZ_=)6σ7~Ǚm;+}ᶵlvbBVwr %QJcpS6a6_oZfquӲHbV8>^bYN\ByajUUMƔcaR1d? ԮՒYSW91 CyL+d`V mD/Ľj%وq+r0 .,1 $mB03 [&]SbJU=9&e}'R0}dG;" DZ.SxНs.¢ʧ}o[nv˿Lse~w~kmk[7 \iͦaX[咶 !\[?]WXW\u"͆;/#j]f4ic/v&f nwu5]YV`M+b}2N~ي`3(k;ah; 5!FbAB2]H YB\"H];z!EȲπO"/ ;NZ4|OĮwN!q]kT~jv>y< "}3h)9'a&o? gΰ~˯Dlֶu \i|ܹ2 [sʕ+,KRJ2=Ȕegnw`'/]$?wyutΝ"omd+h۶x 3;C +cC$6 :|L9aX7 ޓܾ͘-DJk`&&ZcdӶ,W+ڡcJ~r']!''b! Qn˺BҘ1I^WMxăV~|t;MuzJj"JAm6}j?X!~B`}77ֶnB]9<̹ _)j6 x|>m7u2>xv8 /y+8 ̍jj&]BB@ᜣ:^u]z|>hϦg,;OcuBdXŬ[1y6 ĸB?G>GۚK2nz{ɞWM9#f5H3Fe d1A22yet:ՍЊvV&PW5˕eSt9X8!⇈JTfZw%p4!LzXS3FyNDw=0,I@)buzbrzWhйS&jFɎ*1ZUFD˪{ѐJ)%yFe1xQ^^T C)$:Yo{uKbռ{~m/޶u=0 l6a(y \}Ο?l6뤹 P&85qU%buSOl%V*tYc@8iC3_fd뺒C^QHJX^۾z|t]GUUU,Gf +zgm Qp`b(mb֚.)k@]q\u=VTUsF%#k% .m9ھg=!x+덲]Frٔ*v*/T]+O6]ciHd^RʟonNP]ym ok[7u|vj#V>qH)*شkT+2#Ue35cCUe-~R" +c o7{>?}񶵭X}0 x^7Ҽ6dSD+UtʑdRMVBqz[.ݣD9?`\ve{5(,? 0ZL 4ut4,ͣ*d`]L:>]}M,׫Q/$"gf7kr l֢ϖ 12|2+EUlKBJԵ+rY0ꋛZ#yb5ui G>g~ {y˿|ֶnrik#;`]Hڹs穚쏏9>>Fei5B0Z56, '̔h!W)kP:i6 F <\&Gk%+P4Z[RRyOMv>*>CZ"b92_@t@L a[zގ)ጄ !r4Mc^M>HI]WfRY\*֪)o2J%r-Y[ W? x񡤷eŕسJ&mR9SӇK6En$Da,)IcC mϳ~իn[ۺeÒ5ik-Ւ gM-.bjm{i9c-^bb#7"fˤ4͌z΂2N]W 8&i>_o6b Z Zc ¹C BU4{Ȓ.& L`sc}BM,„7$:K~-P%>?=fdw#A(J|s䨰Ɣ)]hz3MIdyj!A82dKR|0X4dܔV<o{uo+ֶ>}o4@TsUUR`v:EF@f; 1t11C0k)3NٖPmۣ:LJ,3|C?)?.PLVtmV9g=9Eak!i-vvNs%K\[C2cdz3Ύ(4!TѶ5uDuhjG=@ΈMӠd/Ѧ1ڠ4 '0C= ,M(M2WC{grR޴TU*rJ8[SWSY*OI@Y!=)%Sl{ (I/zX=99h[-}.ޒs"F33ͬ&qj*bA -spwd*(q XS9U>Ґ.B= CѠwS98[dr?CZxROU !Pc&{c4Z2HѬV)ǔHŗ8 !dYAtߖ$f% s^kL\jIbZK FLiaz &‚[)X'X<,׺Y^J(9%JМ09&ޛmmֶ4 =՚ۼBʫ5ԮY',P)Od5 Rh~ClF 3B{ @ Ni3c%X=ah*E׮hcRrbj4G,;h#J41ZӀ&'VI\{8e$C5Ul^%x|@[[L^41$@Vw)VhޙHe̬3fb@\qC\s q  2Fb86ocg2ۂ2#͈ 5U99_D񼺁$nx\|9TR3N#{ ǣzǨmiuŦto۷*c,XgǵW2 =yxsKIy3L͍Ϝ#neZ1;k[fc,s*M] gst]պuW{'nnn7rl$l[]jfccy k{i|IXLJLI0=8oZk~ѣqaGܣ[[ly/<>`7y`!N'!Pb+WWV1BcZ0t!o{9}-77 v{v֦y&ͮ%΋[e"Nl1 =yM3w牾 q` uekZ! ETՈ&Zeu;ӄ۬fqВy8:N)R4=g-7U9UْT5Y8O43M1ƥw1pcGm-Vi"\V 겊Uoh]Mϯ׆=[l q~-kVťBt'P&<< 9xbld4U9uXg5ɶ ? ֶNJsۑJt:qu>PJ^WZ`E[Y.(:6-5Ssm6&:ӄcHK*ȚY)XŎY; aįik-:y^&n2 Vm@[ð`M=۽=q)oL-K[^vkǭ]ƾX(,Uk G݃W|[l|(Am<>V[\КrJԜꬹTwm]K۽!N|PCu\ޓKfoREvÚ%!R{WfV'yuLz.Kk] L<Ԥը5V%y^+fIx͕@* }ߩJйS纭(^mV0ﻅYn?pF;qZJk]*d.Bn:B%MI\.Kzo~y'[[l2O4O-iy2uea9X Da 4G58i" !oHZwbV~ziЭq#봭>O=KZ1U5)e%ٶ˼4y/ծ`heV\k]&8Yw56'd>h[^G2:`cdm/M^R/jKTVW15X^0s;ɽuZ~>/[lo={O}S;"7qݫ,IL)s>i38Ӊ3|@QEj֫Øsϳj x߱UT2SJf^k[^}i2yn45㔳njmro[Z!PRjݯܗRy(Kmݢ=ߔ,zAO)҄o? ?[l%?L9r; 0gqK7G:l$ibxK=Ngn=Z1NQaJ):{M4gGvi1ILx=.e^|YhbDw}[J)5tCL%H~mczݕG*}؄ E 1: u1*~CUT\oiz~ ^ܹ4y]織nUԨv=8+ T󗎇5\(u_%0‡?G/Dl[l_"Rɼ뾉w󛩵p8cbnŇjը]nLl]97Fhjb/<f5soPӓ{mΌѮDuxgu_XUWluMD_ќ5R3/_轹\b-;1e\k<8MHѣG Y!>&\k15X{yƵTˇ`ysʙn5i+RQTd}2c*S.J͔bթ9 Єќs\WhPWtR ߯kbͱ/Eб՗Ų 3.}a:{sko[|x_>[7<~!cĕDg*Ntj)oj'O{ݑ ^y9y)7іK~70N)%51Y 2b\ =έCDOUrXT֪ gmg>Z5 ))G}ɉ \MCLA^ѤVT &8,1V0έUsN_1sY~B-)u}m5#jjg +dg,G ucǴZJjJάu [V~'OOs-LJܝ"1cg_!b#vIsw{x]Ou\]9=xHͅ'Op:8T4tǽT!6_aq |Sגk/ˬB]ww/ȍ^VU/{ZY{G +q~r#gSp#cn0֩ݦq@{*}}ᗪZ-URʽ]v/%[E[SK' |-u^]J70^!3R ww'|XwGvW{LoI7:ۻ#4Mcyݰ!hKxga`z#B%m|R@.*ZƇ0T!İ:<~Lc] 1FJYj)VJt:ru8HJs>Z&Z\Ƒ 8m;mi: T image/svg+xml Graphics Category Jakub Steiner graphics category pixel vector editor draw paint http://tango-project.org tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-system-file-manager.svg0000644000175000017500000003305713175640533025633 0ustar cedced00000000000000 image/svg+xml File Manager Jakub Steiner http://jimmac.musichall.cz file manager copy move filesystem tryton-4.6.5/tryton/data/pixmaps/tryton/tryton-lock.svg0000644000175000017500000002311313175640533022702 0ustar cedced00000000000000 image/svg+xml Jakub Steiner http://jimmac.musichall.cz/ Cédric Krier tryton-4.6.5/tryton/common/0000755000175000017500000000000013260723567015237 5ustar cedced00000000000000tryton-4.6.5/tryton/common/treeviewcontrol.py0000644000175000017500000000172313251060075021033 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of this # repository contains the full copyright notices and license terms. import gtk import gobject MOVEMENT_KEYS = {gtk.keysyms.Up, gtk.keysyms.Down, gtk.keysyms.space, gtk.keysyms.Left, gtk.keysyms.KP_Left, gtk.keysyms.Right, gtk.keysyms.KP_Right, gtk.keysyms.Home, gtk.keysyms.KP_Home, gtk.keysyms.End, gtk.keysyms.KP_End} __all__ = ['TreeViewControl'] class TreeViewControl(gtk.TreeView): def do_button_press_event(self, event): self.grab_focus() # grab focus because it doesn't whith CONTROL MASK if event.button == 1: event.state ^= gtk.gdk.CONTROL_MASK return gtk.TreeView.do_button_press_event(self, event) def do_key_press_event(self, event): if event.keyval in MOVEMENT_KEYS: event.state ^= gtk.gdk.CONTROL_MASK return gtk.TreeView.do_key_press_event(self, event) gobject.type_register(TreeViewControl) tryton-4.6.5/tryton/common/cellrendererfloat.py0000644000175000017500000000317713251060075021301 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import locale from cellrendererinteger import CellRendererInteger class CellRendererFloat(CellRendererInteger): def __init__(self): super(CellRendererFloat, self).__init__() self.digits = None def do_start_editing(self, event, widget, path, background_area, cell_area, flags): editable = super(CellRendererFloat, self).do_start_editing(event, widget, path, background_area, cell_area, flags) editable.connect('key-press-event', self.key_press_event) return editable def key_press_event(self, widget, event): for name in ('KP_Decimal', 'KP_Separator'): if event.keyval == gtk.gdk.keyval_from_name(name): event.keyval = int(gtk.gdk.unicode_to_keyval( ord(locale.localeconv()['decimal_point']))) def sig_insert_text(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] decimal_point = locale.localeconv()['decimal_point'] if new_value in ('-', decimal_point): return try: value = locale.atof(new_value) except ValueError: entry.stop_emission('insert-text') return if self.digits and not (round(value, self.digits[1]) == float(value)): entry.stop_emission('insert-text') gobject.type_register(CellRendererFloat) tryton-4.6.5/tryton/common/htmltextbuffer.py0000644000175000017500000003227713251060075020653 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from __future__ import division from io import BytesIO import xml.etree.ElementTree as ET from xml.sax.saxutils import escape, unescape from HTMLParser import HTMLParser import pango import gtk import chardet MIME = 'text/html' if hasattr(gtk.gdk, 'Atom'): MIME = gtk.gdk.Atom.intern(MIME, False) def _reverse_dict(dct): return {j: i for i, j in dct.iteritems()} SIZE2SCALE = { '1': pango.SCALE_XX_SMALL, '2': pango.SCALE_X_SMALL, '3': pango.SCALE_SMALL, '4': pango.SCALE_MEDIUM, '5': pango.SCALE_LARGE, '6': pango.SCALE_X_LARGE, '7': pango.SCALE_XX_LARGE, } SCALE2SIZE = _reverse_dict(SIZE2SCALE) ALIGN2JUSTIFICATION = { 'left': gtk.JUSTIFY_LEFT, 'center': gtk.JUSTIFY_CENTER, 'right': gtk.JUSTIFY_RIGHT, 'justify': gtk.JUSTIFY_FILL, } JUSTIFICATION2ALIGN = _reverse_dict(ALIGN2JUSTIFICATION) FAMILIES = ['normal', 'sans', 'serif', 'monospace'] def gdk_to_hex(gdk_color): "Convert color to 2 digit hex" colors = [gdk_color.red, gdk_color.green, gdk_color.blue] return "#" + "".join(["%02x" % (color / 256) for color in colors]) def _markup(text): return '%s' % text def _strip_markup(text): return text[len(u''):-len(u'')] def _strip_newline(text): return ''.join(text.splitlines()) class MarkupHTMLParse(HTMLParser): def __init__(self): HTMLParser.__init__(self) self.root = ET.Element('markup') self._tags = [self.root] self.head = False self.body = True def handle_starttag(self, tag, attrs): if tag in ['b', 'i', 'u', 'div', 'font']: el = ET.SubElement(self._tags[-1], tag) for key, value in attrs: el.set(key, value) self._tags.append(el) elif tag == 'br': ET.SubElement(self._tags[-1], tag) elif tag == 'head': self.head = True def handle_endtag(self, tag): if tag in ['b', 'i', 'u', 'div', 'font']: el = self._tags.pop() assert el.tag == tag elif tag == 'head': self.head = False elif tag == 'body': self.body = False def handle_data(self, data): if self.head or not self.body: return el = self._tags[-1] if len(el) == 0: if el.text is None: el.text = '' el.text += data else: child = el[-1] if child.tail is None: child.tail = '' child.tail += data def parse_markup(markup_text): 'Return plain text and a list of start, end TextTag' markup_text = BytesIO(_markup(markup_text)) plain_text = '' tag_stack = [] tags = [] for event, element in ET.iterparse(markup_text, events=['start', 'end']): if element.tag == 'markup': if event == 'start' and element.text: plain_text += unescape(element.text) if event == 'end' and element.tail: plain_text += unescape(element.tail) continue if event == 'start': tag_stack.append((element, len(plain_text))) if element.text: plain_text += unescape(element.text) elif event == 'end': if element.tag == 'div': plain_text += '\n' assert tag_stack[-1][0] == element _, start = tag_stack.pop() end = len(plain_text) tags.append((start, end, element)) if element.tail: plain_text += unescape(element.tail) return plain_text, tags def normalize_markup(markup_text, method='html'): if isinstance(markup_text, unicode): markup_text = markup_text.encode('utf-8') parser = MarkupHTMLParse() parser.feed(_strip_newline(markup_text)) root = parser.root parent_map = {c: p for p in root.iter() for c in p} def order(em): "Re-order alphabetically tags" if (len(em) == 1 and not em.text and em.tag not in ['div', 'markup']): child, = em if ((em.tag > child.tag or child.tag == 'div') and not child.tail): em.tag, child.tag = child.tag, em.tag em.attrib, child.attrib = child.attrib, em.attrib if em in parent_map: order(parent_map[em]) # Add missing div for the first line if len(root) > 0 and root[0].tag != 'div': div = ET.Element('div') for em in list(root): if em.tag != 'div': root.remove(em) div.append(em) else: break root.insert(0, div) for em in root.iter(): while em.text is None and len(em) == 1: dup, = em if dup.tag == em.tag and dup.tail is None: em.attrib.update(dup.attrib) em.remove(dup) em.extend(dup) em.text = dup.text else: break order(em) # Add missing br to empty lines for em in root.findall('div'): if em.text is None and len(em) == 0: em.append(ET.Element('br')) # TODO order attributes return _strip_markup(ET.tostring(root, encoding='utf-8', method=method)) def find_list_delta(old, new): added = [e for e in new if e not in old] removed = [e for e in reversed(old) if e not in new] return added, removed def serialize(register, content, start, end, data): text = '' if start.compare(end) == 0: return text iter_ = start while True: # Loop over line per line to get a div per line tags = [] active_tags = [] end_line = iter_.copy() if not end_line.ends_line(): end_line.forward_to_line_end() if end_line.compare(end) > 0: end_line = end # Open div of the line align = None for tag in iter_.get_tags(): if tag.props.justification_set: align = JUSTIFICATION2ALIGN[tag.props.justification] if align: text += '
' % align else: text += '
' while True: new_tags = iter_.get_tags() added, removed = find_list_delta(tags, new_tags) for tag in removed: if tag not in active_tags: continue # close all open tags after this one while active_tags: atag = active_tags.pop() text += _get_html(atag, close=True) if atag == tag: break added.insert(0, atag) for tag in added: text += _get_html(tag) active_tags.append(tag) tags = new_tags old_iter = iter_.copy() # Move to next tag toggle while True: iter_.forward_char() if iter_.compare(end) == 0: break if iter_.toggles_tag(): break # Might have moved too far if iter_.compare(end_line) > 0: iter_ = end_line text += escape(old_iter.get_text(iter_)) if iter_.compare(end_line) == 0: break # close any open tags for tag in reversed(active_tags): text += _get_html(tag, close=True) # Close the div of the line text += '
' iter_.forward_char() if iter_.compare(end) >= 0: break return normalize_markup(text) def deserialize(register, content, iter_, text, create_tags, data): if not isinstance(text, unicode): encoding = chardet.detect(text)['encoding'] or 'utf-8' text = text.decode(encoding) text = text.encode('utf-8') text, tags = parse_markup(normalize_markup(text, method='xml')) offset = iter_.get_offset() content.insert(iter_, text) def sort_key(tag): start, end, element = tag return start, -end, element for start, end, element in sorted(tags, key=sort_key): for tag in _get_tags(content, element): istart = content.get_iter_at_offset(start + offset) iend = content.get_iter_at_offset(end + offset) content.apply_tag(tag, istart, iend) return True def setup_tags(text_buffer): for name, props in reversed(_TAGS): text_buffer.create_tag(name, **props) _TAGS = [ ('bold', {'weight': pango.WEIGHT_BOLD}), ('italic', {'style': pango.STYLE_ITALIC}), ('underline', {'underline': pango.UNDERLINE_SINGLE}), ] _TAGS.extend([('family %s' % family, {'family': family}) for family in FAMILIES]) _TAGS.extend([('size %s' % size, {'scale': scale}) for size, scale in SIZE2SCALE.iteritems()]) _TAGS.extend([('justification %s' % align, {'justification': justification}) for align, justification in ALIGN2JUSTIFICATION.iteritems()]) def register_foreground(text_buffer, color): name = 'foreground %s' % color tag_table = text_buffer.get_tag_table() tag = tag_table.lookup(name) if not tag: tag = text_buffer.create_tag(name, foreground_gdk=color) return tag def _get_tags(content, element): 'Return tag for the element' tag_table = content.get_tag_table() if element.tag == 'b': yield tag_table.lookup('bold') elif element.tag == 'i': yield tag_table.lookup('italic') elif element.tag == 'u': yield tag_table.lookup('underline') if 'face' in element.attrib: tag = tag_table.lookup('family %s' % element.attrib['face']) if tag: yield tag size = element.attrib.get('size') if size in SIZE2SCALE: yield tag_table.lookup('size %s' % size) if 'color' in element.attrib: yield register_foreground( content, gtk.gdk.color_parse(element.attrib['color'])) align = element.attrib.get('align') if align in ALIGN2JUSTIFICATION: yield tag_table.lookup('justification %s' % align) # TODO style background-color def _get_html(texttag, close=False, div_only=False): 'Return the html tag' # div alignment is managed at line level tags = [] attrib = {} font = attrib['font'] = {} if texttag.props.weight_set and texttag.props.weight == pango.WEIGHT_BOLD: tags.append('b') if texttag.props.style_set and texttag.props.style == pango.STYLE_ITALIC: tags.append('i') if (texttag.props.underline_set and texttag.props.underline == pango.UNDERLINE_SINGLE): tags.append('u') if texttag.props.family_set and texttag.props.family: font['face'] = texttag.props.family if texttag.props.scale_set and texttag.props.scale != pango.SCALE_MEDIUM: font['size'] = SCALE2SIZE[texttag.props.scale] if (texttag.props.foreground_set and texttag.props.foreground_gdk != gtk.gdk.Color(0, 0, 0)): font['color'] = gdk_to_hex(texttag.props.foreground_gdk) # TODO style background-color if font: tags.append('font') if close: return ''.join('' % t for t in tags) return ''.join('<%s %s>' % (t, ' '.join('%s="%s"' % (a, v) for a, v in attrib.get(t, {}).iteritems())) for t in tags) def get_tags(content, start, end): 'Get all tags' iter_ = start.copy() tags = set() while True: tags.update(iter_.get_tags()) iter_.forward_char() if iter_.compare(end) > 0: iter_ = end if iter_.compare(end) == 0: break tags.update(iter_.get_tags()) return tags def remove_tags(content, start, end, *names): 'Remove all tags starting by names' tags = get_tags(content, start, end) for tag in sorted(tags, key=lambda t: t.get_priority()): for name in names: if tag.props.name and tag.props.name.startswith(name): content.remove_tag(tag, start, end) if __name__ == '__main__': html = u'''Bold Italic Underline

Center
Sans6red
Title
''' win = gtk.Window() win.set_title('HTMLTextBuffer') def cb(window, event): print text_buffer.serialize( text_buffer, MIME, text_buffer.get_start_iter(), text_buffer.get_end_iter()) gtk.main_quit() win.connect('delete-event', cb) vbox = gtk.VBox() win.add(vbox) text_buffer = gtk.TextBuffer() text_view = gtk.TextView() text_view.set_buffer(text_buffer) vbox.pack_start(text_view) setup_tags(text_buffer) text_buffer.register_serialize_format(MIME, serialize, None) text_buffer.register_deserialize_format(MIME, deserialize, None) text_buffer.deserialize( text_buffer, MIME, text_buffer.get_start_iter(), html) result = text_buffer.serialize( text_buffer, MIME, text_buffer.get_start_iter(), text_buffer.get_end_iter()) assert normalize_markup(html) == result win.show_all() gtk.main() tryton-4.6.5/tryton/common/entry_position.py0000644000175000017500000000043113251060075020660 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. def reset_position(entry): if entry.get_alignment() <= 0.5: entry.set_position(0) else: entry.set_position(-1) tryton-4.6.5/tryton/common/cellrendererclickablepixbuf.py0000644000175000017500000000155713175640533023333 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject class CellRendererClickablePixbuf(gtk.CellRendererPixbuf): __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), } def __init__(self): super(CellRendererClickablePixbuf, self).__init__() self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE) def do_activate(self, event, widget, path, background_area, cell_area, flags): if (event and cell_area.x <= event.x <= cell_area.x + cell_area.width and cell_area.y <= event.y <= cell_area.y + cell_area.height): self.emit('clicked', path) gobject.type_register(CellRendererClickablePixbuf) tryton-4.6.5/tryton/common/datetime_.py0000644000175000017500000004241213251060075017533 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext import datetime import pygtk pygtk.require('2.0') import gobject import gtk from dateutil.relativedelta import relativedelta from dateutil.parser import parse from datetime_strftime import datetime_strftime as strftime __all__ = ['Date', 'CellRendererDate', 'Time', 'CellRendererTime', 'DateTime'] _ = gettext.gettext def date_parse(text, format_='%x'): formatted_date = datetime.date(1988, 7, 16).strftime(format_) dayfirst = formatted_date.index('16') == 0 monthfirst = formatted_date.index('7') <= 1 yearfirst = not dayfirst and not monthfirst return parse(text, dayfirst=dayfirst, yearfirst=yearfirst, ignoretz=True) class Date(gtk.Entry): __gtype_name__ = 'Date' __gproperties__ = { 'value': (gobject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), 'format': (gobject.TYPE_STRING, '%x', _('Format'), _('Display format'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), } __gsignals__ = { 'date-changed': (gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()), } def __init__(self): self.__date = None self.__format = '%x' gtk.Entry.__init__(self) self.set_width_chars(12) self.connect('focus-out-event', self.focus_out) self.connect('activate', self.activate) # Calendar Popup self.set_icon_from_stock(gtk.ENTRY_ICON_SECONDARY, 'tryton-find') self.set_icon_tooltip_text(gtk.ENTRY_ICON_SECONDARY, _('Open the calendar')) self.connect('icon-press', self.icon_press) self.__cal_popup = gtk.Window(gtk.WINDOW_POPUP) self.__cal_popup.set_events( self.__cal_popup.get_events() | gtk.gdk.KEY_PRESS_MASK) self.__cal_popup.set_resizable(False) self.__cal_popup.connect('delete-event', self.cal_popup_closed) self.__cal_popup.connect('key-press-event', self.cal_popup_key_pressed) self.__cal_popup.connect('button-press-event', self.cal_popup_button_pressed) self.__calendar = gtk.Calendar() cal_options = gtk.CALENDAR_SHOW_DAY_NAMES | gtk.CALENDAR_SHOW_HEADING self.__calendar.set_display_options(cal_options) self.__cal_popup.add(self.__calendar) self.__calendar.connect('day-selected', self.cal_popup_changed) self.__calendar.connect('day-selected-double-click', self.cal_popup_double_click) self.__calendar.show() def parse(self): text = self.get_text() date = None if text: try: date = date_parse(text, self.__format).date() except (ValueError, OverflowError): pass self.__date = date def update_label(self): if not self.__date: self.set_text('') return self.set_text(strftime(self.__date, self.__format)) def icon_press(self, entry, icon_pos, event): if icon_pos == gtk.ENTRY_ICON_SECONDARY: self.cal_popup_open() def cal_popup_open(self): self.parse() if self.__date: self.__calendar.select_month( self.__date.month - 1, self.__date.year) self.__calendar.select_day(self.__date.day) self.__cal_popup.set_transient_for(self.get_toplevel()) popup_position(self, self.__cal_popup) popup_show(self.__cal_popup) def cal_popup_changed(self, calendar): year, month, day = self.__calendar.get_date() self.__date = datetime.date(year, month + 1, day) self.update_label() self.emit('date-changed') def cal_popup_double_click(self, calendar): self.cal_popup_hide() def cal_popup_key_pressed(self, calendar, event): if event.keyval != gtk.keysyms.Escape: return False self.stop_emission('key-press-event') self.cal_popup_hide() return True def cal_popup_button_pressed(self, calendar, event): child = event.window if child != calendar.window: while child: if child == calendar.window: return False child = child.get_parent() self.cal_popup_hide() return True def cal_popup_closed(self, popup): self.cal_popup_hide() return True def cal_popup_hide(self): popup_hide(self.__cal_popup) self.grab_focus() self.emit('date-changed') def focus_out(self, entry, event): self.parse() self.update_label() self.emit('date-changed') return False def activate(self, entry=None): self.parse() self.update_label() self.emit('date-changed') return False def do_set_property(self, prop, value): if prop.name == 'value': if isinstance(value, basestring): self.set_text(value) self.parse() value = self.__date if value: if isinstance(value, datetime.datetime): value = value.date() assert isinstance(value, datetime.date), value self.__date = value self.update_label() elif prop.name == 'format': self.__format = value self.update_label() def do_get_property(self, prop): if prop.name == 'value': return self.__date elif prop.name == 'format': return self.__format gobject.type_register(Date) class CellRendererDate(gtk.CellRendererText): __gproperties__ = { 'format': (gobject.TYPE_STRING, _('Format'), _('Display format'), '%x', gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), } def __init__(self): self.__format = '%x' gtk.CellRendererText.__init__(self) def do_set_property(self, prop, value): if prop.name == 'format': self.__format = value return gtk.CellRendererText.set_property(self, prop, value) def do_get_property(self, prop): if prop.name == 'format': return self.__format return gtk.CellRendererText.get_property(self, prop) def do_start_editing( self, event, widget, path, background_area, cell_area, flags): widget = add_operators(Date()) # TODO add_operators has option widget.props.format = self.props.format widget.props.value = self.props.text if self.props.background_set: widget.modify_base(gtk.STATE_NORMAL, self.props.background_gdk) if self.props.foreground_set: widget.modify_fg(gtk.STATE_NORMAL, self.props.foreground_gdk) widget.grab_focus() widget.show() return widget gobject.type_register(CellRendererDate) class Time(gtk.ComboBoxEntry): __gtype_name__ = 'Time' __gproperties__ = { 'value': (gobject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), 'format': (gobject.TYPE_STRING, _('Format'), _('Display format'), '%X', gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), } __gsignals__ = { 'time-changed': (gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()), } def __init__(self): self.__time = None self.__format = '%X' gtk.ComboBoxEntry.__init__(self) self.__entry = self.get_child() self.__entry.set_width_chars(10) self.__entry.connect('focus-out-event', self.focus_out) self.__entry.connect('activate', self.activate) self.connect('changed', self.changed) self.__model = gtk.ListStore( gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) self.update_model() self.set_model(self.__model) self.set_text_column(0) def parse(self): text = self.__entry.get_text() time = None if text: try: time = date_parse(text).time() except (ValueError, OverflowError): pass self.__time = time def update_label(self): if self.__time is None: self.__entry.set_text('') return self.__entry.set_text(self.__time.strftime(self.__format)) def update_model(self): self.__model.clear() timelist_set_list( self.__model, datetime.time(0, 0), datetime.time(23, 59), self.__format) def focus_out(self, entry, event): self.parse() self.update_label() self.emit('time-changed') return False def activate(self, entry=None): self.parse() self.update_label() self.emit('time-changed') return False def changed(self, combobox): # "changed" signal is also triggered by text editing # so only parse when a row is active if combobox.get_active_iter(): self.parse() self.update_label() self.emit('time-changed') return False def do_set_property(self, prop, value): if prop.name == 'value': if isinstance(value, basestring): self.__entry.set_text(value) self.parse() value = self.__time if value: if isinstance(value, datetime.datetime): value = value.time() self.__time = value self.update_label() elif prop.name == 'format': self.__format = value self.update_label() self.update_model() def do_get_property(self, prop): if prop.name == 'value': return self.__time elif prop.name == 'format': return self.__format gobject.type_register(Time) class CellRendererTime(gtk.CellRendererText): __gproperties__ = { 'format': (gobject.TYPE_STRING, '%X', _('Format'), _('Display format'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), } def __init__(self): self.__format = '%X' gtk.CellRendererText.__init__(self) def do_set_property(self, prop, value): if prop.name == 'format': self.__format = value return gtk.CellRendererText.set_property(self, prop, value) def do_get_property(self, prop): if prop.name == 'format': return self.__format return gtk.CellRendererText.get_property(self, prop) def do_start_editing( self, event, widget, path, background_area, cell_area, flags): if not self.props.editable: return widget = add_operators(Time()) # TODO add_operators has option widget.props.format = self.props.format widget.props.value = self.props.text if self.props.background_set: widget.modify_base(gtk.STATE_NORMAL, self.props.background_gdk) if self.props.foreground_set: widget.modify_fg(gtk.STATE_NORMAL, self.props.foreground_gdk) widget.grab_focus() widget.show() return widget gobject.type_register(CellRendererTime) class DateTime(gtk.HBox): __gtype_name__ = 'DateTime' __gproperties__ = { 'value': (gobject.TYPE_PYOBJECT, _('Value'), _('Displayed value'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), 'date-format': (gobject.TYPE_STRING, '%x', _('Date Format'), _('Displayed date format'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), 'time-format': (gobject.TYPE_STRING, '%X', _('Date Format'), _('Displayed date format'), gobject.PARAM_READABLE | gobject.PARAM_WRITABLE), } __gsignals__ = { 'datetime-changed': (gobject.SIGNAL_RUN_LAST | gobject.SIGNAL_ACTION, gobject.TYPE_NONE, ()), } def __init__(self): gtk.HBox.__init__(self, spacing=4) self.__date = Date() self.pack_start(self.__date, True, True, 0) self.__date.show() self.__date.connect('date-changed', lambda e: self.emit('datetime-changed')) self.__time = Time() self.pack_start(self.__time, True, True, 0) self.__time.show() self.__time.connect('time-changed', lambda e: self.emit('datetime-changed')) def do_set_property(self, prop, value): if prop.name == 'value': self.__date.props.value = value self.__time.props.value = value elif prop.name == 'date-format': self.__date.props.format = value elif prop.name == 'time-format': self.__time.props.format = value def do_get_property(self, prop): if prop.name == 'value': date = self.__date.props.value time = self.__time.props.value or datetime.time() if date: return datetime.datetime.combine(date, time) else: return elif prop.name == 'date-format': return self.__date.props.format elif prop.name == 'time-format': return self.__time.props.format def modify_bg(self, state, color): self.__date.modify_bg(state, color) self.__time.child.modify_bg(state, color) def modify_base(self, state, color): self.__date.modify_base(state, color) self.__time.child.modify_base(state, color) def modify_fg(self, state, color): self.__date.modify_fg(state, color) self.__time.child.modify_fg(state, color) def modify_text(self, state, color): self.__date.modify_text(state, color) self.__time.child.modify_text(state, color) gobject.type_register(DateTime) def popup_position(widget, popup): allocation = widget.get_allocation() if hasattr(widget.window, 'get_root_coords'): x, y = widget.window.get_root_coords(allocation.x, allocation.y) else: x, y = widget.window.get_origin() width, height = popup.size_request() popup.move(x + allocation.width - width, y + allocation.height) def popup_show(popup): popup.show() popup.grab_focus() popup.grab_add() cursor = gtk.gdk.Cursor(gtk.gdk.ARROW) gtk.gdk.pointer_grab(popup.window, True, (gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK), None, cursor, 0L) def popup_hide(popup): popup.hide() popup.grab_remove() gtk.gdk.pointer_ungrab(0L) def timelist_set_list(model, min_, max_, format_): time = min_ delta = 30 while time < max_: model.append((time.strftime(format_), time)) hour = time.hour minute = time.minute + delta hour += minute / 60 if hour >= 24: break minute = minute % 60 time = datetime.time(hour, minute) def add_operators(widget): def key_press(editable, event): if not editable.get_editable(): return False if event.keyval in OPERATORS: value = widget.props.value if value: if isinstance(value, datetime.time): value = datetime.datetime.combine( datetime.date.today(), value) try: widget.props.value = value + OPERATORS[event.keyval] except TypeError: return False return True elif event.keyval in (gtk.keysyms.KP_Equal, gtk.keysyms.equal): widget.props.value = datetime.datetime.now() return True return False if isinstance(widget, DateTime): for child in widget.get_children(): add_operators(child) return widget if isinstance(widget, gtk.ComboBoxEntry): editable = widget.get_child() else: editable = widget editable.connect('key-press-event', key_press) return widget OPERATORS = { gtk.keysyms.S: relativedelta(seconds=-1), gtk.keysyms.s: relativedelta(seconds=1), gtk.keysyms.I: relativedelta(minutes=-1), gtk.keysyms.i: relativedelta(minutes=1), gtk.keysyms.H: relativedelta(hours=-1), gtk.keysyms.h: relativedelta(hours=1), gtk.keysyms.D: relativedelta(days=-1), gtk.keysyms.d: relativedelta(days=1), gtk.keysyms.W: relativedelta(weeks=-1), gtk.keysyms.w: relativedelta(weeks=1), gtk.keysyms.M: relativedelta(months=-1), gtk.keysyms.m: relativedelta(months=1), gtk.keysyms.Y: relativedelta(years=-1), gtk.keysyms.y: relativedelta(years=1), } if __name__ == '__main__': win = gtk.Window() win.connect('delete-event', gtk.main_quit) v = gtk.VBox() v.show() d = add_operators(Date()) d.show() v.pack_start(d, False, False) t = add_operators(Time()) t.show() v.pack_start(t, False, False) t = add_operators(Time()) t.props.format = '%H:%M' t.show() v.pack_start(t, False, False) dt = add_operators(DateTime()) dt.show() v.pack_start(dt, False, False) win.add(v) win.show() gtk.main() tryton-4.6.5/tryton/common/datetime_strftime.py0000644000175000017500000000312513251060075021307 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. # Copyright (c) 2002-2007 John D. Hunter; All Rights Reserved import datetime import time def datetime_strftime(dt, fmt): ''' Allow datetime strftime formatting for years before 1900. See http://bugs.python.org/issue1777412 ''' if not isinstance(dt, datetime.date): raise TypeError('datetime_strftime requires a ''datetime.date'' object' 'but received a ''%s''' % type(dt)) if dt.year > 1900: return dt.strftime(fmt) def _findall(text, substr): # Also finds overlaps sites = [] i = 0 while True: j = text.find(substr, i) if j == -1: break sites.append(j) i = j + 1 return sites year = dt.year # For every non-leap year century, advance by # 6 years to get into the 28-year repeat cycle delta = 2000 - year off = 6 * (delta // 100 + delta // 400) year = year + off # Move to around the year 2000 year = year + ((2000 - year) // 28) * 28 timetuple = dt.timetuple() s1 = time.strftime(fmt, (year,) + timetuple[1:]) sites1 = _findall(s1, str(year)) s2 = time.strftime(fmt, (year + 28,) + timetuple[1:]) sites2 = _findall(s2, str(year + 28)) sites = [] for site in sites1: if site in sites2: sites.append(site) s = s1 syear = "%04d" % (dt.year,) for site in sites: s = s[:site] + syear + s[site + 4:] return s tryton-4.6.5/tryton/common/popup_menu.py0000644000175000017500000001156613251060075017775 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gettext from tryton.common import RPCExecute, RPCException from tryton.gui.window.view_form.screen import Screen from tryton.action import Action from tryton.gui.window import Window from tryton.gui.window.attachment import Attachment from tryton.gui.window.note import Note _ = gettext.gettext def populate(menu, model, record, title='', field=None, context=None): ''' Fill menu with the actions of model for the record. If title is filled, the actions will be put in a submenu. ''' if record is None: return elif isinstance(record, (int, long)): if record < 0: return elif record.id < 0: return def load(record): if isinstance(record, (int, long)): screen = Screen(model, context=context) screen.load([record]) record = screen.current_record return record def id_(record): if not isinstance(record, (int, long)): return record.id return record def activate(menuitem, action, atype): rec = load(record) action = Action.evaluate(action, atype, rec) data = { 'model': model, 'id': rec.id, 'ids': [rec.id], } event = gtk.get_current_event() allow_similar = False if (event.state & gtk.gdk.CONTROL_MASK or event.state & gtk.gdk.MOD1_MASK): allow_similar = True with Window(hide_current=True, allow_similar=allow_similar): Action._exec_action(action, data, rec.get_context()) def attachment(menuitem): Attachment(load(record), None) def note(menuitem): Note(load(record), None) def edit(menuitem): with Window(hide_current=True, allow_similar=True): Window.create(model, view_ids=field.attrs.get('view_ids', '').split(','), res_id=id_(record), mode=['form'], name=field.attrs.get('string')) if title: if len(menu): menu.append(gtk.SeparatorMenuItem()) title_item = gtk.MenuItem(title) menu.append(title_item) submenu = gtk.Menu() title_item.set_submenu(submenu) action_menu = submenu else: action_menu = menu if len(action_menu): action_menu.append(gtk.SeparatorMenuItem()) if field: edit_item = gtk.MenuItem(_('Edit...')) edit_item.connect('activate', edit) action_menu.append(edit_item) action_menu.append(gtk.SeparatorMenuItem()) attachment_item = gtk.ImageMenuItem() attachment_item.set_label(_('Attachments...')) attachment_icon = gtk.Image() attachment_icon.set_from_stock('tryton-attachment', gtk.ICON_SIZE_MENU) attachment_item.set_image(attachment_icon) action_menu.append(attachment_item) attachment_item.connect('activate', attachment) note_item = gtk.ImageMenuItem() note_item.set_label(_('Notes...')) note_icon = gtk.Image() note_icon.set_from_stock('tryton-note', gtk.ICON_SIZE_MENU) note_item.set_image(note_icon) action_menu.append(note_item) note_item.connect('activate', note) def set_toolbar(toolbar): try: toolbar = toolbar() except RPCException: return for atype, icon, label, flavor in ( ('action', 'tryton-executable', _('Actions...'), None), ('relate', 'tryton-go-jump', _('Relate...'), None), ('print', 'tryton-print-open', _('Report...'), 'open'), ('print', 'tryton-print-email', _('E-Mail...'), 'email'), ('print', 'tryton-print', _('Print...'), 'print'), ): if len(action_menu): action_menu.append(gtk.SeparatorMenuItem()) title_item = gtk.ImageMenuItem() title_item.set_label(label) title_icon = gtk.Image() title_icon.set_from_stock(icon, gtk.ICON_SIZE_MENU) title_item.set_image(title_icon) action_menu.append(title_item) if not toolbar[atype]: title_item.set_sensitive(False) continue submenu = gtk.Menu() title_item.set_submenu(submenu) for action in toolbar[atype]: action = action.copy() item = gtk.MenuItem(action['name']) submenu.append(item) if flavor == 'print': action['direct_print'] = True elif flavor == 'email': action['email_print'] = True item.connect('activate', activate, action, atype) menu.show_all() RPCExecute('model', model, 'view_toolbar_get', callback=set_toolbar) menu.show_all() tryton-4.6.5/tryton/common/widget_style.py0000644000175000017500000000224513255571102020305 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk gtk_version = getattr(gtk, 'get_major_version', lambda: 2)() if gtk_version == 2: def set_widget_style(widget, editable): style = widget.__class__().get_style() if editable: widget.modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_NORMAL]) widget.modify_base(gtk.STATE_NORMAL, style.base[gtk.STATE_NORMAL]) widget.modify_bg(gtk.STATE_NORMAL, style.bg[gtk.STATE_NORMAL]) else: widget.modify_fg(gtk.STATE_NORMAL, style.fg[gtk.STATE_INSENSITIVE]) widget.modify_base( gtk.STATE_NORMAL, style.base[gtk.STATE_INSENSITIVE]) widget.modify_bg(gtk.STATE_NORMAL, style.bg[gtk.STATE_INSENSITIVE]) def widget_class(widget, name, value): pass else: def set_widget_style(widget, editable): pass def widget_class(widget, name, value): style_context = widget.get_style_context() if value: style_context.add_class(name) else: style_context.remove_class(name) tryton-4.6.5/tryton/common/cellrenderertext.py0000644000175000017500000000321313251060075021147 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject class CellRendererText(gtk.CellRendererText): def set_sensitive(self, value): self.set_property('sensitive', value) def do_activate(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return return gtk.CellRendererText.activate(self, event, widget, path, background_area, cell_area, flags) def do_start_editing(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return if not event: if hasattr(gtk.gdk.Event, 'new'): event = gtk.gdk.Event.new(gtk.gdk.KEY_PRESS) else: event = gtk.gdk.Event(gtk.gdk.KEY_PRESS) return gtk.CellRendererText.do_start_editing(self, event, widget, path, background_area, cell_area, flags) class CellRendererTextCompletion(CellRendererText): def __init__(self, set_completion): super(CellRendererTextCompletion, self).__init__() self.set_completion = set_completion def do_start_editing(self, event, widget, path, background_area, cell_area, flags): editable = super(CellRendererTextCompletion, self).do_start_editing(event, widget, path, background_area, cell_area, flags) self.set_completion(editable, path) return editable gobject.type_register(CellRendererText) gobject.type_register(CellRendererTextCompletion) tryton-4.6.5/tryton/common/domain_inversion.py0000644000175000017500000005463413251060066021154 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import operator import types import datetime from collections import defaultdict def in_(a, b): if isinstance(a, (list, tuple)): if isinstance(b, (list, tuple)): return any(operator.contains(b, x) for x in a) else: return operator.contains(a, b) else: return operator.contains(b, a) OPERATORS = defaultdict(lambda: lambda a, b: True) OPERATORS.update({ '=': operator.eq, '>': operator.gt, '<': operator.lt, '<=': operator.le, '>=': operator.ge, '!=': operator.ne, 'in': in_, 'not in': lambda a, b: not in_(a, b), }) def locale_part(expression, field_name, locale_name='id'): if expression == field_name: return locale_name if '.' in expression: fieldname, local = expression.split('.', 1) return local return expression def is_leaf(expression): return (isinstance(expression, (list, tuple)) and len(expression) > 2 and isinstance(expression[1], basestring)) def constrained_leaf(part, boolop=operator.and_): field, operand, value = part[:3] if operand == '=' and boolop == operator.and_: # We should consider that other domain inversion will set a correct # value to this field return True return False def eval_leaf(part, context, boolop=operator.and_): field, operand, value = part[:3] if '.' in field: # In the case where the leaf concerns a m2o then having a value in the # evaluation context is deemed suffisant return bool(context.get(field.split('.')[0])) context_field = context.get(field) if isinstance(context_field, datetime.date) and not value: if isinstance(context_field, datetime.datetime): value = datetime.datetime.min else: value = datetime.date.min if isinstance(value, datetime.date) and not context_field: if isinstance(value, datetime.datetime): context_field = datetime.datetime.min else: context_field = datetime.date.min if isinstance(context_field, (list, tuple)) and value is None: value = type(context_field)() if (isinstance(context_field, basestring) and isinstance(value, (list, tuple))): try: value = '%s,%s' % value except TypeError: pass elif (isinstance(context_field, (list, tuple)) and isinstance(value, basestring)): try: context_field = '%s,%s' % context_field except TypeError: pass if (operand in ('=', '!=') and isinstance(context_field, (list, tuple)) and isinstance(value, (int, long))): operand = { '=': 'in', '!=': 'not in', }[operand] try: return OPERATORS[operand](context_field, value) except TypeError: return False def inverse_leaf(domain): if domain in ('AND', 'OR'): return domain elif is_leaf(domain): if 'child_of' in domain[1]: if len(domain) == 3: return domain else: return [domain[3]] + list(domain[1:]) return domain else: return map(inverse_leaf, domain) def filter_leaf(domain, field, model): if domain in ('AND', 'OR'): return domain elif is_leaf(domain): if domain[0].startswith(field) and len(domain) > 3: if domain[3] != model: return ('id', '=', None) return domain else: return [filter_leaf(d, field, model) for d in domain] def eval_domain(domain, context, boolop=operator.and_): "compute domain boolean value according to the context" if is_leaf(domain): return eval_leaf(domain, context, boolop=boolop) elif not domain and boolop is operator.and_: return True elif not domain and boolop is operator.or_: return False elif domain[0] == 'AND': return eval_domain(domain[1:], context) elif domain[0] == 'OR': return eval_domain(domain[1:], context, operator.or_) else: return boolop(eval_domain(domain[0], context), eval_domain(domain[1:], context, boolop)) def localize_domain(domain, field_name=None, strip_target=False): "returns only locale part of domain. eg: langage.code -> code" if domain in ('AND', 'OR', True, False): return domain elif is_leaf(domain): if 'child_of' in domain[1]: if len(domain) == 3: return domain else: return [domain[3]] + list(domain[1:-1]) locale_name = 'id' if isinstance(domain[2], basestring): locale_name = 'rec_name' n = 3 if strip_target else 4 return [locale_part(domain[0], field_name, locale_name)] \ + list(domain[1:n]) + list(domain[4:]) else: return [localize_domain(part, field_name, strip_target) for part in domain] def simplify(domain): "remove unused domain delimiter" if is_leaf(domain): return domain elif domain in ('OR', 'AND'): return domain elif domain in (['OR'], ['AND']): return [] elif (isinstance(domain, list) and len(domain) == 1 and not is_leaf(domain[0])): return simplify(domain[0]) elif (isinstance(domain, list) and len(domain) == 2 and domain[0] in ('AND', 'OR')): return [simplify(domain[1])] else: return [simplify(branch) for branch in domain] def merge(domain, domoperator=None): if not domain or domain in ('AND', 'OR'): return [] domain_type = 'OR' if domain[0] == 'OR' else 'AND' if is_leaf(domain): return [domain] elif domoperator is None: return [domain_type] + reduce(operator.add, [merge(e, domain_type) for e in domain]) elif domain_type == domoperator: return reduce(operator.add, [merge(e, domain_type) for e in domain]) else: # without setting the domoperator return [merge(domain)] def concat(*domains, **kwargs): domoperator = kwargs.get('domoperator') result = [] if domoperator: result.append(domoperator) for domain in domains: if domain: result.append(domain) return simplify(merge(result)) def unique_value(domain): "Return if unique, the field and the value" if (isinstance(domain, list) and len(domain) == 1 and '.' not in domain[0][0] and domain[0][1] == '='): return True, domain[0][1], domain[0][2] else: return False, None, None def parse(domain): if is_leaf(domain): return domain elif not domain: return And([]) elif domain[0] == 'OR': return Or(domain[1:]) else: return And(domain[1:] if domain[0] == 'AND' else domain) def domain_inversion(domain, symbol, context=None): """compute an inversion of the domain eventually the context is used to simplify the expression""" if context is None: context = {} expression = parse(domain) if symbol not in expression.variables: return True return expression.inverse(symbol, context) class And(object): def __init__(self, expressions): self.branches = map(parse, expressions) self.variables = set() for expression in self.branches: if is_leaf(expression): self.variables.add(self.base(expression[0])) elif isinstance(expression, And): self.variables |= expression.variables def base(self, expression): if '.' not in expression: return expression else: return expression.split('.')[0] def inverse(self, symbol, context): result = [] for part in self.branches: if isinstance(part, And): part_inversion = part.inverse(symbol, context) evaluated = isinstance(part_inversion, types.BooleanType) if not evaluated: result.append(part_inversion) elif part_inversion: continue else: return False elif is_leaf(part) and self.base(part[0]) == symbol: result.append(part) else: field = part[0] if (field not in context or field in context and (eval_leaf(part, context, operator.and_) or constrained_leaf(part, operator.and_))): result.append(True) else: return False result = filter(lambda e: e is not True, result) if result == []: return True else: return simplify(result) class Or(And): def inverse(self, symbol, context): result = [] known_variables = set(context.keys()) if (symbol not in self.variables and not known_variables >= self.variables): # In this case we don't know anything about this OR part, we # consider it to be True (because people will have the constraint # on this part later). return True for part in self.branches: if isinstance(part, And): part_inversion = part.inverse(symbol, context) evaluated = isinstance(part_inversion, types.BooleanType) if symbol not in part.variables: if evaluated and part_inversion: return True continue if not evaluated: result.append(part_inversion) elif part_inversion: return True else: continue elif is_leaf(part) and self.base(part[0]) == symbol: result.append(part) else: field = part[0] field = self.base(field) if (field in context and (eval_leaf(part, context, operator.or_) or constrained_leaf(part, operator.or_))): return True elif (field in context and not eval_leaf(part, context, operator.or_)): result.append(False) result = filter(lambda e: e is not False, result) if result == []: return False else: return simplify(['OR'] + result) # Test stuffs def test_simple_inversion(): domain = [['x', '=', 3]] assert domain_inversion(domain, 'x') == [['x', '=', 3]] domain = [] assert domain_inversion(domain, 'x') is True assert domain_inversion(domain, 'y') is True assert domain_inversion(domain, 'x', {'x': 5}) is True assert domain_inversion(domain, 'z', {'x': 7}) is True domain = [['x.id', '>', 5]] assert domain_inversion(domain, 'x') == [['x.id', '>', 5]] def test_and_inversion(): domain = [['x', '=', 3], ['y', '>', 5]] assert domain_inversion(domain, 'x') == [['x', '=', 3]] assert domain_inversion(domain, 'x', {'y': 4}) is False assert domain_inversion(domain, 'x', {'y': 6}) == [['x', '=', 3]] domain = [['x', '=', 3], ['y', '=', 5]] assert domain_inversion(domain, 'z') is True assert domain_inversion(domain, 'z', {'x': 2, 'y': 7}) is True assert domain_inversion(domain, 'x', {'y': None}) == [['x', '=', 3]] domain = [['x.id', '>', 5], ['y', '<', 3]] assert domain_inversion(domain, 'y') == [['y', '<', 3]] assert domain_inversion(domain, 'y', {'x': 3}) == [['y', '<', 3]] assert domain_inversion(domain, 'x') == [['x.id', '>', 5]] def test_or_inversion(): domain = ['OR', ['x', '=', 3], ['y', '>', 5], ['z', '=', 'abc']] assert domain_inversion(domain, 'x') == [['x', '=', 3]] assert domain_inversion(domain, 'x', {'y': 4}) == [['x', '=', 3]] assert domain_inversion(domain, 'x', {'y': 4, 'z': 'ab'}) ==\ [['x', '=', 3]] assert domain_inversion(domain, 'x', {'y': 7}) is True assert domain_inversion(domain, 'x', {'y': 7, 'z': 'b'}) is True assert domain_inversion(domain, 'x', {'z': 'abc'}) is True assert domain_inversion(domain, 'x', {'y': 4, 'z': 'abc'}) is True domain = ['OR', ['x', '=', 3], ['y', '=', 5]] assert domain_inversion(domain, 'x', {'y': None}) == [['x', '=', 3]] domain = ['OR', ['x', '=', 3], ['y', '>', 5]] assert domain_inversion(domain, 'z') is True domain = ['OR', ['x.id', '>', 5], ['y', '<', 3]] assert domain_inversion(domain, 'y') == [['y', '<', 3]] assert domain_inversion(domain, 'y', {'z': 4}) == [['y', '<', 3]] assert domain_inversion(domain, 'y', {'x': 3}) is True domain = [u'OR', [u'length', u'>', 5], [u'language.code', u'=', u'de_DE']] assert domain_inversion(domain, 'length', {'length': 0, 'name': 'n'}) ==\ [['length', '>', 5]] def test_orand_inversion(): domain = ['OR', [['x', '=', 3], ['y', '>', 5], ['z', '=', 'abc']], [['x', '=', 4]], [['y', '>', 6]]] assert domain_inversion(domain, 'x') is True assert domain_inversion(domain, 'x', {'y': 4}) == [[['x', '=', 4]]] assert domain_inversion(domain, 'x', {'z': 'abc', 'y': 7}) is True assert domain_inversion(domain, 'x', {'y': 7}) is True assert domain_inversion(domain, 'x', {'z': 'ab'}) is True def test_andor_inversion(): domain = [['OR', ['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]] assert domain_inversion(domain, 'z') == [['z', '=', 3]] assert domain_inversion(domain, 'z', {'x': 5}) == [['z', '=', 3]] assert domain_inversion(domain, 'z', {'x': 5, 'y': 5}) is False assert domain_inversion(domain, 'z', {'x': 5, 'y': 7}) == [['z', '=', 3]] def test_andand_inversion(): domain = [[['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]] assert domain_inversion(domain, 'z') == [['z', '=', 3]] assert domain_inversion(domain, 'z', {'x': 5}) == [['z', '=', 3]] assert domain_inversion(domain, 'z', {'y': 5}) is False assert domain_inversion(domain, 'z', {'x': 4, 'y': 7}) == [['z', '=', 3]] domain = [[['x', '=', 4], ['y', '>', 6], ['z', '=', 2]], [['w', '=', 2]]] assert domain_inversion(domain, 'z', {'x': 4}) == [['z', '=', 2]] def test_oror_inversion(): domain = ['OR', ['OR', ['x', '=', 3], ['y', '>', 5]], ['OR', ['x', '=', 2], ['z', '=', 'abc']], ['OR', ['y', '=', 8], ['z', '=', 'y']]] assert domain_inversion(domain, 'x') is True assert domain_inversion(domain, 'x', {'y': 4}) is True assert domain_inversion(domain, 'x', {'z': 'ab'}) is True assert domain_inversion(domain, 'x', {'y': 7}) is True assert domain_inversion(domain, 'x', {'z': 'abc'}) is True assert domain_inversion(domain, 'x', {'z': 'y'}) is True assert domain_inversion(domain, 'x', {'y': 8}) is True assert domain_inversion(domain, 'x', {'y': 8, 'z': 'b'}) is True assert domain_inversion(domain, 'x', {'y': 4, 'z': 'y'}) is True assert domain_inversion(domain, 'x', {'y': 7, 'z': 'abc'}) is True assert domain_inversion(domain, 'x', {'y': 4, 'z': 'b'}) == \ ['OR', [['x', '=', 3]], [['x', '=', 2]]] def test_parse(): domain = parse([['x', '=', 5]]) assert domain.variables == set('x') domain = parse(['OR', ['x', '=', 4], ['y', '>', 6]]) assert domain.variables == set('xy') domain = parse([['OR', ['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]]) assert domain.variables == set('xyz') domain = parse([[['x', '=', 4], ['y', '>', 6]], ['z', '=', 3]]) assert domain.variables == set('xyz') def test_simplify(): domain = [['x', '=', 3]] assert simplify(domain) == [['x', '=', 3]] domain = [[['x', '=', 3]]] assert simplify(domain) == [['x', '=', 3]] domain = ['OR', ['x', '=', 3]] assert simplify(domain) == [['x', '=', 3]] domain = ['OR', [['x', '=', 3]], [['y', '=', 5]]] assert simplify(domain) == ['OR', [['x', '=', 3]], [['y', '=', 5]]] domain = ['OR', ['x', '=', 3], ['AND', ['y', '=', 5]]] assert simplify(domain) == ['OR', ['x', '=', 3], [['y', '=', 5]]] domain = ['AND'] assert simplify(domain) == [] domain = ['OR'] assert simplify(domain) == [] def test_merge(): domain = [['x', '=', 6], ['y', '=', 7]] assert merge(domain) == ['AND', ['x', '=', 6], ['y', '=', 7]] domain = ['AND', ['x', '=', 6], ['y', '=', 7]] assert merge(domain) == ['AND', ['x', '=', 6], ['y', '=', 7]] domain = [['z', '=', 8], ['AND', ['x', '=', 6], ['y', '=', 7]]] assert merge(domain) == ['AND', ['z', '=', 8], ['x', '=', 6], ['y', '=', 7]] domain = ['OR', ['x', '=', 1], ['y', '=', 2], ['z', '=', 3]] assert merge(domain) == ['OR', ['x', '=', 1], ['y', '=', 2], ['z', '=', 3]] domain = ['OR', ['x', '=', 1], ['OR', ['y', '=', 2], ['z', '=', 3]]] assert merge(domain) == ['OR', ['x', '=', 1], ['y', '=', 2], ['z', '=', 3]] domain = ['OR', ['x', '=', 1], ['AND', ['y', '=', 2], ['z', '=', 3]]] assert merge(domain) == ['OR', ['x', '=', 1], ['AND', ['y', '=', 2], ['z', '=', 3]]] domain = [['z', '=', 8], ['OR', ['x', '=', 6], ['y', '=', 7]]] assert merge(domain) == ['AND', ['z', '=', 8], ['OR', ['x', '=', 6], ['y', '=', 7]]] domain = ['AND', ['OR', ['a', '=', 1], ['b', '=', 2]], ['OR', ['c', '=', 3], ['AND', ['d', '=', 4], ['d2', '=', 6]]], ['AND', ['d', '=', 5], ['e', '=', 6]], ['f', '=', 7]] assert merge(domain) == ['AND', ['OR', ['a', '=', 1], ['b', '=', 2]], ['OR', ['c', '=', 3], ['AND', ['d', '=', 4], ['d2', '=', 6]]], ['d', '=', 5], ['e', '=', 6], ['f', '=', 7]] def test_concat(): domain1 = [['a', '=', 1]] domain2 = [['b', '=', 2]] assert concat(domain1, domain2) == ['AND', ['a', '=', 1], ['b', '=', 2]] assert concat([], domain1) == domain1 assert concat(domain2, []) == domain2 assert concat([], []) == [] assert concat(domain1, domain2, domoperator='OR') == [ 'OR', [['a', '=', 1]], [['b', '=', 2]]] def test_unique_value(): domain = [['a', '=', 1]] assert unique_value(domain) == (True, '=', 1) domain = [['a', '!=', 1]] assert unique_value(domain)[0] is False domain = [['a', '=', 1], ['a', '=', 2]] assert unique_value(domain)[0] is False domain = [['a.b', '=', 1]] assert unique_value(domain)[0] is False def test_evaldomain(): domain = [['x', '>', 5]] assert eval_domain(domain, {'x': 6}) assert not eval_domain(domain, {'x': 4}) domain = [['x', '>', None]] assert eval_domain(domain, {'x': datetime.date.today()}) assert eval_domain(domain, {'x': datetime.datetime.now()}) domain = [['x', '<', datetime.date.today()]] assert eval_domain(domain, {'x': None}) domain = [['x', '<', datetime.datetime.now()]] assert eval_domain(domain, {'x': None}) domain = [['x', 'in', [3, 5]]] assert eval_domain(domain, {'x': 3}) assert not eval_domain(domain, {'x': 4}) assert eval_domain(domain, {'x': [3]}) assert eval_domain(domain, {'x': [3, 4]}) assert not eval_domain(domain, {'x': [1, 2]}) domain = [['x', 'not in', [3, 5]]] assert not eval_domain(domain, {'x': 3}) assert eval_domain(domain, {'x': 4}) assert not eval_domain(domain, {'x': [3]}) assert not eval_domain(domain, {'x': [3, 4]}) assert eval_domain(domain, {'x': [1, 2]}) domain = ['OR', ['x', '>', 10], ['x', '<', 0]] assert eval_domain(domain, {'x': 11}) assert eval_domain(domain, {'x': -4}) assert not eval_domain(domain, {'x': 5}) domain = ['OR', ['x', '>', 0], ['x', '=', None]] assert eval_domain(domain, {'x': 1}) assert eval_domain(domain, {'x': None}) assert not eval_domain(domain, {'x': -1}) assert not eval_domain(domain, {'x': 0}) domain = [['x', '>', 0], ['OR', ['x', '=', 3], ['x', '=', 2]]] assert not eval_domain(domain, {'x': 1}) assert eval_domain(domain, {'x': 3}) assert eval_domain(domain, {'x': 2}) assert not eval_domain(domain, {'x': 4}) assert not eval_domain(domain, {'x': 5}) assert not eval_domain(domain, {'x': 6}) domain = ['OR', ['x', '=', 4], [['x', '>', 6], ['x', '<', 10]]] assert eval_domain(domain, {'x': 4}) assert eval_domain(domain, {'x': 7}) assert not eval_domain(domain, {'x': 3}) assert not eval_domain(domain, {'x': 5}) assert not eval_domain(domain, {'x': 11}) domain = [['x', '=', 'test,1']] assert eval_domain(domain, {'x': ('test', 1)}) assert eval_domain(domain, {'x': 'test,1'}) assert not eval_domain(domain, {'x': ('test', 2)}) assert not eval_domain(domain, {'x': 'test,2'}) domain = [['x', '=', ('test', 1)]] assert eval_domain(domain, {'x': ('test', 1)}) assert eval_domain(domain, {'x': 'test,1'}) assert not eval_domain(domain, {'x': ('test', 2)}) assert not eval_domain(domain, {'x': 'test,2'}) domain = [['x', '=', 1]] assert eval_domain(domain, {'x': [1, 2]}) assert not eval_domain(domain, {'x': [2]}) domain = [['x', '=', None]] assert eval_domain(domain, {'x': []}) def test_localize(): domain = [['x', '=', 5]] assert localize_domain(domain) == [['x', '=', 5]] domain = [['x', '=', 5], ['x.code', '=', 7]] assert localize_domain(domain, 'x') == [['id', '=', 5], ['code', '=', 7]] domain = [['x', 'ilike', 'foo%'], ['x.code', '=', 'test']] assert localize_domain(domain, 'x') == \ [['rec_name', 'ilike', 'foo%'], ['code', '=', 'test']] domain = ['OR', ['AND', ['x', '>', 7], ['x', '<', 15]], ['x.code', '=', 8]] assert localize_domain(domain, 'x') == \ ['OR', ['AND', ['id', '>', 7], ['id', '<', 15]], ['code', '=', 8]] domain = [['x', 'child_of', [1]]] assert localize_domain(domain, 'x') == [['x', 'child_of', [1]]] domain = [['x', 'child_of', [1], 'y']] assert localize_domain(domain, 'x') == [['y', 'child_of', [1]]] domain = [['x.id', '=', 1, 'y']] assert localize_domain(domain, 'x', False) == [['id', '=', 1, 'y']] assert localize_domain(domain, 'x', True) == [['id', '=', 1]] domain = [['a.b.c', '=', 1, 'y', 'z']] assert localize_domain(domain, 'x', False) == [['b.c', '=', 1, 'y', 'z']] assert localize_domain(domain, 'x', True) == [['b.c', '=', 1, 'z']] if __name__ == '__main__': test_simple_inversion() test_and_inversion() test_or_inversion() test_orand_inversion() test_andor_inversion() test_andand_inversion() test_oror_inversion() test_parse() test_simplify() test_evaldomain() test_localize() tryton-4.6.5/tryton/common/focus.py0000644000175000017500000000567413251060075016730 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from functools import cmp_to_key import gtk def get_invisible_ancestor(widget): if not widget.get_visible(): return widget if not widget.props.parent: return None return get_invisible_ancestor(widget.props.parent) def find_focused_child(widget): if widget.has_focus(): return widget if not hasattr(widget, 'get_children'): return None for child in widget.get_children(): focused_widget = find_focused_child(child) if focused_widget: return focused_widget def tab_compare(a, b): text_direction = gtk.widget_get_default_direction() a_allocation = a.get_allocation() b_allocation = b.get_allocation() y1 = a_allocation.y + a_allocation.height // 2 y2 = b_allocation.y + b_allocation.height // 2 if y1 == y2: x1 = a_allocation.x + a_allocation.width // 2 x2 = b_allocation.x + b_allocation.width // 2 if text_direction == gtk.TEXT_DIR_RTL: return (x2 > x1) - (x2 < x1) else: return (x1 > x2) - (x1 < x2) else: return (y1 > y2) - (y1 < y2) def get_focus_chain(widget): focus_chain = widget.get_focus_chain() # If the focus_chain is not defined on the widget then we will simply # search into all its children widgets return (focus_chain if focus_chain is not None else sorted(widget.get_children(), key=cmp_to_key(tab_compare))) def find_focusable_child(widget): if not widget.get_visible(): return None if widget.get_can_focus(): return widget if not hasattr(widget, 'get_children'): return None for child in get_focus_chain(widget): focusable = find_focusable_child(child) if focusable: return focusable def next_focus_widget(widget): if not widget.props.parent: return None focus_chain = widget.props.parent.get_focus_chain() if focus_chain is not None: idx = focus_chain.index(widget) focus_widget = None for widget in focus_chain[idx:] + focus_chain[:idx]: focus_widget = find_focusable_child(widget) if focus_widget: return focus_widget if not focus_widget: return next_focus_widget(widget.props.parent) else: focus_widget = find_focusable_child(widget.props.parent) if focus_widget: return focus_widget else: return next_focus_widget(widget.props.parent) def find_first_focus_widget(ancestor, widgets): "Return the widget from widgets which should have first the focus" if len(widgets) == 1: return widgets[0] for child in get_focus_chain(ancestor): common = [w for w in widgets if w.is_ancestor(child)] if common: return find_first_focus_widget(child, common) tryton-4.6.5/tryton/common/environment.py0000644000175000017500000000321713175640533020154 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. class EvalEnvironment(dict): def __init__(self, parent, eval_type='eval'): super(EvalEnvironment, self).__init__() self.parent = parent assert eval_type in ('eval', 'on_change') self.eval_type = eval_type def __getitem__(self, item): if item == 'id': return self.parent.id if item == '_parent_' + self.parent.parent_name and self.parent.parent: return EvalEnvironment(self.parent.parent, eval_type=self.eval_type) if self.eval_type == 'eval': return self.parent.get_eval()[item] else: return self.parent.group.fields[item].get_on_change_value( self.parent) def __getattr__(self, item): try: return self.__getitem__(item) except KeyError: raise AttributeError(item) def get(self, item, default=None): try: return self.__getitem__(item) except KeyError: pass return super(EvalEnvironment, self).get(item, default) def __nonzero__(self): return True def __str__(self): return str(self.parent) __repr__ = __str__ def __contains__(self, item): if item == 'id': return True if item == '_parent_' + self.parent.parent_name and self.parent.parent: return True if self.eval_type == 'eval': return item in self.parent.get_eval() else: return item in self.parent.group.fields tryton-4.6.5/tryton/common/common.py0000644000175000017500000012713313255571102017076 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import glib import pango import gettext import os import subprocess import re import logging import unicodedata import colorsys from decimal import Decimal from functools import partial from tryton.config import CONFIG from tryton.config import TRYTON_ICON, PIXMAPS_DIR import sys import xmlrpclib try: import hashlib except ImportError: hashlib = None import md5 import webbrowser import traceback import tryton.rpc as rpc import socket import thread import urllib from string import Template import shlex try: import ssl except ImportError: ssl = None from threading import Lock import dateutil.tz from tryton.exceptions import TrytonServerError, TrytonError from tryton.pyson import PYSONEncoder _ = gettext.gettext class TrytonIconFactory(gtk.IconFactory): batchnum = 10 _tryton_icons = [] _name2id = {} _locale_icons = set() _loaded_icons = set() def load_client_icons(self): for fname in os.listdir(PIXMAPS_DIR): name = os.path.splitext(fname)[0] if not name.startswith('tryton-'): continue if not os.path.isfile(os.path.join(PIXMAPS_DIR, fname)): continue try: pixbuf = gtk.gdk.pixbuf_new_from_file( os.path.join(PIXMAPS_DIR, fname).decode('utf-8')) except (IOError, glib.GError): continue finally: self._locale_icons.add(name) icon_set = gtk.IconSet(pixbuf) self.add(name, icon_set) for name in ('ok', 'cancel'): icon_set = gtk.Style().lookup_icon_set('gtk-%s' % name) self.add('tryton-%s' % name, icon_set) self._locale_icons.add('tryton-%s' % name) def load_icons(self, refresh=False): if not refresh: self._name2id.clear() self._loaded_icons.clear() del self._tryton_icons[:] try: icons = rpc.execute('model', 'ir.ui.icon', 'list_icons', rpc.CONTEXT) except TrytonServerError: icons = [] for icon_id, icon_name in icons: if refresh and icon_name in self._loaded_icons: continue self._tryton_icons.append((icon_id, icon_name)) self._name2id[icon_name] = icon_id def register_icon(self, iconname): # iconname might be '' when page do not define icon if (not iconname or iconname in (self._loaded_icons | self._locale_icons)): return if iconname not in self._name2id: self.load_icons(refresh=True) icon_ref = (self._name2id[iconname], iconname) idx = self._tryton_icons.index(icon_ref) to_load = slice(max(0, idx - self.batchnum // 2), idx + self.batchnum // 2) ids = [e[0] for e in self._tryton_icons[to_load]] try: icons = rpc.execute('model', 'ir.ui.icon', 'read', ids, ['name', 'icon'], rpc.CONTEXT) except TrytonServerError: icons = [] for icon in icons: pixbuf = _data2pixbuf(icon['icon']) self._tryton_icons.remove((icon['id'], icon['name'])) del self._name2id[icon['name']] self._loaded_icons.add(icon['name']) iconset = gtk.IconSet(pixbuf) self.add(icon['name'], iconset) ICONFACTORY = TrytonIconFactory() ICONFACTORY.add_default() class ModelAccess(object): batchnum = 100 _access = {} _models = [] def load_models(self, refresh=False): if not refresh: self._access.clear() del self._models[:] try: self._models = rpc.execute('model', 'ir.model', 'list_models', rpc.CONTEXT) except TrytonServerError: pass def __getitem__(self, model): if model in self._access: return self._access[model] if model not in self._models: self.load_models(refresh=True) idx = self._models.index(model) to_load = slice(max(0, idx - self.batchnum // 2), idx + self.batchnum // 2) try: access = rpc.execute('model', 'ir.model.access', 'get_access', self._models[to_load], rpc.CONTEXT) except TrytonServerError: access = {} self._access.update(access) return self._access[model] MODELACCESS = ModelAccess() class ModelHistory(object): _models = set() def load_history(self): self._models.clear() try: self._models.update(rpc.execute('model', 'ir.model', 'list_history', rpc.CONTEXT)) except TrytonServerError: pass def __contains__(self, model): return model in self._models MODELHISTORY = ModelHistory() class ViewSearch(object): searches = {} def __init__(self): class Encoder(PYSONEncoder): def default(self, obj): if isinstance(obj, Decimal): return float(obj) return super(Encoder, self).default(obj) self.encoder = Encoder() def load_searches(self): try: self.searches = rpc.execute('model', 'ir.ui.view_search', 'get_search', rpc.CONTEXT) except TrytonServerError: self.searches = {} def __getitem__(self, model): return self.searches.get(model, []) def add(self, model, name, domain): try: id_, = RPCExecute('model', 'ir.ui.view_search', 'create', [{ 'model': model, 'name': name, 'domain': self.encoder.encode(domain), }]) except RPCException: return self.searches.setdefault(model, []).append((id_, name, domain)) def remove(self, model, id_): try: RPCExecute('model', 'ir.ui.view_search', 'delete', [id_]) except RPCException: return for i, domain in enumerate(self.searches[model]): if domain[0] == id_: del self.searches[model][i] break VIEW_SEARCH = ViewSearch() def find_in_path(name): if os.name == "nt": sep = ';' else: sep = ':' path = [directory for directory in os.environ['PATH'].split(sep) if os.path.isdir(directory)] for directory in path: val = os.path.join(directory, name) if os.path.isfile(val) or os.path.islink(val): return val return name def request_server(server_widget): result = False parent = get_toplevel_window() dialog = gtk.Dialog( title=_('Tryton Connection'), parent=parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG,) vbox = gtk.VBox() table = gtk.Table(2, 2, False) table.set_border_width(12) table.set_row_spacings(6) vbox.pack_start(table, False, True, 0) label_server = gtk.Label(_("Server:")) label_server.set_alignment(1, 0) label_server.set_padding(3, 0) table.attach(label_server, 0, 1, 0, 1, yoptions=False, xoptions=gtk.FILL) entry_port = gtk.Entry() entry_port.set_max_length(5) entry_port.set_text("8000") entry_port.set_activates_default(True) entry_port.set_width_chars(16) table.attach(entry_port, 1, 2, 1, 2, yoptions=False, xoptions=gtk.FILL) entry_server = gtk.Entry() entry_server.set_text("localhost") entry_server.set_activates_default(True) entry_server.set_width_chars(16) table.attach(entry_server, 1, 2, 0, 1, yoptions=False, xoptions=gtk.FILL | gtk.EXPAND) label_port = gtk.Label(_("Port:")) label_port.set_alignment(1, 0.5) label_port.set_padding(3, 3) table.attach(label_port, 0, 1, 1, 2, yoptions=False, xoptions=False) dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) dialog.add_button("gtk-ok", gtk.RESPONSE_OK) dialog.vbox.pack_start(vbox) dialog.set_icon(TRYTON_ICON) dialog.show_all() dialog.set_default_response(gtk.RESPONSE_OK) netloc = server_widget.get_text() entry_server.set_text(get_hostname(netloc)) entry_port.set_text(str(get_port(netloc))) res = dialog.run() if res == gtk.RESPONSE_OK: host = entry_server.get_text() port = entry_port.get_text() url = '%s:%s' % (host, port) server_widget.set_text(url) result = (get_hostname(url), get_port(url)) parent.present() dialog.destroy() return result def get_toplevel_window(): for window in gtk.window_list_toplevels(): if window.is_active() and window.props.type == gtk.WINDOW_TOPLEVEL: return window from tryton.gui.main import Main return Main.get_main().window def get_sensible_widget(window): from tryton.gui.main import Main main = Main.get_main() if main and window == main.window: focus_widget = window.get_focus() page = main.get_page() if page and focus_widget and focus_widget.is_ancestor(page.widget): return page.widget return window def center_window(window, parent, sensible): sensible_allocation = sensible.get_allocation() if hasattr(sensible.get_window(), 'get_root_coords'): x, y = sensible.get_window().get_root_coords( sensible_allocation.x, sensible_allocation.y) else: x, y = sensible.get_window().get_origin() x += sensible_allocation.x y += sensible_allocation.y window_allocation = window.get_allocation() x = x + int((sensible_allocation.width - window_allocation.width) / 2) y = y + int((sensible_allocation.height - window_allocation.height) / 2) window.move(x, y) def selection(title, values, alwaysask=False): if not values or len(values) == 0: return None elif len(values) == 1 and (not alwaysask): key = values.keys()[0] return (key, values[key]) parent = get_toplevel_window() dialog = gtk.Dialog(_('Selection'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) dialog.set_icon(TRYTON_ICON) dialog.set_default_response(gtk.RESPONSE_OK) dialog.set_default_size(400, 400) label = gtk.Label(title or _('Your selection:')) dialog.vbox.pack_start(label, False, False) dialog.vbox.pack_start(gtk.HSeparator(), False, True) scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) treeview = gtk.TreeView() treeview.set_headers_visible(False) scrolledwindow.add(treeview) dialog.vbox.pack_start(scrolledwindow, True, True) treeview.get_selection().set_mode(gtk.SELECTION_SINGLE) cell = gtk.CellRendererText() column = gtk.TreeViewColumn("Widget", cell, text=0) treeview.append_column(column) treeview.set_search_column(0) model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_INT) keys = values.keys() keys.sort() i = 0 for val in keys: model.append([str(val), i]) i += 1 treeview.set_model(model) treeview.connect('row-activated', lambda x, y, z: dialog.response(gtk.RESPONSE_OK) or True) dialog.show_all() response = dialog.run() res = None if response == gtk.RESPONSE_OK: sel = treeview.get_selection().get_selected() if sel: (model, i) = sel if i: index = model.get_value(i, 1) value = keys[index] res = (value, values[value]) parent.present() dialog.destroy() return res def file_selection(title, filename='', action=gtk.FILE_CHOOSER_ACTION_OPEN, preview=True, multi=False, filters=None): parent = get_toplevel_window() if action == gtk.FILE_CHOOSER_ACTION_OPEN: buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK) else: buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_SAVE, gtk.RESPONSE_OK) win = gtk.FileChooserDialog(title, None, action, buttons) win.set_transient_for(parent) win.set_icon(TRYTON_ICON) if filename: if action in (gtk.FILE_CHOOSER_ACTION_SAVE, gtk.FILE_CHOOSER_ACTION_CREATE_FOLDER): win.set_current_name(filename) else: win.set_filename(filename) if hasattr(win, 'set_do_overwrite_confirmation'): win.set_do_overwrite_confirmation(True) win.set_select_multiple(multi) win.set_default_response(gtk.RESPONSE_OK) if filters is not None: for filt in filters: win.add_filter(filt) def update_preview_cb(win, img): have_preview = False filename = win.get_preview_filename() if filename: try: pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( filename, 128, 128) img.set_from_pixbuf(pixbuf) have_preview = True except (IOError, glib.GError): pass win.set_preview_widget_active(have_preview) return if preview: img_preview = gtk.Image() win.set_preview_widget(img_preview) win.connect('update-preview', update_preview_cb, img_preview) if os.name == 'nt': encoding = 'utf-8' else: encoding = sys.getfilesystemencoding() button = win.run() if button != gtk.RESPONSE_OK: result = None elif not multi: result = win.get_filename() if result: result = unicode(result, encoding) else: result = [unicode(path, encoding) for path in win.get_filenames()] parent.present() win.destroy() return result _slugify_strip_re = re.compile(r'[^\w\s-]') _slugify_hyphenate_re = re.compile(r'[-\s]+') def slugify(value): if not isinstance(value, unicode): value = unicode(value) value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore') value = unicode(_slugify_strip_re.sub('', value).strip().lower()) return _slugify_hyphenate_re.sub('-', value) def file_open(filename, type, print_p=False): def save(): save_name = file_selection(_('Save As...'), action=gtk.FILE_CHOOSER_ACTION_SAVE) if save_name: file_p = open(filename, 'rb') save_p = open(save_name, 'wb+') save_p.write(file_p.read()) save_p.close() file_p.close() if os.name == 'nt': operation = 'open' if print_p: operation = 'print' try: os.startfile(os.path.normpath(filename), operation) except WindowsError: save() elif sys.platform == 'darwin': try: subprocess.Popen(['/usr/bin/open', filename]) except OSError: save() else: try: subprocess.Popen(['xdg-open', filename]) except OSError: save() def mailto(to=None, cc=None, subject=None, body=None, attachment=None): if CONFIG['client.email']: cmd = Template(CONFIG['client.email']).substitute( to=to or '', cc=cc or '', subject=subject or '', body=body or '', attachment=attachment or '', ) args = shlex.split(str(cmd)) subprocess.Popen(args) return if os.name != 'nt' and sys.platform != 'darwin': args = ['xdg-email', '--utf8'] if cc: args.extend(['--cc', cc]) if subject: args.extend(['--subject', subject]) if body: args.extend(['--body', body]) if attachment: args.extend(['--attach', attachment]) if to: args.append(to) try: subprocess.Popen(args) return except OSError: pass # http://www.faqs.org/rfcs/rfc2368.html url = "mailto:" if to: if isinstance(to, unicode): to = to.encode('utf-8') url += urllib.quote(to.strip(), "@,") url += '?' if cc: if isinstance(cc, unicode): cc = cc.encode('utf-8') url += "&cc=" + urllib.quote(cc, "@,") if subject: if isinstance(subject, unicode): subject = subject.encode('utf-8') url += "&subject=" + urllib.quote(subject, "") if body: if isinstance(body, unicode): body = body.encode('utf-8') body = "\r\n".join(body.splitlines()) url += "&body=" + urllib.quote(body, "") if attachment: if isinstance(attachment, unicode): attachment = attachment.encode('utf-8') url += "&attachment=" + urllib.quote(attachment, "") webbrowser.open(url, new=1) class UniqueDialog(object): def __init__(self): self.running = False def build_dialog(self, *args): raise NotImplementedError def __call__(self, *args): if self.running: return parent = get_toplevel_window() dialog = self.build_dialog(parent, *args) dialog.set_icon(TRYTON_ICON) self.running = True dialog.show_all() response = dialog.run() parent.present() dialog.destroy() self.running = False return response class MessageDialog(UniqueDialog): def build_dialog(self, parent, message, msg_type): dialog = gtk.MessageDialog(parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, msg_type, gtk.BUTTONS_OK, message) return dialog def __call__(self, message, msg_type=gtk.MESSAGE_INFO): super(MessageDialog, self).__call__(message, msg_type) message = MessageDialog() class WarningDialog(UniqueDialog): def build_dialog(self, parent, message, title, buttons=gtk.BUTTONS_OK): dialog = gtk.MessageDialog(parent, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, buttons) dialog.set_markup('%s' % (to_xml(title))) dialog.format_secondary_markup(to_xml(message)) return dialog warning = WarningDialog() class UserWarningDialog(WarningDialog): def __init__(self): super(UserWarningDialog, self).__init__() self.always = False def _set_always(self, toggle): self.always = toggle.get_active() def build_dialog(self, parent, message, title): dialog = super(UserWarningDialog, self).build_dialog(parent, message, title, gtk.BUTTONS_YES_NO) check = gtk.CheckButton(_('Always ignore this warning.')) check.connect_after('toggled', self._set_always) alignment = gtk.Alignment(0, 0.5) alignment.add(check) dialog.vbox.pack_start(alignment, True, False) label = gtk.Label(_('Do you want to proceed?')) label.set_alignment(1, 0.5) dialog.vbox.pack_start(label, True, True) return dialog def __call__(self, message, title): response = super(UserWarningDialog, self).__call__(message, title) if response == gtk.RESPONSE_YES: if self.always: return 'always' return 'ok' return 'cancel' userwarning = UserWarningDialog() class ConfirmationDialog(UniqueDialog): def build_dialog(self, parent, message): dialog = gtk.Dialog(_('Confirmation'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG) hbox = gtk.HBox() image = gtk.Image() image.set_from_stock('tryton-dialog-information', gtk.ICON_SIZE_DIALOG) image.set_padding(15, 15) hbox.pack_start(image, False, False) label = gtk.Label('%s' % (to_xml(message))) hbox.pack_start(label, True, True) dialog.vbox.pack_start(hbox) return dialog class SurDialog(ConfirmationDialog): def build_dialog(self, parent, message): dialog = super(SurDialog, self).build_dialog(parent, message) dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) dialog.set_default(dialog.add_button("gtk-ok", gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) return dialog def __call__(self, message): response = super(SurDialog, self).__call__(message) return response == gtk.RESPONSE_OK sur = SurDialog() class Sur3BDialog(ConfirmationDialog): response_mapping = { gtk.RESPONSE_YES: 'ok', gtk.RESPONSE_NO: 'ko', gtk.RESPONSE_CANCEL: 'cancel' } def build_dialog(self, parent, message): dialog = super(Sur3BDialog, self).build_dialog(parent, message) dialog.add_button("gtk-cancel", gtk.RESPONSE_CANCEL) dialog.add_button("gtk-no", gtk.RESPONSE_NO) dialog.set_default(dialog.add_button("gtk-yes", gtk.RESPONSE_YES)) dialog.set_default_response(gtk.RESPONSE_YES) return dialog def __call__(self, message): response = super(Sur3BDialog, self).__call__(message) return self.response_mapping.get(response, 'cancel') sur_3b = Sur3BDialog() class AskDialog(UniqueDialog): def build_dialog(self, parent, question, visibility): win = gtk.Dialog(CONFIG['client.title'], parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) win.set_default_response(gtk.RESPONSE_OK) hbox = gtk.HBox() image = gtk.Image() image.set_from_stock('tryton-dialog-information', gtk.ICON_SIZE_DIALOG) hbox.pack_start(image) vbox = gtk.VBox() vbox.pack_start(gtk.Label(question)) self.entry = gtk.Entry() self.entry.set_activates_default(True) self.entry.set_visibility(visibility) vbox.pack_start(self.entry) hbox.pack_start(vbox) win.vbox.pack_start(hbox) return win def __call__(self, question, visibility=True): if self.running: return parent = get_toplevel_window() dialog = self.build_dialog(parent, question, visibility=visibility) dialog.set_icon(TRYTON_ICON) self.running = True dialog.show_all() response = dialog.run() result = None if response == gtk.RESPONSE_OK: result = self.entry.get_text() parent.present() dialog.destroy() self.running = False return result ask = AskDialog() class ConcurrencyDialog(UniqueDialog): def build_dialog(self, parent, resource, obj_id, context): dialog = gtk.Dialog(_('Concurrency Exception'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT | gtk.WIN_POS_CENTER_ON_PARENT | gtk.gdk.WINDOW_TYPE_HINT_DIALOG) dialog.set_default_response(gtk.RESPONSE_CANCEL) hbox = gtk.HBox() image = gtk.Image() image.set_from_stock('tryton-dialog-information', gtk.ICON_SIZE_DIALOG) image.set_padding(15, 15) hbox.pack_start(image, False, False) label = gtk.Label() label.set_padding(15, 15) label.set_use_markup(True) label.set_markup(_('Write Concurrency Warning:\n\n' 'This record has been modified while you were editing it.\n' ' Choose:\n' ' - "Cancel" to cancel saving;\n' ' - "Compare" to see the modified version;\n' ' - "Write Anyway" to save your current version.')) hbox.pack_start(label, True, True) dialog.vbox.pack_start(hbox) dialog.add_button('gtk-cancel', gtk.RESPONSE_CANCEL) compare_button = gtk.Button(_('Compare')) image = gtk.Image() image.set_from_stock('tryton-find-replace', gtk.ICON_SIZE_BUTTON) compare_button.set_image(image) dialog.add_action_widget(compare_button, gtk.RESPONSE_APPLY) write_button = gtk.Button(_('Write Anyway')) image = gtk.Image() image.set_from_stock('tryton-save', gtk.ICON_SIZE_BUTTON) write_button.set_image(image) dialog.add_action_widget(write_button, gtk.RESPONSE_OK) return dialog def __call__(self, resource, obj_id, context): res = super(ConcurrencyDialog, self).__call__(resource, obj_id, context) if res == gtk.RESPONSE_OK: return True if res == gtk.RESPONSE_APPLY: from tryton.gui.window import Window Window.create(resource, res_id=obj_id, domain=[('id', '=', obj_id)], context=context, mode=['form', 'tree']) return False concurrency = ConcurrencyDialog() class ErrorDialog(UniqueDialog): def build_dialog(self, parent, title, details): dialog = gtk.Dialog(_('Error'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) but_send = gtk.Button(_('Report Bug')) dialog.add_action_widget(but_send, gtk.RESPONSE_OK) dialog.add_button("gtk-close", gtk.RESPONSE_CANCEL) dialog.set_default_response(gtk.RESPONSE_CANCEL) vbox = gtk.VBox() label_title = gtk.Label() label_title.set_markup('' + _('Application Error.') + '') label_title.set_padding(-1, 5) vbox.pack_start(label_title, False, False) vbox.pack_start(gtk.HSeparator(), False, False) hbox = gtk.HBox() image = gtk.Image() image.set_from_stock('tryton-dialog-error', gtk.ICON_SIZE_DIALOG) hbox.pack_start(image, False, False) scrolledwindow = gtk.ScrolledWindow() scrolledwindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) scrolledwindow.set_shadow_type(gtk.SHADOW_NONE) viewport = gtk.Viewport() viewport.set_shadow_type(gtk.SHADOW_NONE) box = gtk.VBox() label_error = gtk.Label() label_error.set_markup('') label_error.set_alignment(0, 0.5) label_error.set_padding(-1, 14) label_error.modify_font(pango.FontDescription("monospace")) label_error.set_markup('' + _('Error: ') + '' + to_xml(title)) box.pack_start(label_error, False, False) textview = gtk.TextView() buf = gtk.TextBuffer() buf.set_text(details) textview.set_buffer(buf) textview.set_editable(False) textview.set_sensitive(True) textview.modify_font(pango.FontDescription("monospace")) box.pack_start(textview, False, False) viewport.add(box) scrolledwindow.add(viewport) hbox.pack_start(scrolledwindow) vbox.pack_start(hbox) button_roundup = gtk.Button() button_roundup.set_relief(gtk.RELIEF_NONE) label_roundup = gtk.Label() label_roundup.set_markup(_('To report bugs you must have an account' ' on %s') % CONFIG['roundup.url']) label_roundup.set_alignment(1, 0.5) label_roundup.set_padding(20, 5) button_roundup.connect('clicked', lambda widget: webbrowser.open(CONFIG['roundup.url'], new=2)) button_roundup.add(label_roundup) vbox.pack_start(button_roundup, False, False) dialog.vbox.pack_start(vbox) dialog.set_default_size(600, 400) return dialog def __call__(self, title, details): if title == details: title = '' log = logging.getLogger(__name__) log.error(details + '\n' + title) response = super(ErrorDialog, self).__call__(title, details) if response == gtk.RESPONSE_OK: send_bugtracker(title, details) error = ErrorDialog() def send_bugtracker(title, msg): from tryton import rpc parent = get_toplevel_window() win = gtk.Dialog(_('Bug Tracker'), parent, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK)) win.set_icon(TRYTON_ICON) win.set_default_response(gtk.RESPONSE_OK) hbox = gtk.HBox() image = gtk.Image() image.set_from_stock('tryton-dialog-information', gtk.ICON_SIZE_DIALOG) hbox.pack_start(image, False, False) table = gtk.Table(2, 2) table.set_col_spacings(3) table.set_row_spacings(3) table.set_border_width(1) label_user = gtk.Label(_('User:')) label_user.set_alignment(1.0, 0.5) table.attach(label_user, 0, 1, 0, 1, yoptions=False, xoptions=gtk.FILL) entry_user = gtk.Entry() entry_user.set_activates_default(True) table.attach(entry_user, 1, 2, 0, 1, yoptions=False, xoptions=gtk.FILL) label_password = gtk.Label(_('Password:')) label_password.set_alignment(1.0, 0.5) table.attach(label_password, 0, 1, 1, 2, yoptions=False, xoptions=gtk.FILL) entry_password = gtk.Entry() entry_password.set_activates_default(True) entry_password.set_visibility(False) table.attach(entry_password, 1, 2, 1, 2, yoptions=False, xoptions=gtk.FILL) hbox.pack_start(table) win.vbox.pack_start(hbox) win.show_all() if rpc._USERNAME: entry_user.set_text(rpc._USERNAME) entry_password.grab_focus() else: entry_user.grab_focus() response = win.run() parent.present() user = entry_user.get_text() password = entry_password.get_text() win.destroy() if response == gtk.RESPONSE_OK: try: msg = msg.encode('ascii', 'replace') protocol = 'http' if ssl or hasattr(socket, 'ssl'): protocol = 'https' quote = partial(urllib.quote, safe="!$&'()*+,;=:") server = xmlrpclib.Server( ('%s://%s:%s@' + CONFIG['roundup.xmlrpc']) % (protocol, quote(user), quote(password)), allow_none=True) if hashlib: msg_md5 = hashlib.md5(msg + '\n' + title).hexdigest() else: msg_md5 = md5.new(msg + '\n' + title).hexdigest() if not title: title = '[no title]' issue_id = None msg_ids = server.filter('msg', None, {'summary': str(msg_md5)}) for msg_id in msg_ids: summary = server.display( 'msg%s' % msg_id, 'summary')['summary'] if summary == msg_md5: issue_ids = server.filter( 'issue', None, {'messages': msg_id}) if issue_ids: issue_id = issue_ids[0] break if issue_id: # issue to same message already exists, add user to nosy-list server.set('issue' + str(issue_id), *['nosy=+' + user]) message( _('The same bug was already reported by another user.\n' 'To keep you informed your username is added ' 'to the nosy-list of this issue') + '%s' % issue_id) else: # create a new issue for this error-message # first create message msg_id = server.create('msg', *['content=' + msg, 'author=' + user, 'summary=' + msg_md5]) # second create issue with this message issue_id = server.create('issue', *['messages=' + str(msg_id), 'nosy=' + user, 'title=' + title, 'priority=bug']) message(_('Created new bug with ID ') + 'issue%s' % issue_id) webbrowser.open(CONFIG['roundup.url'] + 'issue%s' % issue_id, new=2) except (socket.error, xmlrpclib.Fault), exception: if (isinstance(exception, xmlrpclib.Fault) and 'roundup.cgi.exceptions.Unauthorised' in exception.faultString): message(_('Connection error.\nBad username or password.')) return send_bugtracker(title, msg) tb_s = reduce(lambda x, y: x + y, traceback.format_exception(sys.exc_type, sys.exc_value, sys.exc_traceback)) message(_('Exception:') + '\n' + tb_s, msg_type=gtk.MESSAGE_ERROR) def to_xml(string): return string.replace('&', '&' ).replace('<', '<').replace('>', '>') PLOCK = Lock() def process_exception(exception, *args, **kwargs): rpc_execute = kwargs.get('rpc_execute', rpc.execute) if isinstance(exception, TrytonServerError): if exception.faultCode == 'UserWarning': name, msg, description = exception.args res = userwarning(description, msg) if res in ('always', 'ok'): RPCExecute('model', 'res.user.warning', 'create', [{ 'user': rpc._USER, 'name': name, 'always': (res == 'always'), }], process_exception=False) return rpc_execute(*args) elif exception.faultCode == 'UserError': msg, description = exception.args warning(description, msg) elif exception.faultCode == 'ConcurrencyException': if len(args) >= 6: if concurrency(args[1], args[3][0], args[5]): if '_timestamp' in args[5]: del args[5]['_timestamp'] return rpc_execute(*args) else: message(_('Concurrency Exception'), msg_type=gtk.MESSAGE_ERROR) elif (exception.faultCode.startswith('403') or exception.faultCode.startswith('401')): from tryton.gui.main import Main if PLOCK.acquire(False): language = CONFIG['client.lang'] func = lambda parameters: rpc.login( rpc._HOST, rpc._PORT, rpc._DATABASE, rpc._USERNAME, parameters, language) try: Login(func) except TrytonError, exception: if exception.faultCode == 'QueryCanceled': Main.get_main().sig_quit() raise finally: PLOCK.release() if args: return rpc_execute(*args) else: error(exception.faultCode, exception.faultString) else: error(str(exception), traceback.format_exc()) raise RPCException(exception) class Login(object): def __init__(self, func): parameters = {} while True: try: func(parameters) except TrytonServerError, exception: if exception.faultCode.startswith('403'): parameters.clear() continue if exception.faultCode != 'LoginException': raise name, message, type = exception.args value = getattr(self, 'get_%s' % type)(message) if value is None: raise TrytonError('QueryCanceled') parameters[name] = value continue else: return @classmethod def get_char(self, message): return ask(message) @classmethod def get_password(self, message): return ask(message, visibility=False) def node_attributes(node): result = {} attrs = node.attributes if attrs is None: return {} for i in range(attrs.length): result[str(attrs.item(i).localName)] = str(attrs.item(i).nodeValue) return result def hex2rgb(hexstring, digits=2): """ Converts a hexstring color to a rgb tuple. Example: #ff0000 -> (1.0, 0.0, 0.0) digits is an integer number telling how many characters should be interpreted for each component in the hexstring. """ if isinstance(hexstring, (tuple, list)): return hexstring top = float(int(digits * 'f', 16)) r = int(hexstring[1:digits + 1], 16) g = int(hexstring[digits + 1:digits * 2 + 1], 16) b = int(hexstring[digits * 2 + 1:digits * 3 + 1], 16) return r / top, g / top, b / top def highlight_rgb(r, g, b, amount=0.1): h, s, v = colorsys.rgb_to_hsv(r, g, b) return colorsys.hsv_to_rgb(h, s, (v + amount) % 1) def generateColorscheme(masterColor, keys, light=0.1): """ Generates a dictionary where the keys match the keys argument and the values are colors derivated from the masterColor. Each color has a value higher then the previous of `light`. Each color has a hue separated from the previous by the golden angle. The masterColor is given in a hex string format. """ r, g, b = hex2rgb(COLOR_SCHEMES.get(masterColor, masterColor)) h, s, v = colorsys.rgb_to_hsv(r, g, b) if keys: light = min(light, (1. - v) / len(keys)) golden_angle = 0.618033988749895 return {key: colorsys.hsv_to_rgb((h + golden_angle * i) % 1, s, (v + light * i) % 1) for i, key in enumerate(keys)} class RPCException(Exception): def __init__(self, exception): super(RPCException, self).__init__(exception) self.exception = exception class RPCProgress(object): def __init__(self, method, args): self.method = method self.args = args self.parent = None self.res = None self.error = False self.exception = None def start(self): try: self.res = getattr(rpc, self.method)(*self.args) except Exception, exception: self.error = True self.res = False self.exception = exception else: if not self.res: self.error = True if self.callback: # Post to GTK queue to be run by the main thread gobject.idle_add(self.process) return True def run(self, process_exception_p=True, callback=None): self.process_exception_p = process_exception_p self.callback = callback if callback: # Parent is only useful if it is asynchronous # otherwise the cursor is not updated. self.parent = get_toplevel_window() if self.parent.get_window(): watch = gtk.gdk.Cursor(gtk.gdk.WATCH) self.parent.get_window().set_cursor(watch) thread.start_new_thread(self.start, ()) return else: self.start() return self.process() def process(self): if self.parent and self.parent.get_window(): self.parent.get_window().set_cursor(None) if self.exception and self.process_exception_p: def rpc_execute(*args): return RPCProgress('execute', args).run( self.process_exception_p, self.callback) try: return process_exception( self.exception, *self.args, rpc_execute=rpc_execute) except RPCException, exception: self.exception = exception def return_(): if self.exception: raise self.exception else: return self.res if self.callback: self.callback(return_) else: return return_() def RPCExecute(*args, **kwargs): rpc_context = rpc.CONTEXT.copy() if kwargs.get('context'): rpc_context.update(kwargs['context']) args = args + (rpc_context,) process_exception = kwargs.get('process_exception', True) callback = kwargs.get('callback') return RPCProgress('execute', args).run(process_exception, callback) def RPCContextReload(callback=None): def update(context): rpc.CONTEXT.clear() try: rpc.CONTEXT.update(context()) except RPCException: pass if callback: callback() # Use RPCProgress to not send rpc.CONTEXT RPCProgress('execute', ('model', 'res.user', 'get_preferences', True, {}) ).run(True, update) class Tooltips(object): _tooltips = None def set_tip(self, widget, tip_text): if hasattr(widget, 'set_tooltip_text'): return widget.set_tooltip_text(tip_text) if not self._tooltips: self._tooltips = gtk.Tooltips() return self._tooltips.set_tip(widget, tip_text) def enable(self): if self._tooltips: self._tooltips.enable() def disable(self): if self._tooltips: self._tooltips.disable() COLOR_SCHEMES = { 'red': '#cf1d1d', 'green': '#3fb41b', 'blue': '#224565', 'grey': '#444444', 'black': '#000000', 'darkcyan': '#305755', } def filter_domain(domain): ''' Return the biggest subset of domain with only AND operator ''' res = [] for arg in domain: if isinstance(arg, basestring): if arg == 'OR': res = [] break continue if isinstance(arg, tuple): res.append(arg) elif isinstance(arg, list): res.extend(filter_domain(arg)) return res def timezoned_date(date, reverse=False): lzone = dateutil.tz.tzlocal() szone = dateutil.tz.tzutc() if reverse: lzone, szone = szone, lzone return date.replace(tzinfo=szone).astimezone(lzone).replace(tzinfo=None) def untimezoned_date(date): return timezoned_date(date, reverse=True).replace(tzinfo=None) def humanize(size): for x in ('bytes', 'KB', 'MB', 'GB', 'TB', 'PB'): if size < 1000: return '%3.1f%s' % (size, x) size /= 1000.0 def get_hostname(netloc): if '[' in netloc and ']' in netloc: hostname = netloc.split(']')[0][1:] elif ':' in netloc: hostname = netloc.split(':')[0] else: hostname = netloc return hostname.strip() def get_port(netloc): netloc = netloc.split(']')[-1] if ':' in netloc: try: return int(netloc.split(':')[1]) except ValueError: pass return 8000 def resize_pixbuf(pixbuf, width, height): img_height = pixbuf.get_height() height = min(img_height, height) if height != -1 else img_height img_width = pixbuf.get_width() width = min(img_width, width) if width != -1 else img_width if img_width / width < img_height / height: width = float(img_width) / float(img_height) * float(height) else: height = float(img_height) / float(img_width) * float(width) return pixbuf.scale_simple(int(width), int(height), gtk.gdk.INTERP_BILINEAR) def _data2pixbuf(data): loader = gtk.gdk.PixbufLoader() loader.write(bytes(data)) loader.close() return loader.get_pixbuf() BIG_IMAGE_SIZE = 10 ** 6 with open(os.path.join(PIXMAPS_DIR, 'tryton-noimage.png'), 'rb') as no_image: NO_IMG_PIXBUF = _data2pixbuf(no_image.read()) def data2pixbuf(data): pixbuf = NO_IMG_PIXBUF if data: try: pixbuf = _data2pixbuf(data) except glib.GError: pass return pixbuf def get_label_attributes(readonly, required): "Return the pango attributes applied to a label according to its state" if readonly: style = pango.STYLE_NORMAL weight = pango.WEIGHT_NORMAL else: style = pango.STYLE_ITALIC if required: weight = pango.WEIGHT_BOLD else: weight = pango.WEIGHT_NORMAL attrlist = pango.AttrList() if hasattr(pango, 'AttrWeight'): attrlist.change(pango.AttrWeight(weight, 0, -1)) if hasattr(pango, 'AttrStyle'): attrlist.change(pango.AttrStyle(style, 0, -1)) return attrlist def ellipsize(string, length): if len(string) <= length: return string ellipsis = _('...') return string[:length - len(ellipsis)] + ellipsis tryton-4.6.5/tryton/common/button.py0000644000175000017500000000414213251060075017111 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gettext import gtk from tryton.common import ICONFACTORY _ = gettext.gettext class Button(gtk.Button): def __init__(self, attrs=None): self.attrs = attrs or {} self.label = '_' + attrs.get('string', '').replace('_', '__') super(Button, self).__init__(label=self.label, stock=None, use_underline=True) self._set_icon(attrs.get('icon')) def _set_icon(self, stock): image = self.get_image() if not image and not stock: return elif image and image.get_stock()[0] == stock: return if not stock: self.set_image(gtk.Image()) return ICONFACTORY.register_icon(stock) icon = gtk.Image() icon.set_from_stock(stock, gtk.ICON_SIZE_SMALL_TOOLBAR) self.set_image(icon) def state_set(self, record): if record: states = record.expr_eval(self.attrs.get('states', {})) else: states = {} if states.get('invisible', False): self.hide() else: self.show() self.set_sensitive(not states.get('readonly', False)) self._set_icon(states.get('icon', self.attrs.get('icon'))) if self.attrs.get('rule'): label = self.label tip = self.attrs.get('help', '') if record: clicks = record.get_button_clicks(self.attrs['name']) if clicks: label += ' (%s)' % len(clicks) if tip: tip += '\n' tip += _('By: ') + _(', ').join(clicks.itervalues()) self.set_label(label) self.set_tooltip_text(tip) if self.attrs.get('type', 'class') == 'class': parent = record.parent if record else None while parent: if parent.modified: self.set_sensitive(False) break parent = parent.parent tryton-4.6.5/tryton/common/__init__.py0000644000175000017500000000062613175640533017350 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from common import * from datetime_strftime import * from domain_inversion import domain_inversion, eval_domain, localize_domain, \ merge, inverse_leaf, filter_leaf, concat, simplify, unique_value from environment import EvalEnvironment import timedelta tryton-4.6.5/tryton/common/cellrendererinteger.py0000644000175000017500000000204413175640533021631 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gobject from cellrenderertext import CellRendererText import locale class CellRendererInteger(CellRendererText): def do_start_editing(self, event, widget, path, background_area, cell_area, flags): editable = super(CellRendererInteger, self).do_start_editing(event, widget, path, background_area, cell_area, flags) editable.set_alignment(1.0) editable.connect('insert_text', self.sig_insert_text) return editable def sig_insert_text(self, entry, new_text, new_text_length, position): value = entry.get_text() position = entry.get_position() new_value = value[:position] + new_text + value[position:] if new_value == '-': return try: locale.atoi(new_value) except ValueError: entry.stop_emission('insert-text') gobject.type_register(CellRendererInteger) tryton-4.6.5/tryton/common/cellrenderercombo.py0000644000175000017500000000227313251060075021267 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject from tryton.common.selection import selection_shortcuts class CellRendererCombo(gtk.CellRendererCombo): def set_sensitive(self, value): self.set_property('sensitive', value) def do_activate(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return return gtk.CellRendererCombo.do_activate(self, event, widget, path, background_area, cell_area, flags) def do_start_editing(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return if not event: if hasattr(gtk.gdk.Event, 'new'): event = gtk.gdk.Event.new(gtk.gdk.KEY_PRESS) else: event = gtk.gdk.Event(gtk.gdk.KEY_PRESS) editable = gtk.CellRendererCombo.do_start_editing(self, event, widget, path, background_area, cell_area, flags) return selection_shortcuts(editable) gobject.type_register(CellRendererCombo) tryton-4.6.5/tryton/common/completion.py0000644000175000017500000000520013255571102017745 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import logging import gettext import gtk import gobject from tryton.config import CONFIG from tryton.common import RPCExecute from tryton.exceptions import TrytonServerError, TrytonError _ = gettext.gettext logger = logging.getLogger(__name__) def get_completion(search=True, create=True): "Return a EntryCompletion" completion = gtk.EntryCompletion() completion.set_match_func(lambda *a: True) completion.set_model(gtk.ListStore(str, int)) completion.set_text_column(0) completion.props.popup_set_width = False if search: completion.insert_action_markup(0, _('Search...')) if create: completion.insert_action_markup(1, _('Create...')) return completion def update_completion(entry, record, field, model, domain=None): "Update entry completion" def update(search_text, domain): if not entry.props.window: return False if search_text != entry.get_text().decode('utf-8'): return False completion_model = entry.get_completion().get_model() if not search_text or not model: completion_model.clear() completion_model.search_text = search_text return False if getattr(completion_model, 'search_text', None) == search_text: return False if domain is None: domain = field.domain_get(record) context = field.get_context(record) domain = [('rec_name', 'ilike', '%' + search_text + '%'), domain] def callback(results): try: results = results() except (TrytonError, TrytonServerError): results = [] if search_text != entry.get_text().decode('utf-8'): return False completion_model.clear() for result in results: completion_model.append([result['rec_name'], result['id']]) completion_model.search_text = search_text # Force display of popup entry.emit('changed') try: RPCExecute('model', model, 'search_read', domain, 0, CONFIG['client.limit'], None, ['rec_name'], context=context, process_exception=False, callback=callback) except Exception: logging.warn( _("Unable to search for completion of %s") % model, exc_info=True) return False search_text = entry.get_text().decode('utf-8') gobject.timeout_add(300, update, search_text, domain) tryton-4.6.5/tryton/common/selection.py0000644000175000017500000001710013251060075017561 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import operator import math import gtk import gobject from tryton.common import RPCExecute, RPCException from tryton.common import eval_domain class SelectionMixin(object): def __init__(self, *args, **kwargs): super(SelectionMixin, self).__init__(*args, **kwargs) self.nullable_widget = True self.selection = None self.inactive_selection = [] self._last_domain = None self._values2selection = {} self._domain_cache = {} def init_selection(self, value=None): if value is None: value = dict((k, None) for k in self.attrs.get('selection_change_with') or []) key = freeze_value(value) selection = self.attrs.get('selection', [])[:] if (not isinstance(selection, (list, tuple)) and key not in self._values2selection): try: if self.attrs.get('selection_change_with'): selection = RPCExecute('model', self.model_name, selection, value) else: selection = RPCExecute('model', self.model_name, selection) except RPCException: selection = [] self._values2selection[key] = selection elif key in self._values2selection: selection = self._values2selection[key] if self.attrs.get('sort', True): selection.sort(key=operator.itemgetter(1)) self.selection = selection[:] self.inactive_selection = [] def update_selection(self, record, field): if not field: return domain = field.domain_get(record) if field.attrs['type'] == 'reference': # The domain on reference field is not only based on the selection # so the selection can not be filtered. domain = [] if 'relation' not in self.attrs: change_with = self.attrs.get('selection_change_with') or [] value = record._get_on_change_args(change_with) del value['id'] self.init_selection(value) self.filter_selection(domain, record, field) else: context = field.get_context(record) domain_cache_key = (freeze_value(domain), freeze_value(context)) if domain_cache_key in self._domain_cache: self.selection = self._domain_cache[domain_cache_key] self._last_domain = (domain, context) if (domain, context) == self._last_domain: return try: result = RPCExecute('model', self.attrs['relation'], 'search_read', domain, 0, None, None, ['rec_name'], context=context) except RPCException: result = False if isinstance(result, list): selection = [(x['id'], x['rec_name']) for x in result] if self.nullable_widget: selection.append((None, '')) self._last_domain = (domain, context) self._domain_cache[domain_cache_key] = selection else: selection = [] self._last_domain = None self.selection = selection[:] self.inactive_selection = [] def filter_selection(self, domain, record, field): if not domain: return test = lambda value: eval_domain(domain, { self.field_name: value[0], }) self.selection = filter(test, self.selection) def get_inactive_selection(self, value): if 'relation' not in self.attrs: return '' for val, text in self.inactive_selection: if str(val) == str(value): return text else: try: result, = RPCExecute('model', self.attrs['relation'], 'read', [value], ['rec_name']) self.inactive_selection.append((result['id'], result['rec_name'])) return result['rec_name'] except RPCException: return '' def selection_shortcuts(entry): def key_press(widget, event): if (event.type == gtk.gdk.KEY_PRESS and event.state & gtk.gdk.CONTROL_MASK and event.keyval == gtk.keysyms.space): widget.popup() entry.connect('key_press_event', key_press) return entry def freeze_value(value): if isinstance(value, dict): return tuple(sorted((k, freeze_value(v)) for k, v in value.iteritems())) elif isinstance(value, (list, set)): return tuple(freeze_value(v) for v in value) else: return value class PopdownMixin(object): def set_popdown(self, selection, entry): child = entry.get_child() if not child: # entry is destroyed return model, lengths = self.get_popdown_model(selection) entry.set_model(model) # GTK 2.24 and above use a ComboBox instead of a ComboBoxEntry if hasattr(entry, 'set_text_column'): entry.set_text_column(0) else: entry.set_entry_text_column(0) completion = gtk.EntryCompletion() completion.set_inline_selection(True) completion.set_model(model) child.set_completion(completion) if lengths: pop = sorted(lengths, reverse=True) average = sum(pop) / len(pop) deviation = int(math.sqrt(sum((x - average) ** 2 for x in pop) / len(pop))) width = max(next((x for x in pop if x < (deviation * 4)), 10), 10) else: width = 10 child.set_width_chars(width) if lengths: child.set_max_length(max(lengths)) completion.set_text_column(0) completion.connect('match-selected', self.match_selected, entry) def get_popdown_model(self, selection): model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_PYOBJECT) lengths = [] for (value, name) in selection: name = str(name) model.append((name, value)) lengths.append(len(name)) return model, lengths def match_selected(self, completion, model, iter_, entry): value, = model.get(iter_, 1) model = entry.get_model() for i, values in enumerate(model): if values[1] == value: entry.set_active(i) break def get_popdown_value(self, entry, index=1): active = entry.get_active() if active < 0: return None else: model = entry.get_model() return model[active][index] def get_popdown_text(self, entry): return self.get_popdown_value(entry, index=0) def set_popdown_value(self, entry, value): active = -1 model = entry.get_model() for i, selection in enumerate(model): if selection[1] == value: active = i break else: if value: return False entry.set_active(active) if active == -1: # When setting no item GTK doesn't clear the entry entry.get_child().set_text('') return True def test_freeze_value(): assert freeze_value({'foo': 'bar'}) == (('foo', 'bar'),) assert freeze_value([1, 42, 2, 3]) == (1, 42, 2, 3) assert freeze_value('foo') == 'foo' assert freeze_value({'foo': {'bar': 42}}) == (('foo', (('bar', 42),)),) tryton-4.6.5/tryton/common/domain_parser.py0000644000175000017500000013701213251060075020424 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from shlex import shlex from types import GeneratorType import gettext import locale import decimal from decimal import Decimal import datetime import io from collections import OrderedDict from tryton.common import untimezoned_date, timezoned_date, datetime_strftime from tryton.common.datetime_ import date_parse from tryton.common.timedelta import parse as timedelta_parse from tryton.common.timedelta import format as timedelta_format from tryton.pyson import PYSONDecoder __all__ = ['DomainParser'] _ = gettext.gettext ListGeneratorType = type(iter([])) TupleGeneratorType = type(iter(())) OPERATORS = ( '!=', '<=', '>=', '=', '!', '<', '>', ) class udlex(shlex): "A lexical analyzer class for human domain syntaxes." def __init__(self, instream=None): shlex.__init__(self, io.StringIO(instream), posix=True) self.commenters = '' self.quotes = '"' class DummyWordchars(object): "Simulate str that contains all chars except somes" def __contains__(self, item): return item not in (u':', u'>', u'<', u'=', u'!', u'"', u';', u'(', u')') self.wordchars = DummyWordchars() def isgenerator(value): "Test if value is a generator type" return isinstance(value, (GeneratorType, ListGeneratorType, TupleGeneratorType)) def rlist(value): "Convert recursivly generator into list" if isgenerator(value) or isinstance(value, list): return [rlist(x) for x in value] return value def simplify(value): "Remove double nested list" if isinstance(value, list): if len(value) == 1 and isinstance(value[0], list): return simplify(value[0]) elif (len(value) == 2 and value[0] in ('AND', 'OR') and isinstance(value[1], list)): return simplify(value[1]) elif (len(value) == 3 and value[0] in ('AND', 'OR') and isinstance(value[1], list) and value[0] == value[1][0]): value = simplify(value[1]) + [value[2]] return [simplify(x) for x in value] return value def group_operator(tokens): "Group token of operators" cur = next(tokens) nex = None for nex in tokens: if nex == '=' and cur and cur + nex in OPERATORS: yield cur + nex cur = None else: if cur is not None: yield cur cur = nex if cur is not None: yield cur def test_group_operator(): assert list(group_operator(iter(['a', '>', '=']))) == ['a', '>='] assert list(group_operator(iter(['>', '=', 'b']))) == ['>=', 'b'] assert list(group_operator(iter(['a', '=', 'b']))) == ['a', '=', 'b'] assert list(group_operator(iter(['a', '>', '=', 'b']))) == ['a', '>=', 'b'] assert list(group_operator(iter(['a', '>', '=', '=']))) == ['a', '>=', '='] def likify(value): "Add % if needed" if not value: return '%' escaped = value.replace('%%', '__') if '%' in escaped: return value else: return '%' + value + '%' def quote(value): "Quote string if needed" if not isinstance(value, basestring): return value if '\\' in value: value = value.replace('\\', '\\\\') if '"' in value: value = value.replace('"', '\\"') for test in (':', ' ', '(', ')') + OPERATORS: if test in value: return '"%s"' % value return value def test_quote(): assert quote('test') == 'test' assert quote('foo bar') == '"foo bar"' assert quote('"foo"') == '\\\"foo\\\"' assert quote('foo\\bar') == 'foo\\\\bar' def ending_clause(domain, deep=0): "Return the ending clause" if not domain: return None, deep if isinstance(domain[-1], list): return ending_clause(domain[-1], deep + 1) return domain[-1], deep def replace_ending_clause(domain, clause): "Replace the ending clause" for dom in domain[:-1]: yield dom if isinstance(domain[-1], list): yield replace_ending_clause(domain[-1], clause) else: yield clause def append_ending_clause(domain, clause, deep): "Append clause after the ending clause" if not domain: yield clause raise StopIteration for dom in domain[:-1]: yield dom if isinstance(domain[-1], list): yield append_ending_clause(domain[-1], clause, deep - 1) else: yield domain[-1] if deep == 0: yield clause def default_operator(field): "Return default operator for field" if field['type'] in ('char', 'text', 'many2one', 'many2many', 'one2many', 'reference'): return 'ilike' else: return '=' def negate_operator(operator): "Return negate operator" if operator == 'ilike': return 'not ilike' elif operator == '=': return '!=' elif operator == 'in': return 'not in' def time_format(field): return PYSONDecoder({}).decode(field['format']) def split_target_value(field, value): "Split the reference value into target and value" assert field['type'] == 'reference' target = None if isinstance(value, basestring): for key, text in field['selection']: if value.lower().startswith(text.lower() + ','): target = key value = value[len(text) + 1:] break return target, value def test_split_target_value(): field = { 'type': 'reference', 'selection': [ ('spam', 'Spam'), ('ham', 'Ham'), ('e', 'Eggs'), ] } for value, result in ( ('Spam', (None, 'Spam')), ('foo', (None, 'foo')), ('Spam,', ('spam', '')), ('Ham,bar', ('ham', 'bar')), ('Eggs,foo', ('e', 'foo')), ): assert split_target_value(field, value) == result def convert_value(field, value, context=None): "Convert value for field" if context is None: context = {} def convert_boolean(): if isinstance(value, basestring): return any(test.decode('utf-8').lower().startswith(value.lower()) for test in ( _('y'), _('Yes'), _('True'), _('t'), '1')) else: return bool(value) def convert_float(): try: return locale.atof(value) except (ValueError, AttributeError): return def convert_integer(): try: return int(locale.atof(value)) except (ValueError, AttributeError): return def convert_numeric(): try: return locale.atof(value, Decimal) except (decimal.InvalidOperation, AttributeError): return def convert_selection(): if isinstance(value, basestring): for key, text in field['selection']: if value.lower() == text.lower(): return key return value def convert_datetime(): if not value: return format_ = context.get('date_format', '%x') + ' %X' try: dt = date_parse(value, format_) if dt.time() == datetime.time.min: return dt return untimezoned_date(dt) except ValueError: return def convert_date(): if not value: return format_ = context.get('date_format', '%x') try: return date_parse(value, format_).date() except (ValueError, TypeError): return def convert_time(): if not value: return try: return date_parse(value).time() except (ValueError, TypeError): return def convert_timedelta(): return timedelta_parse(value, context.get(field.get('converter'))) def convert_many2one(): if value == '': return None return value converts = { 'boolean': convert_boolean, 'float': convert_float, 'integer': convert_integer, 'numeric': convert_numeric, 'selection': convert_selection, 'reference': convert_selection, 'datetime': convert_datetime, 'date': convert_date, 'time': convert_time, 'timedelta': convert_timedelta, 'many2one': convert_many2one, } return converts.get(field['type'], lambda: value)() def test_convert_boolean(): field = { 'type': 'boolean', } for value, result in ( ('Y', True), ('yes', True), ('t', True), ('1', True), ('N', False), ('False', False), ('no', False), ('0', False), (None, False), ): assert convert_value(field, value) == result def test_convert_float(): field = { 'type': 'float', } for value, result in ( ('1', 1.0), ('1.5', 1.5), ('', None), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_integer(): field = { 'type': 'integer', } for value, result in ( ('1', 1), ('1.5', 1), ('', None), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_numeric(): field = { 'type': 'numeric', } for value, result in ( ('1', Decimal(1)), ('1.5', Decimal('1.5')), ('', None), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_selection(): field = { 'type': 'selection', 'selection': [ ('male', 'Male'), ('female', 'Female'), ], } field_with_empty = field.copy() field_with_empty['selection'] = (field_with_empty['selection'] + [('', '')]) for value, result in ( ('Male', 'male'), ('male', 'male'), ('test', 'test'), (None, None), ('', ''), ): assert convert_value(field, value) == result assert convert_value(field_with_empty, value) == result def test_convert_datetime(): field = { 'type': 'datetime', 'format': '"%H:%M:%S"', } for value, result in ( ('12/04/2002', datetime.datetime(2002, 12, 4)), ('12/04/2002 12:30:00', untimezoned_date( datetime.datetime(2002, 12, 4, 12, 30))), ('02/03/04', datetime.datetime(2004, 2, 3)), ('02/03/04 05:06:07', untimezoned_date( datetime.datetime(2004, 2, 3, 5, 6, 7))), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_date(): field = { 'type': 'date', } for value, result in ( ('12/04/2002', datetime.date(2002, 12, 4)), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_time(): field = { 'type': 'time', 'format': '"%H:%M:%S"', } for value, result in ( ('12:30:00', datetime.time(12, 30, 0)), ('test', None), (None, None), ): assert convert_value(field, value) == result def test_convert_timedelta(): field = { 'type': 'timedelta', } for value, result in [ ('1d 2:00', datetime.timedelta(days=1, hours=2)), ('foo', datetime.timedelta()), (None, None), ]: assert convert_value(field, value) == result def format_value(field, value, target=None, context=None): "Format value for field" if context is None: context = {} def format_boolean(): return _('True') if value else _('False') def format_integer(): if value or value is 0 or isinstance(value, float): return str(int(value)) return '' def format_float(): if (not value and value is not 0 and not isinstance(value, (float, Decimal))): return '' try: digit = len(str(value).split('.')[1]) except IndexError: digit = 0 return locale.format('%.*f', (digit, value or 0), True) def format_selection(): selections = dict(field['selection']) return selections.get(value, value) or '' def format_reference(): if not target: return format_selection() selections = dict(field['selection']) return '%s,%s' % (selections.get(target, target), value) def format_datetime(): if not value: return '' format_ = context.get('date_format', '%x') + ' ' + time_format(field) if (not isinstance(value, datetime.datetime) or value.time() == datetime.time.min): format_ = '%x' time = value else: time = timezoned_date(value) return datetime_strftime(time, format_) def format_date(): if not value: return '' format_ = context.get('date_format', '%x') return datetime_strftime(value, format_) def format_time(): if not value: return '' return datetime.time.strftime(value, time_format(field)) def format_timedelta(): if not value: return '' return timedelta_format(value, context.get(field.get('converter'))) def format_many2one(): if value is None: return '' return value converts = { 'boolean': format_boolean, 'integer': format_integer, 'float': format_float, 'numeric': format_float, 'selection': format_selection, 'reference': format_reference, 'datetime': format_datetime, 'date': format_date, 'time': format_time, 'timedelta': format_timedelta, 'many2one': format_many2one, } if isinstance(value, (list, tuple)): return ';'.join(format_value(field, x, context=context) for x in value) return quote(converts.get(field['type'], lambda: value if value is not None else '')()) def test_format_boolean(): field = { 'type': 'boolean', } for value, result in ( (True, 'True'), (False, 'False'), (None, 'False'), ): assert format_value(field, value) == result def test_format_integer(): field = { 'type': 'integer', } for value, result in ( (1, '1'), (1.5, '1'), (0, '0'), (0.0, '0'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_float(): field = { 'type': 'float', } for value, result in ( (1, '1'), (1.5, '1.5'), (1.50, '1.5'), (150.79, '150.79'), (0, '0'), (0.0, '0.0'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_numeric(): field = { 'type': 'numeric', } for value, result in ( (Decimal(1), '1'), (Decimal('1.5'), '1.5'), (Decimal('1.50'), '1.50'), (Decimal('150.79'), '150.79'), (Decimal(0), '0'), (Decimal('0.0'), '0.0'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_selection(): field = { 'type': 'selection', 'selection': [ ('male', 'Male'), ('female', 'Female'), ], } field_with_empty = field.copy() field_with_empty['selection'] = (field_with_empty['selection'] + [('', '')]) for value, result in ( ('male', 'Male'), ('test', 'test'), (False, ''), (None, ''), ('', ''), ): assert format_value(field, value) == result assert format_value(field_with_empty, value) == result def test_format_datetime(): field = { 'type': 'datetime', 'format': '"%H:%M:%S"', } for value, result in ( (datetime.date(2002, 12, 4), '12/04/2002'), (datetime.datetime(2002, 12, 4), '12/04/2002'), (untimezoned_date(datetime.datetime(2002, 12, 4, 12, 30)), '"12/04/2002 12:30:00"'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_date(): field = { 'type': 'date', } for value, result in ( (datetime.date(2002, 12, 4), '12/04/2002'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_time(): field = { 'type': 'time', 'format': '"%H:%M:%S"', } for value, result in ( (datetime.time(12, 30, 0), '"12:30:00"'), (False, ''), (None, ''), ): assert format_value(field, value) == result def test_format_timedelta(): field = { 'type': 'timedelta', } for value, result in [ (datetime.timedelta(days=1, hours=2), '"1d 02:00"'), (datetime.timedelta(), ''), (None, ''), ('', ''), ]: assert format_value(field, value) == result def complete_value(field, value): "Complete value for field" def complete_boolean(): if value: yield False else: yield True def complete_selection(): test_value = value if value is not None else '' if isinstance(value, list): test_value = value[-1] or '' test_value = test_value.strip('%') for svalue, test in field['selection']: if test.lower().startswith(test_value.lower()): if isinstance(value, list): yield value[:-1] + [svalue] else: yield svalue def complete_reference(): test_value = value if value is not None else '' if isinstance(value, list): test_value = value[-1] test_value = test_value.strip('%') for svalue, test in field['selection']: if test.lower().startswith(test_value.lower()): if isinstance(value, list): yield value[:-1] + [svalue] else: yield likify(svalue) def complete_datetime(): yield datetime.date.today() yield datetime.datetime.utcnow() def complete_date(): yield datetime.date.today() def complete_time(): yield datetime.datetime.now().time() completes = { 'boolean': complete_boolean, 'selection': complete_selection, 'reference': complete_reference, 'datetime': complete_datetime, 'date': complete_date, 'time': complete_time, } return completes.get(field['type'], lambda: [])() def test_complete_selection(): field = { 'type': 'selection', 'selection': [ ('male', 'Male'), ('female', 'Female'), ], } for value, result in ( ('m', ['male']), ('test', []), ('', ['male', 'female']), (None, ['male', 'female']), (['male', 'f'], [['male', 'female']]), (['male', None], [['male', 'male'], ['male', 'female']]), ): assert list(complete_value(field, value)) == result field_with_empty = field.copy() field_with_empty['selection'] = (field_with_empty['selection'] + [('', '')]) for value, result in ( ('m', ['male']), ('test', []), ('', ['male', 'female', '']), (None, ['male', 'female', '']), (['male', 'f'], [['male', 'female']]), ): assert list(complete_value(field_with_empty, value)) == result def test_complete_reference(): field = { 'type': 'reference', 'selection': [ ('spam', 'Spam'), ('ham', 'Ham'), ('', ''), ], } for value, result in ( ('s', ['%spam%']), ('test', []), ('', ['%spam%', '%ham%', '%']), (None, ['%spam%', '%ham%', '%']), (['spam', 'h'], [['spam', 'ham']]), ): assert list(complete_value(field, value)) == result def parenthesize(tokens): "Nest tokens according to parenthesis" for token in tokens: if token == '(': yield iter(list(parenthesize(tokens))) elif token == ')': break else: yield token def test_parenthesize(): for value, result in ( (['a'], ['a']), (['a', 'b'], ['a', 'b']), (['(', 'a', ')'], [['a']]), (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f', ')', 'g'], ['a', 'b', ['c', ['d', 'e'], 'f'], 'g']), (['a', 'b', '(', 'c'], ['a', 'b', ['c']]), (['a', 'b', '(', 'c', '(', 'd', 'e', ')', 'f'], ['a', 'b', ['c', ['d', 'e'], 'f']]), (['a', 'b', ')'], ['a', 'b']), (['a', 'b', ')', 'c', ')', 'd)'], ['a', 'b']), ): assert rlist(parenthesize(iter(value))) == result def operatorize(tokens, operator='or'): "Convert operators" test = (operator, (operator,)) cur = next(tokens) while cur in test: cur = next(tokens) if isgenerator(cur): cur = operatorize(cur, operator) nex = None for nex in tokens: if isgenerator(nex): nex = operatorize(nex, operator) if nex in test: try: nex = next(tokens) while nex in test: nex = next(tokens) if isgenerator(nex): nex = operatorize(nex, operator) cur = iter([operator.upper(), cur, nex]) except StopIteration: if cur not in test: yield iter([operator.upper(), cur]) cur = None nex = None else: if cur not in test: yield cur cur = nex else: if nex is not None and nex not in test: yield nex elif cur is not None and cur not in test: yield cur def test_operatorize(): a = ('a', 'a', 'a') b = ('b', 'b', 'b') c = ('c', 'c', 'c') null_ = ('d', None, 'x') double_null_ = ('e', None, None) for value, result in ( (['a'], ['a']), (['a', 'or', 'b'], [['OR', 'a', 'b']]), (['a', 'or', 'b', 'or', 'c'], [['OR', ['OR', 'a', 'b'], 'c']]), (['a', 'b', 'or', 'c'], ['a', ['OR', 'b', 'c']]), (['a', 'or', 'b', 'c'], [['OR', 'a', 'b'], 'c']), (['a', iter(['b', 'c'])], ['a', ['b', 'c']]), (['a', iter(['b', 'c']), 'd'], ['a', ['b', 'c'], 'd']), (['a', 'or', iter(['b', 'c'])], [['OR', 'a', ['b', 'c']]]), (['a', 'or', iter(['b', 'c']), 'd'], [['OR', 'a', ['b', 'c']], 'd']), (['a', iter(['b', 'c']), 'or', 'd'], ['a', ['OR', ['b', 'c'], 'd']]), (['a', 'or', iter(['b', 'or', 'c'])], [['OR', 'a', [['OR', 'b', 'c']]]]), (['or'], []), (['or', 'a'], ['a']), (['a', iter(['or', 'b'])], ['a', ['b']]), (['a', 'or', 'or', 'b'], [['OR', 'a', 'b']]), (['or', 'or', 'a'], ['a']), (['or', 'or', 'a', 'b'], ['a', 'b']), (['or', 'or', 'a', 'or', 'b'], [['OR', 'a', 'b']]), (['a', iter(['b', 'or', 'c'])], ['a', [['OR', 'b', 'c']]]), ([a, iter([b, ('or',), c])], [a, [['OR', b, c]]]), (['a', iter(['b', 'or'])], ['a', [['OR', 'b']]]), ([null_], [null_]), ([null_, 'or', double_null_], [['OR', null_, double_null_]]), ): assert rlist(operatorize(iter(value))) == result class DomainParser(object): "A parser for domain" def __init__(self, fields, context=None): self.fields = OrderedDict((name, f) for name, f in fields.iteritems() if f.get('searchable', True)) self.strings = dict((f['string'].lower(), f) for f in fields.itervalues() if f.get('searchable', True)) self.context = context def parse(self, input_): "Return domain for the input string" try: tokens = udlex(input_) tokens = group_operator(tokens) tokens = parenthesize(tokens) tokens = self.group(tokens) tokens = operatorize(tokens, 'or') tokens = operatorize(tokens, 'and') tokens = self.parse_clause(tokens) return simplify(rlist(tokens)) except ValueError, exception: if exception.message == 'No closing quotation': return self.parse(input_ + '"') def stringable(self, domain): def stringable_(clause): if not clause: return True if (((clause[0] in ('AND', 'OR')) or isinstance(clause[0], (list, tuple))) and all(isinstance(c, (list, tuple)) for c in clause[1:])): return self.stringable(clause) if clause[0] in self.fields or clause[0] == 'rec_name': return True return False if not domain: return True if domain[0] in ('AND', 'OR'): domain = domain[1:] return all(stringable_(clause) for clause in domain) def string(self, domain): "Return string for the domain" def string_(clause): if not clause: return '' if (not isinstance(clause[0], basestring) or clause[0] in ('AND', 'OR')): return '(%s)' % self.string(clause) name, operator, value = clause[:3] if name.endswith('.rec_name'): name = name[:-9] if name not in self.fields: escaped = value.replace('%%', '__') if escaped.startswith('%') and escaped.endswith('%'): value = value[1:-1] return quote(value) field = self.fields[name] if len(clause) > 3: target = clause[3] else: target = None if 'ilike' in operator: escaped = value.replace('%%', '__') if escaped.startswith('%') and escaped.endswith('%'): value = value[1:-1] elif '%' not in escaped: if operator == 'ilike': operator = '=' else: operator = '!' value = value.replace('%%', '%') def_operator = default_operator(field) if def_operator == operator.strip(): operator = '' if value in OPERATORS: # As the value could be interpreted as an operator, # the default operator must be forced operator = '"" ' elif (def_operator in operator and ('not' in operator or '!' in operator)): operator = operator.rstrip(def_operator ).replace('not', '!').strip() if operator.endswith('in'): if operator == 'not in': operator = '!' else: operator = '' formatted_value = format_value(field, value, target, self.context) if (operator in OPERATORS and field['type'] in ('char', 'text', 'selection') and value == ''): formatted_value = '""' return '%s: %s%s' % (quote(field['string']), operator, formatted_value) if not domain: return '' if domain[0] in ('AND', 'OR'): nary = ' ' if domain[0] == 'AND' else ' or ' domain = domain[1:] else: nary = ' ' return nary.join(string_(clause) for clause in domain) def completion(self, input_): "Return completion for the input string" domain = self.parse(input_) closing = 0 for i in xrange(1, len(input_)): if input_[-i] not in (')', ' '): break if input_[-i] == ')': closing += 1 ending, deep_ending = ending_clause(domain) deep = deep_ending - closing if deep: pslice = slice(-deep) else: pslice = slice(None) if self.string(domain)[pslice] != input_: yield self.string(domain)[pslice] complete = None if ending is not None and closing == 0: for complete in self.complete(ending): yield self.string(rlist( replace_ending_clause(domain, complete)))[pslice] if input_: if input_[-1] != ' ': return if len(input_) >= 2 and input_[-2] == ':': return for field in self.strings.itervalues(): operator = default_operator(field) value = '' if 'ilike' in operator: value = likify(value) yield self.string(rlist(append_ending_clause(domain, (field['name'], operator, value), deep)))[pslice] def complete(self, clause): "Return all completion for the clause" if len(clause) == 1: name, = clause elif len(clause) == 3: name, operator, value = clause else: name, operator, value, target = clause if name.endswith('.rec_name'): name = name[:-9] value = target if name == 'rec_name': if operator == 'ilike': escaped = value.replace('%%', '__') if escaped.startswith('%') and escaped.endswith('%'): value = value[1:-1] elif '%' not in escaped: value = value.replace('%%', '%') operator = None name = value value = '' if not name: name = '' if (name.lower() not in self.strings and name not in self.fields): for field in self.strings.itervalues(): if field['string'].lower().startswith(name.lower()): operator = default_operator(field) value = '' if 'ilike' in operator: value = likify(value) yield (field['name'], operator, value) return if name in self.fields: field = self.fields[name] else: field = self.strings[name.lower()] if not operator: operator = default_operator(field) value = '' if 'ilike' in operator: value = likify(value) yield (field['name'], operator, value) else: for comp in complete_value(field, value): yield (field['name'], operator, comp) def group(self, tokens): "Group tokens by clause" def _group(parts): try: i = parts.index(':') except ValueError: for part in parts: yield (part,) raise StopIteration for j in range(i): name = ' '.join(parts[j:i]) if name.lower() in self.strings: if parts[:j]: for part in parts[:j]: yield (part,) else: yield (None,) name = (name,) # empty string is also the default operator if (i + 1 < len(parts) and parts[i + 1] in OPERATORS + ('',)): name += (parts[i + 1],) i += 1 else: name += (None,) lvalue = [] while i + 2 < len(parts): if parts[i + 2] == ';': lvalue.append(parts[i + 1]) i += 2 else: break for part in _group(parts[i + 1:]): if name: if lvalue: if part[0] is not None: lvalue.append(part[0]) yield name + (lvalue,) else: yield name + part name = None else: yield part if name: if lvalue: yield name + (lvalue,) else: yield name + (None,) break parts = [] for token in tokens: if isgenerator(token): for group in _group(parts): if group != (None,): yield group parts = [] yield self.group(token) else: parts.append(token) for group in _group(parts): if group != (None,): yield group def parse_clause(self, tokens): "Parse clause" for clause in tokens: if isgenerator(clause): yield self.parse_clause(clause) elif clause in ('OR', 'AND'): yield clause else: if len(clause) == 1: yield ('rec_name', 'ilike', likify(clause[0])) else: name, operator, value = clause field = self.strings[name.lower()] field_name = field['name'] target = None if field['type'] == 'reference': target, value = split_target_value(field, value) if target: field_name += '.rec_name' if not operator: operator = default_operator(field) if isinstance(value, list): if operator == '!': operator = 'not in' else: operator = 'in' if operator == '!': operator = negate_operator(default_operator(field)) if field['type'] in ('integer', 'float', 'numeric', 'datetime', 'date', 'time'): if value and '..' in value: lvalue, rvalue = value.split('..', 1) lvalue = convert_value(field, lvalue, self.context) rvalue = convert_value(field, rvalue, self.context) yield iter([ (field_name, '>=', lvalue), (field_name, '<=', rvalue), ]) continue if isinstance(value, list): value = [convert_value(field, v, self.context) for v in value] if field['type'] in ('many2one', 'one2many', 'many2many', 'one2one'): field_name += '.rec_name' else: value = convert_value(field, value, self.context) if 'like' in operator: value = likify(value) if target: yield (field_name, operator, value, target) else: yield field_name, operator, value def test_stringable(): dom = DomainParser({ 'name': { 'string': 'Name', 'type': 'char', }, }) valid = ('name', '=', 'Doe') invalid = ('surname', '=', 'John') assert dom.stringable([valid]) assert not dom.stringable([invalid]) assert dom.stringable(['AND', valid]) assert not dom.stringable(['AND', valid, invalid]) assert dom.stringable([[valid]]) assert not dom.stringable([[valid], [invalid]]) def test_string(): dom = DomainParser({ 'name': { 'string': 'Name', 'type': 'char', }, 'surname': { 'string': '(Sur)Name', 'type': 'char', }, 'date': { 'string': 'Date', 'type': 'date', }, 'selection': { 'string': 'Selection', 'type': 'selection', 'selection': [ ('male', 'Male'), ('female', 'Female'), ('', ''), ], }, 'reference': { 'string': 'Reference', 'type': 'reference', 'selection': [ ('spam', 'Spam'), ('ham', 'Ham'), ] }, 'many2one': { 'string': 'Many2One', 'name': 'many2one', 'type': 'many2one', }, }) assert dom.string([('name', '=', 'Doe')]) == 'Name: =Doe' assert dom.string([('name', '=', None)]) == 'Name: =' assert dom.string([('name', '=', '')]) == 'Name: =""' assert dom.string([('name', 'ilike', '%')]) == 'Name: ' assert dom.string([('name', 'ilike', '%Doe%')]) == 'Name: Doe' assert dom.string([('name', 'ilike', '%<%')]) == 'Name: "" "<"' assert dom.string([('name', 'ilike', 'Doe')]) == 'Name: =Doe' assert dom.string([('name', 'ilike', 'Doe%')]) == 'Name: Doe%' assert dom.string([('name', 'ilike', 'Doe%%')]) == 'Name: =Doe%' assert dom.string([('name', 'not ilike', '%Doe%')]) == 'Name: !Doe' assert dom.string([('name', 'in', ['John', 'Jane'])]) == 'Name: John;Jane' assert dom.string([('name', 'not in', ['John', 'Jane'])]) == \ 'Name: !John;Jane' assert dom.string([ ('name', 'ilike', '%Doe%'), ('name', 'ilike', '%Jane%')]) == 'Name: Doe Name: Jane' assert dom.string(['AND', ('name', 'ilike', '%Doe%'), ('name', 'ilike', '%Jane%')]) == 'Name: Doe Name: Jane' assert dom.string(['OR', ('name', 'ilike', '%Doe%'), ('name', 'ilike', '%Jane%')]) == 'Name: Doe or Name: Jane' assert dom.string([ ('name', 'ilike', '%Doe%'), ['OR', ('name', 'ilike', '%John%'), ('name', 'ilike', '%Jane%')]]) == \ 'Name: Doe (Name: John or Name: Jane)' assert dom.string([]) == '' assert dom.string([('surname', 'ilike', '%Doe%')]) == '"(Sur)Name": Doe' assert dom.string([('date', '>=', datetime.date(2012, 10, 24))]) == \ 'Date: >=10/24/2012' assert dom.string([('selection', '=', '')]) == 'Selection: ' assert dom.string([('selection', '=', None)]) == 'Selection: ' assert dom.string([('selection', '!=', '')]) == 'Selection: !""' assert dom.string([('selection', '=', 'male')]) == 'Selection: Male' assert dom.string([('selection', '!=', 'male')]) == 'Selection: !Male' assert dom.string([('reference', 'ilike', '%foo%')]) == \ 'Reference: foo' assert dom.string([('reference.rec_name', 'ilike', '%bar%', 'spam')]) == \ 'Reference: Spam,bar' assert dom.string([('reference', 'in', ['foo', 'bar'])]) == \ 'Reference: foo;bar' assert dom.string([('many2one', 'ilike', '%John%')]) == 'Many2One: John' assert dom.string([('many2one.rec_name', 'in', ['John', 'Jane'])]) == \ 'Many2One: John;Jane' def test_group(): dom = DomainParser({ 'name': { 'string': 'Name', }, 'firstname': { 'string': 'First Name', }, 'surname': { 'string': '(Sur)Name', }, }) assert rlist(dom.group(udlex(u'Name: Doe'))) == [('Name', None, 'Doe')] assert rlist(dom.group(udlex(u'"(Sur)Name": Doe'))) == [ ('(Sur)Name', None, 'Doe'), ] assert rlist(dom.group(udlex(u'Name: Doe Name: John'))) == [ ('Name', None, 'Doe'), ('Name', None, 'John')] assert rlist(dom.group(udlex(u'Name: Name: John'))) == [ ('Name', None, None), ('Name', None, 'John')] assert rlist(dom.group(udlex(u'First Name: John'))) == [ ('First Name', None, 'John'), ] assert rlist(dom.group(udlex(u'Name: Doe First Name: John'))) == [ ('Name', None, 'Doe'), ('First Name', None, 'John'), ] assert rlist(dom.group(udlex(u'First Name: John Name: Doe'))) == [ ('First Name', None, 'John'), ('Name', None, 'Doe'), ] assert rlist(dom.group(udlex(u'First Name: John First Name: Jane'))) == [ ('First Name', None, 'John'), ('First Name', None, 'Jane'), ] assert rlist(dom.group(udlex(u'Name: John Doe'))) == [ ('Name', None, 'John'), ('Doe',), ] assert rlist(dom.group(udlex(u'Name: "John Doe"'))) == [ ('Name', None, 'John Doe'), ] assert rlist(dom.group(udlex(u'Name: =Doe'))) == [('Name', '=', 'Doe')] assert rlist(dom.group(udlex(u'Name: =Doe Name: >John'))) == [ ('Name', '=', 'Doe'), ('Name', '>', 'John'), ] assert rlist(dom.group(udlex(u'First Name: =John First Name: =Jane'))) == [ ('First Name', '=', 'John'), ('First Name', '=', 'Jane'), ] assert rlist(dom.group(udlex(u'Name: John;Jane'))) == [ ('Name', None, ['John', 'Jane']) ] assert rlist(dom.group(udlex(u'Name: John;'))) == [ ('Name', None, ['John']) ] assert rlist(dom.group(udlex(u'Name: John;Jane Name: Doe'))) == [ ('Name', None, ['John', 'Jane']), ('Name', None, 'Doe'), ] assert rlist(dom.group(udlex(u'Name: John; Name: Doe'))) == [ ('Name', None, ['John']), ('Name', None, 'Doe'), ] assert rlist(dom.group(udlex(u'Name:'))) == [ ('Name', None, None), ] assert rlist(dom.group(udlex(u'Name: ='))) == [ ('Name', '=', None), ] assert rlist(dom.group(udlex(u'Name: =""'))) == [ ('Name', '=', ''), ] assert rlist(dom.group(udlex(u'Name: = ""'))) == [ ('Name', '=', ''), ] assert rlist(dom.group(udlex(u'Name: = Name: Doe'))) == [ ('Name', '=', None), ('Name', None, 'Doe'), ] assert rlist(dom.group(udlex(u'Name: \\"foo\\"'))) == [ ('Name', None, '"foo"'), ] assert rlist(dom.group(udlex(u'Name: "" <'))) == [ ('Name', '', '<'), ] def test_parse_clause(): dom = DomainParser({ 'name': { 'string': 'Name', 'name': 'name', 'type': 'char', }, 'integer': { 'string': 'Integer', 'name': 'integer', 'type': 'integer', }, 'selection': { 'string': 'Selection', 'name': 'selection', 'type': 'selection', 'selection': [ ('male', 'Male'), ('female', 'Female'), ], }, 'reference': { 'string': 'Reference', 'name': 'reference', 'type': 'reference', 'selection': [ ('spam', 'Spam'), ('ham', 'Ham'), ] }, 'many2one': { 'string': 'Many2One', 'name': 'many2one', 'type': 'many2one', }, }) assert rlist(dom.parse_clause([('John',)])) == [ ('rec_name', 'ilike', '%John%')] assert rlist(dom.parse_clause([('Name', None, None)])) == [ ('name', 'ilike', '%')] assert rlist(dom.parse_clause([('Name', '', None)])) == [ ('name', 'ilike', '%')] assert rlist(dom.parse_clause([('Name', '=', None)])) == [ ('name', '=', None)] assert rlist(dom.parse_clause([('Name', '=', '')])) == [ ('name', '=', '')] assert rlist(dom.parse_clause([('Name', None, 'Doe')])) == [ ('name', 'ilike', '%Doe%')] assert rlist(dom.parse_clause([('Name', '!', 'Doe')])) == [ ('name', 'not ilike', '%Doe%')] assert rlist(dom.parse_clause([('Name', None, ['John', 'Jane'])])) == [ ('name', 'in', ['John', 'Jane']), ] assert rlist(dom.parse_clause([('Name', '!', ['John', 'Jane'])])) == [ ('name', 'not in', ['John', 'Jane']), ] assert rlist(dom.parse_clause([('Selection', None, None)])) == [ ('selection', '=', None), ] assert rlist(dom.parse_clause([('Selection', None, '')])) == [ ('selection', '=', ''), ] assert rlist(dom.parse_clause([('Selection', None, ['Male', 'Female'])])) \ == [ ('selection', 'in', ['male', 'female']) ] assert rlist(dom.parse_clause([('Integer', None, None)])) == [ ('integer', '=', None), ] assert rlist(dom.parse_clause([('Integer', None, '3..5')])) == [[ ('integer', '>=', 3), ('integer', '<=', 5), ]] assert rlist(dom.parse_clause([('Reference', None, 'foo')])) == [ ('reference', 'ilike', '%foo%'), ] assert rlist(dom.parse_clause([('Reference', None, 'Spam')])) == [ ('reference', 'ilike', '%spam%'), ] assert rlist(dom.parse_clause([('Reference', None, 'Spam,bar')])) == [ ('reference.rec_name', 'ilike', '%bar%', 'spam'), ] assert rlist(dom.parse_clause([('Reference', None, ['foo', 'bar'])])) == [ ('reference', 'in', ['foo', 'bar']), ] assert rlist(dom.parse_clause(['OR', ('Name', None, 'John'), ('Name', None, 'Jane')])) == ['OR', ('name', 'ilike', '%John%'), ('name', 'ilike', '%Jane%'), ] assert rlist(dom.parse_clause([('Many2One', None, 'John')])) == [ ('many2one', 'ilike', '%John%'), ] assert rlist(dom.parse_clause([('Many2One', None, ['John', 'Jane'])])) == [ ('many2one.rec_name', 'in', ['John', 'Jane']), ] def test_completion(): dom = DomainParser({ 'name': { 'string': 'Name', 'name': 'name', 'type': 'char', }, }) assert list(dom.completion(u'Nam')) == ['Name: '] assert list(dom.completion(u'Name:')) == ['Name: '] assert list(dom.completion(u'Name: foo')) == [] assert list(dom.completion(u'Name: !=')) == [] assert list(dom.completion(u'Name: !=foo')) == [] assert list(dom.completion(u'')) == ['Name: '] assert list(dom.completion(u' ')) == ['', 'Name: '] tryton-4.6.5/tryton/common/placeholder_entry.py0000644000175000017500000000502313251060075021300 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk if hasattr(gtk.Entry, 'set_placeholder_text'): PlaceholderEntry = gtk.Entry else: class PlaceholderEntry(gtk.Entry): _placeholder = '' _default = True def __init__(self, *args, **kwargs): super(PlaceholderEntry, self).__init__(*args, **kwargs) style = self.get_style() self._text_color_normal = style.text[gtk.STATE_NORMAL] self._text_color_placeholder = style.text[gtk.STATE_INSENSITIVE] self.connect('focus-in-event', PlaceholderEntry._focus_in) self.connect('focus-out-event', PlaceholderEntry._focus_out) def _focus_in(self, event): if self._default: super(PlaceholderEntry, self).set_text('') self.modify_text(gtk.STATE_NORMAL, self._text_color_normal) self._default = False def _focus_out(self, event=None): if super(PlaceholderEntry, self).get_text() == '': super(PlaceholderEntry, self).set_text(self._placeholder) self.modify_text(gtk.STATE_NORMAL, self._text_color_placeholder) self._default = True else: self.modify_text(gtk.STATE_NORMAL, self._text_color_normal) self._default = False def set_placeholder_text(self, text): self._placeholder = text if not self.has_focus(): if self._default: super(PlaceholderEntry, self).set_text('') self._focus_out() def get_text(self): if self._default: return '' return super(PlaceholderEntry, self).get_text() def set_text(self, text): super(PlaceholderEntry, self).set_text(text) if not self.has_focus(): self._focus_out() if __name__ == '__main__': win = gtk.Window() win.set_title('PlaceholderEntry') def cb(window, event): gtk.main_quit() win.connect('delete-event', cb) vbox = gtk.VBox() win.add(vbox) entry = gtk.Entry() vbox.pack_start(entry) placeholder_entry = PlaceholderEntry() placeholder_entry.set_placeholder_text('Placeholder') # Set twice to check placeholder does not become text placeholder_entry.set_placeholder_text('Placeholder') vbox.pack_start(placeholder_entry) win.show_all() gtk.main() tryton-4.6.5/tryton/common/cellrenderertoggle.py0000644000175000017500000000212613251060075021446 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject class CellRendererToggle(gtk.CellRendererToggle): def set_sensitive(self, value): self.set_property('sensitive', value) def do_activate(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return if not event: if hasattr(gtk.gdk.Event, 'new'): event = gtk.gdk.Event.new(gtk.gdk.KEY_PRESS) else: event = gtk.gdk.Event(gtk.gdk.KEY_PRESS) return gtk.CellRendererToggle.do_activate(self, event, widget, path, background_area, cell_area, flags) def do_start_editing(self, event, widget, path, background_area, cell_area, flags): if not self.props.visible: return return gtk.CellRendererToggle.do_start_editing(self, event, widget, path, background_area, cell_area, flags) gobject.type_register(CellRendererToggle) tryton-4.6.5/tryton/common/cellrendererbutton.py0000644000175000017500000001350013251060075021476 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import pango gtk_version = getattr(gtk, 'get_major_version', lambda: 2)() class CellRendererButton(gtk.GenericCellRenderer): # TODO Add keyboard editing __gproperties__ = { "text": (gobject.TYPE_STRING, None, "Text", "Displayed text", gobject.PARAM_READWRITE), 'visible': (gobject.TYPE_INT, 'Visible', 'Visible', 0, 10, 0, gobject.PARAM_READWRITE), 'sensitive': (gobject.TYPE_INT, 'Sensitive', 'Sensitive', 0, 10, 0, gobject.PARAM_READWRITE), } __gsignals__ = { 'clicked': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), } def __init__(self, text=""): self.__gobject_init__() self.text = text self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE) self.clicking = False self.visible = True self.sensitive = True def do_set_property(self, pspec, value): setattr(self, pspec.name, value) def do_get_property(self, pspec): return getattr(self, pspec.name) if gtk_version == 2: def on_render(self, window, widget, background_area, cell_area, expose_area, flags): if not self.visible: return # Handle Pixmap window as pygtk failed if type(window) == gtk.gdk.Pixmap: return state = gtk.STATE_NORMAL shadow = gtk.SHADOW_OUT if self.clicking and flags & gtk.CELL_RENDERER_SELECTED: state = gtk.STATE_ACTIVE shadow = gtk.SHADOW_IN elif not self.sensitive: state = gtk.STATE_INSENSITIVE widget.style.paint_box(window, state, shadow, None, widget, "button", cell_area.x, cell_area.y, cell_area.width, cell_area.height) layout = widget.create_pango_layout('') layout.set_font_description(widget.style.font_desc) w, h = layout.get_size() x = cell_area.x y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2) window.draw_layout(widget.style.text_gc[0], x, y, layout) widget.style.paint_layout(window, state, True, expose_area, widget, "cellrendererbutton", x, y, layout) layout = widget.create_pango_layout(self.text) layout.set_font_description(widget.style.font_desc) layout.set_ellipsize(pango.ELLIPSIZE_END) w, h = layout.get_size() if cell_area.width < w / pango.SCALE: x = cell_area.x + 2 / pango.SCALE else: x = int(cell_area.x + (cell_area.width - w / pango.SCALE) / 2) y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2) layout.set_width((cell_area.width - 4) * pango.SCALE) layout.set_wrap(pango.WRAP_CHAR) widget.style.paint_layout(window, state, True, expose_area, widget, "cellrendererbutton", x, y, layout) else: def do_render(self, cr, widget, background_area, cell_area, flags): if not self.visible: return state = gtk.StateFlags.NORMAL if self.clicking and flags & gtk.CELL_RENDERER_SELECTED: state = gtk.StateFlags.ACTIVE elif not self.sensitive: state = gtk.StateFlags.INSENSITIVE context = widget.get_style_context() context.save() context.add_class('button') context.set_state(state) xpad, ypad = self.get_padding() x = cell_area.x + xpad y = cell_area.y + ypad w = cell_area.width - 2 * xpad h = cell_area.height - 2 * ypad gtk.render_background(context, cr, x, y, w, h) gtk.render_frame(context, cr, x, y, w, h) padding = context.get_padding(state) layout = widget.create_pango_layout(self.text) layout.set_width((w - padding.left - padding.right) * pango.SCALE) layout.set_ellipsize(pango.ELLIPSIZE_END) layout.set_wrap(pango.WRAP_CHAR) lw, lh = layout.get_size() # Can not use get_pixel_extents lw /= pango.SCALE lh /= pango.SCALE if w < lw: x = x + padding.left else: x = x + padding.left + 0.5 * ( w - padding.left - padding.right - lw) y = y + padding.top + 0.5 * (h - padding.top - padding.bottom - lh) gtk.render_layout(context, cr, x, y, layout) context.restore() def on_get_size(self, widget, cell_area=None): if cell_area is None: return (0, 0, 30, 18) else: return (cell_area.x, cell_area.y, cell_area.width, cell_area.height) do_get_size = on_get_size def on_start_editing(self, event, widget, path, background_area, cell_area, flags): if not self.visible or not self.sensitive: return if (event is None) or ((event.type == gtk.gdk.BUTTON_PRESS) or (event.type == gtk.gdk.KEY_PRESS and event.keyval == gtk.keysyms.space)): self.clicking = True widget.queue_draw() while gtk.events_pending(): gtk.main_iteration() self.emit("clicked", path) def timeout(self, widget): self.clicking = False widget.queue_draw() gobject.timeout_add(60, timeout, self, widget) do_start_editing = on_start_editing gobject.type_register(CellRendererButton) tryton-4.6.5/tryton/common/timedelta.py0000644000175000017500000001036513251060075017552 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from __future__ import division import datetime import gettext import locale import operator __all__ = ['format', 'parse'] _ = gettext.gettext DEFAULT_CONVERTER = { 's': 1, } DEFAULT_CONVERTER['m'] = DEFAULT_CONVERTER['s'] * 60 DEFAULT_CONVERTER['h'] = DEFAULT_CONVERTER['m'] * 60 DEFAULT_CONVERTER['d'] = DEFAULT_CONVERTER['h'] * 24 DEFAULT_CONVERTER['w'] = DEFAULT_CONVERTER['d'] * 7 DEFAULT_CONVERTER['M'] = DEFAULT_CONVERTER['d'] * 30 DEFAULT_CONVERTER['Y'] = DEFAULT_CONVERTER['d'] * 365 def _get_separators(): return { 'Y': _('Y'), 'M': _('M'), 'w': _('w'), 'd': _('d'), 'h': _('h'), 'm': _('m'), 's': _('s'), } def format(value, converter=None): 'Convert timedelta to text' if value is None: return '' if not converter: converter = DEFAULT_CONVERTER text = [] value = value.total_seconds() sign = '' if value < 0: sign = '-' value = abs(value) converter = sorted(converter.items(), key=operator.itemgetter(1), reverse=True) values = [] for k, v in converter: part = value // v value -= part * v values.append(part) for (k, _), v in zip(converter[:-3], values): if v: text.append(locale.format('%d', v, True) + _get_separators()[k]) if any(values[-3:]) or not text: time = '%02d:%02d' % tuple(values[-3:-1]) if values[-1] or value: time += ':%02d' % values[-1] text.append(time) text = sign + ' '.join(text) if value: if not any(values[-3:]): # Add space if no time text += ' ' text += ('%.6f' % value)[1:] return text def parse(text, converter=None): if not text: return if not converter: converter = DEFAULT_CONVERTER for separator in _get_separators().values(): text = text.replace(separator, separator + ' ') seconds = 0 for part in text.split(): if ':' in part: for t, v in zip(part.split(':'), [converter['h'], converter['m'], converter['s']]): try: seconds += abs(float(t)) * v except ValueError: pass else: for key, separator in _get_separators().items(): if part.endswith(separator): part = part[:-len(separator)] try: seconds += abs(int(part)) * converter[key] except ValueError: pass break else: try: seconds += abs(float(part)) except ValueError: pass if '-' in text: seconds *= -1 return datetime.timedelta(seconds=seconds) _tests = [ (None, ''), (datetime.timedelta(), '00:00'), (datetime.timedelta(days=3, hours=5, minutes=30), '3d 05:30'), (datetime.timedelta(weeks=48), '11M 6d'), (datetime.timedelta(weeks=50), '11M 2w 6d'), (datetime.timedelta(weeks=52), '12M 4d'), (datetime.timedelta(days=360), '12M'), (datetime.timedelta(days=364), '12M 4d'), (datetime.timedelta(days=365), '1Y'), (datetime.timedelta(days=366), '1Y 1d'), (datetime.timedelta(hours=2, minutes=5, seconds=10), '02:05:10'), (datetime.timedelta(minutes=15, microseconds=42), '00:15:00.000042'), (datetime.timedelta(days=1, microseconds=42), '1d .000042'), (datetime.timedelta(seconds=-1), '-00:00:01'), (datetime.timedelta(days=-1, hours=-5, minutes=-30), '-1d 05:30'), ] def test_format(): for timedelta, text in _tests: assert format(timedelta) == text _tests_parse = [ (datetime.timedelta(), ' '), (datetime.timedelta(), 'foo'), (datetime.timedelta(), '1.5d'), (datetime.timedelta(days=-2), '1d -1d'), (datetime.timedelta(hours=1, minutes=5, seconds=10), '1:5:10:42'), (datetime.timedelta(hours=2), '1: 1:'), (datetime.timedelta(hours=.25), ':15'), ] def test_parse(): for timedelta, text, in _tests + _tests_parse: assert parse(text) == timedelta tryton-4.6.5/tryton/common/cellrendererbinary.py0000644000175000017500000002376113255571102021463 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import gtk import gobject import pango gtk_version = getattr(gtk, 'get_major_version', lambda: 2)() BUTTON_BORDER = 2 BUTTON_SPACING = 1 class CellRendererBinary(gtk.GenericCellRenderer): __gproperties__ = { 'visible': (gobject.TYPE_BOOLEAN, 'Visible', 'Visible', True, gobject.PARAM_READWRITE), 'editable': (gobject.TYPE_BOOLEAN, 'Editable', 'Editable', False, gobject.PARAM_READWRITE), 'size': (gobject.TYPE_STRING, 'Size', 'Size', '', gobject.PARAM_READWRITE), } __gsignals__ = { 'select': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 'open': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 'save': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), 'clear': (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), } def __init__(self, use_filename): self.__gobject_init__() self.visible = True self.editable = False self.set_property('mode', gtk.CELL_RENDERER_MODE_EDITABLE) self.use_filename = use_filename self.clicking = '' self.images = {} widget = gtk.Button() for key, stock_name in ( ('select', 'tryton-find'), ('open', 'tryton-open'), ('save', 'tryton-save-as'), ('clear', 'tryton-clear')): # hack to get gtk.gdk.Image from stock icon img_sensitive = widget.render_icon(stock_name, gtk.ICON_SIZE_SMALL_TOOLBAR) img_insensitive = img_sensitive.copy() img_sensitive.saturate_and_pixelate(img_insensitive, 0, False) width = img_sensitive.get_width() height = img_sensitive.get_height() self.images[key] = (img_sensitive, img_insensitive, width, height) @property def buttons(self): buttons = [] if self.size: if self.use_filename: buttons.append('open') buttons.append('save') buttons.append('clear') else: buttons.append('select') return buttons def do_set_property(self, pspec, value): setattr(self, pspec.name, value) def do_get_property(self, pspec): return getattr(self, pspec.name) def button_width(self): return (sum(width for n, (_, _, width, _) in self.images.iteritems() if n in self.buttons) + (2 * (BUTTON_BORDER + BUTTON_SPACING) * len(self.buttons)) - 2 * BUTTON_SPACING) def on_get_size(self, widget, cell_area=None): if cell_area is None: return (0, 0, 30, 18) else: return (cell_area.x, cell_area.y, cell_area.width, cell_area.height) do_get_size = on_get_size def on_start_editing(self, event, widget, path, background_area, cell_area, flags): if event is None: return button_width = self.button_width() for index, button_name in enumerate(self.buttons): _, _, pxbf_width, _ = self.images[button_name] if index == 0 and button_name == 'open': x_offset = 0 else: x_offset = (cell_area.width - button_width + (pxbf_width + (2 * BUTTON_BORDER) + BUTTON_SPACING) * index) x_button = cell_area.x + x_offset if x_button < event.x < (x_button + pxbf_width + (2 * BUTTON_BORDER)): break else: button_name = None if not self.visible or not button_name: return if not self.editable and button_name in ('select', 'clear'): return if not self.size and button_name == 'save': return if event.type == gtk.gdk.BUTTON_PRESS: self.clicking = button_name self.emit(button_name, path) def timeout(self, widget): self.clicking = '' widget.queue_draw() gobject.timeout_add(60, timeout, self, widget) do_start_editing = on_start_editing if gtk_version == 2: def on_render(self, window, widget, background_area, cell_area, expose_area, flags): if not self.visible: return # Handle Pixmap window as pygtk failed if type(window) == gtk.gdk.Pixmap: return button_width = self.button_width() # display size layout = widget.create_pango_layout(self.size) layout.set_font_description(widget.style.font_desc) w, h = layout.get_size() x = int(cell_area.x + cell_area.width - button_width - w / pango.SCALE - BUTTON_SPACING) y = int(cell_area.y + (cell_area.height - h / pango.SCALE) / 2) layout.set_width(((cell_area.width / 2) - 2) * pango.SCALE) state = gtk.STATE_NORMAL if flags & gtk.CELL_RENDERER_SELECTED: state = gtk.STATE_ACTIVE if x >= cell_area.x: widget.style.paint_layout(window, state, True, expose_area, widget, "cellrendererbinary", x, y, layout) # display buttons for index, button_name in enumerate(self.buttons): state = gtk.STATE_NORMAL shadow = gtk.SHADOW_OUT pxbf_sens, pxbf_insens, pxbf_width, pxbf_height = \ self.images[button_name] if (self.clicking == button_name and flags & gtk.CELL_RENDERER_SELECTED): state = gtk.STATE_ACTIVE shadow = gtk.SHADOW_IN if (not self.editable and button_name in ('select', 'clear') or not self.size and button_name in ('open', 'save')): state = gtk.STATE_INSENSITIVE pixbuf = pxbf_insens else: pixbuf = pxbf_sens if index == 0 and button_name == 'open': x_offset = 0 else: x_offset = (cell_area.width - button_width + (pxbf_width + (2 * BUTTON_BORDER) + BUTTON_SPACING) * index) if x_offset < 0: continue widget.style.paint_box(window, state, shadow, None, widget, "button", cell_area.x + x_offset, cell_area.y, pxbf_width + (2 * BUTTON_BORDER), cell_area.height) window.draw_pixbuf(widget.style.black_gc, pixbuf, 0, 0, cell_area.x + x_offset + BUTTON_BORDER, cell_area.y + (cell_area.height - pxbf_height) / 2) else: def do_render(self, cr, widget, background_area, cell_area, flags): if not self.visible: return button_width = self.button_width() state = self.get_state(widget, flags) context = widget.get_style_context() context.save() context.add_class('button') xpad, ypad = self.get_padding() x = cell_area.x + xpad y = cell_area.y + ypad w = cell_area.width - 2 * xpad h = cell_area.height - 2 * ypad padding = context.get_padding(state) layout = widget.create_pango_layout(self.size) lwidth = w - button_width - padding.left - padding.right if lwidth < 0: lwidth = 0 layout.set_width(lwidth * pango.SCALE) layout.set_ellipsize(pango.ELLIPSIZE_END) layout.set_wrap(pango.WRAP_CHAR) layout.set_alignment(pango.ALIGN_RIGHT) if lwidth > 0: lw, lh = layout.get_size() # Can not use get_pixel_extents lw /= pango.SCALE lh /= pango.SCALE lx = x + padding.left if self.buttons and self.buttons[0] == 'open': pxbf_width = self.images['open'][2] lx += pxbf_width + 2 * BUTTON_BORDER + BUTTON_SPACING ly = y + padding.top + 0.5 * ( h - padding.top - padding.bottom - lh) gtk.render_layout(context, cr, lx, ly, layout) for index, button_name in enumerate(self.buttons): pxbf_sens, pxbf_insens, pxbf_width, pxbf_height = \ self.images[button_name] state = gtk.StateFlags.NORMAL if (self.clicking == button_name and flags & gtk.CELL_RENDERER_SELECTED): state = gtk.StateFlags.ACTIVE if (not self.editable and button_name in {'select', 'clear'} or not self.size and button_name in {'open', 'save'}): state = gtk.StateFlags.INSENSITIVE pixbuf = pxbf_insens else: pixbuf = pxbf_sens if index == 0 and button_name == 'open': x_offset = 0 else: x_offset = (w - button_width + (pxbf_width + (2 * BUTTON_BORDER) + BUTTON_SPACING) * index) if x_offset < 0: continue bx = cell_area.x + x_offset by = cell_area.y bw = pxbf_width + (2 * BUTTON_BORDER) gtk.render_background(context, cr, bx, by, bw, h) gtk.render_frame(context, cr, bx, by, bw, h) gtk.gdk.cairo_set_source_pixbuf( cr, pixbuf, bx + BUTTON_BORDER, by + (h - pxbf_height) / 2) cr.paint() context.restore() gobject.type_register(CellRendererBinary) tryton-4.6.5/tryton/translate.py0000644000175000017500000001445513251060075016313 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Translate" import os import locale import gettext import logging import gtk import sys from tryton.config import CURRENT_DIR _ = gettext.gettext _LOCALE2WIN32 = { 'af_ZA': 'Afrikaans_South Africa', 'ar_AE': 'Arabic_UAE', 'ar_BH': 'Arabic_Bahrain', 'ar_DZ': 'Arabic_Algeria', 'ar_EG': 'Arabic_Egypt', 'ar_IQ': 'Arabic_Iraq', 'ar_JO': 'Arabic_Jordan', 'ar_KW': 'Arabic_Kuwait', 'ar_LB': 'Arabic_Lebanon', 'ar_LY': 'Arabic_Libya', 'ar_MA': 'Arabic_Morocco', 'ar_OM': 'Arabic_Oman', 'ar_QA': 'Arabic_Qatar', 'ar_SA': 'Arabic_Saudi_Arabia', 'ar_SY': 'Arabic_Syria', 'ar_TN': 'Arabic_Tunisia', 'ar_YE': 'Arabic_Yemen', 'az-Cyrl-AZ': 'Azeri_Cyrillic', 'az-Latn-AZ': 'Azeri_Latin', 'be_BY': 'Belarusian_Belarus', 'bg_BG': 'Bulgarian_Bulgaria', 'bs_BA': 'Serbian (Latin)', 'ca_ES': 'Catalan_Spain', 'cs_CZ': 'Czech_Czech Republic', 'da_DK': 'Danish_Denmark', 'de_AT': 'German_Austrian', 'de_CH': 'German_Swiss', 'de_DE': 'German_Germany', 'de_LI': 'German_Liechtenstein', 'de_LU': 'German_Luxembourg', 'el_GR': 'Greek_Greece', 'en_AU': 'English_Australian', 'en_BZ': 'English_Belize', 'en_CA': 'English_Canadian', 'en_IE': 'English_Irish', 'en_JM': 'English_Jamaica', 'en_TT': 'English_Trinidad', 'en_US': 'English_USA', 'en_ZW': 'English_Zimbabwe', 'es_AR': 'Spanish_Argentina', 'es_BO': 'Spanish_Bolivia', 'es_CL': 'Spanish_Chile', 'es_CO': 'Spanish_Colombia', 'es_CR': 'Spanish_Costa_Rica', 'es_DO': 'Spanish_Dominican_Republic', 'es_EC': 'Spanish_Ecuador', 'es_ES': 'Spanish_Spain', 'es_ES_tradnl': 'Spanish_Traditional_Sort', 'es_GT': 'Spanish_Guatemala', 'es_HN': 'Spanish_Honduras', 'es_MX': 'Spanish_Mexican', 'es_NI': 'Spanish_Nicaragua', 'es_PA': 'Spanish_Panama', 'es_PE': 'Spanish_Peru', 'es_PR': 'Spanish_Puerto_Rico', 'es_PY': 'Spanish_Paraguay', 'es_SV': 'Spanish_El_Salvador', 'es_UY': 'Spanish_Uruguay', 'es_VE': 'Spanish_Venezuela', 'et_EE': 'Estonian_Estonia', 'eu_ES': 'Basque_Spain', 'fa_IR': 'Farsi_Iran', 'fi_FI': 'Finnish_Finland', 'fr_BE': 'French_Belgian', 'fr_CA': 'French_Canadian', 'fr_CH': 'French_Swiss', 'fr_FR': 'French_France', 'fr_LU': 'French_Luxembourg', 'fr_MC': 'French_Monaco', 'ga': 'Scottish Gaelic', 'gl_ES': 'Galician_Spain', 'gu': 'Gujarati_India', 'he_IL': 'Hebrew', 'he_IL': 'Hebrew_Israel', 'hi_IN': 'Hindi', 'hi_IN': 'Hindi', 'hr_HR': 'Croatian', 'hu_HU': 'Hungarian', 'hu': 'Hungarian_Hungary', 'hy_AM': 'Armenian', 'id_ID': 'Indonesian_indonesia', 'is_IS': 'Icelandic_Iceland', 'it_CH': 'Italian_Swiss', 'it_IT': 'Italian_Italy', 'ja_JP': 'Japanese_Japan', 'ka_GE': 'Georgian_Georgia', 'kk_KZ': 'Kazakh', 'km_KH': 'Khmer', 'kn_IN': 'Kannada', 'ko_IN': 'Konkani', 'ko_KR': 'Korean_Korea', 'lo_LA': 'Lao_Laos', 'lt_LT': 'Lithuanian_Lithuania', 'lv_LV': 'Latvian_Latvia', 'mi_NZ': 'Maori', 'mi_NZ': 'Maori', 'mi_NZ': 'Maori', 'mk_MK': 'Macedonian', 'ml_IN': 'Malayalam_India', 'mn': 'Cyrillic_Mongolian', 'mr_IN': 'Marathi', 'ms_BN': 'Malay_Brunei_Darussalam', 'ms_MY': 'Malay_Malaysia', 'nb_NO': 'Norwegian_Bokmal', 'nl_BE': 'Dutch_Belgian', 'nl_NL': 'Dutch_Netherlands', 'nn_NO': 'Norwegian-Nynorsk_Norway', 'ph_PH': 'Filipino_Philippines', 'pl_PL': 'Polish_Poland', 'pt_BR': 'Portuguese_Brazil', 'pt_PT': 'Portuguese_Portugal', 'ro_RO': 'Romanian_Romania', 'ru_RU': 'Russian_Russia', 'sa_IN': 'Sanskrit', 'sk_SK': 'Slovak_Slovakia', 'sl_SI': 'Slovenian_Slovenia', 'sq_AL': 'Albanian_Albania', 'sr_CS': 'Serbian (Cyrillic)_Serbia and Montenegro', 'sv_FI': 'Swedish_Finland', 'sv_SE': 'Swedish_Sweden', 'sw_KE': 'Swahili', 'ta_IN': 'Tamil', 'th_TH': 'Thai_Thailand', 'tr_IN': 'Urdu', 'tr_TR': 'Turkish_Turkey', 'tt_RU': 'Tatar', 'uk_UA': 'Ukrainian_Ukraine', 'uz-Cyrl_UZ': 'Uzbek_Cyrillic', 'uz-Latn_UZ': 'Uzbek_Latin', 'vi_VN': 'Vietnamese_Viet Nam', 'zh_CN': 'Chinese_PRC', 'zh_HK': 'Chinese_Hong_Kong', 'zh_MO': 'Chinese_Macau', 'zh_SG': 'Chinese_Singapore', 'zh_TW': 'Chinese_Taiwan', } def setlang(lang=None, locale_dict=None): "Set language" locale_dir = os.path.join(CURRENT_DIR, 'data/locale') if not os.path.isdir(locale_dir): # do not import when frozen import pkg_resources locale_dir = pkg_resources.resource_filename( 'tryton', 'data/locale') if lang: encoding = locale.getdefaultlocale()[1] if not encoding: encoding = 'UTF-8' if encoding.lower() in ('utf', 'utf8'): encoding = 'UTF-8' if encoding == 'cp1252': encoding = '1252' try: lang2 = locale.normalize(lang).split('.')[0] if os.name == 'nt': lang2 = _LOCALE2WIN32.get(lang2, lang2) elif sys.platform == 'darwin': encoding = 'UTF-8' # ensure environment variable are str lang, lang2, encoding = str(lang), str(lang2), str(encoding) os.environ['LANGUAGE'] = lang os.environ['LC_ALL'] = lang2 + '.' + encoding os.environ['LC_MESSAGES'] = lang2 + '.' + encoding os.environ['LANG'] = lang + '.' + encoding locale.setlocale(locale.LC_ALL, lang2 + '.' + encoding) except locale.Error: logging.getLogger(__name__).info( _('Unable to set locale %s') % lang2 + '.' + encoding) if os.path.isdir(locale_dir): gettext.bindtextdomain('tryton', locale_dir) gettext.textdomain('tryton') if locale_dict: conv = locale.localeconv() for field in locale_dict.keys(): if field == 'date': continue conv[field] = locale_dict[field] locale.localeconv = lambda: conv def set_language_direction(direction): if direction == 'rtl': gtk.widget_set_default_direction(gtk.TEXT_DIR_RTL) else: gtk.widget_set_default_direction(gtk.TEXT_DIR_LTR) tryton-4.6.5/tryton/config.py0000644000175000017500000001457013255571102015563 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. "Options" import ConfigParser import optparse import os import gettext import logging import sys import locale import gtk from tryton.exceptions import TrytonError from tryton import __version__ _ = gettext.gettext def get_config_dir(): if os.name == 'nt': appdata = os.environ['APPDATA'] if not isinstance(appdata, unicode): appdata = unicode(appdata, sys.getfilesystemencoding()) return os.path.join(appdata, '.config', 'tryton', __version__.rsplit('.', 1)[0]) return os.path.join(os.environ['HOME'], '.config', 'tryton', __version__.rsplit('.', 1)[0]) if not os.path.isdir(get_config_dir()): os.makedirs(get_config_dir(), 0700) class ConfigManager(object): "Config manager" def __init__(self): short_version = '.'.join(__version__.split('.', 2)[:2]) demo_server = 'demo%s.tryton.org' % short_version demo_database = 'demo%s' % short_version self.defaults = { 'login.profile': demo_server, 'login.login': 'demo', 'login.host': demo_server, 'login.db': demo_database, 'login.expanded': False, 'client.title': 'Tryton', 'client.default_width': 900, 'client.default_height': 750, 'client.modepda': False, 'client.toolbar': 'default', 'client.maximize': False, 'client.save_width_height': True, 'client.save_tree_state': True, 'client.fast_tabbing': True, 'client.spellcheck': False, 'client.lang': locale.getdefaultlocale()[0], 'client.language_direction': 'ltr', 'client.email': '', 'client.can_change_accelerators': False, 'client.limit': 1000, 'roundup.url': 'http://bugs.tryton.org/', 'roundup.xmlrpc': 'roundup-xmlrpc.tryton.org', 'menu.pane': 200, 'menu.expanded': True, } self.config = {} self.options = {} self.arguments = [] def parse(self): parser = optparse.OptionParser(version=("Tryton %s" % __version__), usage="Usage: %prog [options] [url]") parser.add_option("-c", "--config", dest="config", help=_("specify alternate config file")) parser.add_option("-d", "--dev", action="store_true", default=False, dest="dev", help=_("development mode")) parser.add_option("-v", "--verbose", action="store_true", default=False, dest="verbose", help=_("logging everything at INFO level")) parser.add_option("-l", "--log-level", dest="log_level", help=_("specify the log level: " "DEBUG, INFO, WARNING, ERROR, CRITICAL")) parser.add_option("-u", "--user", dest="login", help=_("specify the login user")) parser.add_option("-s", "--server", dest="host", help=_("specify the server hostname:port")) opt, self.arguments = parser.parse_args() if len(self.arguments) > 1: raise TrytonError(_('Too much arguments')) if opt.config and not os.path.isfile(opt.config): raise TrytonError(_('File "%s" not found') % (opt.config,)) self.rcfile = opt.config or os.path.join( get_config_dir(), 'tryton.conf') self.load() self.options['dev'] = opt.dev logging.basicConfig() loglevels = { 'DEBUG': logging.DEBUG, 'INFO': logging.INFO, 'WARNING': logging.WARNING, 'ERROR': logging.ERROR, 'CRITICAL': logging.CRITICAL, } if not opt.log_level: if opt.verbose: opt.log_level = 'INFO' else: opt.log_level = 'ERROR' logging.getLogger().setLevel(loglevels[opt.log_level.upper()]) for arg in ['login', 'host']: if getattr(opt, arg): self.options['login.' + arg] = getattr(opt, arg) def save(self): try: configparser = ConfigParser.ConfigParser() for entry in self.config.keys(): if not len(entry.split('.')) == 2: continue section, name = entry.split('.') if not configparser.has_section(section): configparser.add_section(section) configparser.set(section, name, self.config[entry]) configparser.write(open(self.rcfile, 'wb')) except IOError: logging.getLogger(__name__).warn( _('Unable to write config file %s.') % (self.rcfile,)) return False return True def load(self): configparser = ConfigParser.ConfigParser() configparser.read([self.rcfile]) for section in configparser.sections(): for (name, value) in configparser.items(section): if value.lower() == 'true': value = True elif value.lower() == 'false': value = False if section == 'client' and name == 'limit': # First convert to float to be backward compatible with old # configuration value = int(float(value)) self.config[section + '.' + name] = value return True def __setitem__(self, key, value, config=True): self.options[key] = value if config: self.config[key] = value def __getitem__(self, key): return self.options.get(key, self.config.get(key, self.defaults.get(key))) CONFIG = ConfigManager() CURRENT_DIR = os.path.dirname(__file__) if hasattr(sys, 'frozen'): CURRENT_DIR = os.path.dirname(sys.executable) if not isinstance(CURRENT_DIR, unicode): CURRENT_DIR = unicode(CURRENT_DIR, sys.getfilesystemencoding()) PIXMAPS_DIR = os.path.join(CURRENT_DIR, 'data', 'pixmaps', 'tryton') if not os.path.isdir(PIXMAPS_DIR): # do not import when frozen import pkg_resources PIXMAPS_DIR = pkg_resources.resource_filename( 'tryton', 'data/pixmaps/tryton') TRYTON_ICON = gtk.gdk.pixbuf_new_from_file( os.path.join(PIXMAPS_DIR, 'tryton-icon.png').encode('utf-8')) tryton-4.6.5/tryton/pyson.py0000644000175000017500000004575013251060075015470 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import json import datetime from dateutil.relativedelta import relativedelta from functools import reduce, wraps def reduced_type(types): types = types.copy() for k, r in [(long, int), (str, basestring), (unicode, basestring)]: if k in types: types.remove(k) types.add(r) return types def reduce_type(func): @wraps(func) def wrapper(*args, **kwargs): return reduced_type(func(*args, **kwargs)) return wrapper class PYSON(object): def pyson(self): raise NotImplementedError def types(self): raise NotImplementedError @staticmethod def eval(dct, context): raise NotImplementedError def __invert__(self): if self.types() != set([bool]): return Not(Bool(self)) else: return Not(self) def __and__(self, other): if (isinstance(other, PYSON) and other.types() != set([bool])): other = Bool(other) if (isinstance(self, And) and not isinstance(self, Or)): self._statements.append(other) return self if self.types() != set([bool]): return And(Bool(self), other) else: return And(self, other) __rand__ = __and__ def __or__(self, other): if (isinstance(other, PYSON) and other.types() != set([bool])): other = Bool(other) if isinstance(self, Or): self._statements.append(other) return self if self.types() != set([bool]): return Or(Bool(self), other) else: return Or(self, other) __ror__ = __or__ def __eq__(self, other): return Equal(self, other) def __ne__(self, other): return Not(Equal(self, other)) def __gt__(self, other): return Greater(self, other) def __ge__(self, other): return Greater(self, other, True) def __lt__(self, other): return Less(self, other) def __le__(self, other): return Less(self, other, True) def get(self, k, d=''): return Get(self, k, d) def in_(self, obj): return In(self, obj) def contains(self, k): return In(k, self) def __repr__(self): klass = self.__class__.__name__ return '%s(%s)' % (klass, ', '.join(map(repr, self.__repr_params__))) @property def __repr_params__(self): return NotImplementedError class PYSONEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, PYSON): return obj.pyson() elif isinstance(obj, datetime.date): if isinstance(obj, datetime.datetime): return DateTime(obj.year, obj.month, obj.day, obj.hour, obj.minute, obj.second, obj.microsecond ).pyson() else: return Date(obj.year, obj.month, obj.day).pyson() return super(PYSONEncoder, self).default(obj) class PYSONDecoder(json.JSONDecoder): def __init__(self, context=None, noeval=False): self.__context = context or {} self.noeval = noeval super(PYSONDecoder, self).__init__(object_hook=self._object_hook) def _object_hook(self, dct): if '__class__' in dct: klass = CONTEXT.get(dct['__class__']) if klass: if not self.noeval: return klass.eval(dct, self.__context) else: dct = dct.copy() del dct['__class__'] return klass(**dct) return dct class Eval(PYSON): def __init__(self, v, d=''): super(Eval, self).__init__() self._value = v self._default = d @property def __repr_params__(self): return self._value, self._default def pyson(self): return { '__class__': 'Eval', 'v': self._value, 'd': self._default, } @reduce_type def types(self): if isinstance(self._default, PYSON): return self._default.types() else: return set([type(self._default)]) @staticmethod def eval(dct, context): return context.get(dct['v'], dct['d']) class Not(PYSON): def __init__(self, v): super(Not, self).__init__() if isinstance(v, PYSON): assert v.types() == set([bool]), 'value must be boolean' else: assert isinstance(v, bool), 'value must be boolean' self._value = v @property def __repr_params__(self): return (self._value,) def pyson(self): return { '__class__': 'Not', 'v': self._value, } def types(self): return set([bool]) @staticmethod def eval(dct, context): return not dct['v'] class Bool(PYSON): def __init__(self, v): super(Bool, self).__init__() self._value = v @property def __repr_params__(self): return (self._value,) def pyson(self): return { '__class__': 'Bool', 'v': self._value, } def types(self): return set([bool]) @staticmethod def eval(dct, context): return bool(dct['v']) class And(PYSON): def __init__(self, *statements, **kwargs): super(And, self).__init__() statements = list(statements) + kwargs.get('s', []) for statement in statements: if isinstance(statement, PYSON): assert statement.types() == set([bool]), \ 'statement must be boolean' else: assert isinstance(statement, bool), \ 'statement must be boolean' assert len(statements) >= 2, 'must have at least 2 statements' self._statements = statements @property def __repr_params__(self): return tuple(self._statements) def pyson(self): return { '__class__': 'And', 's': self._statements, } def types(self): return set([bool]) @staticmethod def eval(dct, context): return bool(reduce(lambda x, y: x and y, dct['s'])) class Or(And): def pyson(self): res = super(Or, self).pyson() res['__class__'] = 'Or' return res @staticmethod def eval(dct, context): return bool(reduce(lambda x, y: x or y, dct['s'])) class Equal(PYSON): def __init__(self, s1, s2): statement1, statement2 = s1, s2 super(Equal, self).__init__() if isinstance(statement1, PYSON): types1 = statement1.types() else: types1 = reduced_type(set([type(s1)])) if isinstance(statement2, PYSON): types2 = statement2.types() else: types2 = reduced_type(set([type(s2)])) assert types1 == types2, 'statements must have the same type' self._statement1 = statement1 self._statement2 = statement2 @property def __repr_params__(self): return (self._statement1, self._statement2) def pyson(self): return { '__class__': 'Equal', 's1': self._statement1, 's2': self._statement2, } def types(self): return set([bool]) @staticmethod def eval(dct, context): return dct['s1'] == dct['s2'] class Greater(PYSON): def __init__(self, s1, s2, e=False): statement1, statement2, equal = s1, s2, e super(Greater, self).__init__() for i in (statement1, statement2): if isinstance(i, PYSON): assert i.types().issubset({int, long, float, type(None)}), \ 'statement must be an integer or a float' else: assert isinstance(i, (int, long, float, type(None))), \ 'statement must be an integer or a float' if isinstance(equal, PYSON): assert equal.types() == set([bool]) else: assert isinstance(equal, bool) self._statement1 = statement1 self._statement2 = statement2 self._equal = equal @property def __repr_params__(self): return (self._statement1, self._statement2, self._equal) def pyson(self): return { '__class__': 'Greater', 's1': self._statement1, 's2': self._statement2, 'e': self._equal, } def types(self): return set([bool]) @staticmethod def _convert(dct): for i in ('s1', 's2'): if dct[i] is None: dct[i] = 0.0 if not isinstance(dct[i], (int, long, float)): dct = dct.copy() dct[i] = float(dct[i]) return dct @staticmethod def eval(dct, context): dct = Greater._convert(dct) if dct['e']: return dct['s1'] >= dct['s2'] else: return dct['s1'] > dct['s2'] class Less(Greater): def pyson(self): res = super(Less, self).pyson() res['__class__'] = 'Less' return res @staticmethod def eval(dct, context): dct = Less._convert(dct) if dct['e']: return dct['s1'] <= dct['s2'] else: return dct['s1'] < dct['s2'] class If(PYSON): def __init__(self, c, t, e=None): condition, then_statement, else_statement = c, t, e super(If, self).__init__() if isinstance(condition, PYSON): assert condition.types() == set([bool]), \ 'condition must be boolean' else: assert isinstance(condition, bool), 'condition must be boolean' if isinstance(then_statement, PYSON): then_types = then_statement.types() else: then_types = reduced_type(set([type(then_statement)])) if isinstance(else_statement, PYSON): else_types = else_statement.types() else: else_types = reduced_type(set([type(else_statement)])) assert then_types == else_types, \ 'then and else statements must be the same type' self._condition = condition self._then_statement = then_statement self._else_statement = else_statement @property def __repr_params__(self): return (self._condition, self._then_statement, self._else_statement) def pyson(self): return { '__class__': 'If', 'c': self._condition, 't': self._then_statement, 'e': self._else_statement, } @reduce_type def types(self): if isinstance(self._then_statement, PYSON): return self._then_statement.types() else: return set([type(self._then_statement)]) @staticmethod def eval(dct, context): if dct['c']: return dct['t'] else: return dct['e'] class Get(PYSON): def __init__(self, v, k, d=''): obj, key, default = v, k, d super(Get, self).__init__() if isinstance(obj, PYSON): assert obj.types() == set([dict]), 'obj must be a dict' else: assert isinstance(obj, dict), 'obj must be a dict' self._obj = obj if isinstance(key, PYSON): assert key.types() == set([basestring]), 'key must be a string' else: assert isinstance(key, basestring), 'key must be a string' self._key = key self._default = default @property def __repr_params__(self): return (self._obj, self._key, self._default) def pyson(self): return { '__class__': 'Get', 'v': self._obj, 'k': self._key, 'd': self._default, } @reduce_type def types(self): if isinstance(self._default, PYSON): return self._default.types() else: return set([type(self._default)]) @staticmethod def eval(dct, context): return dct['v'].get(dct['k'], dct['d']) class In(PYSON): def __init__(self, k, v): key, obj = k, v super(In, self).__init__() if isinstance(key, PYSON): assert key.types().issubset(set([basestring, int])), \ 'key must be a string or an integer or a long' else: assert isinstance(key, (basestring, int, long)), \ 'key must be a string or an integer or a long' if isinstance(obj, PYSON): assert obj.types().issubset(set([dict, list])), \ 'obj must be a dict or a list' if obj.types() == set([dict]): assert isinstance(key, basestring), 'key must be a string' else: assert isinstance(obj, (dict, list)) if isinstance(obj, dict): assert isinstance(key, basestring), 'key must be a string' self._key = key self._obj = obj @property def __repr_params__(self): return (self._key, self._obj) def pyson(self): return { '__class__': 'In', 'k': self._key, 'v': self._obj, } def types(self): return set([bool]) @staticmethod def eval(dct, context): return dct['k'] in dct['v'] class Date(PYSON): def __init__(self, year=None, month=None, day=None, delta_years=0, delta_months=0, delta_days=0, **kwargs): year = kwargs.get('y', year) month = kwargs.get('M', month) day = kwargs.get('d', day) delta_years = kwargs.get('dy', delta_years) delta_months = kwargs.get('dM', delta_months) delta_days = kwargs.get('dd', delta_days) super(Date, self).__init__() for i in (year, month, day, delta_years, delta_months, delta_days): if isinstance(i, PYSON): assert i.types().issubset(set([int, long, type(None)])), \ '%s must be an integer or None' % (i,) else: assert isinstance(i, (int, long, type(None))), \ '%s must be an integer or None' % (i,) self._year = year self._month = month self._day = day self._delta_years = delta_years self._delta_months = delta_months self._delta_days = delta_days @property def __repr_params__(self): return (self._year, self._month, self._day, self._delta_years, self._delta_months, self._delta_days) def pyson(self): return { '__class__': 'Date', 'y': self._year, 'M': self._month, 'd': self._day, 'dy': self._delta_years, 'dM': self._delta_months, 'dd': self._delta_days, } def types(self): return set([datetime.date]) @staticmethod def eval(dct, context): return datetime.date.today() + relativedelta( year=dct['y'], month=dct['M'], day=dct['d'], years=dct['dy'], months=dct['dM'], days=dct['dd'], ) class DateTime(Date): def __init__(self, year=None, month=None, day=None, hour=None, minute=None, second=None, microsecond=None, delta_years=0, delta_months=0, delta_days=0, delta_hours=0, delta_minutes=0, delta_seconds=0, delta_microseconds=0, **kwargs): hour = kwargs.get('h', hour) minute = kwargs.get('m', minute) second = kwargs.get('s', second) microsecond = kwargs.get('ms', microsecond) delta_hours = kwargs.get('dh', delta_hours) delta_minutes = kwargs.get('dm', delta_minutes) delta_seconds = kwargs.get('ds', delta_seconds) delta_microseconds = kwargs.get('dms', delta_microseconds) super(DateTime, self).__init__(year=year, month=month, day=day, delta_years=delta_years, delta_months=delta_months, delta_days=delta_days, **kwargs) for i in (hour, minute, second, microsecond, delta_hours, delta_minutes, delta_seconds, delta_microseconds): if isinstance(i, PYSON): assert i.types() == set([int, type(None)]), \ '%s must be an integer or None' % (i,) else: assert isinstance(i, (int, long, type(None))), \ '%s must be an integer or None' % (i,) self._hour = hour self._minute = minute self._second = second self._microsecond = microsecond self._delta_hours = delta_hours self._delta_minutes = delta_minutes self._delta_seconds = delta_seconds self._delta_microseconds = delta_microseconds @property def __repr_params__(self): date_params = super(DateTime, self).__repr_params__ return (date_params[:3] + (self._hour, self._minute, self._second, self._microsecond) + date_params[3:] + (self._delta_hours, self._delta_minutes, self._delta_seconds, self._delta_microseconds)) def pyson(self): res = super(DateTime, self).pyson() res['__class__'] = 'DateTime' res['h'] = self._hour res['m'] = self._minute res['s'] = self._second res['ms'] = self._microsecond res['dh'] = self._delta_hours res['dm'] = self._delta_minutes res['ds'] = self._delta_seconds res['dms'] = self._delta_microseconds return res def types(self): return set([datetime.datetime]) @staticmethod def eval(dct, context): return datetime.datetime.now() + relativedelta( year=dct['y'], month=dct['M'], day=dct['d'], hour=dct['h'], minute=dct['m'], second=dct['s'], microsecond=dct['ms'], years=dct['dy'], months=dct['dM'], days=dct['dd'], hours=dct['dh'], minutes=dct['dm'], seconds=dct['ds'], microseconds=dct['dms'], ) class Len(PYSON): def __init__(self, v): super(Len, self).__init__() if isinstance(v, PYSON): assert v.types().issubset(set([dict, list, basestring])), \ 'value must be a dict or a list or a string' else: assert isinstance(v, (dict, list, basestring)), \ 'value must be a dict or list or a string' self._value = v @property def __repr_params__(self): return (self._value,) def pyson(self): return { '__class__': 'Len', 'v': self._value, } def types(self): return set([int]) @staticmethod def eval(dct, context): return len(dct['v']) CONTEXT = { 'Eval': Eval, 'Not': Not, 'Bool': Bool, 'And': And, 'Or': Or, 'Equal': Equal, 'Greater': Greater, 'Less': Less, 'If': If, 'Get': Get, 'In': In, 'Date': Date, 'DateTime': DateTime, 'Len': Len, } tryton-4.6.5/tryton/action/0000755000175000017500000000000013260723567015224 5ustar cedced00000000000000tryton-4.6.5/tryton/action/main.py0000644000175000017500000001755513251060075016523 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. import tryton.rpc as rpc from tryton.common import message, selection, file_open, mailto from tryton.gui.window import Window from tryton.pyson import PYSONDecoder import gettext import tempfile import os import webbrowser from tryton.common import RPCProgress, RPCExecute, RPCException, slugify from tryton.config import CONFIG _ = gettext.gettext class Action(object): @staticmethod def exec_report(name, data, direct_print=False, email_print=False, email=None, context=None): if context is None: context = {} if email is None: email = {} data = data.copy() ctx = rpc.CONTEXT.copy() ctx.update(context) ctx['direct_print'] = direct_print ctx['email_print'] = email_print ctx['email'] = email args = ('report', name, 'execute', data.get('ids', []), data, ctx) try: res = RPCProgress('execute', args).run() except RPCException: return False if not res: return False (type, data, print_p, name) = res if not print_p and direct_print: print_p = True dtemp = tempfile.mkdtemp(prefix='tryton_') fp_name = os.path.join(dtemp, slugify(name) + os.extsep + slugify(type)) with open(fp_name, 'wb') as file_d: file_d.write(data) if email_print: mailto(to=email.get('to'), cc=email.get('cc'), subject=email.get('subject'), body=email.get('body'), attachment=fp_name) else: file_open(fp_name, type, print_p=print_p) return True @staticmethod def execute(act_id, data, action_type=None, context=None, keyword=False): # Must be executed synchronously to avoid double execution # on double click. if not action_type: action, = RPCExecute('model', 'ir.action', 'read', [act_id], ['type'], context=context) action_type = action['type'] action, = RPCExecute('model', action_type, 'search_read', [('action', '=', act_id)], 0, 1, None, None, context=context) if keyword: keywords = { 'ir.action.report': 'form_report', 'ir.action.wizard': 'form_action', 'ir.action.act_window': 'form_relate', } action.setdefault('keyword', keywords.get(action_type, '')) Action._exec_action(action, data, context=context) @staticmethod def _exec_action(action, data=None, context=None): if context is None: context = {} if data is None: data = {} else: data = data.copy() if 'type' not in (action or {}): return def add_name_suffix(name): if not data.get('ids') or not data.get('model'): return name max_records = 5 rec_names = RPCExecute('model', data['model'], 'read', data['ids'][:max_records], ['rec_name']) name_suffix = _(', ').join([x['rec_name'] for x in rec_names]) if len(data['ids']) > max_records: name_suffix += _(u',\u2026') return _('%s (%s)') % (name, name_suffix) data['action_id'] = action['id'] if action['type'] == 'ir.action.act_window': view_ids = [] view_mode = None if action.get('views', []): view_ids = [x[0] for x in action['views']] view_mode = [x[1] for x in action['views']] elif action.get('view_id', False): view_ids = [action['view_id'][0]] action.setdefault('pyson_domain', '[]') ctx = { 'active_model': data.get('model'), 'active_id': data.get('id'), 'active_ids': data.get('ids', []), } ctx.update(rpc.CONTEXT) ctx['_user'] = rpc._USER decoder = PYSONDecoder(ctx) action_ctx = context.copy() action_ctx.update( decoder.decode(action.get('pyson_context') or '{}')) ctx.update(action_ctx) ctx.update(context) ctx['context'] = ctx decoder = PYSONDecoder(ctx) domain = decoder.decode(action['pyson_domain']) order = decoder.decode(action['pyson_order']) search_value = decoder.decode(action['pyson_search_value'] or '[]') tab_domain = [(n, decoder.decode(d), c) for n, d, c in action['domains']] name = action.get('name', '') if action.get('keyword', '') == 'form_relate': name = add_name_suffix(name) res_model = action.get('res_model', data.get('res_model')) res_id = action.get('res_id', data.get('res_id')) limit = action.get('limit') if limit is None: limit = CONFIG['client.limit'] Window.create(res_model, view_ids=view_ids, res_id=res_id, domain=domain, context=action_ctx, order=order, mode=view_mode, name=name, limit=limit, search_value=search_value, icon=(action.get('icon.rec_name') or ''), tab_domain=tab_domain, context_model=action['context_model'], context_domain=action['context_domain']) elif action['type'] == 'ir.action.wizard': name = action.get('name', '') if action.get('keyword', 'form_action') == 'form_action': name = add_name_suffix(name) Window.create_wizard(action['wiz_name'], data, direct_print=action.get('direct_print', False), email_print=action.get('email_print', False), email=action.get('email'), name=name, context=context, icon=(action.get('icon.rec_name') or ''), window=action.get('window', False)) elif action['type'] == 'ir.action.report': Action.exec_report(action['report_name'], data, direct_print=action.get('direct_print', False), email_print=action.get('email_print', False), email=action.get('email'), context=context) elif action['type'] == 'ir.action.url': if action['url']: webbrowser.open(action['url'], new=2) @staticmethod def exec_keyword(keyword, data=None, context=None, warning=True, alwaysask=False): actions = [] model_id = data.get('id', False) try: actions = RPCExecute('model', 'ir.action.keyword', 'get_keyword', keyword, (data['model'], model_id)) except RPCException: return False keyact = {} for action in actions: keyact[action['name'].replace('_', '')] = action res = selection(_('Select your action'), keyact, alwaysask=alwaysask) if res: (name, action) = res Action._exec_action(action, data, context=context) return (name, action) elif not len(keyact) and warning: message(_('No action defined.')) return False @staticmethod def evaluate(action, atype, record): ''' Evaluate the action with the record. ''' action = action.copy() email = {} if 'pyson_email' in action: email = record.expr_eval(action['pyson_email']) if not email: email = {} if 'subject' not in email: email['subject'] = action['name'].replace('_', '') action['email'] = email return action tryton-4.6.5/tryton/action/__init__.py0000644000175000017500000000024313175640533017330 0ustar cedced00000000000000# This file is part of Tryton. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from main import * tryton-4.6.5/french.nsh0000644000175000017500000000176113175640533014370 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_FRENCH} LangString LicenseText ${CURLANG} "Tryton est publi sous la GNU General Public License comme publie par la Free Software Foundation, soit la version 3 de la License, ou ( votre choix) toute version ultrieure. S'il vous plat lisez attentivement la license. Cliquez sur Suivant pour continuer." LangString LicenseNext ${CURLANG} "&Suivant" LangString PreviousInstall ${CURLANG} "Veuillez dsinstaller la prcdente installation de Tryton" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "Installe tryton.exe et d'autres fichiers requis" LangString SecStartMenuName ${CURLANG} "Raccourcis dans le menu Dmarrer et sur le bureau" LangString SecStartMenuDesc ${CURLANG} "Cr les raccourcis dans le menu Dmarrer et sur le bureau" tryton-4.6.5/CHANGELOG0000644000175000017500000002576313260723566013636 0ustar cedced00000000000000Version 4.6.5 - 2018-04-03 * Bug fixes (see mercurial logs for details) Version 4.6.4 - 2018-03-15 * Bug fixes (see mercurial logs for details) Version 4.6.3 - 2018-03-01 * Bug fixes (see mercurial logs for details) Version 4.6.2 - 2018-01-04 * Bug fixes (see mercurial logs for details) Version 4.6.1 - 2017-12-04 * Bug fixes (see mercurial logs for details) Version 4.6.0 - 2017-10-30 * Bug fixes (see mercurial logs for details) * Allow to export model and record name of Reference fields * Re-position buttons on Binary/Image widget * Improve treeview headers * Update states of both toolbar and menu * Improve toolbar order * Make readonly, required and invalid widget themable * Load user CSS theme * Use profile name or login details in title Version 4.4.0 - 2017-05-01 * Bug fixes (see mercurial logs for details) * Verify certificate with default CA * Replace URL entry by a toolbar button Version 4.2.0 - 2016-11-28 * Bug fixes (see mercurial logs for details) * Add support for GTK+ 3.0 * Add PYSON Widget * Show records names in wizard title * Add support for datetime_field to Reference * Show non editable widget as insensitive * Move info-bar at the bottom * Manage readonly on fields translation dialog * Restore tab default order when no manual change * Call autocompletion when setting record value * Remove database management * Limit readonly state for xxx2Many * Show records names in relate window title * Add support for count on Action Window Domains * Manage custom login process * Add clear icon on Many2One * Re-position icons on Many2One widget Version 4.0.0 - 2016-05-02 * Bug fixes (see mercurial logs for details) * Improvement of charts design * Timedelta uses 30 days for month * Add all available encoding for import/export * Add CSV parameters to export window * Add DnD on import window * Manage context model of ir.action.act_window * Add Note * Manage view_ids on tree view * Use Apple key for copy/past of list Version 3.8.0 - 2015-11-02 * Bug fixes (see mercurial logs for details) * Use italic labels for editable fields * Escape '_' in button string and page string * Export selected records only * Use HTML for RichText widget * Change Progressbar to work with float between 0 and 1 * Add Fast Tabbing option * Remove colors on widgets * Bold label of required fields * Explicit error message for invalid record * Add reversed operators to PYSON expressions Version 3.6.0 - 2015-04-20 * Bug fixes (see mercurial logs for details) * Hide columns containing always the same value * Remove Tabs Position option * Manage product attribute * Remove float_time widget * Add TimeDelta field * Improve date/time widgets * Remove datetime widget on list/tree view * Allow to put many times the same field on tree view * Add search completion on dictionary widget * Merge host and port field in profile editor * New color scheme for graph * Replace img_{width,height} by width and height attributes Version 3.4.0 - 2014-10-20 * Bug fixes (see mercurial logs for details) * Add DnD on export window * Allow to overide predefined export * Prefill export window with current view fields * Manage field context on Group value * Add export of selection string * Load plugins from local user directory * Manage tree_state attribute * Add simple tree_state support on form view * Change range operator of search widget to be included * Explicitly set value of parent field Version 3.2.0 - 2014-04-21 * Bug fixes (see mercurial logs for details) * Add option to show revisions * Add a multi selection widget for many2many * Remove auto-refresh * Add support of domain for non-relation field * Allow drag & drop on the attachment button * Replace sha widget by password * Add Len to PYSON * Use a pool of connection * Manage client actions from button and wizard * Add tree_invisible attribute to button in tree view * Add buttons of the view in actions menu * Don't evaluate anymore relate action with the record * Paste on editable list create new records if needed * Drop support of Python 2.6 * Allow to search on rec_name of Reference fields * Use local timezone * Sanitize report file extension Version 3.0.0 - 2013-10-21 * Bug fixes (see mercurial logs for details) * Add factor on number widgets * Add calendar view * Add URL entry * Remove request Version 2.8.0 - 2013-04-22 * Bug fixes (see mercurial logs for details) * Manage dynamic label * Manage prefix, suffix on tree view * Manage selection_change_with on Selection and Reference fields * Add Dict fields on form * Remove Goto * Add global search * Add toggle button for menu * Replace shortcuts by menu favorites * Move Plugins into toolbar Actions * Add url to list view * Add dynamic icon for url * Add completion on Many2One, Many2Many and One2Many * Add bookmark on search widget * Manage domains on Action Window * Use range for Date/Time fields in filter box * Allow multi-selection for Selection field in filter box Version 2.6.0 - 2012-10-22 * Bug fixes (see mercurial logs for details) * Allow to paste in editable list view * Manage readonly state on group * Remove "Please wait" box * Refactorize date widgets * Manage tuple on Reference * Add constant interpolation on line graph * Make Import/Export Data no-modal * Deactivate switch view button when there is only 1 view * Manage create/delete field access * Add dynamic size limit on the One2Many, Many2Many and Char * Search only on fields in XML view * Cache action keyword * Always use cached views * Manage model access * Manage time format * Deactivate attachment button when record is not created Version 2.4.0 - 2012-04-23 * Bug fixes (see mercurial logs for details) * Remove workflow * Improve contextual menu: - Actions for all relation fields on list view - Use icons - Add attachments entry * Use RPCProgress almost everywhere * Add a simple search box * New domain parser using shlex * Better translation dialog box * Add the richtext widget for WYSIWYG Editor on text fields * Add a record pool to prefetch more records * Add Time widget * Add support for fuzzy_translation * Activate save button on editing * Refactor set/get and set/get_client of fields * Display binary size alongside the buttons in treeview * Set correctly the focus on tab switching * Add shortcut to focus search entry * Add binary field to tree views * Improve board view: - use the same search widget as form - link double click to open popup Version 2.2.0 - 2011-10-24 * Bug fixes (see mercurial logs for details) * New search widget * Improve memory management of Binary fields * Support buffer for Binary fields * Remove delete on Escape in editable tree * Use JSON-RPC * Limit size of field when possible * Add xalign and yalign as fields attributes * Convert many popup to be no-modal * Add window manager for: - replace current window - prevent simmilar window * Merge and review toolbars in form and board * Drop support of Python 2.5 * Use the same design for Many2Many than One2Many * Allow resize columns smaller than the header Version 2.0.0 - 2011-04-26 * Bug fixes (see mercurial logs for details) * Popup form dialog has 3 buttons (close, ok, new) * New UI layout * Add DnD on tree view * Merge tree and list views * Remove generic default value on right-click * Made numpad locale aware * Selection widget used for many2one dynamically change their content following the domain specification * Add open button on binary and image widgets * Hide buttons on image widget if readonly * Added a connection manager à la gajim * Fix warning in wizards * Added possibility to use server-side icons * Added additional gtk.Entry for filename on BinaryField * Display deleted lines in One2Many and Many2Many * Handle URL * Add communication between boards * Added domain inversion feature * Handle loading attribute on fields * Use default format for value in wizard form * Add One2One field Version 1.8.0 - 2010-11-01 * Bug fixes (see mercurial logs for details) * More fully integrate GTK menubar for Mac OS * Allow to configure search limit * Add Previous/Next on list view * Set non-applicable form controls in one2many view to be insensitive Version 1.6.0 - 2010-05-08 * Bug fixes (see mercurial logs for details) * Don't stop wizard execution when exception occurs * Use ir.attachment view instead of a custom one * Add fingerprint and CA check for SSL connection * Use lazy load in Import/Export windows * Validate record before switching view * Refactoring: * Better naming in model * Group extends list * Add an index to Group * New common windows for dialog of many2one, one2many and many2many * one2many and many2many dialog use the same screen than the widget * Reduce the number of option in Screen * Remove RPCProxy to handle logout exception on every server call * Better naming of event signals * Fix on_change detection for many2many for issue1400 * Add PySON to replace python string evaluation * Don't show "Spell Checking" option if gtkspell is not present * Use the same internal model for many2many and one2many fields * Remove egenix-mx-base and replace it by python-dateutil * Add cache to safe_eval * Use versioned configuration directory * Next and Previous scroll per page on list and don't loop * Add AccelGroup on search windows (CTRL+Return) * Use same keyboard shortcut for xxx2many than for other fields Version 1.4.0 - 2009-10-19 * Bug fixes (see mercurial logs for details) * Handle datetime_field in xxx2Many * Add new safe_eval * Ask previous password for set_preferences on password change * Add "Statusbar" option * Add default filename for database backup * Add checkbox on restore to update database * Add 'login.host' options to hide server connection * Handle required attribute with local domains * Allow to run wizard in tabs * Remove statusbar on form for more space * Add "Change Accelerators" option * Use gzip in pysocket * Use the report name to create the temporary file to open it * Allow to store wizard size * Add reset default on fields * Store in config default width and height of main window * Added arrow navigation if supported by gtk * Add 'starts with' and 'ends with' on char search * Handle domain with '=' or '!=' as operator on selection * Extend fields domain with local domains * Improve float time widget to handle year, month, week and day and handle float_time attribute for contextual time convertion Version 1.2.0 - 2009-04-20 * Bug fixes (see mercurial logs for details) * Make graph works also with datetime * Add edition on Many2Many * Fix open in csv export to use file actions * Update client labels at language change * Handle datetime_field in Many2One * Set readonly on records with _datetime in the context * Display values of reference fields even if there is no model * Allow to directly print or create email with reports * Handle invisible states on list view * Add user warnings * Add Model in logs * Allow to duplicate many records at once * Improve netrpc communication speed * Improve date widget to display mask only when having focus * Fix for host with IPv6 enable but without default IPv6 route * Add desktop entry * Add win32 single executable * Allow egg installation Version 1.0.0 - 2008-11-17 * Initial release tryton-4.6.5/LICENSE0000644000175000017500000010451313175640533013415 0ustar cedced00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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 Lesser General Public License instead of this License. But first, please read . tryton-4.6.5/.hgtags0000644000175000017500000000215013260723566013663 0ustar cedced00000000000000923b3073b686c6dc5a921d0561c934adf3eeb879 1.0.0 9a6434d63616f46520b6fa1b2be31906ff6f4f6a 1.2.0 de84c1443d4bad908eabb99c381578b988c2117f 1.4.0 3976912b23dfc5db2525d4c2e55d17f099d9492d 1.6.0 8aa050da53cbdfabe1353a37da91c011b7fff549 1.8.0 1876747b3f963ba6011b4bcf6968e681624c6e24 2.0.0 5364f8ca6cd2cccfb5f7f39c69bb20bae2b5f495 2.2.0 fe15da23f7333e0e90d2693aadddf6bed53ed602 2.4.0 d069f9f1cdc3fea39e71415268582abb2b333ea1 2.6.0 21fbf8bd36096d926c472acfecd3963369204af8 2.8.0 9197d90b0257ec7c4576a38092fd592b3e87f7a4 3.0.0 9721289ee2fdaab8b990de9327c3eab87363c88c 3.2.0 8e5cba59137f9d0a063fa6d7855e09a51bc5889c 3.4.0 1ac658605d42d82988cfb232afebfe359aba7776 3.6.0 f4b9c8a84cf61935afec788c3c639982731452ef 3.8.0 44d8ed92ff90cf98c4c01d37f12d344d9d66e7f1 4.0.0 94037cff031ef897c9533a579356977c8a3cf695 4.2.0 763dc5d8e1d7e483edbf9977dd96afc114555555 4.4.0 d7ed5002e47249d019fbc546f6ac562db44c54f2 4.6.0 96a0be692975ddf6e51eaa975f9eb00162554c7f 4.6.1 3d1f0896293833c094938d39ec5621f60de0614f 4.6.2 6e8b9c5b96d3a067c69a35fd9f4a6ba535a577c2 4.6.3 a0ed25c3ff30154e8f0072f0fbc9fb3a88ffaec1 4.6.4 f5750370d31c8c9edbe9e03c45532a3af6db4027 4.6.5 tryton-4.6.5/russian.nsh0000644000175000017500000000167213175640533014610 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_RUSSIAN} LangString LicenseText ${CURLANG} "Tryton GNU General Public License, Free Software Foundation, 3, ( ) . , . , ." LangString LicenseNext ${CURLANG} "&" LangString PreviousInstall ${CURLANG} " Tryton" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} " tryton.exe " LangString SecStartMenuName ${CURLANG} " " LangString SecStartMenuDesc ${CURLANG} " " tryton-4.6.5/german.nsh0000644000175000017500000000175113175640533014373 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_GERMAN} LangString LicenseText ${CURLANG} "Tryton wird unter der GNU General Public License wie von der Free Software Foundation verffentlicht freigegeben, entweder Version 3 der Lizenz oder (nach Ihrer Wahl) jeder spteren Version. Bitte lesen Sie die Lizenz aufmerksam. Klicken Sie auf Weiter, um fortzufahren." LangString LicenseNext ${CURLANG} "&Weiter" LangString PreviousInstall ${CURLANG} "Bitte deinstallieren Sie die vorherige Installation des Tryton Clients" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "tryton.exe und andere bentigte Dateien installieren" LangString SecStartMenuName ${CURLANG} "Startmen und Desktop-Verknpfungen" LangString SecStartMenuDesc ${CURLANG} "Verknpfungen im Startmen und auf dem Desktop erstellen" tryton-4.6.5/tryton.desktop0000644000175000017500000000230613251060075015327 0ustar cedced00000000000000[Desktop Entry] Version=1.0 Type=Application Name=Tryton GenericName=Client for the Tryton Application Platform GenericName[ca_ES]=Client per l'aplicació Tryton GenericName[de]=Client für die Tryton Applikationsplattform GenericName[es_AR]=Cliente para la aplicación Tryton GenericName[es_EC]=Cliente para la aplicación Tryton GenericName[es_ES]=Cliente para la aplicación Tryton GenericName[es_CO]=Cliente para la Aplicación Tryton GenericName[fr]=Client de la plate-forme applicative Tryton GenericName[ru]=Клиент для платформы приложений Tryton GenericName[sl]=Odjemalec za Tryton programsko platformo Comment=Access Tryton server Comment[de]=Verbindet zu einem Tryton Server Comment[es_AR]=Acceso al servidor Tryton Comment[es_EC]=Acceso al servidor Tryton Comment[ca_ES]=Accés al servidor Tryton Comment[es_ES]=Acceso al servidor Tryton Comment[es_CO]=Acceso al servidor Tryton Comment[fr]=Accéder au serveur Tryton Comment[ru]=Подключение к серверу Tryton Comment[sl]=Dostop do Tryton strežnika Keywords=Business;Management;Enterprise;ERP;Framework;Client; Exec=tryton %u Icon=tryton-icon Terminal=false MimeType=application/tryton; Categories=Office;Finance; tryton-4.6.5/win32/0000755000175000017500000000000013260723567013352 5ustar cedced00000000000000tryton-4.6.5/win32/gtk-2.0/0000755000175000017500000000000013260723567014434 5ustar cedced00000000000000tryton-4.6.5/win32/gtk-2.0/gdk-pixbuf.loaders0000644000175000017500000000100213251060075020024 0ustar cedced00000000000000# GdkPixbuf Image Loader Modules file # Automatically generated file, do not edit # Created by gdk-pixbuf-query-loaders.exe from gdk-pixbuf-2.35.4 # # LoaderDir = lib/gdk-pixbuf-2.0/2.10.0/loaders # "lib/gdk-pixbuf-2.0/2.10.0/loaders/libpixbufloader-svg.dll" "svg" 6 "gdk-pixbuf" "Scalable Vector Graphics" "LGPL" "image/svg+xml" "image/svg" "image/svg-xml" "image/vnd.adobe.svg+xml" "text/xml-svg" "image/svg+xml-compressed" "" "svg" "svgz" "svg.gz" "" " = 5 put python modules under lib directory sys.path.append(os.path.join(prefix, 'lib')) os.environ.setdefault('SSL_CERT_FILE', os.path.join(etc, 'ssl', 'cert.pem')) os.environ.setdefault('SSL_CERT_DIR', os.path.join(etc, 'ssl', 'certs')) # On first launch the MacOSX app launcher may append an extra unique # argument starting with -psn_. This must be filtered to not crash the # option parser. if sys.platform == 'darwin': sys.argv = [a for a in sys.argv if not a.startswith('-psn_')] # Disable dbusmenu to show second menu in tabs os.environ['UBUNTU_MENUPROXY'] = '0' # overlay-scrollbar breaks treeview height os.environ['LIBOVERLAY_SCROLLBAR'] = '0' from tryton import client if '--profile' in sys.argv: import profile import pstats import tempfile import os sys.argv.remove('--profile') statfile = tempfile.mkstemp(".stat", "tryton-")[1] profile.run('client.TrytonClient().run()', statfile) s = pstats.Stats(statfile) s.sort_stats('cumulative').print_stats() s.sort_stats('call').print_stats() s.sort_stats('time').print_stats() s.sort_stats('time') s.print_callers() s.print_callees() os.remove(statfile) else: client.TrytonClient().run() tryton-4.6.5/README0000644000175000017500000000166613175640533013275 0ustar cedced00000000000000tryton ====== The client of the Tryton application platform. A three-tiers high-level general purpose application platform written in Python and use Postgresql as database engine. It is the core base of an Open Source ERP. It provides modularity, scalability and security. Installing ---------- See INSTALL Package Contents ---------------- bin/ Script for startup. doc/ sphinx documentation in reStructuredText. To generate the HTML: python doc/build.py tryton/ tryton sources. Support ------- If you encounter any problems with Tryton, please don't hesitate to ask questions on the Tryton bug tracker, mailing list, wiki or IRC channel: http://bugs.tryton.org/ http://groups.tryton.org/ http://wiki.tryton.org/ irc://irc.freenode.net/tryton License ------- See LICENSE Copyright --------- See COPYRIGHT For more information please visit the Tryton web site: http://www.tryton.org/ tryton-4.6.5/portuguese.nsh0000644000175000017500000000171213175640533015321 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. !verbose 3 !ifdef CURLANG !undef CURLANG !endif !define CURLANG ${LANG_ENGLISH} LangString LicenseText ${CURLANG} "Tryton é licenciado sob a General Public License conforme publicada pela Free Software Foundation, conforme a versão 3 da licença, ou (segundo sua escolha) qualquer versão posterior. Favor ler a licença cuidadosamente. Clique em Seguinte para continuar." LangString LicenseNext ${CURLANG} "&Seguinte" LangString PreviousInstall ${CURLANG} "Favor remover a instalação anterior do Tryton" LangString SecTrytonName ${CURLANG} "Tryton" LangString SecTrytonDesc ${CURLANG} "Instala tryton.exe e outros arquivos necessários" LangString SecStartMenuName ${CURLANG} "Menu Iniciar e Atalhos da Área de Trabalho" LangString SecStartMenuDesc ${CURLANG} "Criar atalhos no menu iniciar e na área de trabalho" tryton-4.6.5/setup.cfg0000644000175000017500000000073613260723567014237 0ustar cedced00000000000000[extract_messages] copyright_holder = Tryton msgid_bugs_address = issue_tracker@tryton.org output_file = tryton/data/locale/tryton.pot keywords = _, gettext [init_catalog] domain = tryton input_file = tryton/data/locale/tryton.pot output_dir = tryton/data/locale [compile_catalog] domain = tryton directory = tryton/data/locale [update_catalog] domain = tryton input_file = tryton/data/locale/tryton.pot output_dir = tryton/data/locale [egg_info] tag_build = tag_date = 0 tryton-4.6.5/INSTALL0000644000175000017500000000007613175640533013440 0ustar cedced00000000000000Installing tryton ================= See doc/installation.rst tryton-4.6.5/COPYRIGHT0000644000175000017500000000201213260723566013675 0ustar cedced00000000000000Copyright (C) 2012-2013 Antoine Smolders. Copyright (C) 2010-2018 Nicolas Évrard. Copyright (C) 2007-2018 Cédric Krier. Copyright (C) 2007-2013 Bertrand Chenal. Copyright (C) 2008-2018 B2CK SPRL. Copyright (C) 2008-2011 Udo Spallek. Copyright (C) 2008-2011 virtual things - Preisler & Spallek GbR. Copyright (C) 2011-2012 Rodrigo Hübner. Copyright (C) 2007-2009 Lorenzo Gil Sanchez. Copyright (C) 2004-2008 Tiny SPRL. 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 3 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, see . tryton-4.6.5/setup-freeze.py0000644000175000017500000000446513251060075015375 0ustar cedced00000000000000import os import sys import user from subprocess import Popen, PIPE from cx_Freeze import setup, Executable include_files = [ ('tryton/data', 'data'), ('tryton/plugins', 'plugins'), (os.path.join(sys.prefix, 'lib/gtk-2.0'), 'lib/gtk-2.0'), (os.path.join(sys.prefix, 'lib/gdk-pixbuf-2.0'), 'lib/gdk-pixbuf-2.0'), (os.path.join(sys.prefix, 'share/locale'), 'share/locale'), ('%s/gtk-2.0/gtkrc' % sys.platform, 'etc/gtk-2.0/gtkrc'), ('%s/gtk-2.0/gtk.immodules' % sys.platform, 'etc/gtk-2.0/gtk.immodules'), ('%s/gtk-2.0/gdk-pixbuf.loaders' % sys.platform, 'etc/gtk-2.0/gdk-pixbuf.loaders'), ] if sys.platform == 'win32': include_files.extend([ (os.path.join(sys.prefix, 'share/themes/MS-Windows'), 'share/themes/MS-Windows'), (os.path.join(sys.prefix, 'ssl'), 'etc/ssl'), ]) dll_paths = os.getenv('PATH', os.defpath).split(os.pathsep) required_dlls = [ 'librsvg-2-2.dll', 'libcroco-0.6-3.dll', ] for dll in required_dlls: for path in dll_paths: path = os.path.join(path, dll) if os.path.isfile(path): break else: raise Exception('%s not found' % dll) include_files.append((path, dll)) elif sys.platform == 'darwin': include_files.extend([ (os.path.join(sys.prefix, 'share/themes/Clearlooks'), 'share/themes/Clearlooks'), (os.path.join(sys.prefix, 'share/themes/Mac'), 'share/themes/Mac'), ]) version = Popen( 'python setup.py --version', stdout=PIPE, shell=True).stdout.read() version = version.strip() setup(name='tryton', version=version, options={ 'build_exe': { 'no_compress': True, 'include_files': include_files, 'silent': True, 'packages': ['gtk'], 'include_msvcr': True, }, 'bdist_mac': { 'iconfile': os.path.join( 'tryton', 'data', 'pixmaps', 'tryton', 'tryton.icns'), 'bundle_name': 'Tryton', } }, executables=[Executable( 'bin/tryton', base='Win32GUI' if sys.platform == 'win32' else None, icon=os.path.join( 'tryton', 'data', 'pixmaps', 'tryton', 'tryton.ico'), )]) tryton-4.6.5/setup.nsi0000644000175000017500000001160413175640533014261 0ustar cedced00000000000000;This file is part of Tryton. The COPYRIGHT file at the top level of ;this repository contains the full copyright notices and license terms. ;Check version !ifndef VERSION !error "Missing VERSION! Specify it with '/DVERSION='" !endif ;Include Modern UI !include "MUI.nsh" ;General Name "Tryton ${VERSION}" OutFile "tryton-setup-${VERSION}.exe" SetCompressor lzma SetCompress auto ;Default installation folder InstallDir "$PROGRAMFILES\tryton-${VERSION}" ;Get installation folder from registry if available InstallDirRegKey HKCU "Software\tryton-${VERSION}" "" BrandingText "Tryton ${VERSION}" ;Vista redirects $SMPROGRAMS to all users without this RequestExecutionLevel admin ;Variables Var MUI_TEMP Var STARTMENU_FOLDER ;Interface Settings !define MUI_ABORTWARNING ;Language Selection Dialog Settings ;Remember the installer language !define MUI_LANGDLL_REGISTRY_ROOT "HKCU" !define MUI_LANGDLL_REGISTRY_KEY "Software\Modern UI Test" !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language" ;Pages !define MUI_ICON "tryton\data\pixmaps\tryton\tryton.ico" !define MUI_LICENSEPAGE_TEXT_BOTTOM "$(LicenseText)" !define MUI_LICENSEPAGE_BUTTON "$(LicenseNext)" !insertmacro MUI_PAGE_LICENSE "LICENSE" !insertmacro MUI_PAGE_DIRECTORY !insertmacro MUI_PAGE_STARTMENU Application $STARTMENU_FOLDER !insertmacro MUI_PAGE_INSTFILES !insertmacro MUI_UNPAGE_CONFIRM !insertmacro MUI_UNPAGE_INSTFILES ;Languages !insertmacro MUI_LANGUAGE "English" ; First is the default !include "english.nsh" !insertmacro MUI_LANGUAGE "Catalan" !include "catalan.nsh" !insertmacro MUI_LANGUAGE "French" !include "french.nsh" !insertmacro MUI_LANGUAGE "German" !include "german.nsh" !insertmacro MUI_LANGUAGE "Slovenian" !include "slovenian.nsh" !insertmacro MUI_LANGUAGE "Spanish" !include "spanish.nsh" !insertmacro MUI_LANGUAGE "Russian" !include "russian.nsh" ;Reserve Files ;If you are using solid compression, files that are required before ;the actual installation should be stored first in the data block, ;because this will make your installer start faster. !insertmacro MUI_RESERVEFILE_LANGDLL ;Installer Sections Function .onInit ClearErrors ReadRegStr $0 HKCU "Software\tryton-${VERSION}" "" IfErrors DoInstall 0 MessageBox MB_OK "$(PreviousInstall)" Quit DoInstall: FunctionEnd Section $(SecTrytonName) SecTryton SectionIn 1 2 RO ;Set output path to the installation directory SetOutPath "$INSTDIR" ;Put file File /r "dist\*" File "COPYRIGHT" File "INSTALL" File "LICENSE" File "README" File "CHANGELOG" SetOutPath "$INSTDIR\doc" File /r "doc\*" ;Register URL protocol WriteRegStr HKCR "tryton" "" "URL:Tryton Protocol" WriteRegStr HKCR "tryton" "URL Protocol" "" WriteRegStr HKCR "tryton\DefaultIcon" "" "$INSTDIR\tryton.exe,1" WriteRegStr HKCR "tryton\shell\open\command" "" '$INSTDIR\tryton.exe "%1"' ;Write the installation path into the registry WriteRegStr HKCU "Software\tryton-${VERSION}" "" $INSTDIR WriteRegStr HKLM "Software\tryton-${VERSION}" "" $INSTDIR ;Write the uninstall keys for Windows WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\tryton-${VERSION}" "DisplayName" "Tryton ${VERSION} (remove only)" WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\tryton-${VERSION}" "UninstallString" "$INSTDIR\uninstall.exe" ;Create the uninstaller WriteUninstaller uninstall.exe SectionEnd Section $(SecStartMenuName) SecStartMenu SectionIn 1 2 !insertmacro MUI_STARTMENU_WRITE_BEGIN Application SetShellVarContext all CreateDirectory "$SMPROGRAMS\$STARTMENU_FOLDER" CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0 CreateShortCut "$SMPROGRAMS\$STARTMENU_FOLDER\Tryton-${VERSION}.lnk" "$INSTDIR\tryton.exe" "" "$INSTDIR\tryton.exe" 0 CreateShortCut "$DESKTOP\Tryton-${VERSION}.lnk" "$INSTDIR\tryton.exe" "" "$INSTDIR\tryton.exe" 0 !insertmacro MUI_STARTMENU_WRITE_END SectionEnd ;Descriptions !insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN !insertmacro MUI_DESCRIPTION_TEXT ${SecTryton} $(SecTrytonDesc) !insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenu} $(SecStartMenuDesc) !insertmacro MUI_FUNCTION_DESCRIPTION_END Section "Uninstall" ;Add your stuff here RMDIR /r "$INSTDIR" ;remove registry keys DeleteRegKey HKCU "Software\tryton-${VERSION}" DeleteRegKey HKLM "Software\tryton-${VERSION}" DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\tryton-${VERSION}" SetShellVarContext all Delete "$DESKTOP\Tryton-${VERSION}.lnk" !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP StrCmp $MUI_TEMP "" noshortcuts Delete "$SMPROGRAMS\$MUI_TEMP\Uninstall.lnk" Delete "$SMPROGRAMS\$MUI_TEMP\Tryton-${VERSION}.lnk" RMDir "$SMPROGRAMS\$MUI_TEMP" noshortcuts: SectionEnd