diff -Nru datovka-4.7.0/ChangeLog datovka-4.7.1/ChangeLog --- datovka-4.7.0/ChangeLog 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/ChangeLog 2017-01-19 09:29:26.000000000 +0000 @@ -1,3 +1,19 @@ +4.7.1 / 2017-01-19 + * User is notified about existent files when storing all attachments. + * Added forward message action. + * Fixed problem in which the main window was placed slightly off-screen when + run for the first time. + * Added script datovka-log.bat. Its purpose it to run the application in + debugging mode where all debugging messages are written into a file. + * Fixed most obvious problems when using UHD displays on Windows. Text lines + in table views (especially in message list) should now be displayed + correctly even with font size above 200%. + * When composing messages, attachment files s can be rearranged using drag and + drop actions. + * Fixed bug. Message model is updated after tags have been edited. + * Fixes errors in application localisation. + * Merged mojeid-datovka functionality. The code is inactivated. + 4.7.0 / 2016-10-19 * The application can be compiled against OpenSSL 1.1.0. * Re-written the login sequence. Fixed some bugs related to creating new diff -Nru datovka-4.7.0/datovka.pro datovka-4.7.1/datovka.pro --- datovka-4.7.0/datovka.pro 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/datovka.pro 2017-01-19 09:29:26.000000000 +0000 @@ -10,7 +10,7 @@ TEMPLATE = app APP_NAME = datovka # VERSION must contain only three dot-separated numbers because of OS X deployment. -VERSION = 4.7.0 +VERSION = 4.7.1 # Generate localisation. Must be run manually. #system(lrelease datovka.pro) @@ -262,6 +262,7 @@ src/crypto/crypto_threads.cpp \ src/delegates/tag_item.cpp \ src/delegates/tags_delegate.cpp \ + src/dimensions/dimensions.cpp \ src/gui/datovka.cpp \ src/gui/dlg_about.cpp \ src/gui/dlg_account_from_db.cpp \ @@ -302,6 +303,7 @@ src/log/log.cpp \ src/log/log_c.cpp \ src/main.cpp \ + src/model_interaction/attachment_interaction.cpp \ src/models/accounts_model.cpp \ src/models/files_model.cpp \ src/models/messages_model.cpp \ @@ -313,7 +315,8 @@ src/settings/proxy.cpp \ src/single/single_instance.cpp \ src/views/attachment_table_view.cpp \ - src/views/attachment_table_widget.cpp \ + src/views/lowered_table_view.cpp \ + src/views/lowered_table_widget.cpp \ src/views/table_home_end_filter.cpp \ src/views/table_key_press_filter.cpp \ src/views/table_space_selection_filter.cpp \ @@ -334,7 +337,19 @@ src/worker/task_search_owner.cpp \ src/worker/task_send_message.cpp \ src/worker/task_vacuum_db_set.cpp \ - src/worker/task_verify_message.cpp + src/worker/task_verify_message.cpp \ + src/web/net.cpp \ + src/web/json.cpp \ + src/worker/task_download_message_list_mojeid.cpp \ + src/worker/task_sync_mojeid.cpp \ + src/worker/task_get_account_list_mojeid.cpp \ + src/worker/task_download_message_mojeid.cpp \ + src/gui/dlg_search_mojeid.cpp \ + src/worker/task_send_message_mojeid.cpp \ + src/io/wd_sessions.cpp \ + src/io/tag_db_container.cpp \ + src/worker/task_tag_sync_mojeid.cpp \ + src/gui/dlg_login_mojeid.cpp HEADERS += \ src/cli/cli.h \ @@ -345,6 +360,7 @@ src/crypto/crypto_threads.h \ src/delegates/tag_item.h \ src/delegates/tags_delegate.h \ + src/dimensions/dimensions.h \ src/gui/datovka.h \ src/gui/dlg_about.h \ src/gui/dlg_account_from_db.h \ @@ -384,6 +400,7 @@ src/log/log_c.h \ src/log/log_common.h \ src/log/log.h \ + src/model_interaction/attachment_interaction.h \ src/models/accounts_model.h \ src/models/files_model.h \ src/models/messages_model.h \ @@ -395,7 +412,8 @@ src/settings/proxy.h \ src/single/single_instance.h \ src/views/attachment_table_view.h \ - src/views/attachment_table_widget.h \ + src/views/lowered_table_view.h \ + src/views/lowered_table_widget.h \ src/views/table_home_end_filter.h \ src/views/table_key_press_filter.h \ src/views/table_space_selection_filter.h \ @@ -416,7 +434,21 @@ src/worker/task_search_owner.h \ src/worker/task_send_message.h \ src/worker/task_vacuum_db_set.h \ - src/worker/task_verify_message.h + src/worker/task_verify_message.h \ + src/web/net.h \ + src/web/net_consts.h \ + src/web/json.h \ + src/worker/task_download_message_list_mojeid.h \ + src/worker/task_sync_mojeid.h \ + src/worker/task_get_account_list_mojeid.h \ + src/worker/task_download_message_mojeid.h \ + src/gui/dlg_search_mojeid.h \ + src/worker/task_send_message_mojeid.h \ + src/io/wd_sessions.h \ + src/io/tag_db_container.h \ + src/worker/task_tag_sync_mojeid.h \ + src/gui/dlg_login_mojeid.h + FORMS += \ src/gui/ui/datovka.ui \ @@ -439,7 +471,9 @@ src/gui/ui/dlg_tags.ui \ src/gui/ui/dlg_timestamp_expir.ui \ src/gui/ui/dlg_view_zfo.ui \ - src/gui/ui/dlg_yes_no_checkbox.ui + src/gui/ui/dlg_yes_no_checkbox.ui \ + src/gui/ui/dlg_search_mojeid.ui \ + src/gui/ui/dlg_login_mojeid.ui RESOURCES += \ res/resources.qrc diff -Nru datovka-4.7.0/debian/changelog datovka-4.7.1/debian/changelog --- datovka-4.7.0/debian/changelog 2016-10-19 13:06:02.000000000 +0000 +++ datovka-4.7.1/debian/changelog 2017-02-01 08:55:17.000000000 +0000 @@ -1,3 +1,11 @@ +datovka (4.7.1-1) unstable; urgency=medium + + * Update d/watch to match the name without -src + * New upstream version 4.7.1 + * Rebase patches on top of 4.7.1 release + + -- Ondřej Surý Wed, 01 Feb 2017 09:55:17 +0100 + datovka (4.7.0-1) unstable; urgency=medium * Imported Upstream version 4.7.0 diff -Nru datovka-4.7.0/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch datovka-4.7.1/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch --- datovka-4.7.0/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch 2016-10-19 13:06:02.000000000 +0000 +++ datovka-4.7.1/debian/patches/0002-Allow-compilation-with-older-Qt5-versions.patch 2017-02-01 08:55:17.000000000 +0000 @@ -7,7 +7,7 @@ 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/datovka.pro b/datovka.pro -index 209b70b..43d14fb 100644 +index 117701a..c673962 100644 --- a/datovka.pro +++ b/datovka.pro @@ -35,14 +35,14 @@ ADVISED_MINOR = 3 diff -Nru datovka-4.7.0/debian/watch datovka-4.7.1/debian/watch --- datovka-4.7.0/debian/watch 2016-10-19 13:06:02.000000000 +0000 +++ datovka-4.7.1/debian/watch 2017-02-01 08:55:17.000000000 +0000 @@ -1,4 +1,4 @@ # Compulsory line, this is a version 3 file version=3 -https://secure.nic.cz/files/datove_schranky/([\d\.]+)/datovka-([\d\.]+)-src\.tar\.xz +https://secure.nic.cz/files/datove_schranky/([\d\.]+)/datovka-([\d\.]+)(-src)?\.tar\.xz diff -Nru datovka-4.7.0/locale/datovka_cs.ts datovka-4.7.1/locale/datovka_cs.ts --- datovka-4.7.0/locale/datovka_cs.ts 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/locale/datovka_cs.ts 2017-01-19 09:29:26.000000000 +0000 @@ -14,43 +14,11 @@ O Datovce - Datovka - Datovka - - - free graphical interface for 'Datové schránky' -based on the libisds library - Svobodné grafické rozhraní pro "Datové schránky" -Založeno na knihovně libisds - - - Free graphical interface for 'Datové schránky'. -Based on the libisds library. - Svobodné grafické rozhraní pro "Datové schránky". -Založeno na knihovně libisds. - - - Free graphical interface for 'Datové schránky'. - Svobodné grafické rozhraní pro "Datové schránky". - - - Copyright © 2014 CZ.NIC <http://www.nic.cz> - Copyright © 2014 CZ.NIC <http://www.nic.cz> - - - Free client for Datové schránky. - Svobodný klient pro Datové schránky. - - Copyright © Copyright © - www.nic.cz - www.nic.cz - - Licence Licence @@ -62,16 +30,9 @@ - AccountDb - - unknown or without expiration - Neznámý nebo bez expirace - - - AccountModel - + Accounts Účty @@ -102,6 +63,61 @@ + AttachmentInteraction + + + Error storing attachment. + Chyba ukládání přílohy. + + + + Cannot write temporary file for attachment '%1'. + Nelze zapsat dočasný soubor s přílohou '%1'. + + + + + Save attachment + Uložit přílohu + + + + + Error saving attachment. + Chyba při ukládání přílohy. + + + + Cannot write file '%1'. + Nemohu zapsat soubor '%1'. + + + + Save attachments + Uložit všechny přílohy + + + + Some files already exist. + Některé soubory již existují. + + + + In total %1 attachment files could not be written. + Celkem '%1' souborů s přílohami nemohlo být uloženo. + + + + These are: + Jsou to: + + + + Error saving attachments. + Chyba při ukládání příloh. + + + ChangeDirectory @@ -167,10 +183,6 @@ Změnit heslo - Please enter you current and new password below: - Prosím, zadejte staré a nové heslo níže: - - DataBox ID: ID datové schránky: @@ -189,25 +201,11 @@ alespoň jednu číslici a jedno velké písmeno. - The password must be at least 8 characters long -and must contain least one number and capital letter. - Heslo musí být alespoň 8 znaků dlouhé a musí -obsahovat nejméně jednu číslici a velké písmeno. - - New password: Nové heslo: - Repeat the password. The password must -be at least 8 characters long and must -contain least one number and capital letter. - Zopakujte heslo. Heslo musí být alespoň -8 znaků dlouhé a musí obsahovat nejméně -jednu číslici a velké písmeno. - - This sets a new password on the ISDS server. Please enter your current and new password below: Zde se nastavuje nové heslo na serveru ISDS. Zadejte prosím stávající a nové heslo: @@ -267,18 +265,10 @@ Send SMS code Odeslat SMS kód - - Security code: - Bezpečnostní kód: - Contacts - Find recipient - Hledat příjemce - - Add recipient Přidat příjemce @@ -299,17 +289,17 @@ Vyčistit - + ID ID - + Name Jméno - + Address Adresa @@ -317,10 +307,6 @@ CorrespondenceOverview - Dialog - Přehled a export korespondence - - Correspondence overview Přehled korespondence @@ -390,10 +376,6 @@ PDF delivery info files Doručenku do PDF - - Export ZFO of selected messages - Exportovat vybrané zprávy do souboru ZFO - CreateAccount @@ -504,10 +486,6 @@ Synchronise account when "Synchronise all" is activated Synchronizovat účet při aktivaci hromadné synchronizace - - Synchronize account when "Synchronize all" is activated - Synchronizovat tento účet když je povoleno stahování na pozadí - CreateAccountFromDb @@ -541,41 +519,38 @@ - DbImport + DbFlsTblModel - Import database - Importovat databázový soubor - - - How do you want to import? - Jakým způsobem chcete importovat? + + local database + místní databáze - Database file(s) from directory - Databázové soubory z adresáře + + File size + Velikost souboru - Selected database file(s) - Vybrat databázové soubory + + File path + Cesta k souboru - - - DbImportDialog - A new account will be created according to the name and the content of the database file. This account will operate over the selected database. Should such an account or database file already exist in Datovka then the import will fail. During the import no database file copy is created nor is the content of the database file modified. Nevertheless, we strongly advice you to back-up all important files before importing a database file. In order for the import to succeed you will need an active connection to the ISDS server. - Z názvu a obsahu vybraného databázového souboru se v Datovce vytvoří nový účet, který bude pracovat s vybranou databází. Pokud tento účet a databáze v Datovce již existují, bude import neúspěšný. Při importu se nevytváří žádná kopie databázového souboru ani se nemodifikuje její obsah, přesto silně doporučujeme databázové soubory pře importem zálohovat. Pro úspěšný import je také zapotřebí aktivní připojení na server Datové schránky. + + unknown + neznámý DbMsgsTblModel - - + + Attachments downloaded Přílohy staženy - + Processing state Stav vyřizování @@ -720,10 +695,6 @@ Restartujte aplikaci. Nezapomeňte si také zapamatovat nové heslo, abyste je byli schopni použít pro přihlašování přes webové rozhraní. - Please, set your new password in the account settings and restarts the application. Otherwise you can not connect to your databox. - Nastavte si, prosím, nové heslo v nastavení účtu a restartujte aplikaci, jinak se nebudete moct přihlásit k Vaší schránce. - - Error: Chyba: @@ -744,38 +715,22 @@ Napravte chybu a zkuste to znovu. - Password has been changed successfully... - Heslo bylo úspěšně změněno... - - - Reference number: - Referenční číslo: - - Password error Chybné heslo - - An error occurred while password was changed - Při změně hesla došlo k chybě - - - ErrorType: - Typ chyby: - DlgContacts - - - + + + no ne - + yes ano @@ -783,10 +738,6 @@ DlgCorrespondenceOverview - (messages: - zpráv: - - messages: @@ -808,10 +759,6 @@ Příjemce: - Overview- - Prehled- - - Sent Odeslané @@ -925,10 +872,6 @@ soubor s přehledem korespondence byl exportován do CSV. - correspondence overview file was exported to CVS. - soubor s přehledem korespondence byl exportován do CVS. - - correspondence overview file was exported. soubor s přehledem korespondence byl exportován. @@ -983,10 +926,6 @@ Ke zprávě '%1' chybí data doručenky, která jsou potřeba pro export do PDF. - Message '%1' does not contain deivery info data necessary for PDF export. - Zpráva '%1' neobsahuje data potřebná pro export doručenky do PDF souboru. - - delivery infos were successfully exported to PDF. doručenek bylo exportováno do PDF. @@ -1012,19 +951,11 @@ Více informací v podrobnostech... - Select directory to save correspondence - Vyberte adresář pro uložení přehledu korespondence - - Overview Prehled - Select file to save correspondence overview to - Vybrat soubor pro uložení přehledu korespondence - - Files Soubory @@ -1035,131 +966,80 @@ Correspondence overview file '%1' could not be written. Soubor s přehledem korespondence '%1' nemohl být zapsán. - - Select directory to save ZFO files - Vybrat adresář pro export ZFO souborů - - - There were some errors during saving of the overview: - Při exportu přehledu se objevily problémy: - - - Message - Zpráva - - - does not contain data necessary for ZFO export - neobsahuje data potřebná k exportu do souboru ZFO - - - And many more - A několik dalších - - - messages were successfully exported to ZFO - zpráv bylo úspěšně exportováno do ZFO - DlgCreateAccount - + Password Heslo - + Certificate Certifikát - + Certificate + Password Certifikát + heslo - + Password + Secure code Heslo + Bezpečnostní kód - + Password + Secure SMS Heslo + SMS kód - + Update account %1 Aktualizovat účet %1 - + Enter password for account %1 Zadejte heslo pro účet %1 - + Set certificate for account %1 Nastavit certifikát pro účet %1 - + Enter password/certificate for account %1 Zadejte heslo/certifikát pro účet %1 - Update account - Aktualizovat účet - - - Enter password for account - Zadejte heslo pro účet - - - Set certificate for account - Nastavit certifikát pro účet - - - Enter password/certificate for account - Zadejte heslo/certifikát pro účet - - - Enter ID of your databox for account - Zadejte ID Vaší schránky pro tento účet + + mojeID + mojeID - Databox ID: - ID schránky: - - - + Open Certificate Otevřít certifikát - + Certificate Files (*.p12 *.pem) Soubory certifikátů (*.p12 *.pem) - - Certificate File (*.p12) - Certifikát (*.p12) - - - Add - Přidat - DlgDsSearch - - + + Your account is of type Váš účet je typu - + You have also Post Data Messages activated. This means you can only search for accounts of type OVM and accounts that have Post Data Messages delivery activated. Because of this limitation the results of your current search might not contain all otherwise matching databoxes. @@ -1170,186 +1050,202 @@ všechny datové schránky, které by jinak vyhovovaly parametrům. - + commercial messages are enabled poštovní datové zprávy jsou povoleny - + This means you can only search for accounts of type OVM. The current search settings will thus probably yield no result. To znamená, že můžete vyhledávat pouze schránky typu OVM. Vyhledávání s aktuálními parametry tak pravděpodobně nevrátí žádné výsledky. - + commercial messages are disabled poštovní datové zprávy jsou vypnuty - + OVM – Orgán veřejné moci OVM – Orgán veřejné moci - + PO – Právnická osoba PO – Právnická osoba - + PFO – Podnikající fyzická osoba PFO – Podnikající fyzická osoba - + FO – Fyzická osoba FO – Fyzická osoba - - + + Subject Name: Název subjektu: - - - - + + + + Enter name of subject Zadejte název instituce - + Name: Jméno: - - + + Enter PFO last name or company name. Zadejte příjmení PFO nebo název firmy. - Enter PFO last name or firm name. - Zadejte příjmení PFO nebo název firmy. - - - + Last Name: Příjmení: - - + + Enter last name or birth last name of FO. Zadejte příjmení nebo rodné příjmení FO. - - - + + + Search result Výsledek hledání - + This is a special ID for system databox of Datové schránky. You can't use this ID for message delivery. Try again. Toto je speciální ID "systémové schránky" systému Datových schránek. Momentálně není možné zasílat zprávy do této schránky. Hledejte dál. - + It is not possible find databox because Není možné najít datovou schránku protože - + It is not possible find databox because error occurred during search process! Není možné najít datovou schráku protože v průběhu vyhledávání nastala chyba. - Too many matching results were found. Some found results cannot be displayed.<br><br>Specify the criteria more clearly in order to narrow the selection. - Bylo nalezeno příliš mnoho výsledků. Některé položky nebudou zobrazeny.<br><br>Zadejte více vyhledávacích kritérií za účelem zúžení výběru. + + Search error + Chyba při vyhledávání - This is a special ID for system databox of Datové schránky. -You can't use this ID for message delivery. - Toto je speciální ID "systémové schránky" systému Datových schránek. -Momentálně není možné zasílat zprávy do této schránky. Hledejte dál. + + + no + ne - Sorry, item(s) not found.<br><br>Try again... - Bohužel, těmto požadavkům neodpovídá žádný záznam.<br><br>Zkuste to znova... + + yes + ano + + + DlgDsSearchMojeId - Ambiguous lookup values.<br><br>Try again... - Nejednoznačná kritéria vyhledávání.<br><br>Zkuste to znova... + + Search + Vyhledat - Too many results were found.<br><br>Not all matches are going to be displayed. - Bylo nalezeno příliš knoho shod.<br><br> + + Search next + Vyhledat další + + + DlgLoginToMojeId - - Search error - Chyba při vyhledávání + + Password + Heslo - It is not possible find databox, because error... - Nebylo možné vyhledat záznamy, protože došlo k chybě... + + Certificate + Certifikát - - - no - ne + + Password + Secure code + Heslo + Bezpečnostní kód - - yes - ano + + Login to account: %1 + Přihlásit se do účtu: %1 + + + + Open Certificate + Otevřít certifikát + + + + Certificate Files (*.p12 *.pem) + Soubory certifikátů (*.p12 *.pem) DlgMsgSearch - + Here it is possible to search for messages according to supplied criteria. You can search for messages in selected account or in all accounts. Double clicking on a found message will change focus to the selected message in the application window. Note: You can view additional information when hovering your mouse cursor over the message ID. Zde je možné vyhledávat zprávy podle zvolených kritérií. Je možné vyhledávat zprávy v aktivním účtu nebo ve všech účtech. Dvojklik na nalezenou zprávu změní fokus na zvolenou zprávu v hlavním okně. Poznámka: Dodatečné informace je možné zobrazit najetím kurzoru myši nad identifikátor zprávy. - + Account Účet - + Message ID ID zprávy - + Subject Předmět - + Sender Odesílatel - + Recipient Příjemce - + Delivery Year Rok doručení - + Message Type Typ zprávy @@ -1357,18 +1253,18 @@ DlgPreferences - + Note: If you have a slow network connection or you cannot download complete messages, here you can increase the connection timeout. Default value is %1 minutes. Use 0 to disable timeout limit (not recommended). Poznámka: Pokud máte pomalé síťové připojení, nebo se Vám nedaří stáhnout komplentí zprávu, můžete zvýšit časový limit spojení. Výchozí hodnota je %1 minut. Použijte 0 pro vypnutí limitu (není doporučeno). - + Note: Marked unread message will be marked as read after set interval. Default value is %1 seconds. Use -1 disable the function. Poznámka: Nepřečtená zpráva bude označena jako lokálně přečtená za nastavený čas. Výchozí hodnota je %1 sekund. Použijte -1 pro vytnutí této funkce. - - + + Select directory Vybrat adresář pro import @@ -1391,478 +1287,238 @@ DlgSendMessage - PDZ is enabled - PDZ je povolena - - - PDZ is disabled - PDZ je zakázaná - - - commercial messages are enabled - poštovní datové zprávy jsou povoleny - - - commercial messages are disabled - poštovní datové zprávy jsou vypnuty - - - sending of commercial messages (PDZ) is enabled - posílání poštovních datových zpráv (PDZ) je povoleno - - - sending of commercial messages (PDZ) is disabled - posílání poštovních datových zpráv (PDZ) je zakázáno - - - + sending of PDZ: enabled posílání PDZ: povoleno - + remaining credit: zbývající kredit: - + sending of PDZ: disabled posílání PDZ: zakázáno - - + + no ne - - - + + + yes ano - Your reference number: - Vaše referenční číslo: - - - - unknown - neznámý - - - - local database - místní databáze - - - Wrong file size - Neplatná velikost souboru - - - File '%1' could not be added into attachment because its size is bigger than 10MB. - Soubor '%1' nemohl být přidán do přílohy, protože jeho velikost přesahuje 10MB. - - - File '%1' could not be added into attachment because its size is bigger than 20MB. - Soubor '%1' nemohl být přidán do přílohy, protože jeho velikost přesahuje 20MB. - - - + Our reference number: Naše číslo jednací: - + Enter reference number: Zadejte Vaše referenční číslo: - + Warning: The permitted amount (%1) of attachments has been exceeded. Upozornění: Povolený počet (%1) příloh byl překročen. - + Total size of attachments is ~%1 KB Celková velikost příloh je ~%1 KB - + Warning: Total size of attachments is larger than %1 MB! Upozornění: Celková velikost příloh přesahuje %1 MB! - + Total size of attachments is ~%1 B Celková velikost příloh je ~%1 B - - Error opening attachment. - Chyba při otevírání přílohy. - - - - Cannot write file '%1'. - Nemohu zapsat soubor '%1'. - - - + Message contains non-OVM recipients. Zpráva obsahuje více ne-OVM příjemců. - + Your message contains %1 non-OVM recipients therefore this message will be sent as a commercial messages (PDZ) for these recipients. Vaše zpráva obsahuje %1 ne-OVM příjemců, proto bude zpráva těmto příjemcům odeslaná v režimu placená poštovní datová zpráva (PDZ). - + Message contains non-OVM recipient. Zpráva obsahuje ne-OVM příjemce. - + Your message contains non-OVM recipient therefore this message will be sent as a commercial message (PDZ) for this recipient. Vaše zpráva obsahuje jednoho ne-OVM příjemce, proto bude zpráva tomuto příjemci odeslaná v režimu placená poštovní datová zpráva (PDZ). - + Your remaining credit is Váš zbývající kredit je - + Message has successfully been sent to <i>%1 (%2)</i> as PDZ with number <i>%3</i>. Zpráva byla úspěšně odeslána příjemci <i>%1 (%2)</i> jako PDZ s číslem <i>%3</i>. - + Message has successfully been sent to <i>%1 (%2)</i> as message number <i>%3</i>. Zpráva byla úspěšně odeslána příjemci <i>%1 (%2)</i> jako zpráva číslo <i>%3</i>. - + Message has NOT been sent to <i>%1 (%2)</i>. Server says: %3 Zpráva NEbyla odeslána příjemci <i>%1 (%2)</i>. Server říká: %3 - + + Message sent Zpráva odeslána - + + Message has successfully been sent to all recipients. Zpráva byla úspěšně odeslána všem příjemcům. - + + Message sending error Chyba odesílání zprávy - + + Message has NOT been sent to all recipients. Zpráva NEbyla odeslána všem příjemcům - An error has occurred during message creation. Memory allocation failed. - Došlo k chybě během vytváření zprávy. Nepodařilo se alokovat potřebnou paměť. - - - An error has occurred during loading of attachments into message. - Došlo k chybě během vkládání přiložených souborů do zprávy. - - - An error has occurred during message envelope creation. - Došlo k chybě během vytváření obálky zprávy. - - - It was not possible to establish a connection to the server or authorization failed. - Nebylo možné navázat spojení se serverem nebo selhala autorizace uživatele. - - - Message was successfully sent to all recipients. - Zpráva byla úspěšně odeslána všem příjemcům. - - - Message was sent with error - Odeslání zprávy nebylo úspěšné - - - Message was NOT successfully sent to all recipients. - Zpráva nebyla úspěšně odeslána všem příjemcům. - - - + + Do you want to close the Send message form? Chcete zavřít formulář pro odesílání zpráv a zahodit vyplněné údaje? - + Send message error Chyba při odesílání zprávy - - + + Total size of attachments is %1 B Celková velikost příloh je %1 B - + An error occurred while loading attachments into message. Nastala chyba v průběhu vkládání příloh do zprávy. - + An error occurred during message envelope creation. Nastala chyba v průběhu vytváření obálky zprávy. - + It has not been possible to send a message to the server Datové schránky. Nebylo možné odeslat zprávu serveru Datových schránek. - + The message will be discarded. Zpráva bude zahozena. - It can be caused by following - Možné příčiny - - - It was not possible to establish a connection to the server. - Nebylo možné navázat spojení se serverem Datové schránky. - - - Authorization on the server failed. - Nezdařilo se přihlášení/autentizace na server Datové schránky. - - - Wrong/unsupported MIME type of some file in the attachment. - Zpráva obsahuje špatné nebo nepodporované MIME typy některých přiložených souborů. - - - An internal error has occurred in the application. - Vyskytla se interní chyba Datvoky při vytváření zprávy. - - - + Databox ID ID datové schránky - + Enter Databox ID (7 characters): Vložte ID datové schránky (7 znaků) - Message contains Commercial messages (PDZ) - Zpráva obsahuje poštovní datové zprávy (PDZ) - - - Your message contains %1 non-OVM recipients therefore these messages will be sent as aCommercial messages (PDZ) - Vaše zpráva obsahuje %1 ne-OVM příjemců, proto bude těmto příjemcům zpráva odeslaná v režimu placená Poštovní datová zpráva (PDZ) - - - + Do you want to send all messages? Chcete opravdu odeslat tuto zprávu všem příjemcům? - Message contains Commercial message (PDZ) - Zpráva obsahuje poštovní datovou zprávu (PDZ) - - - Your message contains %1 non-OVM recipient therefore this message will be sent as Commercial message (PDZ) - Vaše zpráva obsahuje %1 ne-OVM příjemce, proto bude tato zpráva odeslaná tomuto příjemci v režimu placená Poštovní datová zpráva (PDZ) - - - + Do you want to send message? Chcete opravdu odeslat zprávu tomuto příjemci? + + + DlgTag - Message was successfully sent to <i>%1 (%2)</i> as PDZ with number <i>%3</i>. - Zpráva byla úspěšně odeslána do schránky <i>%1 (%2)</i> jako PDZ s číslem <i>%3</i>. - - - Message was successfully sent to <i>%1 (%2)</i> as message number <i>%3</i>. - Zpráva byla úspěšně odeslána do schránky <i>%1 (%2)</i> s číslem <i>%3</i>. - - - Message was NOT successfully sent to <i>%1 (%2)</i>. Server says: %3 - Zpráva nebyla úspěšně odeslána do schránky <i>%1 (%2)</i>. Server říká: %3 - - - Message was sent - Zpráva byla odeslána - - - Messages was sent into ISDS successfully. - Zpráva byla úspěšné odeslána do systému Datových schránek. - - - Send multiple message problem! - Problém při odesílání zprávy více příjemcům! - - - Send multiple message finished with an problem! - Nepodařilo se odeslat zprávu některým příjemcům! - - - It can be caused sending of the message to the unactivated databox or some of recipient does not exist. - Pravděpodobně některý z příjemců buď nemá momentálně aktivní datovou schránku nebo již neexistuje. - - - Download list of sent messages and check which recipients didn't receive your message. - Stáhněte seznam odeslaných zpráv ze serveru Datové schránky a zjistěte, kteří příjemci Vaší zprávu neobdrželi. - - - It was not possible to send message to server Datové schránky. - Nebylo možné odeslat zprávu na server Datové schránky. - - - ISDS error - Chyba ISDS - - - Connection to the server timed out! - Nepodařilo se navázat spojení v předepsaném čase! - - - Sent message was refused by server Datové schránky. - Odeslaná zpráva byla odmítnuta serverem Datové schránky. - - - Problem with attachment of message! - Problém s přílohou zprávy! - - - Server did not accept message for this databox and returned message back. - Server Datové schránky nepřijal zprávu do systému a vrátil ji zpět. - - - It can be caused by a wrong/unsupported MIME type of some file in the attachment or if an attachment contains an archive. - Pravděpodobně zpráva obsahuje špatné nebo nepodporované MIME typy některých přiložených souborů nebo obsahuje nějaký komprimovaný archiv. - - - It was not possible to send message to the server Datové schránky. - Nebylo možné odeslat zprávu na server Datové schránky. - - - Error: - Chyba: - - - It was not possible create send message request because an internal error has occurred. - Nebylo možné vytvořit požadavek na odeslání nové zprávy na server Datové schránky, protože se vyskytla interní chyba aplikace. - - - Do you want to abort sending of the message and close the send message dialog? - Chcete ukončit odesílání této zprávy a zavřít okno s vytvořenou zprávou? - - - Multiple message error! - Chyba při odesílání zprávy více příjemcům! - - - It was not possible to send message to all recipients. - Zpráva nebyla odeslaná některým příjemcům. - - - Send multiple message finished with error! - Odeslaní zprávy více příjemcům skončilo s chybou! - - - Please check your credentials including the test-environment setting. - Prosím, zkontrolujte svoje přihlašovací údaje včetně nastavení testovacích účtů. - - - It is possible that your password has expired - in this case, you need to use the official web interface of Datové schránky to change it. - Je možné, že vypršela platnost vašeho hesla. V tomto případě potřebujete navštívit oficiální webové rozhraní Datových schránek a změnit ho. - - - Send message error! - Chyba při odeslání zprávy na server Datové schránky! - - - It was not possible to send message to ISDS. - Nebylo možné odeslat zprávu na server Datové schránky. - - - Authorization failed! - Chyba autorizace! - - - Send message to ISDS timeout! - Chyba při odesílání zprávy - vypršel timeout! - - - It was not possible to establish a connection within a set time. - Nebylo možné vytvořit spojení ve stanoveném čase. - - - Please check your internet connection and try again. - Prosím, zkontrolujte Vaše připojení k internetu a zkuste akci opakovat. - - - Internal error! - Interní chyba! - - - It was not possible a create send message request because an internal error has occurred. - Nebylo možné odeslat zprávu na server Datové schránky protože se vyskytla interní chyba. - - - Connection to ISDS failed! - Připojení k datové schránce selhalo! - - - It was not possible a connection between your computer and the server of Datove schranky. - Nebylo možné navázat spojení mezi Vaším počítačem a serverem Datové schránky. - - - Do you want to close send message dialog - Chcete zrušit odesílání zprávy a zahodit vyplněné údaje - - - - DlgTag - - + Choose tag colour Vyberte barvu tagu - - + + + Tag error Chyba tagu - + Tag name is empty. Jméno tagu je prázdné - + Tag wasn't created. Tag nebyl vytvořen - + + Tag update error + Chyba aktualizace tagu + + + + Tag with name '%1'' wasn't updated in the WebDatovka database. + Tag pojmenovaný '%1' nebyl aktualizován v databázi WebDatovky. + + + + Tag insert error + Chyba vložení tagu + + + + Tag with name '%1'' wasn't' created in WebDatovka database. + Tag pojmenovaný '%1' nebyl vytvořen v databázi WebDatovky. + + + + Tag with name '%1'' already exists in database. Tag se jménem '%1' již v databázi existuje. - + + Tag wasn't created again. Tag nebyl znovu vytvořen. @@ -1935,174 +1591,119 @@ - Save attachment Uložit přílohu - Save attachments Uložit všechny přílohy - - Error saving attachment. - Chyba při ukládání přílohy. - - - - - Cannot write file '%1'. - Nemohu zapsat soubor '%1'. - - - - - Error saving attachments. - Chyba při ukládání příloh. - - - - Could not save all attachments. - Nemohly být uloženy všechny přílohy. - - - - In total %1 attachment files could not be written. - Celkem '%1' souborů s přílohami nemohlo být uloženo. - - - - These are: - Jsou to: - - - - Error opening attachment. - Chyba při otevírání přílohy. - - - + Identification Identifikace - + ID ID - + Subject Předmět - + Message type Typ zprávy - + Sender Odesílatel - + Sender Databox ID ID datové schránky odesílatele - + Sender Address Adresa odesílatele - + Recipient Příjemce - + Recipient Databox ID ID datové schránky příjemce - + Events Události - To - Příjemce - - - + Recipient Address Adresa - - + + Status Stav - + Delivery time Čas doručení - + Acceptance time Čas přijetí - + Attachments Přílohy - + Signature Podpis - + Message signature Podpis zprávy - + Signing certificate Podepisující certifikát - + Time stamp Časové razítko - - Time-stamp - Časové razítko - DsSearch - Add recipient - Přidat příjemce - - Enter the ID, IČ or at least three letters from the name of the data box you look for: Zadejte ID, IČ nebo alespoň tři písmena z názvu hledané datové schránky: - Type: - Typ schránky: - - Search recipient Vyhledat příjemce @@ -2118,18 +1719,6 @@ n/a - Your account is of type FO and you have Post Data Messages activated. -This means you can only search for accounts of type OVM and accounts -that have Post Data Messages delivery activated. -Because of this limitation the results of your current search might not -contain all otherwise matching databoxes. - Váš účet je typu FO a máte aktivované příjímání poštovních datových zpráv. -This means you can only search for accounts of type OVM and accounts -that have Post Data Messages delivery activated. -Because of this limitation the results of your current search might not -contain all otherwise matching databoxes. - - Your account is not of type OVM or ne-OVM. You have Post Data Messages activated. This means you can only search for accounts of type OVM and accounts @@ -2176,32 +1765,75 @@ Vyhledat - + ID ID - + Name Jméno - + Address Adresa - + Postal code Směrovací číslo - + PDZ PDZ + DsSearchMojeId + + + Search recipient + Vyhledat příjemce + + + + Current account: + Aktuální účet: + + + + n/a + n/a + + + + Keyword: + Klíčové slovo: + + + + Search + Vyhledat + + + + ID + ID + + + + Name + Jméno + + + + Address + Adresa + + + ImportZFO @@ -2214,14 +1846,6 @@ Co chcete importovat? - Message ZFO file(s) - ZFO zpráv - - - Delivery info ZFO file(s) - ZFO doručenek - - Message and delivery info ZFO file(s) Zprávy a doručenky současně @@ -2321,22 +1945,10 @@ 0 - Number of successfully imported files: - Počet úspěšně importovaných souborů: - - - List of successfully imported ZFO files: - Výčet úspěšně importovaných ZFO souborů: - - Number of unsuccessfully imported files: Počet neúspěšně importovaných souborů: - - List of unsuccessfully imported ZFO files: - Výčet neúspěšně importovaných ZFO souborů: - IsdsLogin @@ -2495,10 +2107,6 @@ Toto může být způsobeno chybou požadavku SOAP nebo obsah XML pro tuto službu není validní. - This is maybe caused by a missing certificate for the SSL communication or the application cannot open an SSL socket. - Pravděpodobně chybí potřebný certifikát pro HTTPS komunikaci se serverem nebo se nepodařilo otevřít SSL soket. - - It is also possible that some libraries (e.g. CURL, SSL) may be missing or may be incorrectly configured. Je také možné, že nebyly nalezeny některé potřebné knihovny (např. CURL, SSL) anebo jsou nesprávně nakonfigurovány. @@ -2509,10 +2117,6 @@ Problém s HTTPS spojením či bezpečnostní problém! - This is maybe caused by a missing SSL certificate needed for communicating with the server or it was not possible establish a secure connection with the ISDS server. - Toto může být způsobeno chybějícím SSL certifikátem, který je potřeba pro komunikaci se serverem, nebo nebylo možné ustavit bezpečný komunikační kanál se serverem Datové schránky. - - It is also possible that the certificate has expired. Dále je možné, že vypršela platnost certifikátu. @@ -2523,10 +2127,6 @@ Problém SOAP či XML! - This may be caused by an error in SOAP or the XML content for this web service is wrong. - Toto může být způsobeno chybou požadavku SOAP nebo obsah XML pro tuto službu není validní. - - It is also possible that the ISDS server is inoperative or busy. Try again later. Je také možné, že server ISDS je momentálně mimo provoz nebo přetížen. Zkuste to později. @@ -2549,1194 +2149,995 @@ + JsonLayer + + + Login to mojeID failed. You must choose correct login method and enter correct login data. Try again. + Přihlášení do mojeID selhalo. Musíte vybrat správný způsob přihlašování a zadat správné přihlašovací údaje. Zkuste to znovu. + + + + Cannot open client certificate from path '%1' + Nelze otevřít certifikát z cesty '%1' + + + + Certificate password + Heslo certifikátu + + + + Enter certificate password: + Zadejte heslo k certifikátu: + + + + Cannot parse client certificate from path '%1' + Nemohu načíst certifikát z cesty '%1' + + + + + + + + + + + + + + + + + + + + + + User is not logged to mojeID + Uživatel není přihlášen do mojeID + + + + + + + + + + + + + + + + + + Reply content missing + Chybí obsah odpovědi + + + + LoginToMojeId + + + Add a new mojeID account(s) + Přidejte účet mojeID + + + + Please select login method and enter credentials for mojeID. + Vyberte způsob přihlašování a zadejte přihlašovací údaje do mojeID. + + + + Login method: + Způsob přihlášení: + + + + Select authorization method for login into your databox + Vyberte metodu přihlašování do datové schránky + + + + Username: + Uživatelské jméno: + + + + Enter your username + Zadejte své přihlašovací jméno + + + + Password: + Heslo: + + + + Enter your password + Zadejte své heslo + + + + Certificate file: + Soubor certifikátu: + + + + Select a certificate + Vyberte certifikát + + + + Add + Přidat + + + + Security code (OTP): + Bezpečnostní kód (OTP): + + + + Account will be included into synchronisation +process of all accounts on the background + Účet bude zahrnut do hromadné synchronizace +všech účtů na pozadí aplikace + + + + Synchronise account(s) when "Synchronise all" is activated + Synchronizovat účet při aktivaci hromadné synchronizace + + + MainWindow - + Search: Vyhledat: - + Clear search field Vymazat pole - Ready - Připraven - - - + Mode: offline Režim: nepřipojeno (offline) - Status: - Stav: - - - + All messages Všechny zprávy - Remove Account - Odstranit účet - - - + Add new account Vytvořit nový účet - Create a new message - Vytvořit novou zprávu - - - + Save attachments Uložit všechny přílohy - Delete message - Smazat zprávu - - - Do you want to delete message - Chcete opravdu smazat zprávu - - - + Test account Testovací účet - + Standard account Standardní účet - + Account name Název účtu - + User name Uživatelské jméno - + Yes Ano - + No Ne - + Password expiration date Datum a čas expirace hesla - - + + Received messages Přijaté zprávy - - - + + + none žádné - - + + Sent messages Odeslané zprávy - QDatovka - Free interface for Datové schránky - QDatovka - Svobodné rozhraní pro Datové schránky - - - + Version Verze - + Powered by Vytvořil - + Datovka: Database file present Datovka: Databázový soubor přítomen - + Database file for account '%1' already exists. Databázový soubor pro účet '%1' již existuje. - The existing database file '%1' is going to be used. - Bude použit existující databázový soubor '%1'. - - - + If you want to use a new blank file then delete, rename or move the existing file so that the application can create a new empty file. Pokud chcete použít nový prázdný soubor, pak odstraňte, přejmenujte nebo přesuňte stávající soubor, aby aplikace mohla vytvořit nový prázdný soubor. - - - - - + + + + + Datovka: Problem loading database Datovka: Problém otevírání databáze - - - - - - + + + + + + Could not load data from the database for account '%1' Nemohu načíst data z databázového souboru pro účet '%1' - Database file '%1' is missing. - Je postrádán databázový soubor '%1'. - - - + I'll try to create an empty one. Pokusím se vytvořit prázdný. - Database location '%1' is not a file. - Umístění databáze '%1' není soubor. - - - Database file '%1' cannot be accessed. - Nemáte přístup k databázovému souboru '%1'. - - - - + + Datovka - Free client for Datové schránky Datovka - Svobodný klient pro Datové schránky - + No account synchronised. Nebyl synchronizován žádný účet. - + Account and user information could not be acquired. Nepodařilo se získat informace o účtu a uživateli. - + User information Informace o uživateli - + Databox information Informace o datové schránce - + The existing database files %1 in '%2' are going to be used. Existující databázové soubory %1 v '%2' budou použity. - + Database files are missing in '%1'. Databázové soubory chybí v '%1'. - + Some databases of %1 in '%2' are not a file. Některé databáze %1 v '%2' asi nejsou soubory. - + Some databases of '%1' in '%2' cannot be accessed. Některé databáze %1 v '%2' nelze zpřístupnit. - + You don't have enough access rights to use the file. Nemáte dostatečná oprávnění k použití souboru. - Database file '%1' cannot used. - Nelze použít databázový soubor '%1'. - - - + The file either does not contain an sqlite database or the file is corrupted. Soubor buď neobsahuje slite databázi nebo je poškozen. - + Datovka: Database opening error Datovka: Chyba otevírání databáze - Database file '%1' cannot be created or is corrupted. - Databázový soubor '%1' nelze vytvořit nebo je soubor poškozen. - - - + Remove account Odstranit účet - + Do you want to remove account Chcete opravdu odstranit účet - + Delete also message database from storage Odstranit také databázi zpráv z disku - + Warning: If you delete the message database then all locally accessible messages that are not stored on the ISDS server will be lost. Upozornění: Jestli-že smažete databázi zpráv potom všechny zprávy, které nejsou uloženy na serveru ISDS budou ztraceny. - + Account '%1' was deleted together with message database file. Účet '%1' byl smazán společně s jeho databází zpráv. - Account '%1' was deleted but its message database file . - Učet '%1' byl smazán, ale jeho databázový soubor but its message database file . - - - + Account '%1' was deleted. Účet '%1' byl smazán. - - - - - - + + + + + + Change data directory for current account Změnit adresář pro ukládání dat pro aktuální účet - Database file - Databázový soubor - - - was successfully moved to - byl úspěšně přesunut do - - - was NOT successfully moved to - nebyl úspěšně přesunut do - - - was successfully copied to - byl úspěšně zkopírován do - - - was NOT successfully copied to - nebyl úspěšně zkopírován do - - - New database file - Nový databázový soubor - - - was successfully created to - byl úspěšně vytvořen ve složce - - - was NOT successfully created to - nebyl úspěšně vytvořen ve - - - Account error - Chyba účtu - - - It was not possible to get user info and databox info for this account from server. - Nebylo možné získat informace o uživateli a jeho datové schránce ze serveru datové schránky. - - - + Connection to ISDS or user authentication failed! Připojení k serveru datové schránky se nezdařilo nebo selhala autorizace uživatele! - + Please check your internet connection and try again or it is possible that your password (certificate) has expired - in this case, you need to use the official web interface of Datové schránky to change it. Zkontrolujte prosím připojení k internetu a zkuste to znovu. Také je možné, že vaše heslo (certifikát) již vypršelo - v tomto případě musíte použít oficiální webové rozhraní Datové schránky a heslo si změnit. - The account " - Účet - - - was not created! - nebyl vytvořen! - - - - + + Add ZFO file Vybrat ZFO soubor - - - - - + + + + + ZFO file (*.zfo) Soubor ZFO (*.zfo) - + Message is authentic Zpráva je autentická - ISDS confirms that the message is valid. - Server Datové schránky potvrdil, že zpráva je autentická. - - - + Message is not authentic Zpráva není autentická - ISDS confirms that the message is invalid. - Server Datové schránky potvrdil, že zpráva není autentická. - - - Welcome - Vítejte - - - - + + disk disk - - + + memory paměť - + Storage: Úložiště: - + New version of Datovka is available: Nová verze Datovky je k dispozici: - - + + New version of Datovka Nová verze Datovky - - + + New version of Datovka is available. Nová verze Datovky je k dispozici. - + Current version is %1 Vaše současná verze je %1 - + New version is %1 Nová verze je %1 - + Do you want to download new version? Chcete nyní stáhnout novou verzi? - + Current version is "%1" Vaše verze je "%1" - + New version is "%1" Nová verze je "%1" - + Update your application... Aktualizujte aplikaci... - + Database files for account '%1' cannot be accessed in location '%2'. Databázové soubory pro účet '%1' nelze zpřístupnit ve složce '%2'. - + All received messages Všechny přijaté zprávy - + All sent messages Všechny odeslané zprávy - - - - + + + + As Unsettled Nevyřízeno - - - - + + + + As in Progress Vyřizuje se - - - - + + + + As Settled Vyřízeno - - Saving attachment of message to files was not successful! - Nepodařilo se uložit vybranou přílohu na disk! - - - - - Saving attachment of message "%1" to files was not successful! - Nepodařilo se uložit vybranou přílohu zprávy "%1" na disk! + + First you must download the complete message to continue with the action. + Před pokračováním akce musíte nejdříve stáhnout úplnou zprávu. - - Saving attachment of message "%1" to file was not successful! - Nepodařilo se uložit vybranou přílohu zprávy "%1" na disk! - - - - Saving attachment of message "%1" to file was successful. - Vybraná příloha zprávy "%1" byla úspěšně uložena na disk. - - - - All attachments of message "%1" were saved. - Všechny přílohy zprávy "%1" byly uloženy na disk. - - - - - Some attachments of message "%1" were not saved to disk! - Některé přílohy zprávy "%1" nebyly uloženy na disk! - - - + Invalid certificate data Neplatná data certifikátu - + The certificate or the supplied pass-phrase are invalid. Certifikát nebo zadané heslo jsou neplatné. - + Please enter a path to a valid certificate and/or provide a correct key to unlock the certificate. Prosím zadejte cestu k platnému certifikátu a/nebo zadejte správný klíč pro odemknutí certifikátu. - + Bad certificate data for account "%1". Špatná data certifikátu pro účet "%1". - + The log-in method used in account "%1" is not implemented. Přihlašovací metoda použitá v účtu "%1" není implementována. - + Account "%1" requires authentication via OTP<br/>security code for connection to data box. Pro připojení ke schránce pro účet "%1" je<br/>vyžadována OTP autentizace bezpečnostním kódem. - + Account "%1" requires authentication via security code for connection to data box. Účet "%1" vyžaduje pro přihlášení k datové schránce autorizaci bezpečnostním kódem OTP. - + Security code will be sent to you via a Premium SMS. Bezpečnostní kód Vám bude zaslán Prémiovou SMS zprávou. - + Do you want to send a Premium SMS with a security code into your mobile phone? Chcete zaslat Prémiovou SMS s bezpečnostním kódem do Vašeho mobilu? - + Enter sought expression Zadete hledaný výraz - + In Progress Vyřizuje se - + Database access error Chyba přístupu k databázi - + The file cannot be accessed or is corrupted. Please fix the access privileges or remove or rename the file so that the application can create a new empty file. Nelze přistoupik k souboru nebo je soubor poškozen. Opravte prosím přístupová oprávnění nebo odstraňte nebo přejmenujte soubor, aby aplikace mohla vytvořit nový prázdný soubor. - + Create a backup copy of the affected file. This will help when trying to perform data recovery. Vytvořte si kopii postiženého souboru. Může to pomoct při případném obnovování dat. - + In general, it is recommended to create backup copies of the database files to prevent data loss. Všeobecně je doporučováno vyrábět záložní kopie databázových souborů aby se zamezilo ztrátě dat. - - + + Mark Označit - All as Read - Vše jako přečtené - - - All as Unread - Vše jako nepřečtené - - - All as Unsettled - Vše jako nevyřízeno - - - All as in Progress - Vše jako vyřizuje se - - - All as Settled - Vše jako vyřízeno - - - - - - + + + + As Read Přečtené - - - - + + + + As Unread Nepřečtené - AS Unsettled - Nevyřízeno - - - AS in Progress - Vyřizuje se - - - AS Settled - Vyřízeno - - - - Error saving attachment of message '%1'. - Chyba při ukládání přílohy zprávy '%1'. - - - - - - - - + + + + Cannot write file '%1'. Nemohu uložit soubor '%1'. - - + Error saving attachments of message '%1'. Chyba při ukládání příloh zprávy '%1'. - - Could not save all attachments of message '%1'. - Nemohly být uloženy všechny přílohy zprávy '%1'. - - - + In total %1 attachment files could not be written. Celkem '%1' souborů s přílohami nemohlo být uloženo. - + These are: Jsou to: - - Attachment '%1' stored to temporary file '%2'. - Příloha '%1' uložena do dočasného souboru '%2'. - - - - Attachment '%1' couldn't be stored to temporary file. - Příloha '%1' nemohla být uložena do dočasného souboru. - - - - Error opening attachment. - Chyba při otevírání přílohy. - - - - It was not possible download received message list from ISDS server. - Nebylo možné stáhnout seznam přijatých zpráv ze serveru ISDS. - - - + Download message list error Chyba stahování seznamu zpráv - - + ISDS: ISDS: - A connection error occured. - Vyskytla se chyba spojení. - - - - It was not possible download sent message list from ISDS server. - Nebylo možné stáhnout seznam odeslaných zpráv ze serveru ISDS. - - - + It was not possible to download a complete message "%1" from server Datové schránky. Nebylo možné stáhnout kompletní zprávu "%1" ze serveru Datové schránky. - A connection error occured or the message has already been deleted from the server. - Pravděpodobně selhalo spojení se serverem nebo zpráva již byla ze serveru odstraněna. - - - + + Delete message %1 Mazání zprávy %1 - + + Do you want to delete message '%1'? Chcete smazat zprávu '%1'? - + Delete this message also from server ISDS Smazat tuto zprávu také z ISDS - + Warning: If you delete the message from ISDS then this message will be lost forever. Upozornění: Jestli-že smažete zprávu ze serveru ISDS, bude tato zpráva navždy ztracena. - + + Delete messages Mazaní zpráv - + + Do you want to delete selected messages? Chcete smazat vybrané zprávy? - + Delete these messages also from server ISDS Smazat tyto zprávy také z ISDS - - Warning: If you delete selected messages from ISDS then these message will be lost forever. - Upozornění: Jestli-že smažete vybrané zprávy ze serveru ISDS, budou tyto zprávy navždy ztraceny. - - - + No ZFO files to import. Žádné ZFO soubory k importování - + There is no account to import of ZFO files into. Není účet, do kterého lze importovat ZFO soubory - + Import of ZFO files ... Planned Import ZFO souborů ... Naplánováno - + Complete message '%1' is missing. Chybí úplná zpráva '%1'. - - First you must download the complete message before export. - Před exportem musíte nejdříve stáhnout úplnou zprávu. - - - + Do you want to download the complete message now? Chcete nyní stáhnout úplnou zprávu? - + Complete message '%1' has been downloaded. Úplná zpráva '%1' byla stažena. - + Complete message '%1' has not been downloaded. Úplná zpráva '%1' nebyla stažena. - + Data message Datová zpráva - + Data messages Datové zprávy - + Attachments of message Přílohy zprávy - + Attachments of messages Přílohy zpráv - + Attachment of message %1 Příloha zprávy %1 - + Attachments of message %1 Přílohy zprávy %1 - Error during a connection to ISDS server! - Během navazování spojení se vyskytla chyba! - - - Error during authentication! - Chyba během autentizace! - - - It was not possible to connect to your Databox from account "%1". - Nebylo možné se připojit k Vaší datové schránce z účtu "%1". - - - Authentication failed! - Chyba autentizace! - - - Error: - Chyba: - - - Please check your credentials and login method together with your password. - Prosím, zkontrolujte své přihlašovací údaje, metodu přihlašení či heslo. - - - It is also possible that your password has expired - in this case, you need to use the official web interface of Datové schránky to change it. - Také je možné, že vypršela platnost Vašeho hesla - v tomto případě se musíte přihlásit na stránky datové schránky a heslo si změnit. - - - Error during OTP authentication! - Chyba během OTP autentizace! - - - OTP authentication failed! - Selhala OTP autentizace! - - - Please check your credentials together with entered security/SMS code and try again. - Prosím, zkontrolujte své přihlašovací údaje, metodu přihlášení a zadaný bezpečnostní/SMS kód a zkuste to znovu. - - - Timeout for connection to server expired! - Vypršel timeout pro připojení k serveru! - - - It might be necessary to use a proxy to connect to the server. Also is possible that the server ISDS is inoperative or busy. Try again later. - Je možné, že pro spojení se serverem je třeba použít proxy. Také je možné, že server Datové schránky je mimo provoz nebo zaneprázdněný. Zkuste to později. - - - It was not possible to establish a connection between your computer and the server Datove schranky. - Nebylo možné navázat spojení mezi Vaším počítačem a serverem Datové schránky. - - - HTTPS problem occurred or redirect to server failed! - Vyskytl se problém s HTTPS nebo selhalo přesměrování na server! - - - This is usually caused by either lack of internet connection or by some problem with the server ISDS. - Tento problém je obvykle způsoben velmi pomalým či nestabilním spojením se serverem Datové schránky. - - - It is possible that the server ISDS is inoperative or busy. Try again later. - Pravděpodobně je server Datové schránky mimo provoz nebo momentálně zaneprázdněný. Zkuste to později. - - - ISDS server problem or service was not found! - Problém serveru ISDS nebo požadována služba nebyla nalezena! - - - Connection to server failed or problem with network occurred! - Připojení k serveru selhalo nebo aktivní připojení k sítí internet nebylo nalezeno! - - - Problem with HTTPS connection! - Problém s HTTPS spojením! - - - This is maybe caused by missing certificate for SSL communication or application cannot open SSL socket. - Pravděpodobně chybí potřebný certifikát pro HTTPS komunikaci se serverem nebo se nepodařilo otevřít SSL soket. - - - It is also possible that some connection libraries are missing (CURL, SSL). - Je také možné, že nebyly nalezeny některé potřebné knihovny (CURL, SSL). - - - HTTPS problem or security problem! - Problém s HTTPS spojením či bezpečnostní problém! - - - This is maybe caused by missing SSL certificate needed for communication with server or it was not possible establish secure connection with the server ISDS. - Toto může být způsobeno chybějícím SSL certifikátem, který je potřeba pro komunikaci se serverem, nebo nebylo možné ustavit bezpečný komunikační kanál se serverem Datové schránky. - - - It is possible that the certificate expired. - Je možné, že vypršela platnost certifikátu. - - - SOAP problem or XML problem! - Problém SOAP či XML! - - - This is maybe caused by error in SOAP or XML content for this web service is wrong. - Toto může být způsobeno chybou požadavku SOAP nebo obsah XML pro tuto službu není validní. - - - Also it is possible that the server ISDS is inoperative or busy. Try again later. - Je také možné, že server Datové schránky je momentálně mimo provoz nebo přetížen. Zkuste to později. - - - It was not possible to establish a connection to server Datove schranky. - Nebylo možné navázat spojení se serverem Datové schránky. - - - An unexpected error occurred. Please restart application and try again or you should contact the support for this application. - Objevila se neočekávaná chyba v aplikaci. Prosím, restartujte aplikaci a zkuste to znova, nebo kontaktujte podporu. - - - + Datovka is currently processing some tasks. Datovka právě zpracovává úlohy. - + Do you want to abort pending actions and close Datovka? Přejete si zrušit nedokončené akce a zavřít Datovku? - - + + Adding new account failed Přidávání nového účtu selhalo - + Account could not be added because an error occurred. Účet nemohl být přidán, protože nastala chyba. - + Account could not be added because account already exists. Účet nemohl být přidán, protože účet již existuje. - + This file does not contain a valid database filename. Tento soubor neobsahuje správný název databáze. - + This file does not contain a valid username in the database filename. Tento soubor neobsahuje platné uživatelské jméno v názvu databáze. - + This database file does not contain valid year in the database filename. Tento soubor neobsahuje platný rok v názvu databáze. - + This file does not contain valid database filename. Tento soubor neobsahuje správný název databáze. - + This database file does not contain valid database filename. Tento soubor neobsahuje správný název databáze. - + This file does not contain a valid account type flag or filename has wrong format. Tento soubor neobsahuje informaci o typu účtu v názvu databáze. - + This file does not contain a valid message database or filename has wrong format. Tento soubor pravděpodobně neobsahuje platnou databázi zpráv nebo souboru má špatný formát. - + Import of mesages from database Import zpráv z databáze - + This action allow to import messages from selected database files into current account. Keep in mind that this action may takes a few minutes based on number of messages in the imported database. Import progress will be displayed in the status bar. Tato akce umožňuje importovat zprávy z vybraných databázových souborů do aktuálního účtu. Mějte na paměti, že tato akce může trvat i několik minut v závislosti na počtu zpráv v importované databázi. Průběh importu zpráv se bude zobrazovat ve stavovém panelu aplikace. - - - + + + Do you want to continue? Chcete pokračovat? - + Select database file(s) Vyberte databázové soubory - + DB file (*.db) DB soubor (*.db) - + Import of messages from %1 to account %2 Import zpráv z %1 do účtu %2 - + Import of messages from %1 to account %2 is running Import zpráv z %1 do účtu %2 běží - - - - - + + + + + Database import: %1 Import zpráv: %1 - + This database file cannot import into selected account because username of account and username of database file do not correspond. Zprávy z této databáze nemohou být importovány to aktuálního účtu protože uživatelská jména účtu a databáze si neodpovídají. - + Failed to open import database file. Chyba při otevírání databáze zpráv. - - + + Failed to open database file of target account '%1' Chyba při otevírání databáze zpráv cílového účtu '%1' - + Importing of message %1 into account %2 ... Importuji zprávu %1 do účtu %2 ... - + Message '%1' already exists in database for this account. Zpráva '%1 již existuje v databázi pro tento účet. - + Message '%1' cannot be imported into this account. Message does not contain any valid ID of databox corresponding with this account. Zpráva '%1' nebyla importována do aktuálního účtu. Zpráva neobsahuje identifikátor datové schránky korespondující s tímto účtem. - + Message '%1' cannot be inserted into database of this account. An error occurred during insertion procedure. Zpráva '%1' nebyla vložena do databáze aktuálního účtu. Zpráva neobsahuje validní informace pro import nebo se vyskytla neočekávaná chyba během importu. - + Messages import result Výsledek importu zpráv - + Import of messages into account '%1' finished with result: Import zpráv do účtu '%1' skončil s tímto výsledkem: - + Source database file: '%1' Zdrojový databázový soubor: '%1' - + Imported messages: %1 Importováno zpráv: '%1' - + Non-imported messages: %1 Ignorováno zpráv: '%1' - + Import of messages from %1 to account %2 finished Import zpráv z %1 do účtu %2 skončil - + Database split Rozdělení databáze - + This action split current account message database into several new databases which will contain messages relevant by year only. It is recommended for large database because the performance of application will be better. Tato akce umožňuje rozdělit stávající databázi zpráv do několika menších databází podle roku dodání zpráv. Akce je doporučena spíše pro účty s velkou databází, která obsahuje mnoho zpráv. Rozdělení databáze může vést ke zrychlení aplikace i rychlejšímu přístupu k datům jednotlivých zpráv. - + Original database file will copy to selected directory and new database files will created in the same location. If action finished with success, new databases will be used instead of original. Restart of application is required. Aktuální databáze zpráv bude zkopírována do vybrané složky. Nové databázové soubory budou vytvořeny do stejné složky. Jestli-že bude proces rozdělení úspěšný, původní databáze bude nehrazena novými databázemi. Poté je třeba provést restart aplikace. - + Note: Keep in mind that this action may takes a few minutes based on number of messages in the database. Poznámka: Mějte na paměti, že tato akce může trvat i několik minut v závislosti na počtu zpráv v databázi. - + Split of message database finished with error Rozdělení databáze skončilo s chybou - + Database split: %1 Rozdělení databáze: %1 - + Action was canceled and original database file was returned back. Akce byla zrušena a původní databáze byla navrácena zpět. - + Existing file '%1' could not be deleted. Existující soubor '%1' nemohl být smazán. - + Error to set and open original database for account '%1' Nepodařilo se nastavit a otevřít původní databázi pro účet '%1' - + Action was canceled and the origin database is now used from location: '%1' Akce byla zrušena a původní databáze byla nově načtena z: '%1' - + Action was canceled because new databases cannot move from '%1' to origin path @@ -3747,633 +3148,520 @@ '%2' - + Opening of new database files Otevírání nových databázových souborů - + Vacuum cannot be performed on databases in memory. Vakuum nelze aplikovat na databáze v paměti. - + Database operation error Chyba funkce databáze - + Database clean-up cannot be performed on database in memory. Pročištění databáze nelze provést s databází v paměti. - + Cannot call VACUUM on database in memory. Nelze volat VACUUM na databázi v paměti. - + Clean message database Pročisti databázi zpráv - + Performs a message database clean-up for the selected account. This action will block the entire application. The action may take several minutes to be completed. Furthermore, it requires more than %1 of free disk space to successfully proceed. Provede pročištění databáze zpráv ve zvoleném účtu. Tato akce zablokuje celou aplikaci. Dokončení akce může trvat několik minut. Akce navíc k úspěšnému dokončení vyžaduje více jak %1 volného místa na disku. - + Performing database clean-up. Provádím pročišťování databáze. - + Database clean-up finished. Počištění databáze dokončeno. - + Database clean-up successful Pročištění úspěšně dokončeno - + The database clean-up has finished successfully. Pročištění databáze bylo úspěšně dokončeno. - + Database clean-up failure Pročištění selhalo - + The database clean-up failed with error message: %1 Pročišťování databáze selhalo s chybovým hlášením: %1 - Action will be canceled. - Akce bude zrušena. + + You have to be logged into the WebDatovka if you want to modify tags. + Musíte být přihlášeni do WebDatovky, aby bylo možné upravovat tagy. - - + + Add account(s) error + Chyba přidávání účtu + + + + There aren't any Webdatovka accounts for this mojeID identity. + Pro tuto mojeID identitu nejsou žádné účty ve WebDatovce. + + + + + You are login into wrong mojeID identity. + Jste přihlášeni do špatné mojeID identity. + + + + Please enter correct mojeID login for account '%1'. + Zadejte prosím správné mojeID přihlašovací jméno '%1'. + + + + New mojeID identity has some account(s). + Nová modeID identita má nějaké účty. + + + + Do you want to add account(s) for this mojeID identity to Datovka? + Chcete přidat účet pro tuto mojeID identitu do Datovky? + + + + Some account(s) were removed from Webdatovka for this mojeID identity. + Některé účty byly odebrány z WebDatovky pro tuto mojeID identitu. + + + + Do you want to also remove these accounts from Datovka? + Chcete také odebrat tyto účty z Datovky? + + + + This action is not supported for MojeID account '%1' + Tato akce není podporována pro mojeID účet '%1' + + + + Login problem + Problém přihlášení + + + + Database file for account '%1' does not exist. Databázový soubor pro účet '%1' neexistuje. - + Database file cannot split by years because this account already use database files split according to years. Databázový soubor nelze rozdělit podle roků. Tento účet již má databázi rozdělenou přes jednotlivé roky. - + Select directory for new databases Vyberte složku pro nové databáze - + Database file cannot split into same directory. Databázový soubor nelze rozdělit do stejné složky. - + Please, you must choose another directory. Prosím, vyberte jinou složku. - + Copying origin database file to selected location Kopírování původní databáze do vybrané složky - + Cannot copy database file for account '%1' to '%2' Nebylo možné zkopírovat původní databázi pro účet '%1' do '%2' - + Probably not enough disk space. Pravděpodobně není dostatek místa na disku. - + Set of new database files for account '%1' could not be created. Nové databázové soubory pro účet '%1' nebudou vytvořeny. - + Creating a new database file for year %1 Vytvářím novou databázi pro rok %1 - + New database file for account '%1' corresponds with year '%2' could not be created. Nový databázový soubor pro účet '%1' korespondující s rokem '%2' nebyl vytvořen. - + Messages were not copied. Zprávy nebyly zkopírovány. - + Messages correspond with year '%1' for account '%2' were not copied. Zprávy korespondující s rokem '%1' pro účet '%2' nebyly zkopírovány. - Error to set original database for account '%1' - Chyba při nastavení původní databáze pro účet '%1' - - - + Replacing of new database files to origin database location Přemisťování nových databázových souborů do původní složky - + Error when move new databases for account '%1' Chyba při přesouvání nových databázových souborů pro účet '%1' - Action was canceled because new databases cannot move from -'%1' to origin path -'%2' - Akce byla zrušena protože se nepodařilo přesunout nové databázové soubory z -'%1' -do původního umístění -'%2' - - - + Probably not enough disk space. The origin database is still used. Pravděpodobně není dostatek místa na disku. Bude použita původní databáze. - + Deleting of old database from origin location Mazání staré databáze z původní lokace - + Error when removed origin database for account '%1' Nepodařilo se odstranit původní databázi pro účet '%1' - + Action was canceled. Please, remove the origin database file manually from origin location: '%1' Akce byla zrušena. Prosím, odstraňte ručně původní databázi z adresáře: '%1' - Open new database files from origin location - nových databázových souborů z původní lokace - - - + A problem when opening new databases for account '%1' Objevil se problém s otevřením nových databázových souborů pro účet '%1' - + Action was done but it cannot open new database files. Please, restart the application. Akce rozdělení sice proběhla, nepodařilo se však otevřít nové databáze. Prosím, restartujte aplikaci. - + Split of message database finished Rozdělení databáze zpráv skončilo - + Congratulation: message database for account '%1' was split successfully. Please, restart the application for loading of new databases. Gratulujeme: databáze zpráv pro účet '%1' byla úspěšně rozdělena. Prosím, restartujte aplikaci pro načtení nových databází zpráv. - + Note: Original database file was backup to: Původní databáze byla přesunuta do: - Download complete message "%1" from ISDS server. - Stahuje se kompletní zpráva "%1" ze serveru ISDS. - - - + It was not possible download complete message "%1" from ISDS server. Nebylo možné stáhnout celou zprávu "%1" ze serveru ISDS. - + + Download message error Chyba stahování zprávy - It was not possible download complete message "%1" from server Datové schránky. - Nebylo možné stáhnout celou zprávu "%1" ze serveru Datové schránky. - - - It is likely that the message has been deleted from the server. - Je pravděpodobné, že zpráva byla smazána ze serveru. - - - - Message "%1" was downloaded from ISDS server. - Zpráva "%1" byla úspěšně stažena ze serveru ISDS. - - - All messages were marked as locally read. - Všechny zprávy v této složce byly označeny jako lokálně přečtené. - - - Do you want to delete message "%1" from server Datové schránky and local database? - Chcete smazat zprávu "%1" ze serveru Datové schránky i z místní databáze? - - - Do you want to delete message "%1" from local database? - Chcete smazat zprávu "%1" z místní databáze? - - - + Message "%1" was deleted from local database. Zpráva "%1" byla smazána z místní databáze. - + Message "%1" was deleted from ISDS and local database. Zpráva "%1" byla smazána z ISDS i z místní databáze. - + Message "%1" was deleted only from ISDS. Zpráva "%1" byla smazána pouze z ISDS. - + Message "%1" was deleted only from local database. Zpráva "%1" byla smazána pouze z místní databáze. - + Message "%1" was not deleted. Zpráva "%1" nebyla smazána. - + Synchronise all accounts with ISDS server. Synchronizují se všechny účty ze serveru ISDS. - + Messages on the server Zprávy na serveru - + received přijato - - + + new nových - + sent odesláno - Synchronise accounts "%1" with ISDS server. - Synchronizuji účet "%1" se serverem ISDS. - - - Synchronise account "%1" with ISDS server. - Synchronizuji účet "%1" se serverem ISDS. - - - Create and send a new message. - Vytvořit a odeslat novou zprávu. - - - Message from account "%1" was send. - Zpráva z účtu "%1" byla úspěšně odeslána. - - - + Create a new account. Vytvořit nový účet. - Account "%1" was deleted. - Účet "%1" byl odstraněn. - - - - - + + + Select directory Vybrat adresář pro import - + Database file(s) not found in selected directory. Databázové soubory nenalezeny ve vybraném adresáři. - + Select db file(s) Vybrat databázové soubory - + Database file (*.db) Databázový soubor (*.db) - - + + Database file(s) not selected. Databázové soubory nebyly vybrány. - Account and message database with username "%1" already exist. You have to remove this account before database import. - Účet a databáze zpráv s uživatelským jménem "%1" již existuje. Musíte nejprve tento účet odstranit před importem nové databáze. - - - This file has been set as a new database. It is test account with username "%1" - Tento soubor byl nastaven jako aktuální databáze zpráv. Jedná se o testovací účet s uživatelským jménem "%1" - - - This file does not contain a valid message database or file name has wrong format. - Tento soubor neobsahuje validní databázi zpráv nebo název souboru má špatný formát pro import. - - - Import of database directories finished with this result: - Import databázových souborů skončil s tímto výsledkem: - - - + Verifying the ZFO file "%1" Ověřování ZFO souboru "%1" - + Server Datové schránky confirms that the message is authentic. Server Datové schránky potvrdil, že zpráva je autentická. - - + + Message was <b>successfully verified</b> against data on the server Datové schránky. Zpráva byla <b>úspěšně ověřena</b> proti datům na serveru Datové schránky. - - + + This message has passed through the system of Datové schránky and has not been tampered with since. Tato zpráva prošla systémem Datových schránek a nebyla od té doby upravena. - + Server Datové schránky confirms that the message is not authentic. Server Datové schránky potvrdil, že zpráva není autentická. - - + + Message was <b>not</b> authenticated as processed by the system Datové schránky. Zpráva <b>nebyla</b> ověřena jako zpracovaná systémem Datové schránky. - - + + It is either not a valid ZFO file or it was modified since it was downloaded from Datové schránky. Soubor buď neobsahuje platný ZFO obsah, nebo byl od chvíle stažení ze systému Datových schránek modifikován. - - - + + + Message authentication failed Autentizace zprávy selhala - - + + Authentication of message has been stopped because the connection to server Datové schránky failed! Check your internet connection. Autentizace zprávy byla zastavena, protože se nezdařilo připojení k serveru Datové schránky! Zkontrolujte připojení k internetu. - + Server Datové schránky confirms that the message is valid. Server Datové schránky potvrdil, že zpráva je validní. - + Server Datové schránky confirms that the message is not valid. Server Datové schránky potvrdil, že zpráva není validní. - + Message is not valid Zpráva není validní - - - - - + + + + + Message verification failed. Verifikace zprávy selhala. - + Verification failed Verifikace zprávy selhala - - - - + + + + Verification error Chyba verifikace - + The message hash is not in local database. Please download complete message from ISDS and try again. Otisk zprávy nebyl nalezen v lokální databázi. Prosím, stáhněte kompletní zprávu ze serveru Datové schránky a zkuste to znova. - - - - + + + + ZFO file(s) not found in selected directory. V adresáři nebyly nalezeny ZFO soubory. - - - + + + No ZFO file(s) Žádné ZFO soubory - + Select ZFO file(s) Vyberte ZFO soubory - + ZFO file(s) not selected. Nebyly vybrány ZFO soubory. - Processing of ZFO: %1 ... - Zpracování ZFO: %1 ... + + Export of message "%1" to ZFO was successful! + Export zprávy '%1' do ZFO proběhl úspěšně! - Import of ZFO file(s) failed! - Import souborů ZFO selhal! + + Export of message "%1" to ZFO was not successful. + Export zprávy "%1" do souboru ZFO nebyl úspěšný. - Wrong delivery info ZFO format. This file does not contain correct delivery info data for import. - Špatný ZFO formát doručenky. Tento soubor neobsahuje správná data doručenky pro import. + + Error exporting message '%1'. + Chyba při exportu zprávy '%1'. - This file (delivery info) has been imported to message number "%1" into account "%2". - Tento soubor (doručenka) byl importován ke zprávě "%1" do účtu "%2". - - - This file (delivery info) has not been inserted into local database because an error was detected during insertion process. - Tento soubor (doručenka) nebyl importován do místní databáze protože v průběhu vkládání došlo k chybě. - - - This file (message envelope) does not exists on the server Datové schránky. - Tento soubor (obálka zprávy) neexistuje na serveru Datové schránky. - - - It is not possible to connect to server Datové schránky and verify validity of this ZFO file. - Není možné se připojit k serveru Datové schránky a ověřit správnost tohoto ZFO souboru. - - - This file (delivery info) has not been inserted into database because there isn't any related message in the database. - Tento soubor (doručenka) nebyl vložen do databáze, protože v databázi neexistuje odpovídající zpráva. - - - Import of ZFO file(s) ... Done - Import ZFO souborů ... Hotovo - - - Wrong message ZFO format. This file does not contain correct message data for import. - Špatný formát ZFO zprávy. Tetnto soubor neobsahuje platná data zprávy pro import do databáze. - - - This file (message) has been imported as sent message number "%1" into account "%2". - Tento soubor (zpráva) byl vložen do databáze jako odeslaná zpráva "%1" k účtu "%2". - - - This file (message) has not been inserted into local database because an error was detected during insertion process. - Tento soubor (zpráva) nebyl vložen do místní databáze, protože v průběhu vkládání došlo k chybě. - - - This file (message) already exists in the local database. - Tento soubor (zpráva) již v místní databázi existuje. - - - This file (message) has been imported as received message number "%1" into account "%2". - Tento soubor (zpráva) byl vložen do databáze jako obdržená zpráva "%1" k účtu "%2". - - - This file (message) has not been inserted as received message into local database for account "%1" because an error was detected during insertion process. - Tento soubor (zpráva) nebyl vložen do místní databáze jako přijatá zpráva pro účet "%1", protože v průběhu vkládání došlo k chybě. - - - This file (message) already exists as received message (%1) in the local database for account "%2". - Tento soubor (zpráva) již v místní databázi existuje jako přijatá zpráva (%1) pro účet "%2". - - - For this message file does not exist correct databox or relevant account. - Pro tuto zprávu neexistuje odpovídající schránka nebo účet. - - - Cannot export complete message - Nelze exportovat zprávu - - - - Export of message "%1" to ZFO was successful! - Export zprávy '%1' do ZFO proběhl úspěšně! - - - - Export of message "%1" to ZFO was not successful. - Export zprávy "%1" do souboru ZFO nebyl úspěšný. - - - - Error exporting message '%1'. - Chyba při exportu zprávy '%1'. - - - Cannot export delivery info for message - Nelze exportovat informace o doručení pro zprávu - - - + Error exporting message delivery info '%1'. Chyba při exportu doručenky zprávy '%1'. - + Message '%1' stored to temporary file '%2'. Zpráva '%1' uložena do dočasného souboru '%2'. - + Message '%1' couldn't be stored to temporary file. Zpráva '%1' nemohla být uložena do dočasného souboru. - - + + Error opening message '%1'. Chyba při otevírání zprávy '%1'. - + Message delivery information '%1' stored to temporary file '%2'. Doručenka zprávy '%1' uložena do dočasného souboru '%2'. - + Message delivery information '%1' couldn't be stored to temporary file. Doručenka zprávy '%1' nemohla být uložena do dočasného souboru. - Please check your credentials including the test-environment setting and login method. - Prosím, zkontrolujte své přihlašovací údaje, včetně nastavení testovacích účtů a metody přihlašování. - - - It was not possible to connect to your databox from account "%1". - Nebylo možné navázat spojení s Vaší datovou schránkou z účtu "%1". - - - + Password required Vyžadováno heslo - + Account: %1 User name: %2 Certificate file: %3 @@ -4384,93 +3672,33 @@ Zadejte heslo pro odemčení souboru certifikátu: - Cannot decode certificate. - Nemůžu dekódovat certifikát. - - - The certificate file '%1' cannot be decoded by using the supplied password. - Soubor certifikátu '%1' nemohl být pomocí zadaného hesla dekódován. - - - Certificate format not supported - Nepodporovaný formát certifikátu - - - The certificate file '%1' suffix does not match one of the supported file formats. Supported suffixes are: - Připona souboru certifikátu '%1' neodpovídá některému z podporovaných formátů. Podporované přípony jsou: - - - Account "%1" requires authentication via security code for connection to databox. - Účet "%1" vyžaduje pro přihlášení k datové schránce autorizaci pomocí bezpečnostního kódu OTP. - - - Security code will be sent you via Premium SMS. - Bezpečnostní kód Vám bude zaslán přes Prémiovou SMS. - - - Do you want to send Premium SMS with security code into your mobile phone? - Chcete poslat Prémiovou SMS s bezpečnostním kódem do Vašeho mobilu? - - - - - - - - - + + + + + + + It was not possible to connect to your data box from account "%1". Nepodařilo se přihlásit k datové schránce z účtu "%1". - An error occurred while preparing request for SMS with OTP security code. - Došlo k chybě v průběhu přípravy požadavku pro přihlášení pomocí SMS OTP. - - - Please try again later or you have to use the official web interface of Datové schránky for access to your data box. - Zkuste to později nebo použijte oficiální webové rozhraní pro Datové schránky. - - - Error of sending SMS - Chyba při zasílání SMS - - - It was not possible sent SMS with OTP security code for account "%1" - Nebylo možné odeslat SMS s bezpečnostním kódem pro účet "%1" - - - Please try again later or you have to use the official web interface of Datové schránky for access to your databox. - Prosím, zkuste to později, nebo se připojte přes oficiální webové rozhraní Datové schránky a zkontrolujte nastavení. - - - Enter SMS security code - Zadejte SMS bezpečnostní kód - - - SMS security code for account "%1"<br/>has been sent on your mobile phone... - SMS bezpečnostní kód pro účet "%1"<br/>byl zaslán do Vašeho mobilu... - - - Enter SMS security code for account - Zadejte SMS bezpečnostní kód pro účet - - - + Password expiration Expirace hesla - + According to the last available information, your password for account '%1' (login '%2') expired %3 days ago (%4). Podle nejnovějších dostupných informací Vaše heslo pro účet '%1' (přihlašovací jméno '%2') vypršelo před %3 dnem/dny (%4). - + According to the last available information, your password for account '%1' (login '%2') will expire in %3 days (%4). Podle nejnovějších dostupných informací Vaše heslo pro účet '%1' (přihlašovací jméno '%2') vyprší za %3 dny/dnů (%4). - + You can change your password now, or later using the 'Change password' command. Your new password will be valid for 90 days. Change password now? @@ -4479,115 +3707,213 @@ Změnit heslo nyní? - You can change your password now, or later using the 'Databox/Change password' command. Your new password will be valid for 90 days. - -Change password now? - Můžete změnit heslo nyní nebo později pomocí příkazu 'Databox' - -Change password now? - - - + Enter OTP security code Zadejte OTP bezpečnostní kód - Account information could not be acquired. - Informace k účtu se nepodařilo získat. - - - + Database is stored in memory. Data will be lost on application exit. Databáze je uložena v paměti. Data budou ztracena při vypnutí aplikace. - - + + Local database file location Umístění souboru místní databáze - + Create and send a message. Vytvoř a odešli zprávu. - + Account '%1' was deleted but its message database was not deleted. Účet '%1' byl smazán, ale jeho databázi zpráv se smazat nepodařilo. - Account with username '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. - Účet s uživatelským jménem '%1' a jeho databáze již existují. Nový účet nebyl vytvořen a vybraná databáze nebyla k účtu přiřazena. - - - Account with name '%1' has been created (username '%1'). - Účet s názvem '%1' byl vytvořen (uživatelské jméno '%1'). - - - + This database file has been set as actual message database for this account. Maybe you have to change account properties for correct login to the server Datové schránky. Tento databázový soubor byl nastaven jako aktuální databáze pro ukládání zpráv pro nový účet. Možná bude zapotřebí upravit vlastnosti tohoto účtu aby bylo možné se připojit k serveru Datové schránky. - - - + + + Create account: %1 Nový účet: %1 - + Tags Tagy - + + Saving attachment of message '%1' to files was not successful! + Nepodařilo se uložit přílohu zprávy '%1'! + + + + Saving attachment of message '%1' to file was successful. + Nepodařilo se uložit přílohu zprávy '%1'. + + + + Saving attachment of message '%1' to file was not successful! + Nepodařilo se uložit přílohu zprávy '%1'! + + + + Error saving attachment. + Chyba při ukládání přílohy. + + + + Some files already exist. + Některé soubory již existují. + + + + Some attachments of message '%1' were not saved to disk! + Některé přílohy zprávy '%1' nebyly uloženy na disk! + + + + All attachments of message '%1' were saved. + Všechny přílohy zprávy '%1' byly uloženy na disk. + + + + Attachment '%1' stored into temporary file '%2'. + Příloha '%1' uložena do dočasného souboru '%2'. + + + + Attachment '%1' couldn't be stored into temporary file. + Příloha '%1' nemohla být uložena do dočasného souboru. + + + + A connection error occurred or the message has already been deleted from the server. Nastala chyba spojení, nebo zpráva již byla smazána ze serveru. - + + Couldn't download message '%1'. Nešlo stáhnout zprávu '%1'. - + + It was not possible download complete message "%1" from webdatovka server. + Nebylo možné stáhnout celou zprávu '%1' ze serveru WebDatovky. + + + + It was not possible to download a complete message "%1" from webdatovka server. + Nebylo možné stáhnout celou zprávu '%1' ze serveru WebDatovky. + + + + Webdatovka: + WebDatovka: + + + + It was not possible download received message list from server. + Nebylo možné stáhnout seznam přijatých zpráv ze serveru. + + + + It was not possible download sent message list from server. + Nebylo možné stáhnout seznam odeslaných zpráv ze serveru. + + + + Server: + Server: + + + A connection error occurred. Nastala chyba spojení. - + Message from '%1' (%2) has been successfully sent to '%3' (%4). Zpráva od '%1' (%2) byla úspěšně odeslána příjemci '%3' (%4). - + Error while sending message from '%1' (%2) to '%3' (%4). Chyba během odesílání zprávy od '%1' (%2) příjemci '%3' (%4). - + + Message "%1" was downloaded from server. + Zpráva "%1" byla úspěšně stažena ze serveru. + + + + Warning: If you delete selected messages from ISDS then these messages will be lost forever. + Upozornění: Jestli-že smažete vybrané zprávy ze serveru ISDS, budou tyto zprávy navždy ztraceny. + + + + You have to be logged into the Webdatovka if you want to delete message(s). + Musíte být přihlášeni do WebDatovky, aby bylo možné mazat zprávy. + + + + Warning: If you delete the message from Webdatovka then this message will be lost forever. + Upozornění: Jestliže smažete vybrané zprávy z WebDatovky, budou tyto zprávy navždy ztraceny. + + + + Warning: If you delete selected messages from Webdatovka then these messages will be lost forever. + Upozornění: Jestli-že smažete vybrané zprávy z WebDatovky, budou tyto zprávy navždy ztraceny. + + + + + You have to be logged into the WebDatovka if you want to download complete message. + Musíte být přihlášeni do WebDatovky, aby bylo možné stahovat kompletní zprávy. + + + + MojeID account + MojeID účet + + + Some databases of %1 in '%2' cannot be used. Některé databáze %1 v '%2' nelze použít. - + Conflicting databases %1 in '%2' cannot be used. Konfliktní databáze %1 v '%2' nelze použít. - + Please remove the conflicting files. Prosím, odstraňte konfliktní databázové soubory. - + Database files in '%1' cannot be created or are corrupted. Databázové soubory v '%1' nelze vytvořit nebo jsou poškozené. - + + Full message not present! + Úplná zpráva není k dispozici! + + + Database files for '%1' have been successfully moved to '%2'. @@ -4596,7 +3922,7 @@ '%2'. - + Database files for '%1' could not be moved to '%2'. @@ -4605,7 +3931,7 @@ '%2'. - + Database files for '%1' have been successfully copied to '%2'. @@ -4614,7 +3940,7 @@ '%2'. - + Database files for '%1' could not be copied to '%2'. @@ -4623,7 +3949,7 @@ '%2'. - + New database files for '%1' have been successfully created in '%2'. @@ -4632,7 +3958,7 @@ '%2'. - + New database files for '%1' could not be created in '%2'. @@ -4641,1046 +3967,438 @@ '%2'. - - The selection does not contain any valid ZFO files. - Nebyly nalezeny žádné použitelné ZFO soubory k importu. - - - The selection does not contain any valid ZFO messages. - Nebyly nalezeny žádné ZFO zprávy k importu. - - - The selection does not contain any valid ZFO delivery infos. - Nebyly nalezeny žádné ZFO doručenky k importu. - - - Cannot export complete message '%1'. - Nemohu exportovat kompletní zprávu '%1'. + + You have to be logged into the WebDatovka if you want to find databox. + Musíte být přihlášeni do WebDatovky, aby bylo možné vyhledávat datové schránky. - Cannot export delivery info for message '%1'. - Nemohu exporovat doručenku zprávy '%1'. - - - Account "%1" requires authentication via OTP <br/> security code for connection to databox. - Účet "%1" vyžaduje pro připojení k datové schránce<br/>autorizaci pomocí OTP bezpečnostního kódu. + + The selection does not contain any valid ZFO files. + Nebyly nalezeny žádné použitelné ZFO soubory k importu. - + Enter OTP security code for account Zadejte OTP bezpečnostní kód pro účet - First you must download the whole message before exporting. - Musíte nejprve stáhnout kompletní zprávu před jejím exportem. - - - - + + Portable version Přenosná verze - This file has been set as actual message database. It is test account with username "%1". - Tento soubor byl nastaven jako aktuální databáze zpráv. Jedná se o testovací účet s uživatelským jménem "%1". - - - This file has been set as actual message database. It is legal account with username "%1". - Tento soubor byl nastaven jako aktuální databáze zpráv. Jedná se o standardní účet s uživatelským jménem "%1". - - - This file (delivery info) has not been inserted into local database for account "%1" because an error was detected during insertion process. - Tento soubor (doručenka) nebyl importován do místní databáze pro účet %1", protože v průběhu vkládání došlo k chybě. - - - Couldn't open this file (delivery info) for authentication on the server Datové schránky. - Nepodařilo se otevřít tento soubor pro autentizaci dodejky na serveru Datové schránky. - - - ZFO import problem - Problém s importem ZFO - - - Do you want to continue with import? - Chcete pokračovat v importu ZFO souborů? - - - Action was canceled by user... - Akce byla zrušena uživatelem... - - - Import of ZFO file(s) was canceled - Import ZFO souborů byl zrušen - - - This file (delivery info) has not been inserted into database because there isn't any related message (%1) in the database for account "%2". - Tento soubor (doručenka) nebyl vložen do databáze, protože v databázi neexistuje odpovídající zpráva (%1) pro účet "%2". - - - This file (message) has not been inserted as sent message into local database for account "%1" because an error was detected during insertion process. - Tento soubor (zpráva) nebyl vložen do místní databáze jako odeslaná zpráva pro účet "%1", protože v průběhu vkládání došlo k chybě. - - - This file (message) already exists as sent message (%1) in the local database for account "%2". - Tento soubor (zpráva) již v místní databázi existuje jako odeslaná zpráva (%1) pro účet "%2". - - - Couldn't open this file (message) for authentication on the server Datové schránky. - Nepodařilo se otevřít tento soubor pro autentizaci zprávy na serveru Datové schránky. - - - First you must download message before export. - Musíte nejprve stáhnout kompletní zprávu před jejím exportem. - - - - - + + + PDF file (*.pdf) PDF soubor (*.pdf) - + Export of message delivery info "%1" to PDF was not successful! Export informací o doručení zprávy "%1" do souboru PDF nebyl úspěšný! - + Export of message delivery info "%1" to PDF was successful. Export informací o doručení zprávy "%1" do souboru PDF byl úspěšný. - It was not possible to create account "%1"! - Nebylo možné vytvořit účet "%1"! - - - - + + Change password of account "%1". Změnit heslo pro účet "%1". - + Change properties of account "%1". Změnit vlastnosti účtu "%1". - + Account "%1" was updated. Účet "%1" byl aktualizován. - + Account was moved up. Účet byl posunut nahoru. - + Account was moved down. Účet byl posunut dolů. - + Change data dierctory of account "%1". Změnit adresář pro data u účtu "%1". - Create and send reply on the message. - Vytvořit a odeslat odpověď na zprávu. - - - + Find databoxes from account "%1". Vyhledat datovou schránku z účtu "%1". - Message "%1" was deleted from ISDS and db. - Zpráva "%1" byla smazána z databáze a serveru ISDS. - - - Database file not found in selected directory. - Ve zvoleném adresáři nebyl nalezen žádný databázový soubor. - - - Import failed. No valid db file in directory. - Ve zvoleném adresáři nebyl nalezen žádný platný databázový soubor. - - - %1 database files were imported. - %1 databázových souborů bylo importováno. - - - %1 database file was imported. - %1 databázový soubor byl importován. - - - - - + + + Message authentication failed. Zpráva je validní. - Message authentication error - Chyba ověřování zprávy - - - Authentication of message has been stopped because the connection to ISDS failed! -Check your internet connection. - Ověřování zprávy byl zastaven, protože připojení k ISDS se nezdařilo! -Zkontrolujte připojení k internetu. - - - + Authentication of message has been stopped because the message file has wrong format! Ověřování zprávy bylo zastaveno, protože zpráva má chybný formát! - - - + + + An undefined error occurred! Try again. Došlo k neznámé chybě! Zkuste to znovu. - + Message is valid Zpráva je platná - Hash of message corresponds to ISDS message hash. -Message is valid. - Otisk zprávy odpovídá otisku zprávy na serveru Datové schránky. -Zpráva je validní. - - - ISDS confirms that the message hash is invalid! -Message is invalid. - ISDS potvrzuje, že otisk zprávy je neplatný! -Zpráva není validní. - - - Authenticate message error - Chyba autentizace zprávy - - - The message hash cannot be verified because the connection to ISDS failed! -Check your internet connection. - Ověření otisku zprávy nebylo provedeno, protože selhalo připojení k serveru Datové schránky! -Zkontrolujte Vaše připojení k internetu. - - - Authenticate message warning - Chyba autentizace zprávy - - - The message hash is not in local database. -Please download complete message form ISDS and try again. - Otisk zprávy nebyl nalezen v lokální databázi. -Prosím, stáhněte kompletní zprávu ze serveru Datové schránky a zkuste to znova. - - - + The message hash cannot be verified because an internal error occurred! Try again. Nebylo možné ověřit otisk zprávy, protože se v aplikaci vyskytla chyba! Zkuste to znova. - Content parsing error - Chyba při transformaci - - - Cannot parse the content of - Není možné načíst obsah - - - No ZFO file(s) for import. - Nejsou ZFO soubory pro import. - - - There is no account for import of ZFO file(s). - Neexistuje žádný účet pro import zpráv. - - - + Wrong ZFO format. This file does not contain correct data for import. Špatný formát ZFO. Soubor neobsahuje platná data zprávy pro import do databáze. - Error during file parsing. - Chyba při načítání souboru. - - - Import of ZFO file(s) ... Completed - Import ZFO souborů ... Hotovo - - - Processing of delivery info ZFO: %1 ... - Zpracovává se soubor s doručenkou: %1 ... - - - Imported as delivery info for message "%1", account "%2". - Importováno jako doručenka ke zprávě "%1" do účtu "%2". - - - File has not been imported because an error was detected during insertion process. - Soubor nebyl importován, protože byla zjištěna chyba při vkládání do databáze. - - - Message "%1" does not exists on the server Datové schránky. - Zpráva "%1" neexistuje na serveru Datové schránky. - - - Couldn't open this file for authentication on the server Datové schránky. - Nepodařilo se otevřít tento soubor pro autentizaci na serveru Datové schránky. - - - Delivery info for message "%1" already exists in the local database, account "%2". - Doručenka ke zprávě "%1" již v lokální databázi existuje, účet "%2". - - - This file (delivery info) has not been inserted into database because there isn't any related message (%1) in the databases. - Tento soubor (doručenka) nebyl vložen do databáze, protože v databázi neexistuje odpovídající zpráva (%1). - - - Processing of message ZFO: %1 ... - Zpracovává se soubor: %1 ... - - - Wrong ZFO format. File does not contain correct data for import. - Špatný formát ZFO. Soubor neobsahuje platná data zprávy pro import do databáze. - - - Imported as sent message "%1" into account "%2". - Importováno jako odeslaná zpráva "%1" do účtu "%2". - - - Message "%1" already exists in the local database, account "%2". - Zpráva "%1" již existuje v lokální databázi, účet "%2". - - - Imported as received message "%1" into account "%2". - Importováno jako přijatá zpráva "%1" do účtu "%2". - - - For this file does not exist correct databox or relevant account. - Pro tuto zprávu neexistuje odpovídající schránka nebo účet. - - - Export of message to ZFO was not successful! - Export zprávy do ZFO souboru nebyl úspěšný! - - - - - - - - - + + + + + + + Message export error! Chyba exportu zprávy! - Account "%1" requires authentication via OTP <br/>security code for connection to databox. - Pro připojení ke schránce pro účet "%1" je <br/>vyžadována OTP autentizace bezpečnostním kódem. - - - Authentication by SMS failed - Autentizace pomocí SMS selhala - - - Login error - Chyba přihlášení - - - + You have to change your password from the ISDS web interface. Your new password will be valid for 90 days. Heslo si změňte ve webovém rozhraní ISDS. Vaše nové heslo bude platné 90 dnů. - Time stamp expiration checking - Kontrola expirace časového razítka - - - Do you want to check for messages with expiring time stamps in account '%1' (user name '%2')? - Chcete vyhledat zprávy s expirujícím časovým razítkem v účtu '%1' (uživatelské jméno '%2')? - - - Check for expiring time stamps also in remaining accounts. - Vyhledat zprávy s expirujícím časovým razítkem také v ostatních účtech. - - - Note: Checking in all accounts can be slow. The action cannot be aborted. - Poznámka: Vyhledávání ve všech účtech může být pomalé. Akci nebude možné přerušit. - - - - + + Checking time stamps in account '%1'... Kontrola časových razítek v účtu '%1'... - + Time stamp expiration check results Výsledky kontroly expirace časových razítek - + Time stamp expiration check in account '%1' finished with result: Kontrola časových razítek v účtu '%1' skončila s výsledkem: - Database file '%1' cannot be used. - Nelze použít databázový soubor '%1'. - - - + Loading of ZFO file(s) failed! Načítání ZFO souborů selhalo! - + Time stamp expiration check of ZFO files finished with result: Kontrola časových razítek ZFO souborů skončila s výsledkem: - + Total of ZFO files: %1 Celkem ZFO souborů: %1 - + ZFO files with time stamp expiring within %1 days: %2 ZFO souborů s časovým razítkem expirujícím do %1 dnů: %2 - + Unchecked ZFO files: %1 Nezkontrolovaných ZFO souborů: %1 - - + + Total of messages in database: %1 Celkem zpráv v databázi: %1 - + Messages with time stamp expiring within %1 days: %2 Zpráv s časovým razítkem expirujícím do %1 dnů: %2 - + Unchecked messages: %1 Nezkontrolovaných zpráv: %1 - + See details for more info... Více informací naleznete v podrobnostech... - + Do you want to export the expiring messages to ZFO? Chcete exportovat expirující zprávy do ZFO? - - + + Time stamp of message %1 expires within specified interval. Časové razítko zprávy %1 expiruje do určeného limitu. - - + + Time stamp of message %1 is not present. Časové razítko zprávy %1 není k dispozici. - Timestamp expiration checking - Kontrola expirace časového razítka - - - See detail for more info... - Více informací v podrobnostech... - - - - + + Export ZFO Exportovat ZFO - Can not export complete message. - Nelze exportovat zprávu - - - You must download message firstly before export. - Musíte nejprve stáhnout kompletní zprávu před jejím exportem. - - - Do you want to download complete message now? - Chcete stáhnout kompletní zprávu nyní a pokračovat v akci? - - - Can not export message - Nelze exportovat zprávu - - - You have to download message firstly before export. - Musíte nejprve stáhnout kompletní zprávu před jejím exportem. - - - + Export of message "%1" to ZFO was not successful! Export zprávy "%1" do souboru ZFO nebyl úspěšný! - Export of message "%1" to ZFO was successful. - Export zprávy "%1" do souboru ZFO byl úspěšný. - - - Export of message delivery info to ZFO was not successful! - Export informací o doručení zprávy do souboru ZFO nebyl úspěšný! - - - - + + Delivery info export error! Chyba exportu informací o doručení! - Can not export delivery info for message. - Nelze exportovat informace o doručení. - - - - + + Export of message delivery info "%1" to ZFO was not successful! Export informací o doručení zprávy "%1" do souboru ZFO nebyl úspěšný! - + Export of message delivery info "%1" to ZFO was successful. Export informací o doručení zprávy "%1" do souboru ZFO byl úspěšný. - Export of message devilery info to PDF was not successful! - Export informací o doručení zprávy do souboru PDF nebyl úspěšný! - - - Export of message devilery info "%1" to PDF was not successful! - Export informací o doručení zprávy "%1" do souboru PDF nebyl úspěšný! - - - + Printing of delivery info "%1" to PDF. Please wait... Probíhá tisk informací o dodání zprávy "%1" do PDF. Prosím čekejte... - Export of message devilery info "%1" to PDF was successful. - Export informací o doručení zprávy "%1" do souboru PDF byl úspěšný. - - - Export of message envelope to PDF was not successful! - Export obálky zprávy do souboru PDF nebyl úspěšný! - - - - - - + + + + Export of message envelope "%1" to PDF was not successful! Export obálky zprávy "%1" do souboru PDF nebyl úspěšný! - - + + Export of message envelope "%1" to PDF was successful. Export obálky zprávy "%1" do souboru PDF byl úspěšný. - - + + Datovka - Export error! Datovka - chyba exportu! - - + + Cannot export the message Nelze exportovat zprávu - - + + First you must download message before its export... Musíte nejprve stáhnout kompletní zprávu před exportem... - Datovka internal error! - Datovka interní chyba! - - - + SMS code for account SMS kód pro účet - Enter security code again - Zadejte znovu bezpečnostní kód - - - The security code for this account was not accepted! - Vámi zadaný bezpečnostní kód pro tento účet byl odmítnut! - - - Account: - Účet: - - - Enter the correct security code again. - Zadejte znovu bezpečnostní kód. - - - OTP: Zkontrolujte přihlašovací údaje a zadejte znova bezpečnostní kód. - OTP: Zkontrolujte přihlašovací údaje a zadejte znova bezpečnostní kód. - - - OTP: Váš přístup byl na 60 minut zablokován. Důvodem může být opakované neúspěšné přihlášení. - OTP: Váš přístup byl na 60 minut zablokován. Důvodem může být opakované neúspěšné přihlášení. - - - OTP: Platnost Vašeho hesla nebo bezpečnostního kódu skončila. - OTP: Platnost Vašeho hesla nebo bezpečnostního kódu skončila. - - - OTP: Pro přístup na požadovanou stránku nemá Váš účet potřebné oprávnění. - OTP: Pro přístup na požadovanou stránku nemá Váš účet potřebné oprávnění. - - - + Datovka Datovka - Do you want to close application Datovka? - Chcete opravdu ukončit Datovku? - - - Datovka cannot be closed now because downloading of messages on the background is running... - Datovka teď nemůže být ukončena, protože se právě synchronizuje účet nebo zpráva na pozadí aplikace... - - - Wait until the action will finished and try again. - Počkejte, až bude akce dokončena a zkuste to znova. - - - + New account error Chyba nového účtu - + It was not possible to get user info and databox info from ISDS server for account Nebylo možné získat informace o uživateli a jeho datové schránce ze serveru ISDS pro účet - It was not possible to get user info and databox info for this account from server for user - Nebylo možné získat informace o uživateli a jeho datové schránce ze serveru ISDS pro účet - - - + Account Účet - + was not created! nebyl vytvořen! - Can not export the message - Nelze exportovat zprávu - - - Enter search word - Zadejte hledané slovo - - - + Welcome... Vítejte... - + Storage: disk | disk Úložiště: disk | disk - + unknown or without expiration Neznámý nebo bez expirace - Can not export delivery info for message - Nelze exportovat dodejku zprávy - - - You must download message firstly before its export... - Musíte nejprve stáhnout kompletní zprávu před exportem... - - - + Save message as ZFO file Uložit zprávu do souboru ZFO - Can not export the delivery info - Nelze exportovat dodejku - - - You must download message firstly before export... - Musíte nejprve stáhnout kompletní zprávu před exportem... - - - + Save delivery info as ZFO file Uložit doručenku do soubor ZFO - Export of message delivery info to PDF was not successful! - Export informací o doručení zprávy do souboru PDF nebyl úspěšný! - - - + Save delivery info as PDF file Uložit doručenku do soubor PDF - PDF printing - Tiskne se PDF - - - - + + Save message envelope as PDF file Uložit obálku zprávy do soubor PDF - - + + Printing of message envelope "%1" to PDF. Please wait... Probíhá tisk obálky zprávy "%1" do PDF. Prosím čekejte... - You have to download message firstly before its export... - Musíte nejprve stáhnout kompletní zprávu před jejím exportem... - - - Authentication error! - Chyba autentizace! - - - It was not possible to connect to your Databox. - Nebylo možné se připojit k Vaší datové schránce. - - - Authorization failed! - Chyba autorizace! - - - It was not possible to connect to your Databox from account "%1" - Nebylo možné se připojit k Vaší datové schránce z účtu "%1" - - - ISDS error: - ISDS vrací: - - - Please check your credentials including the test-environment setting. - Prosím, zkontrolujte své přihlašovací údaje, včetně nastavení testovacích účtů. - - - + Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. Účet s uživatelským jménem '%1' a jeho databáze již existují. Nový účet nebyl vytvořen a vybraná databáze nebyla k účtu přiřazena. - + Account with name '%1' has been created (user name '%1'). Účet s názvem '%1' byl vytvořen (uživatelské jméno '%1'). - It is possible that your password has expired - in this case, you need to use the official web interface of Datové schránky to change it. - Je možné, že vypršela platnost vašeho hesla. V tomto případě potřebujete navštívit oficiální webové rozhraní Datových schránek a změnit ho. - - - OTP authentication error! - Selhala OTP autentizace! - - - Authorization via OTP failed! - Selhala OTP autentizace! - - - It is aslo possible that your password has expired - in this case, you need to use the official web interface of Datové schránky to change it. - Také je možné, že vypršela platnost Vašeho hesla - v tomto případě se musíte přihlásit na stránky datové schránky a heslo si změnit. - - - Connection to ISDS error! - Chyba připojení k serveru Datové schránky! - - - It was not possible to establish a connection within a set time. - Nebylo možné vytvořit spojení ve stanoveném čase. - - - Connection to ISDS timeout! - Chyba navazování spojení se serverem Datové schránky! - - - This is either caused by an extremely slow and/or unstable connection or by an improper setup. - Tento problém je obvykle způsoben velmi pomalým a/nebo nestabilním spojením či nesprávným nastavením sítě. - - - Please check your internet connection and try again. - Prosím, zkontrolujte Vaše připojení k internetu a zkuste to znovu. - - - It might be necessary to use a proxy to connect to the server. If yes, please set it up in the File/Proxy settings menu. - Je možné, že pro spojení se serverem je třeba použít proxy. Pokud ano, nastavte ji prosím v menu Soubor/Nastavení proxy. - - - It was not possible to establish a connection to server Datové Schránky. - Nebylo možné navázat spojení se serverem Datové schránky. - - - It was not possible a connection between your computer and the server of Datove schranky. - Nebylo možné navázat spojení mezi Vaším počítačem a serverem Datové schránky. - - - Connection to ISDS failed! - Připojení k datové schránce selhalo! - - - This is usually caused by either lack of internet connection or by a firewall on the way. - Tento problém je obvykle způsoben neexistencí aktivního internetového připojení nebo přítomností firewallu. - - - It was not possible to connect to your databox form account "%1". - Nebylo možné navázat spojení s Vaší datovou schránkou z účtu "%1". - - - + + Mode: online Režim: připojeno (online) - Server connection for - Připojení pro - - - Enter security code for account - Zadejte bezpečnostní kód pro účet - - - There were some errors during saving of the overview: - Při exportu korespondence se objevily problémy: - - - does not contain data necessary for ZFO export - neobsahuje data potřebná k exportu do souboru ZFO - - - And many more - A několik dalších - - - messages were successfully exported to ZFO - zprávy byly úspěšně exportovány do ZFO - - - Accounts - Účty - - - ID - ID - - - Title - Předmět - - - Sender - Odesílatel - - - Delivered - Přijato - - - Accepted - Potvrzeno - - - Read locally - Přečteno lokálně - - - Recipient - Příjemce - - - Status - Stav - - - File name - Název souboru - - - Size - Velikost - - - Date - Datum - - - Save file - Uložit soubor - - - Save all - Uložit vše - - - Open with - Otevřít - - - Remove - Odstranit - - - - - - - - - - - + + + + + + + + + File Soubor - Databox - Databox - - - + Message Zpráva - + Tools Nástroje - + Help Nápověda - + toolBar Panel nástrojů - + Sync all accounts Synchronizovat účty - Add account - Vytvořit účet - - - Datovka - Free interface for Datové schránky - Datovka - svobodné rozhraní pro Datové schránky - - - + Download complete message, including attachments and verify its signature Stáhnout kompletní zprávu, včetně příloh a ověřit její podpis - Save all attachments to files - Uložit všechny přílohy do adresáře - - - Save selected attachment to a file - Uložit vybraný soubor jako - - - + Open attachment in an associated application Otevřít přílohu v přiřazené aplikaci - Verify signature - Ověřit podpis - - - - + + Signature details Detail podpisu - + Data box Schránka - - + + Remove account - Odstranit účet - - - Verify signature of message - Ověřit podpis zprávy - - - Verify -signature - Ověřit -podpis + Odstranit účet - + Show details about electronic signature of this message Zobrazit detailní informace o digitálním podpisu zprávy - Signature -details - Detail -podpisu - - - + For current message you can locally set if the message is not processed, if the message is in progress or if was already @@ -5691,778 +4409,521 @@ nebo vyřízeno (bylo na zprávu odpovězeno) - + Unsettled Nevyřízeno - In progress - Vyřizuje se - - - + Settled Vyřízeno - + Shift+F5 Shift+F5 - + + Proxy settings Nastavení proxy - + Preferences Nastavení - + Preferences of Datovka Nastavení Datovky - + Quit Ukončit - + Ctrl+Q Ctrl+Q - Import database directory - Importovat databázový soubor - - - + + Create account from database Vytvořit účet z databáze - Get messages - Stáhnout zprávy - - - Synchronize account - Synchronizovat účet - - - + F5 F5 - + Create message Vytvořit zprávu - + Ctrl+N Ctrl+N - + Mark all as read Označit vše jako přečtené - + Change password Změnit heslo - + Account properties Vlastnosti účtu - Change account properties - Změnit nastavení vybraného účtu - - - + Move account up Posunout účet nahoru - + Move account down Posunout účet dolů - + Change data directory Změnit adresář pro uložení dat - + About Datovka O Datovce - + About Datovka application O Datovce - Help index - Nápověda - - - - Datovka update - Aktualizace - - - - Update Datovka application - Aktualizovat Datovku - - - + Find Data Box Vyhledat datovou schránku - + Authenticate message file Ověřit zprávu ze souboru ZFO - + View message from ZFO file Zobrazit zprávu ze souboru ZFO - + Export correspondence overview Exportovat přehled korespondence - Sync all - Synchonizovat vše - - - + Synchronize all accounts at once Synchronizovat všechny účty najednou - + + Add new data box account + Přidat nový účet k datovým schránkám + + + + Quit the application + Ukončit aplikaci + + + Sync account Synchronizovat účet - + Synchronize selected account Synchronizovat vybraný účet - + + Mark all messages as read + Označit všechny zprávy jako přečtené + + + Sets a new password to the selected account on the ISDS server Nastaví nové heslo pro zvolený účet na serveru ISDS - + Manage account properties Spravovat vlastnosti účtu - + Move selectet account one position up Posunout vybraný účet jednu pozici nahoru - + Move selectet account one position down Posunout vybraný účet jednu pozici dolů - + Change the directory where data are being stored for the selected account Změnit adresář, kam se ukládají data pro vybraný účet - + + Find data box + Najít datovou schránku + + + + Verify message authenticity + Ověřit pravost zprávy + + + + View content of a ZFO file + Zobrazit obsah ZFO souboru + + + + Create a correspondence overview + Vytvořit přehled korespondence + + + Download signed message Stáhnout podepsanou zprávu - + Reply to the selected message Odpovědět na vybranou zprávu - + Display details about the signature Zobrazit podrobnosti o podpisu - + Deletes message from local database and/or from ISDS server Vymazat zprávu z lokální databáze a/nebo ze serveru ISDS - + Export the selected message as ZFO file Exportovat vybranou zprávu jako ZFO soubor - + Pass the selected message to an external application Předat vybranou zprávu externí aplikaci - + Pass the delivery information of the selected message to an external application Předat doručenku vybrané zprávy externí aplikaci - + Export the delivery information of the selected message as ZFO file Exportovat doručenku vybrané zprávy jako ZFO soubor - + Export the delivery information of the selected message as PDF file Exportovat doručenku vybrané zprávy jako PDF soubor - + Export the envelope of the selected message as PDF file Exportovat obálku vybrané zprávy jako PDF soubor - + Export envelope PDF with attachments Exportovat obálku jako PDF s přílohami - + Export the envelope to a PDF file together with message attachments Exportovat obálku to souboru PDF společně s přílohami zprávy - + Save selected attachments to files Uložit vybrané přílohy do souborů - + Saves all message attachments Uloží všechny přílohy zprávy - + Import messages from ZFO files Importovat zprávy ze souborů ZFO - + + Import a message from ZFO file into the database + Importovat zprávu se souboru ZFO do databáze + + + Use the selected message as a template Použít vybranou zprávu jako šablonu - + Search message Vyhledat zprávu - + + Check whether the message time stamp is not expired or expiring + Oveřit, zda časové razítko zprávy neexpirovalo nebo neexpiruje + + + Homepage Domovská stránka - + + Open the home page of the application + Otevřít domovskou stránku aplikace + + + Import messages from database Importovat zprávy z databáze - + + Import messages into database from an external database file + Importovat zprávy do databáze z externího databázového souboru + + + Split database by years Rozdělit databázi podle roků - + + Messages are going to be stored into separate database files according to years + Zprávy budou ukládány do databázových souborů rozdělených podle let + + + E-mail with ZFOs E-mail se ZFO - + Creates an e-mail containing ZFOs of selected messages Vytvoří e-mail obsahující ZFO vybraných zpráv - + E-mail with all attachments E-mail se všemi přílohami - + Creates an e-mail containing all attachments of selected messages Vytvoří e-mail obsahující všechny přílohy vybraných zpráv - + E-mail with selected attachments E-mail s vybranými přílohami - + Creates an e-mail containing selected attachments Vytvoří e-mail obsahující vybrané přílohy - + + Edit tags Editovat tagy - + Vacuum message database Vakuum databáze zpráv - Received all - Stáhnout vše + + This may reduce the database file size and optimise the access speed + To může zmenšit velikost databáze a optimalizovat přístupovou rychlost - Received messages from all accounts at once - Stáhnout zprávy ze všech účtů najednou + + + Forward message + Přeposlat zprávu - - Use message as template - Použít zprávu jako šablonu + + Add mojeID account + Přidat účet mojeID + + + + Add new mojeID account + Přidat nový mojeID účet - Search for messages in local database - Vyhledat zprávy v místní databázi + + Use message as template + Použít zprávu jako šablonu - + Advanced searching in message envelopes Rozšířené vyhledávání v obálkách zpráv - + Time stamp expiration check Zkontrolovat expirace časových razítek - Search for messages in local database. - Vyhledej zprávy v místní databázi. - - - Advanced searching in message envelopes. - Rozšířené vyhledávání v obálkách zpráv. - - - + Ctrl+Shift+F Ctrl+Shift+F - Delete message from local database - Smazat zprávu z místní databáze - - - Import ZFO file(s) into database - Importovat ZFO soubory do databáze - - - Delete message from server and local database - Smazat zprávu ze serveru a z místní databáze - - - Alt+A - Alt+A - - - Download messages - Stáhnout zprávy - - - Download messages from the box - Stáhnout zprávy ze schránky - - - Alt+D - Alt+D - - - + + User manual Uživatelská příručka - + Create and send a new message Vytvořit a poslat novou zprávu - Reply - Odpovědět - - - Reply on the selected message - Odpovědět na vybranou zprávu - - - Verify message - Ověřit zprávu - - - + Verify the selected message Ověřit vybranou zprávu - Download message signed - Stáhnout podepsanou zprávu - - - + Reply to message Odpovědět na zprávu - + Ctrl+R Ctrl+R - + Authenticate message Ověřit zprávu - + Delete message Vymazat zprávu - + Export message as ZFO Exportovat zprávu jako soubor ZFO - + Open message externally Otevřít zprávu externí aplikací - + Open delivery info externally Otevřít doručenku pomocí externí aplikace - + Export delivery info as ZFO Exportovat doručenku do ZFO - + Export delivery info as PDF Exportovat doručenku do PDF - + Export message envelope as PDF Exportovat obálku zprávy do PDF - + Open attachment Otevřít přílohu - - + Save attachment Uložit soubor jako - + Save all attachments Uložit vše - - Alt+M - Alt+M - - - Reply to the sender - Odpovědět odesílateli - - - Alt+R - Alt+R - - - Verify a message - Ověřit zprávu - - - Alt+V - Alt+V - - - Recent Received - Nedávno přijaté - - - Recent Sent - Nedávno odeslané - - - - MessageDb - - Advice of Delivery - Doručenka - - - Message ID: - ID zprávy: - - - Sender - Odesílatel - - - Name - Jméno - - - Recipient - Příjemce - - - General Information - Obecné informace - - - Subject - Předmět - - - paragraph - paragraf - - - letter - odstavec - - - Delegation - Delegace - - - Not specified - Nespecifikováno - - - Our ref.number - Naše číslo jednací - - - Our doc.id - Naše spisová značka - - - Your ref.number - Vaše číslo jednací - - - Your doc.id - Vaše spisová značka - - - To hands - K rukám - - - yes - Ano - - - no - Ne - - - Personal Delivery - Osobní doručení - - - Prohibit Delivery by Fiction - Zakázat doručení fikcí - - - Delivery/Acceptance Information - Informace o doručení/Přijetí - - - Delivery - Doručeno - - - Acceptance - Přijato - - - Events - Události - - - Time - Čas - - - Envelope - Obálka - - - Databox ID - ID schránky - - - Databox Type - Typ schránky - - - Attachments - Přílohy - - - Identification - Identifikace - - - ID - ID - - - Message type - Typ zprávy - - - Message author - Autor zprávy - - - To - Příjemce - - - Recipient Address - Adresa - - - Status - Stav - - - (downloaded and ready) - (staženo a připraveno) - - - not downloaded yet, ~ - ještě nestaženo, ~ - - - KB; use 'Download' to get them. - KB; použijte 'Stáhnout' k jejich získání. - - - (not available) - (nedostupné) - - - Signature - Podpis - - - Message signature - Podpis zprávy - - - Not present - nepřítomný - - - Invalid - Neplatný - - - Message signature and content do not correspond! - Podpis zprávy a její obsah si neodpovídají! - - - Valid - Platný - - - Certificate revocation check is turned off! - Kontrola zneplatnění certifikátu je vypnutá! - - - Signing certificate - Podepisující certifikát - - - Time-stamp - Časové razítko - - - File Size - Velikost souboru - Preferences - + Downloading Stahování - + Messages downloading Stahování zpráv - Automatically download new messages on background - Automaticky stahovat nové zprávy na pozadí - - - Check new messages every - Zkontrolovat nové zprávy každých - - - - + + minutes minut - + Automatically download whole messages (may be slow) Automaticky stahovat kompletní zprávy (může být pomalé) - + Automatically synchronize all accounts on startup Automaticky synchronizovat všechny účty po spuštění aplikace - + New versions Nové verze @@ -6472,7 +4933,7 @@ Datovka - nastavení - + When allowed, Datovka will automatically download messages on the background of application without blocking of user interface. Download period you can set bellow. @@ -6481,21 +4942,17 @@ Periodu stahování můžete nastavit níže. - + Automatically synchronise all in background Automaticky provádět hromadnou synchronizaci na pozadí - Background check every - Kontrola na pozadí každých - - - + Check every Kontrolovat každých - + When accessing your Databox, only envelopes of messages are downloaded at first. You can then download the whole message, including any attachments, manually. When this option is turned on, Datovka will perform the download of complete @@ -6507,26 +4964,26 @@ přístupu je delší doba stahování při pomalejším internetovém připojení. - + When allowed, Datovka will automatically synchronise accounts and also download new messages on background at startup. Pokud povolíte tuto možnost, Datovka bude automaticky synchronizovat účty a stahovat nové zprávy na pozadí po spuštění aplikace. - + When this option is active, Datovka will automatically check for new Datovka versions on startup. Pokud je tato volba aktivní, Datovka bude automaticky zjišťovat nové verze programu. - + Check for new Datovka versions on startup Kontrolovat nové verze Datovky po spuštění aplikace - + When this option is active, Datovka will send information about your Datovka version and related data as part of the request for new versions. This data contains the version of Datovka, version of libraries, operating @@ -6543,39 +5000,27 @@ Odeslaná data jsou použita pouze pro účely statistiky. - + Send version info alongside the request Posílat informaci o stávající verzi s dotazem - + Security Bezpečnost - It migth be possible for a person with access to your home directory to modify data in the Datovka database with malicious intent or to steal you login credentials for Datové Schránky. - -Using the checkboxes below, you can influence which data Datovka stores on the disk. - -Note: Password storage can be adjusted on per-account basis in the credentials dialog. - Osoba s přístupem k vašemu domovskému adresáři by mohla změnit data v databázi Datovky či odcizit vaše přihlašovací údaje pro Datové schránky. - -Pomocí následujícího nastavení můžete ovlivnit jaké údaje si Datovka ukládá na disk. - -Poznámka: Ukládání hesla můžete nastavit pro každý účet zvlášť v dialogu 'Přihlašovací údaje'. - - - + Storage options Volba uložení dat - + It migth be possible for a person with access to your home directory to modify data in the Datovka database with malicious intent or to steal you login credentials for Datové Schránky. Using the checkboxes below, you can influence which data Datovka stores on the disk. Note: Password storage can be adjusted on per-account basis in the credentials dialog. Osoby, které mají přístup do Vašeho domovského adresáře, mohou zlomyslně modifikovat data v databázi, nebo odcizit přihlašovací údaje k datovým schránkám. Pomocí následujících voleb můžete zvolit, jaká data se budou ukládat na disk. Poznámka: Ukládání hesla se dá nastavit pro jednotlivé účty v nastavení účtu. - + When allowed, messages are stored in a database in your home directory. Such storage might be compromised by an attacker and the content of messages might be modified. When turned off, messages are freshly @@ -6588,12 +5033,12 @@ starší než 90 dní. - + Allow message storage Povolit ukládání zpráv na disk - + Datovka stores some additional data outside the message database. These are data about the databox which allow for example warning about an expiring password. These data might be also changed by @@ -6604,62 +5049,62 @@ povaha činí tuto možnost relativně neškodnou. - + Allow storage of additional data Povolit ukládání ostatních dat na disk - + days dnů - + Navigation Navigace - + When account is opened, select Když je vybrán účet, tak označit - + After an account is opened, the newest message will be activated. Po otevření účtu bude otevřena nejnovější zpráva. - + Newest message Nejnovější zprávu - + When account is opened, the last message displayed in this account will be selected. Po otevření účtu bude vybrána poslední zobrazená zpráva z tohoto účtu. - + Last displayed message Poslední zobrazenou zprávu - + When account is opened, random message displayed in this account will be selected. Po otevření účtu bude vybrána náhodná zpráva z tohoto účtu. - + Nothing Nic - + Specifies file name format for attachment files and other exported files. Default value when saving attachment files is %f (i.e. saved file name will match the original @@ -6670,27 +5115,27 @@ přílohy). - + File name format of saved/exported files Formát jména ukládaných/exportovaných souborů - + Message file name: Jméno souboru zprávy: - + Delivery info file name: Jméno souboru doručenky: - + Attachment file name: Jméno souboru přílohy: - + Saves delivery info for every attachment file separately. The delivery info file name has to contain the original attachment file name (parameter %f is required). @@ -6699,16 +5144,12 @@ název přílohy (je vyžadován parametr %f). - Advanced - Pokročilé - - - + Signing certificate validity Platnost podepisujícího certifikátu - + Validity of the signing certificate will be checked against the current date. This gives the highest protection against compromised certificate exploit. @@ -6717,12 +5158,12 @@ certifikátu. - + Check against current date (safer) Kontrolovat proti aktuálnímu datu (bezpečnější) - + The validity of signing certificate is checked against a stored download date. This allows long-term storage of messages without false alarms about invalid signature. @@ -6734,37 +5175,37 @@ útočník by mohl upravit čas stažení zprávy v databázi Datovky. - + Check against the date of download Kontrolovat proti datu stažení zprávy - + Check certificate revocation list (CRL). Kontrolovat seznam zneplatněných certifikátů. - + Check certificate revocation list (CRL) Kontrolovat seznam zneplatněných certifikátů - + Connection settings Nastavení připojení - + Timeout for message downloading is set on Časový limit pro stahování zpráv je nastaven - + Saving Ukládání - + When allowed, Datovka will use the following directories as paths for loading and saving files in all accounts. Per-account path remembering will be disabled. @@ -6773,84 +5214,72 @@ Pamatování cest pro jednotlivé účty bude vypnuto. - + When saving all attachments also Při ukládání všech příloh také proveď - Note: If you have a slow connection to ISDS or you can not download complete messages, you can increase connection timeout. Default value is 5 minutes. Use 0 to disable timeout limits (not recommended). - Poznámka: Jestli-že máte pomalé připojení k ISDS nebo se Vám nedaří stáhnout kompletní zprávy, můžete navýšit časový limit. Výchozí hodnota je 5 minut. Nulová hodnota znamená, že je limit vypnutý (nedoporučuje se). - - - + Directories Adresáře - + Use global path settings Používat nastavené globální cesty - Note: When allowed, Datovka will use the following directories as paths for loading and saving files in all accounts. Per-account path remembering will be disabled. - Poznámka: Když je povoleno, Datovka bude používat následující adresáře jako výchozí pro vkládání či ukládání příloh ve všech účtech. Pamatování cest pro jednotlivé účty bude vypnuto. - - - + Path for saving of attachments is currently set on: Cesta pro ukládání příloh je aktuálně nastavena na: - - + + Change Změnit - + Path for adding of file to attachments is currently set on: Cesta pro přidávání příloh je aktuálně nastavena na: - + These actions will be performed when saving all message attachments. Tyto akce budou prováděny současně s ukládáním všech příloh. - When saving all attachments also: - Při ukládání všech příloh také proveď: - - - + Save signed message to ZFO Ulož podepsanou zprávu jako ZFO - + Save signed delivery info to ZFO Ulož podepsanou doručenku jako ZFO - + Save delivery info to PDF Ulož doručenku jako PDF - + Save message envelope to PDF Ulož obálku zprávy jako PDF - - + + Allows to set a time interval for automatically synchronise all accounts in the background. Umožňuje nastavit interval pro periodickou synchronizaci všech účtů na pozadí aplikace. - - + + Allows to set a timeout interval for network connection. If you have a slow network connection or you cannot download complete messages, here you can increase @@ -6861,245 +5290,241 @@ udržení spojení. - + Mark message as read settings Nastavení označování přečtených zpráv - - + + Allows to set a timeout interval for automatically marking message as read. Umožňuje nastavit časový interval pro automatické označení zprávy jako přečtené. - + Automatically mark message as read after Automaticky označit zprávu jako lokálně přečtenou za - + seconds sekund - + Message time stamps expiring within the selected numer of days will be included into the expiration notification summary. Časová razítka zpráv expirujících v průběhu zvoleného počtu dnů budou zahrnuta do upozornění o expiraci. - + Message time stamp expiration Expirace časových razítek zpráv - - + + Allows to set a interval how many days before expiring of timestamp will be message included in the check results. Umožňuje nastavit časový interval s jakým předstihem před vypršením platnosti časového razítka bude zpráva zahrnuta do výsledku kontroly. - + Check for time stamps expiring within Zjišťovat časová razítka expirující do - + Interface Rozhraní - + Style of toolbar buttons Vzhled tlačítek v panelu nástrojů - + Only icons will be displayed in the toolbar. Pouze ikony budou zobrazeny v nástrojovém panelu. - + Only display the icon Zobrazovat pouze ikony - + Icons and text beside them will be displayed in the toolbar. Ikony a popisky vedle nich budou zobrazeny v nástrojovém panelu. - + The text appears beside the icon Zobrazovat text za ikonou - + Icons and text under them will be displayed in the toolbar. Ikony a popisky pod nimi budou zobrazeny v nástrojovém panelu. - + The text appears under the icon Zobrazovat text pod ikonou - - Note: toolbar setting will not apllied until you restart the application. + + Note: toolbar settings will not be applied until you restart the application. Poznámka: nastavení panelu nástrojů nebude aktivní dokud nerestartujete aplikaci. - + Select a new path for saving of attachments. Vyberte novou cestu pro ukládání příloh. - + Select a new path for adding of files to attachments. Vyberte novou cestu pro přidávání souborů do příloh. - + When saving all attachments also save signed message as ZFO to the same path. Uložit také podepsanou zprávu jako ZFO soubor do cesty, kam se ukládají přílohy. - + When saving all attachments also save message envelope as PDF to the same path. Uložit také obálku zprávy jako PDF soubor do cesty, kam se ukládají přílohy. - + When saving all attachments also save signed delivery info as ZFO to the same path. Uložit také podepsanou doručenku jako ZFO soubor do cesty, kam se ukládají přílohy. - + When saving all attachments also save delivery info as PDF to the same path. Uložit také informace o doručení jako PDF soubor do cesty, kam se ukládají přílohy. - + delivery year (YYYY) rok doručení (YYYY) - + delivery month (MM) měsíc doručení (MM) - + delivery day (DD) den doručení (DD) - + delivery minute (mm) minuta doručení (mm) - + delivery hour (hh) hodina doručení (hh) - + message ID ID zprávy - + message subject (separated by "-") předmět zprávy (oddělen pomocí "-") - + databox ID ID schránky - + attachment filename (with suffix) jméno souboru přílohy (s příponou) - + user ID ID uživatele - + name of sender (separated by "-") jméno odesílatele (oddělené "-") - + Example: Příklad: - + means znamená - + Note: Illegal characters in the name of file will be replaced. Poznámka: Nepovolené znaky v názvu souboru budou automaticky nahrazeny. - + Save delivery info for every attachment file. Format: Uložit doručenku pro každý soubor přílohy. Formát: - + Language Jazyk - + Application language Jazyk aplikace - + Use system language Použít jazyk systému - + Czech Čeština - + English Angličtina - - Note: language setting will not apllied until you restart the application. + + Note: language settings will not be applied until you restart the application. Poznámka: nastavení jazyka nebude aktivní dokud nerestartujete aplikaci. - - NOTE: language setting will not apllied until you restart the application. - Poznámka: nastavení jazyka nebude aktivní dokud nerestartujete aplikaci. - Proxysets @@ -7139,7 +5564,7 @@ - Manual proxy setting + Manual proxy settings Ruční nastavení proxy @@ -7186,7 +5611,7 @@ Enter your username - Zadejte svoje uživatelské jméno + Zadejte své uživatelské jméno @@ -7265,14 +5690,6 @@ Virtuální - Message bas submitted (originates at ISDS ) - Zpráva byla podána (vznikla v ISDS) - - - Data message and papers signed with time-stamp. - Datová zprava včetně písemností podepsaná časovým razítkem. - - Message did not pass through AV check; infected paper deleted; final status before deletion. Zpráva neprošla AV kontrolou; nakažená písemnost je smazána; konečný stav zprávy před smazáním. @@ -7288,35 +5705,11 @@ Zpráva byla přečtena (na portále nebo akcí ESS). - Message did not pass through AV check; infected paper deleted; final status before deletion - Zpráva neprošla AV kontrolou; nakažená písemnost je smazána; konečný stav zprávy před smazáním - - - Message handed into ISDS (delivery time recorded) - Zpráva dodána do ISDS (zapsán čas dodání) - - - 10 days have passed since the delivery of the public message which has not been accepted by logging-in (assumption of delivery by fiction in nonOVM DS); this state cannot occur for commertial messages. - Uplynulo 10 dnů od dodání veřejné zprávy, která dosud nebyla doručena přihlášením (předpoklad doručení fikcí u ne-OVM DS). - - - A person authorised to read this message has logged-in -- delivered message has been accepted. - Osoba oprávněná číst tuto zprávu se přihlásila - dodaná zpráva byla doručena. - - - Message has been read (on the portal or by ESS action) - Zpráva byla přečtena (na portále nebo akcí ESS) - - Message has been submitted (has been created in ISDS) Zpráva byla podána (vznikla v ISDS) - Data message and including its attachments signed with time-stamp. - Datová zpráva včetně písemností podepsána časovým razítkem. - - Data message including its attachments signed with time-stamp. Datová zpráva včetně písemností podepsána časovým razítkem. @@ -7452,30 +5845,6 @@ Došlo k chybě při zjišťování stavu. - DS je přístupná, lze do ní dodávat zprávy, na Portále lze vyhledat - DS je přístupná, lze do ní dodávat zprávy, na portále lze vyhledat - - - DS je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna - DS je dočasně znepřístupněna (na vlastní žádost), může být později opět zpřístupněna - - - DS je dosud neaktivní, dosud se do ní nikdo nepřihlásil z Portálu a nelze ji zpřístupnit pouze na základě doručení přístupových údajů - DS je dosud neaktivní, dosud se do ní nikdo nepřihlásil z Portálu a nelze ji zpřístupnit pouze na základě doručení přístupových údajů - - - DS je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna) - DS je trvale znepřístupněna, čeká na smazání (může být opět zpřístupněna) - - - DS je smazána (přesto existuje v ISDS) - DS je smazána (přesto existuje v ISDS) - - - Došlo k chybě při zjišťování stavu - Došlo k chybě při zjišťování stavu - - Correspondence overview export error. Chyba při exportu přehledu korespondence. @@ -7486,19 +5855,11 @@ Chyba při exportu přehledu korespondence. - Correspondence export error - Chyba exportu korespondence - - File name Název souboru - Size - Velikost - - Data box ID ID datové schránky @@ -7539,10 +5900,6 @@ Rodné příjmení - Firm name - Název firmy - - Company name @@ -7658,9 +6015,9 @@ - - - + + + Sender Odesílatel @@ -7671,9 +6028,9 @@ - - - + + + Recipient Příjemce @@ -7684,8 +6041,8 @@ - - + + To hands K rukám @@ -7695,10 +6052,6 @@ Sekce - Title - Předmět - - Your reference number Vaše číslo jednací @@ -7729,10 +6082,6 @@ Rok - Selection - Sekce - - Paragraph Odstavec @@ -7764,7 +6113,7 @@ - + Status Stav @@ -7784,171 +6133,135 @@ Přečteno lokálně - + Data box application Aplikace pro datové schránky - + Use <conf-subdir> subdirectory for configuration. Použít <conf-subdir> podadresář pro konfiguraci. - + conf-subdir conf-subdir - + On start load <conf> file. Po spuštění načíst <conf> soubor. - - + + conf conf - + On stop save <conf> file. Po ukončení uložit <conf> soubor. - + Log messages to <file>. Zaznamenávat výpisy do <souboru>. - + file soubor - + Set verbosity of logged messages to <level>. Default is Nastavit podrobnost ladicích zpráv na <level>. Výchozí je - - + + level úroveň - + Set debugging verbosity to <level>. Default is Nastavit podrobnost ladicích informací na <level>. Výchozí je - + Service: connect to isds and login into databox. Služba: připojit se k datové schránce. - + Application is loading... Aplikace se načítá... - Service: connect to isds and loggin into databox. - Služba: připojit k serveru isds a přihlásit se do schránky. - - - - - - - - + + + + + + string-of-parameters řetězec-parametrů - + Service: download list of received/sent messages from ISDS. Služba: stáhnout seznam přijatých a odeslaných zpráv z ISDS. - + Service: create and send a new message to ISDS. Služba: vytvořit a odeslat novou zprávu do ISDS. - + Service: download complete message with signature and time stamp of MV. Služba: stáhnout kompletní zprávu s podpisem a časovým razítkem MV. - + Service: download delivery info of message with signature and time stamp of MV. Služba: stáhnout informace o doručení zprávy s podpisem a časovým razítkem MV. - + Service: get information about user (role, privileges, ...). Služba: stáhnout informace o uživateli (role, oprávnění, ...). - + Service: get information about owner and its databox. Služba: stáhnout informace o vlastníkovi a jeho datové schránce. - + Service: get list of messages where attachment missing (local database only). Služba: získat seznam zpráv bez přílohy (pouze lokální databaze). - + Service: find a databox via several parameters. Služba: vyhledat datovou schránku na ISDS. - + ZFO file to be viewed. Zobrazovaný ZFO soubor. - Accounts - Účty - - - Recent Received - Nedávno přijaté - - - Recent Sent - Nedávno odeslané - - - All - Vše - - - Received - Přijaté - - - Sent - Odeslané - - - unknown or without expiration - Neznáný nebo bez expirace - - - + Advice of Delivery Doručenka - Message ID: - ID zprávy: - - - - + + Message ID: ID zprávy: @@ -7956,304 +6269,280 @@ - - - - + + + + Name Jméno - - + + General Information Obecné informace - - - + + + Subject Předmět - paragraph - odstavec - - - letter - písmeno - - - Attachments downloaded - Přílohy staženy - - - Processing state - Stav vyřizování - - - - + + paragraph odstavec - - + + letter písmeno - - + + Delegation Zmocnění - - - - - - - - - - + + + + + + + + + + Not specified Nebylo zadáno - - + + Our ref.number Naše číslo jednací - - + + Our doc.id Naše spisová značka - - + + Your ref.number Vaše číslo jednací - - + + Your doc.id Vaše spisová značka - - - - + + + + yes ano - - - - + + + + no ne - - + + Personal Delivery Osobní doručení - - + + Prohibit Delivery by Fiction Zakázat doručení fikcí - + List of attachments Seznam příloh - + Delivery/Acceptance Information Informace o dodání a doručení - - + + Delivery Dodejka - + Databox type Typ datové schránky - + Download the complete message in order to verify its time stamp. Stáhněte kompletní zprávu pro ověření jejího časového razítka. - + Acceptance Doručenka - - + + Events Události - + Sender Databox ID ID datové schránky odesílatele - + Recipient Databox ID ID datové schránky příjemce - + Time Čas - + Envelope Obálka - - + + Databox ID ID schránky - + Databox Type Typ datové schránky - - - - + + + + Attachments Přílohy - + Identification Identifikace - + Message ID ID zprávy - + Message type Typ zprávy - From - Od - - - + Sender Address Adresa odesílatele - + Message author Odesílající osoba - To - Komu - - - + Recipient Address Adresa příjemce - + (downloaded and ready) (staženo a připraveno) - + not downloaded yet, ~ ještě nestaženo, ~ - + KB; use 'Download' to get them. KB; použijte 'Stáhnout' k jejich získání. - + (not available) (nestažené) - + Signature Podpis - - - + + + Message signature Podpis zprávy - - + + Not present Není k dispozici - + Download the complete message in order to verify its signature. Stáhněte kompletní zprávu pro ověření jejího podpisu. - + Time stamp Časové razítko - - - - - - + + + + + + Invalid Neplatný - - + + Message signature and content do not correspond! Podpis zprávy a její obsah si neodpovídají! @@ -8262,38 +6551,29 @@ - - - - - + + + + + Valid Platný - - + + Certificate revocation check is turned off! Kontrola zneplatnění certifikátu je vypnutá! - + Signing certificate Podepisující certifikát - Time-stamp - Časové razítko - - - - File Size - Velikost souboru - - Depends on libraries: Závisí na knihovnách: @@ -8305,18 +6585,14 @@ Podpis zprávy není přítomný. - Valid: - Platné: - - - + No Ne - + Yes Ano @@ -8420,72 +6696,12 @@ Organizační jednotka - Cannot check signing certificate - Nelze zkontrolovat podpisový certifikát - - - Version: - Verze: - - - Serial number: - Sériové číslo: - - - Signature algorithm: - Algoritmus podpisu: - - - Issuer: - Vydal: - - - Validity: - Platnost: - - - Valid from: - Platnost od: - - - Valid to: - Platnost do: - - - Subject: - Předmět: - - Time stamp not present. Časové razítko není přítomno. - Time: - Čas: - - - Issuer: - Vydal: - - - Organisation: - Organizace: - - - Organisational unit: - Organizační jednotka: - - - Name: - Jméno: - - - Country: - Země: - - - + Created using Datovka Vytvořeno Datovkou @@ -8582,10 +6798,6 @@ Prosím, vyplňte ve formuláři <b>předmět</b>, <b>alespoň jednoho příjemce</b> a <b>alespoň jednu přílohu</b>: - From: - Od: - - Subject: Předmět: @@ -8717,17 +6929,13 @@ Příjemci: - + Attachment size is larger than 20 MB. Message cannot be sent! Velikost příloh je větší než 20 MB. Zprávu nebude možné odeslat! - Add a recipient to the current message - Přidat příjemce do seznamu - - - + Add Přidat @@ -8738,7 +6946,7 @@ - + Remove Odstranit @@ -8778,55 +6986,51 @@ Vložit ID DS - + Id ID - + Databox ID ID datové schránky - ID datové schránky - ID datio - - - + Name Jméno - + Full name of recipient or name of organization Plné jméno příjemce nebo název organizace - + Address Adresa - + Address of recipient Adresa příjemce - + PDZ PDZ - + The message for recipient will be sent as Poštovní Datová Zpráva Zpráva bude odeslána jako placená Poštovní Datová Zpráva - + Even if recipient did not read this message, message is considered as delivered after (currently) 10 days. This is delivery through fiction. @@ -8835,7 +7039,7 @@ (aktuálně) po 10 dnech. Toto je doručení fikcí. - + You will pay the transfer charges of the reply message. This is useful when the recipient does not have sending of postal data messages active. @@ -8844,129 +7048,64 @@ neumožňuje zasílání poštovních datových zpráv. - + Add a new file to the attachments Přidat nový soubor do přílohy - + Remove the selected file from attachments Odstranit vybraný soubor z přílohy - + Open selected file in associated application Otevřít vybraný soubor v externí aplikaci - <html><head/><body><p>Even if recipient did not read this message, message is considered as delivered after (currently) 10 days. This is delivery through fiction.</p><p><br/></p></body></html> - <html><head/><body><p>Even if recipient did not read this message, message is considered as delivered after (currently) 10 days. This is delivery through fiction.</p><p><br/></p></body></html> - - - + Allow delivery through fiction Povolit doručení fikcí - - + + Include sender identification Přidat identifikaci odesílatele - + Pay transfer charges for reply Zaplatit poštovní poplatky za odpověď - - + + Use offered payment of transfer charges by recipient Využít nabízenou platbu za poštovní poplatky příjemcem - + Attachments: Přílohy: - Add a new attachment to the current message - Přidat novou přílohu do zprávy - - - Remove the selected attachment from current message - Odstranit vybraný soubor z přílohy - - - Open selected attachment in associated application - Otevřít vybraný soubor - - - + Open Otevřít - Attachment size is larger than 10 MB. Message cannot be sent! - Velikost příloh je větší než 10 MB. Zprávu nebude možné odeslat! - - - - File - Soubor - - - - File name - Název souboru - - - - Type - Typ - - - - MimeType - Typ MIME - - - - MIME type of file - MIME typ přiloženého souboru - - - - Size - Velikost - - - - Size of file in bytes - Velikost souboru v bajtech - - - - FilePath - Cesta k souboru - - - - Absolute path of file - Plná cesta k souboru - - - + Send message Odeslat zprávu - + Send Odeslat - + Cancel Zrušit @@ -9106,28 +7245,6 @@ - YesNoCheckboxDlg - - Delete action - Akce - - - Question? - Otázka? - - - CheckBox - CheckBox - - - - aboutDialog - - Portable version - Přenosná verze - - - msgSearchDialog @@ -9239,25 +7356,5 @@ Search Vyhledat - - Account - Účet - - - Message ID - ID zprávy - - - Subject - Předmět - - - Sender - Odesílatel - - - Recipient - Příjemce - diff -Nru datovka-4.7.0/locale/datovka_en.ts datovka-4.7.1/locale/datovka_en.ts --- datovka-4.7.0/locale/datovka_en.ts 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/locale/datovka_en.ts 2017-01-19 09:29:26.000000000 +0000 @@ -57,12 +57,67 @@ - + Accounts + AttachmentInteraction + + + Error storing attachment. + + + + + Cannot write temporary file for attachment '%1'. + + + + + + Save attachment + + + + + + Error saving attachment. + + + + + Cannot write file '%1'. + + + + + Save attachments + + + + + Some files already exist. + + + + + In total %1 attachment files could not be written. + + + + + These are: + + + + + Error saving attachments. + + + + ChangeDirectory @@ -231,17 +286,17 @@ - + ID - + Name - + Address @@ -455,15 +510,38 @@ + DbFlsTblModel + + + local database + + + + + File size + + + + + File path + + + + + unknown + + + + DbMsgsTblModel - - + + Attachments downloaded - + Processing state @@ -636,14 +714,14 @@ DlgContacts - - - + + + no - + yes @@ -883,57 +961,62 @@ DlgCreateAccount - + Password - + Certificate - + Certificate + Password - + Password + Secure code - + Password + Secure SMS - + Update account %1 - + Enter password for account %1 - + Set certificate for account %1 - + Enter password/certificate for account %1 - + + mojeID + + + + Open Certificate - + Certificate Files (*.p12 *.pem) @@ -941,168 +1024,214 @@ DlgDsSearch - - + + Your account is of type - + You have also Post Data Messages activated. This means you can only search for accounts of type OVM and accounts that have Post Data Messages delivery activated. Because of this limitation the results of your current search might not contain all otherwise matching databoxes. - + commercial messages are enabled - + This means you can only search for accounts of type OVM. The current search settings will thus probably yield no result. - + commercial messages are disabled - + OVM – Orgán veřejné moci - + PO – Právnická osoba - + PFO – Podnikající fyzická osoba - + FO – Fyzická osoba - - + + Subject Name: - - - - + + + + Enter name of subject - + Name: - + Last Name: - - + + Enter last name or birth last name of FO. - - - + + + Search result - + This is a special ID for system databox of Datové schránky. You can't use this ID for message delivery. Try again. - + It is not possible find databox because - + It is not possible find databox because error occurred during search process! - + Search error - - + + Enter PFO last name or company name. - - + + no - + yes + DlgDsSearchMojeId + + + Search + + + + + Search next + + + + + DlgLoginToMojeId + + + Password + + + + + Certificate + + + + + Password + Secure code + + + + + Login to account: %1 + + + + + Open Certificate + + + + + Certificate Files (*.p12 *.pem) + + + + DlgMsgSearch - + Here it is possible to search for messages according to supplied criteria. You can search for messages in selected account or in all accounts. Double clicking on a found message will change focus to the selected message in the application window. Note: You can view additional information when hovering your mouse cursor over the message ID. - + Account - + Message ID - + Subject - + Sender - + Recipient - + Delivery Year - + Message Type @@ -1110,18 +1239,18 @@ DlgPreferences - + Note: If you have a slow network connection or you cannot download complete messages, here you can increase the connection timeout. Default value is %1 minutes. Use 0 to disable timeout limit (not recommended). - + Note: Marked unread message will be marked as read after set interval. Default value is %1 seconds. Use -1 disable the function. - - + + Select directory @@ -1144,196 +1273,181 @@ DlgSendMessage - - + + no - - - + + + yes - - unknown - - - - - local database - - - - + Enter reference number: - + Warning: The permitted amount (%1) of attachments has been exceeded. - + Total size of attachments is ~%1 KB - + Warning: Total size of attachments is larger than %1 MB! - + Total size of attachments is ~%1 B - - Error opening attachment. - - - - - Cannot write file '%1'. - - - - + Message contains non-OVM recipients. - + Your message contains %1 non-OVM recipients therefore this message will be sent as a commercial messages (PDZ) for these recipients. - + Message contains non-OVM recipient. - + Your message contains non-OVM recipient therefore this message will be sent as a commercial message (PDZ) for this recipient. - + Your remaining credit is - + + Do you want to close the Send message form? - + Send message error - + An error occurred while loading attachments into message. - + An error occurred during message envelope creation. - + It has not been possible to send a message to the server Datové schránky. - + The message will be discarded. - + Message has successfully been sent to <i>%1 (%2)</i> as PDZ with number <i>%3</i>. - + Message has successfully been sent to <i>%1 (%2)</i> as message number <i>%3</i>. - + Message has NOT been sent to <i>%1 (%2)</i>. Server says: %3 - + + Message sent - + + Message has successfully been sent to all recipients. - + + Message sending error - + + Message has NOT been sent to all recipients. - + Databox ID - + Enter Databox ID (7 characters): - + Do you want to send all messages? - - + + Total size of attachments is %1 B - + sending of PDZ: enabled - + remaining credit: - + sending of PDZ: disabled - + Our reference number: - + Do you want to send message? @@ -1341,33 +1455,56 @@ DlgTag - + Choose tag colour - - + + + Tag error - + Tag name is empty. - + Tag wasn't created. - + + Tag update error + + + + + Tag with name '%1'' wasn't updated in the WebDatovka database. + + + + + Tag insert error + + + + + Tag with name '%1'' wasn't' created in WebDatovka database. + + + + + Tag with name '%1'' already exists in database. - + + Tag wasn't created again. @@ -1424,105 +1561,66 @@ - Save attachment - Save attachments - - Error saving attachment. - - - - - - Cannot write file '%1'. - - - - - - Error saving attachments. - - - - - Could not save all attachments. - - - - - In total %1 attachment files could not be written. - - - - - These are: - - - - - Error opening attachment. - - - - + Identification - + ID - + Subject - + Message type - + Sender - + Sender Databox ID - + Sender Address - + Recipient - + Recipient Databox ID - + Events - + Recipient Address @@ -1543,43 +1641,43 @@ - - + + Status - + Delivery time - + Acceptance time - + Attachments - + Signature - + Message signature - + Signing certificate - + Time stamp @@ -1651,32 +1749,75 @@ - + ID - + Name - + Address - + Postal code - + PDZ + DsSearchMojeId + + + Search recipient + + + + + Current account: + + + + + n/a + + + + + Keyword: + + + + + Search + + + + + ID + + + + + Name + + + + + Address + + + + ImportZFO @@ -1989,1033 +2130,1233 @@ - MainWindow + JsonLayer - - Search: + + Login to mojeID failed. You must choose correct login method and enter correct login data. Try again. - - Clear search field + + Cannot open client certificate from path '%1' - - Mode: offline + + Certificate password - - - disk + + Enter certificate password: - - - memory + + Cannot parse client certificate from path '%1' - - Storage: + + + + + + + + + + + + + + + + + + + + User is not logged to mojeID - - New version of Datovka is available: + + + + + + + + + + + + + + + + Reply content missing + + + LoginToMojeId - - - New version of Datovka + + Add a new mojeID account(s) - - - New version of Datovka is available. + + Please select login method and enter credentials for mojeID. - - Current version is %1 + + Login method: - - New version is %1 + + Select authorization method for login into your databox - - Do you want to download new version? + + Username: - - Current version is "%1" + + Enter your username - - New version is "%1" + + Password: - - Update your application... + + Enter your password - - All messages + + Certificate file: - - Add new account + + Select a certificate - - Saving attachment of message to files was not successful! + + Add - - - Saving attachment of message "%1" to files was not successful! + + Security code (OTP): - - Saving attachment of message "%1" to file was not successful! + + Account will be included into synchronisation +process of all accounts on the background - - Saving attachment of message "%1" to file was successful. + + Synchronise account(s) when "Synchronise all" is activated + + + MainWindow - - Save attachments + + Search: - - All attachments of message "%1" were saved. + + Clear search field - - - Some attachments of message "%1" were not saved to disk! + + Mode: offline - - Error saving attachment of message '%1'. + + + disk - - - - - - - Cannot write file '%1'. + + + memory - - - Error saving attachments of message '%1'. + + Storage: - - Could not save all attachments of message '%1'. + + New version of Datovka is available: - - In total %1 attachment files could not be written. + + + New version of Datovka - - These are: + + + New version of Datovka is available. - - Attachment '%1' stored to temporary file '%2'. + + Current version is %1 - - Attachment '%1' couldn't be stored to temporary file. + + New version is %1 - - Error opening attachment. + + Do you want to download new version? - - Message "%1" was downloaded from ISDS server. + + Current version is "%1" + + + + + New version is "%1" + + + + + Update your application... + + + + + All messages + + + + + Add new account + + + + + Save attachments + + + + + + + + Cannot write file '%1'. + + + + + Error saving attachments of message '%1'. + + + + + In total %1 attachment files could not be written. + + + + + These are: - + Synchronise all accounts with ISDS server. - + Messages on the server - + Database files for account '%1' cannot be accessed in location '%2'. - + All received messages - + All sent messages - + + Delete message %1 - + + Do you want to delete message '%1'? - + Delete this message also from server ISDS - + Warning: If you delete the message from ISDS then this message will be lost forever. - + + Delete messages - + + Do you want to delete selected messages? - + Delete these messages also from server ISDS - - Warning: If you delete selected messages from ISDS then these message will be lost forever. - - - - + received - - + + new - + sent - + Test account - + Standard account - + Account name - + User name - + Yes - + No - + unknown or without expiration - + Password expiration date - - + + Received messages - - - + + + none - - + + Sent messages - + Version - + Powered by - + Datovka: Database file present - + Database file for account '%1' already exists. - + If you want to use a new blank file then delete, rename or move the existing file so that the application can create a new empty file. - - - - - + + + + + Datovka: Problem loading database - - - - - - + + + + + + Could not load data from the database for account '%1' - + I'll try to create an empty one. - - + + Datovka - Free client for Datové schránky - + Enter sought expression - + In Progress - - + + Mark - - - - + + + + As Read - - - - + + + + As Unread - + It was not possible to download a complete message "%1" from server Datové schránky. - + No account synchronised. - + You don't have enough access rights to use the file. - + The file either does not contain an sqlite database or the file is corrupted. - + Datovka: Database opening error - + Create a new account. - + Remove account - + Do you want to remove account - + Account '%1' was deleted but its message database was not deleted. - - - + + + Select directory - + Database file(s) not found in selected directory. - + Select db file(s) - + Database file (*.db) - - + + Database file(s) not selected. - + Account with user name '%1' and its message database already exist. New account was not created and selected database file was not associated with this account. - + Account with name '%1' has been created (user name '%1'). - + Verifying the ZFO file "%1" - + Server Datové schránky confirms that the message is authentic. - - + + Message was <b>successfully verified</b> against data on the server Datové schránky. - - + + This message has passed through the system of Datové schránky and has not been tampered with since. - + Server Datové schránky confirms that the message is not authentic. - - + + Message was <b>not</b> authenticated as processed by the system Datové schránky. - - + + It is either not a valid ZFO file or it was modified since it was downloaded from Datové schránky. - - - + + + Message authentication failed - - + + Authentication of message has been stopped because the connection to server Datové schránky failed! Check your internet connection. - + Server Datové schránky confirms that the message is valid. - + Server Datové schránky confirms that the message is not valid. - + Message is not valid - - - - - + + + + + Message verification failed. - + Verification failed - - - - + + + + Verification error - + Tags - + + Couldn't download message '%1'. - + The message hash is not in local database. Please download complete message from ISDS and try again. - - - - - ZFO file(s) not found in selected directory. + + + + + ZFO file(s) not found in selected directory. + + + + + + + No ZFO file(s) + + + + + Select ZFO file(s) + + + + + ZFO file(s) not selected. + + + + + Export of message "%1" to ZFO was successful! + + + + + Export of message "%1" to ZFO was not successful. + + + + + Error exporting message '%1'. + + + + + Complete message '%1' is missing. + + + + + Do you want to download the complete message now? + + + + + Complete message '%1' has been downloaded. + + + + + Complete message '%1' has not been downloaded. + + + + + Error exporting message delivery info '%1'. + + + + + Printing of delivery info "%1" to PDF. Please wait... + + + + + + Printing of message envelope "%1" to PDF. Please wait... + + + + + Data message + + + + + Data messages + + + + + Attachments of message + + + + + Attachments of messages + + + + + Attachment of message %1 + + + + + Attachments of message %1 + + + + + Message '%1' stored to temporary file '%2'. + + + + + Message '%1' couldn't be stored to temporary file. + + + + + + Error opening message '%1'. + + + + + Message delivery information '%1' stored to temporary file '%2'. + + + + + Message delivery information '%1' couldn't be stored to temporary file. - - - - No ZFO file(s) + + Password required - - Select ZFO file(s) + + Account: %1 +User name: %2 +Certificate file: %3 +Enter password to unlock certificate file: - - ZFO file(s) not selected. + + SMS code for account - - Export of message "%1" to ZFO was successful! + + + + + + + + It was not possible to connect to your data box from account "%1". - - Export of message "%1" to ZFO was not successful. + + Saving attachment of message '%1' to files was not successful! - - Error exporting message '%1'. + + Saving attachment of message '%1' to file was successful. - - Complete message '%1' is missing. + + Saving attachment of message '%1' to file was not successful! - - First you must download the complete message before export. + + Error saving attachment. - - Do you want to download the complete message now? + + Some files already exist. - - Complete message '%1' has been downloaded. + + Some attachments of message '%1' were not saved to disk! - - Complete message '%1' has not been downloaded. + + All attachments of message '%1' were saved. - - Error exporting message delivery info '%1'. + + Attachment '%1' stored into temporary file '%2'. - - Printing of delivery info "%1" to PDF. Please wait... + + Attachment '%1' couldn't be stored into temporary file. - - - Printing of message envelope "%1" to PDF. Please wait... + + It was not possible download complete message "%1" from webdatovka server. - - Data message + + It was not possible to download a complete message "%1" from webdatovka server. - - Data messages + + Webdatovka: - - Attachments of message + + It was not possible download received message list from server. - - Attachments of messages + + It was not possible download sent message list from server. - - Attachment of message %1 + + Server: - - Attachments of message %1 + + Message "%1" was downloaded from server. - - Message '%1' stored to temporary file '%2'. + + Warning: If you delete selected messages from ISDS then these messages will be lost forever. - - Message '%1' couldn't be stored to temporary file. + + You have to be logged into the Webdatovka if you want to delete message(s). - - - Error opening message '%1'. + + Warning: If you delete the message from Webdatovka then this message will be lost forever. - - Message delivery information '%1' stored to temporary file '%2'. + + Warning: If you delete selected messages from Webdatovka then these messages will be lost forever. - - Message delivery information '%1' couldn't be stored to temporary file. + + + You have to be logged into the WebDatovka if you want to download complete message. - - Password required + + MojeID account - - Account: %1 -User name: %2 -Certificate file: %3 -Enter password to unlock certificate file: + + Full message not present! - - SMS code for account + + You have to be logged into the WebDatovka if you want to find databox. - - - - - - - - It was not possible to connect to your data box from account "%1". + + First you must download the complete message to continue with the action. - + Invalid certificate data - + The certificate or the supplied pass-phrase are invalid. - + Please enter a path to a valid certificate and/or provide a correct key to unlock the certificate. - + Bad certificate data for account "%1". - + Datovka is currently processing some tasks. - + Do you want to abort pending actions and close Datovka? - - + + Adding new account failed - + Account could not be added because an error occurred. - + Account could not be added because account already exists. - - + + Checking time stamps in account '%1'... - + Time stamp expiration check results - + This file does not contain a valid database filename. - + This file does not contain a valid username in the database filename. - + This database file does not contain valid year in the database filename. - + This file does not contain valid database filename. - + This database file does not contain valid database filename. - + This file does not contain a valid account type flag or filename has wrong format. - + This file does not contain a valid message database or filename has wrong format. - + Import of mesages from database - + This action allow to import messages from selected database files into current account. Keep in mind that this action may takes a few minutes based on number of messages in the imported database. Import progress will be displayed in the status bar. - - - + + + Do you want to continue? - + Select database file(s) - + DB file (*.db) - + Import of messages from %1 to account %2 - + Import of messages from %1 to account %2 is running - - - - - + + + + + Database import: %1 - + This database file cannot import into selected account because username of account and username of database file do not correspond. - + Failed to open import database file. - - + + Failed to open database file of target account '%1' - + Importing of message %1 into account %2 ... - + Message '%1' already exists in database for this account. - + Message '%1' cannot be imported into this account. Message does not contain any valid ID of databox corresponding with this account. - + Message '%1' cannot be inserted into database of this account. An error occurred during insertion procedure. - + Messages import result - + Import of messages into account '%1' finished with result: - + Source database file: '%1' - + Imported messages: %1 - + Non-imported messages: %1 - + Import of messages from %1 to account %2 finished - + Database split - + This action split current account message database into several new databases which will contain messages relevant by year only. It is recommended for large database because the performance of application will be better. - + Original database file will copy to selected directory and new database files will created in the same location. If action finished with success, new databases will be used instead of original. Restart of application is required. - + Note: Keep in mind that this action may takes a few minutes based on number of messages in the database. - + Split of message database finished with error - + Database split: %1 - + Action was canceled and original database file was returned back. - + Existing file '%1' could not be deleted. - + Error to set and open original database for account '%1' - + Action was canceled and the origin database is now used from location: '%1' - + Replacing of new database files to origin database location - + Action was canceled because new databases cannot move from '%1' to origin path @@ -3023,942 +3364,990 @@ - + Opening of new database files - + Vacuum cannot be performed on databases in memory. - + Database operation error - + Database clean-up cannot be performed on database in memory. - + Cannot call VACUUM on database in memory. - + Clean message database - + Performs a message database clean-up for the selected account. This action will block the entire application. The action may take several minutes to be completed. Furthermore, it requires more than %1 of free disk space to successfully proceed. - + Performing database clean-up. - + Database clean-up finished. - + Database clean-up successful - + The database clean-up has finished successfully. - + Database clean-up failure - + The database clean-up failed with error message: %1 - - + + You have to be logged into the WebDatovka if you want to modify tags. + + + + + Add account(s) error + + + + + There aren't any Webdatovka accounts for this mojeID identity. + + + + + + You are login into wrong mojeID identity. + + + + + Please enter correct mojeID login for account '%1'. + + + + + New mojeID identity has some account(s). + + + + + Do you want to add account(s) for this mojeID identity to Datovka? + + + + + Some account(s) were removed from Webdatovka for this mojeID identity. + + + + + Do you want to also remove these accounts from Datovka? + + + + + This action is not supported for MojeID account '%1' + + + + + Login problem + + + + + Database file for account '%1' does not exist. - + + A connection error occurred or the message has already been deleted from the server. - + A connection error occurred. - + Message from '%1' (%2) has been successfully sent to '%3' (%4). - + Error while sending message from '%1' (%2) to '%3' (%4). - + No ZFO files to import. - + There is no account to import of ZFO files into. - + Import of ZFO files ... Planned - + The log-in method used in account "%1" is not implemented. - + Account "%1" requires authentication via OTP<br/>security code for connection to data box. - + Account "%1" requires authentication via security code for connection to data box. - + Security code will be sent to you via a Premium SMS. - + Do you want to send a Premium SMS with a security code into your mobile phone? - + Database file cannot split by years because this account already use database files split according to years. - + Select directory for new databases - + Database file cannot split into same directory. - + Please, you must choose another directory. - + Copying origin database file to selected location - + Cannot copy database file for account '%1' to '%2' - + Probably not enough disk space. - + Set of new database files for account '%1' could not be created. - + Creating a new database file for year %1 - + New database file for account '%1' corresponds with year '%2' could not be created. - + Messages were not copied. - + Messages correspond with year '%1' for account '%2' were not copied. - + Error when move new databases for account '%1' - + Probably not enough disk space. The origin database is still used. - + Deleting of old database from origin location - + Error when removed origin database for account '%1' - + Action was canceled. Please, remove the origin database file manually from origin location: '%1' - + A problem when opening new databases for account '%1' - + Action was done but it cannot open new database files. Please, restart the application. - + Split of message database finished - + Congratulation: message database for account '%1' was split successfully. Please, restart the application for loading of new databases. - + Note: Original database file was backup to: - + Time stamp expiration check in account '%1' finished with result: - + Loading of ZFO file(s) failed! - + Time stamp expiration check of ZFO files finished with result: - + Total of ZFO files: %1 - + ZFO files with time stamp expiring within %1 days: %2 - + Unchecked ZFO files: %1 - - + + Total of messages in database: %1 - + Messages with time stamp expiring within %1 days: %2 - + Unchecked messages: %1 - + See details for more info... - + Do you want to export the expiring messages to ZFO? - - + + Time stamp of message %1 expires within specified interval. - - + + Time stamp of message %1 is not present. - - + + Export ZFO - + New account error - + Account - + was not created! - + Password expiration - + According to the last available information, your password for account '%1' (login '%2') expired %3 days ago (%4). - + You have to change your password from the ISDS web interface. Your new password will be valid for 90 days. - + According to the last available information, your password for account '%1' (login '%2') will expire in %3 days (%4). - + You can change your password now, or later using the 'Change password' command. Your new password will be valid for 90 days. Change password now? - - + + Change password of account "%1". - - + + Portable version - + Database access error - + The file cannot be accessed or is corrupted. Please fix the access privileges or remove or rename the file so that the application can create a new empty file. - + Create a backup copy of the affected file. This will help when trying to perform data recovery. - + In general, it is recommended to create backup copies of the database files to prevent data loss. - - - - + + + + As Unsettled - - - - + + + + As in Progress - - - - + + + + As Settled - - It was not possible download received message list from ISDS server. - - - - + Download message list error - - + ISDS: - - It was not possible download sent message list from ISDS server. - - - - + Account and user information could not be acquired. - + User information - + Databox information - + Database is stored in memory. Data will be lost on application exit. - - + + Local database file location - + Change properties of account "%1". - + Account "%1" was updated. - + Account was moved up. - + Account was moved down. - + Change data dierctory of account "%1". - - - - - - + + + + + + Change data directory for current account - + Find databoxes from account "%1". - + Wrong ZFO format. This file does not contain correct data for import. - + The selection does not contain any valid ZFO files. - + Enter OTP security code - + Enter OTP security code for account - + It was not possible to get user info and databox info from ISDS server for account - + Connection to ISDS or user authentication failed! - + Please check your internet connection and try again or it is possible that your password (certificate) has expired - in this case, you need to use the official web interface of Datové schránky to change it. - - + + Add ZFO file - - - - - + + + + + ZFO file (*.zfo) - + Message is authentic - + Datovka - + Message is not authentic - + It was not possible download complete message "%1" from ISDS server. - + + Download message error - + Message "%1" was deleted from local database. - + Message "%1" was deleted from ISDS and local database. - + Message "%1" was deleted only from ISDS. - + Message "%1" was deleted only from local database. - + Message "%1" was not deleted. - + Create and send a message. - + Delete also message database from storage - + Warning: If you delete the message database then all locally accessible messages that are not stored on the ISDS server will be lost. - + Account '%1' was deleted together with message database file. - + Account '%1' was deleted. - + This database file has been set as actual message database for this account. Maybe you have to change account properties for correct login to the server Datové schránky. - - - + + + Create account: %1 - + The existing database files %1 in '%2' are going to be used. - + Database files are missing in '%1'. - + Some databases of %1 in '%2' are not a file. - + Some databases of '%1' in '%2' cannot be accessed. - + Some databases of %1 in '%2' cannot be used. - + Conflicting databases %1 in '%2' cannot be used. - + Please remove the conflicting files. - + Database files in '%1' cannot be created or are corrupted. - + Database files for '%1' have been successfully moved to '%2'. - + Database files for '%1' could not be moved to '%2'. - + Database files for '%1' have been successfully copied to '%2'. - + Database files for '%1' could not be copied to '%2'. - + New database files for '%1' have been successfully created in '%2'. - + New database files for '%1' could not be created in '%2'. - - - + + + Message authentication failed. - + Authentication of message has been stopped because the message file has wrong format! - - - + + + An undefined error occurred! Try again. - + Message is valid - + The message hash cannot be verified because an internal error occurred! Try again. - - - - - - - + + + + + + + Message export error! - + Export of message "%1" to ZFO was not successful! - - + + Delivery info export error! - - + + Export of message delivery info "%1" to ZFO was not successful! - + Export of message delivery info "%1" to ZFO was successful. - - - - + + + + Export of message envelope "%1" to PDF was not successful! - - + + Export of message envelope "%1" to PDF was successful. - - + + Datovka - Export error! - + Save message as ZFO file - + Welcome... - + Storage: disk | disk - + Save delivery info as ZFO file - + Save delivery info as PDF file - - - + + + PDF file (*.pdf) - + Export of message delivery info "%1" to PDF was not successful! - + Export of message delivery info "%1" to PDF was successful. - - + + Save message envelope as PDF file - - + + Cannot export the message - - + + First you must download message before its export... - + + Mode: online - - - - - - - - - + + + + + + + + + File - + Message - + Tools - + Help - + toolBar - + Sync all accounts - + Download complete message, including attachments and verify its signature - + Open attachment in an associated application - - + + Signature details - - + + Remove account - + Show details about electronic signature of this message - + For current message you can locally set if the message is not processed, if the message is in progress or if was already @@ -3966,418 +4355,492 @@ - + Unsettled - + Settled - + Shift+F5 - + + Add new data box account + + + + + Proxy settings - + Preferences - + Preferences of Datovka - + Quit - + + Quit the application + + + + Ctrl+Q - + F5 - + Create message - + Ctrl+N - + Mark all as read - + + Mark all messages as read + + + + Change password - + Sets a new password to the selected account on the ISDS server - + Account properties - + Manage account properties - + Move account up - + Move selectet account one position up - + Move account down - + Move selectet account one position down - + Change data directory - + Change the directory where data are being stored for the selected account - + About Datovka - + About Datovka application - - Datovka update + + Find Data Box - - Update Datovka application + + Find data box - - Find Data Box + + Authenticate message file - - Authenticate message file + + Verify message authenticity - + View message from ZFO file - + + View content of a ZFO file + + + + Export correspondence overview - + + Create a correspondence overview + + + + Download signed message - + Reply to the selected message - + Display details about the signature - + Deletes message from local database and/or from ISDS server - + Export the selected message as ZFO file - + Pass the selected message to an external application - + Pass the delivery information of the selected message to an external application - + Export the delivery information of the selected message as ZFO file - + Export the delivery information of the selected message as PDF file - + Export the envelope of the selected message as PDF file - + Export envelope PDF with attachments - + Export the envelope to a PDF file together with message attachments - + Save selected attachments to files - + Saves all message attachments - + Import messages from ZFO files - + + Import a message from ZFO file into the database + + + + Use the selected message as a template - + Search message - + + Check whether the message time stamp is not expired or expiring + + + + Homepage - + + Open the home page of the application + + + + Import messages from database - + + Import messages into database from an external database file + + + + Split database by years - + + Messages are going to be stored into separate database files according to years + + + + E-mail with ZFOs - + Creates an e-mail containing ZFOs of selected messages - + E-mail with all attachments - + Creates an e-mail containing all attachments of selected messages - + E-mail with selected attachments - + Creates an e-mail containing selected attachments - + + Edit tags - + Vacuum message database - + + This may reduce the database file size and optimise the access speed + + + + + + Forward message + + + + + Add mojeID account + + + + + Add new mojeID account + + + + Create and send a new message - + Reply to message - + Ctrl+R - + Authenticate message - + Use message as template - + Advanced searching in message envelopes - + Ctrl+Shift+F - + Time stamp expiration check - + Delete message - + Data box - + + Create account from database - + + User manual - + Synchronize all accounts at once - + Sync account - + Synchronize selected account - + Verify the selected message - + Export message as ZFO - + Open message externally - + Open delivery info externally - + Export delivery info as ZFO - + Export delivery info as PDF - + Export message envelope as PDF - + Open attachment - - + Save attachment - + Save all attachments @@ -4385,33 +4848,33 @@ Preferences - + Downloading - + Messages downloading - - + + minutes - + Automatically download whole messages (may be slow) - + Automatically synchronize all accounts on startup - + New versions @@ -4421,31 +4884,31 @@ - + When allowed, Datovka will automatically download messages on the background of application without blocking of user interface. Download period you can set bellow. - + Automatically synchronise all in background - - + + Allows to set a time interval for automatically synchronise all accounts in the background. - + Check every - + When accessing your Databox, only envelopes of messages are downloaded at first. You can then download the whole message, including any attachments, manually. When this option is turned on, Datovka will perform the download of complete @@ -4454,14 +4917,14 @@ - + When allowed, Datovka will automatically synchronise accounts and also download new messages on background at startup. - - + + Allows to set a timeout interval for network connection. If you have a slow network connection or you cannot download complete messages, here you can increase @@ -4469,40 +4932,40 @@ - + Mark message as read settings - - + + Allows to set a timeout interval for automatically marking message as read. - + Automatically mark message as read after - + seconds - + When this option is active, Datovka will automatically check for new Datovka versions on startup. - + Check for new Datovka versions on startup - + When this option is active, Datovka will send information about your Datovka version and related data as part of the request for new versions. This data contains the version of Datovka, version of libraries, operating @@ -4513,27 +4976,27 @@ - + Send version info alongside the request - + Security - + Storage options - + It migth be possible for a person with access to your home directory to modify data in the Datovka database with malicious intent or to steal you login credentials for Datové Schránky. Using the checkboxes below, you can influence which data Datovka stores on the disk. Note: Password storage can be adjusted on per-account basis in the credentials dialog. - + When allowed, messages are stored in a database in your home directory. Such storage might be compromised by an attacker and the content of messages might be modified. When turned off, messages are freshly @@ -4542,12 +5005,12 @@ - + Allow message storage - + Datovka stores some additional data outside the message database. These are data about the databox which allow for example warning about an expiring password. These data might be also changed by @@ -4555,146 +5018,146 @@ - + Allow storage of additional data - - + + Allows to set a interval how many days before expiring of timestamp will be message included in the check results. - + days - + Navigation - + When account is opened, select - + After an account is opened, the newest message will be activated. - + Newest message - + When account is opened, the last message displayed in this account will be selected. - + Last displayed message - + When account is opened, random message displayed in this account will be selected. - + Nothing - + Interface - + Style of toolbar buttons - + Only icons will be displayed in the toolbar. - + Only display the icon - + Icons and text beside them will be displayed in the toolbar. - + The text appears beside the icon - + Icons and text under them will be displayed in the toolbar. - + The text appears under the icon - - Note: toolbar setting will not apllied until you restart the application. + + Note: toolbar settings will not be applied until you restart the application. - + Select a new path for saving of attachments. - + Select a new path for adding of files to attachments. - + When saving all attachments also save signed message as ZFO to the same path. - + When saving all attachments also save message envelope as PDF to the same path. - + When saving all attachments also save signed delivery info as ZFO to the same path. - + When saving all attachments also save delivery info as PDF to the same path. - + Specifies file name format for attachment files and other exported files. Default value when saving attachment files is %f (i.e. saved file name will match the original @@ -4702,61 +5165,61 @@ - + File name format of saved/exported files - + Message file name: - + Delivery info file name: - + Attachment file name: - + name of sender (separated by "-") - + Note: Illegal characters in the name of file will be replaced. - + Saves delivery info for every attachment file separately. The delivery info file name has to contain the original attachment file name (parameter %f is required). - + Signing certificate validity - + Validity of the signing certificate will be checked against the current date. This gives the highest protection against compromised certificate exploit. - + Check against current date (safer) - + The validity of signing certificate is checked against a stored download date. This allows long-term storage of messages without false alarms about invalid signature. @@ -4765,207 +5228,207 @@ - + Check against the date of download - + Check certificate revocation list (CRL). - + Check certificate revocation list (CRL) - + Connection settings - + Timeout for message downloading is set on - + Saving - + When allowed, Datovka will use the following directories as paths for loading and saving files in all accounts. Per-account path remembering will be disabled. - + Directories - + Use global path settings - + Path for saving of attachments is currently set on: - - + + Change - + Path for adding of file to attachments is currently set on: - + These actions will be performed when saving all message attachments. - + When saving all attachments also - + Save signed message to ZFO - + Save signed delivery info to ZFO - + Save delivery info to PDF - + Save message envelope to PDF - + Message time stamps expiring within the selected numer of days will be included into the expiration notification summary. - + Message time stamp expiration - + Check for time stamps expiring within - + delivery year (YYYY) - + delivery month (MM) - + delivery day (DD) - + delivery minute (mm) - + delivery hour (hh) - + message ID - + message subject (separated by "-") - + databox ID - + attachment filename (with suffix) - + user ID - + Example: - + means - + Save delivery info for every attachment file. Format: - + Language - + Application language - + Use system language - + Czech - + English - - Note: language setting will not apllied until you restart the application. + + Note: language settings will not be applied until you restart the application. @@ -5007,7 +5470,7 @@ - Manual proxy setting + Manual proxy settings @@ -5458,9 +5921,9 @@ - - - + + + Sender @@ -5471,9 +5934,9 @@ - - - + + + Recipient @@ -5484,8 +5947,8 @@ - - + + To hands @@ -5556,7 +6019,7 @@ - + Status @@ -5576,135 +6039,135 @@ - + Data box application - + Use <conf-subdir> subdirectory for configuration. - + conf-subdir - + On start load <conf> file. - - + + conf - + On stop save <conf> file. - + Log messages to <file>. - + file - + Set verbosity of logged messages to <level>. Default is - - + + level - + Set debugging verbosity to <level>. Default is - + Service: connect to isds and login into databox. - - - - - - + + + + + + string-of-parameters - + Service: download list of received/sent messages from ISDS. - + Service: create and send a new message to ISDS. - + Service: download complete message with signature and time stamp of MV. - + Service: download delivery info of message with signature and time stamp of MV. - + Service: get information about user (role, privileges, ...). - + Service: get information about owner and its databox. - + Service: get list of messages where attachment missing (local database only). - + Service: find a databox via several parameters. - + ZFO file to be viewed. - + Application is loading... - + Advice of Delivery - - + + Message ID: @@ -5712,280 +6175,280 @@ - - - - + + + + Name - - + + General Information - - - + + + Subject - - + + paragraph - - + + letter - - + + Delegation - - - - - - - - - - + + + + + + + + + + Not specified - - + + Our ref.number - - + + Our doc.id - - + + Your ref.number - - + + Your doc.id - - - - + + + + yes - - - - + + + + no - - + + Personal Delivery - - + + Prohibit Delivery by Fiction - + List of attachments - + Delivery/Acceptance Information - - + + Delivery - + Download the complete message in order to verify its time stamp. - + Acceptance - - + + Events - + Sender Databox ID - + Recipient Databox ID - + Time - + Envelope - - + + Databox ID - + Databox Type - - - - + + + + Attachments - + Identification - + Message ID - + Message type - + Databox type - + Sender Address - + Message author - + Recipient Address - + (downloaded and ready) - + not downloaded yet, ~ - + KB; use 'Download' to get them. - + (not available) - + Signature - - - + + + Message signature - - + + Not present - + Download the complete message in order to verify its signature. - + Time stamp - - - - - - + + + + + + Invalid - - + + Message signature and content do not correspond! @@ -5994,34 +6457,29 @@ - - - - - + + + + + Valid - - + + Certificate revocation check is turned off! - + Signing certificate - - File Size - - - Depends on libraries: @@ -6034,13 +6492,13 @@ - + No - + Yes @@ -6149,7 +6607,7 @@ - + Created using Datovka @@ -6378,7 +6836,7 @@ - + Add @@ -6389,12 +6847,12 @@ - + Remove - + Attachment size is larger than 20 MB. Message cannot be sent! @@ -6409,73 +6867,73 @@ - + Id - + Name - + Full name of recipient or name of organization - + Address - + Address of recipient - + PDZ - + The message for recipient will be sent as Poštovní Datová Zpráva - + Even if recipient did not read this message, message is considered as delivered after (currently) 10 days. This is delivery through fiction. - + You will pay the transfer charges of the reply message. This is useful when the recipient does not have sending of postal data messages active. - + Add a new file to the attachments - + Remove the selected file from attachments - + Open selected file in associated application - + Allow delivery through fiction @@ -6505,94 +6963,49 @@ - + Databox ID - - + + Include sender identification - + Pay transfer charges for reply - - + + Use offered payment of transfer charges by recipient - + Attachments: - + Open - - File - - - - - File name - - - - - Type - - - - - MimeType - - - - - MIME type of file - - - - - Size - - - - - Size of file in bytes - - - - - FilePath - - - - - Absolute path of file - - - - + Send message - + Send - + Cancel Binary files /tmp/tmpwQ3qJp/p0t3AdM6q5/datovka-4.7.0/res/dschranka.png and /tmp/tmpwQ3qJp/FmfXp_yZpr/datovka-4.7.1/res/dschranka.png differ Binary files /tmp/tmpwQ3qJp/p0t3AdM6q5/datovka-4.7.0/res/mojeid2.png and /tmp/tmpwQ3qJp/FmfXp_yZpr/datovka-4.7.1/res/mojeid2.png differ Binary files /tmp/tmpwQ3qJp/p0t3AdM6q5/datovka-4.7.0/res/mojeid.png and /tmp/tmpwQ3qJp/FmfXp_yZpr/datovka-4.7.1/res/mojeid.png differ diff -Nru datovka-4.7.0/res/resources.qrc datovka-4.7.1/res/resources.qrc --- datovka-4.7.0/res/resources.qrc 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/res/resources.qrc 2017-01-19 09:29:26.000000000 +0000 @@ -160,5 +160,8 @@ icons/3party/address_32.png datovka.png splash/datovka-splash.png + mojeid.png + mojeid2.png + dschranka.png diff -Nru datovka-4.7.0/scripts/build_git_archive.sh datovka-4.7.1/scripts/build_git_archive.sh --- datovka-4.7.0/scripts/build_git_archive.sh 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/scripts/build_git_archive.sh 2017-01-19 09:29:26.000000000 +0000 @@ -37,6 +37,11 @@ echo "Building archive version '${DESIRED_VERSION}' from tag '${DESIRED_TAG}'." -TARGET_FILE="datovka-${DESIRED_VERSION}-src.tar.xz" +TARGET_FILE="datovka-${DESIRED_VERSION}.tar.xz" rm -f "${TARGET_FILE}" git archive --format=tar --prefix=datovka-${DESIRED_VERSION}/ "${DESIRED_TAG}" | xz -9 > "${TARGET_FILE}" + +# Create sha256 checksum, if sha256sum exists. +CHECKSUM=sha256sum +SUMSUFF=sha256 +command -v "${CHECKSUM}" >/dev/null 2>&1 && "${CHECKSUM}" "${TARGET_FILE}" | sed -e 's/\s.*$//g' > "${TARGET_FILE}.${SUMSUFF}" diff -Nru datovka-4.7.0/scripts/build_libisds_mingw.sh datovka-4.7.1/scripts/build_libisds_mingw.sh --- datovka-4.7.0/scripts/build_libisds_mingw.sh 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/scripts/build_libisds_mingw.sh 2017-01-19 09:29:26.000000000 +0000 @@ -16,8 +16,8 @@ BUILTDIR="${SCRIPT_LOCATION}/built" -X86_MINGV_HOST=i586-mingw32msvc -#X86_MINGV_HOST=i686-w64-mingw32 # Generated usable debugging information. +#X86_MINGV_HOST=i586-mingw32msvc # This old compiler chain isn't available on newer distros. +X86_MINGV_HOST=i686-w64-mingw32 #X86_MINGV_HOST=i686-pc-mingw32 X86_MINGW_PREFIX=${X86_MINGV_HOST}- X86_MINGW_CC=${X86_MINGV_HOST}-gcc @@ -40,6 +40,15 @@ mkdir "${BUILTDIR}" fi +# Store information about build. +${X86_MINGW_PREFIX}gcc -v 2> "${BUILTDIR}/gcc-version.txt" +${X86_MINGW_PREFIX}g++ -v 2> "${BUILTDIR}/g++-version.txt" +# Curly brackets don't work in plain Bourne shell. +#cat /etc/*{release,version} > "${BUILTDIR}/linux-version.txt" +cat /etc/*release /etc/*version > "${BUILTDIR}/linux-version.txt" +uname -a > "${BUILTDIR}/uname.txt" +git log -n 1 --pretty=format:"%h - %ad : %s" > "${BUILTDIR}/git.txt" + ZLIB_ARCHIVE="${_ZLIB_ARCHIVE}" EXPAT_ARCHIVE="${_EXPAT_ARCHIVE}" @@ -187,6 +196,8 @@ #CONFOPTS="${CONFOPTS} --disable-shared" CONFOPTS="${CONFOPTS} --with-libxml2-prefix=${BUILTDIR}" CONFOPTS="${CONFOPTS} --with-libiconv-prefix=${BUILTDIR}" + CONFOPTS="${CONFOPTS} --enable-threads=win32" + CONFOPTS="${CONFOPTS} --enable-relocatable" # --disable-static ./configure ${CONFOPTS} --host="${X86_MINGV_HOST}" \ @@ -303,6 +314,9 @@ CONFOPTS="${CONFOPTS} ${NLS}" # --disable-static + # Receiving undefined reference to `rpl_malloc' with i686-w64-mingw32. + # The following variable forces the malloc check to pass. + ac_cv_func_malloc_0_nonnull=yes \ ./configure ${CONFOPTS} --host="${X86_MINGV_HOST}" \ CPPFLAGS="-I${BUILTDIR}/include -I${BUILTDIR}/include/libxml2" \ LDFLAGS="-L${BUILTDIR}/lib" diff -Nru datovka-4.7.0/scripts/datovka-log.bat datovka-4.7.1/scripts/datovka-log.bat --- datovka-4.7.0/scripts/datovka-log.bat 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/scripts/datovka-log.bat 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,41 @@ + +rem Runs Datovka application wit enabled logging. +rem This file must be located in the same directory as the main executable. +rem Log file is generated into the user profile directory if run with ordinary +rem application. +rem Log file is generated into the application directory if run with portable +rem application. + +@echo off + +SET APP_PORT=datovka-portable.exe +SET APP_NORM=datovka.exe + +SET LOG_FILE=datovka.log + +SET APP_PATH_BACKSLASH=%~dp0 +SET APP_PATH=%APP_PATH_BACKSLASH:~0,-1% + +SET HOME_PATH=%userprofile% + +if exist "%APP_PATH%\%APP_PORT%" ( + SET APP=%APP_PATH%\%APP_PORT% + SET LOG=%APP_PATH%\%LOG_FILE% +) else ( + if exist "%APP_PATH%\%APP_NORM%" ( + SET APP=%APP_PATH%\%APP_NORM% + SET LOG=%HOME_PATH%\%LOG_FILE% + ) +) + +if not defined APP ( + echo Cannot find application in %APP_PATH%! + exit /b 1 +) else ( + echo Foud application "%APP%". + echo Generating log file "%LOG%". +) + +rem del "%LOG%" +echo "%APP%" --debug-verbosity 2 --log-verbosity 2 --log-file "%LOG%" > "%LOG%" +"%APP%" --debug-verbosity 2 --log-verbosity 2 --log-file "%LOG%" diff -Nru datovka-4.7.0/scripts/dependency_sources.sh datovka-4.7.1/scripts/dependency_sources.sh --- datovka-4.7.0/scripts/dependency_sources.sh 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/scripts/dependency_sources.sh 2017-01-19 09:29:26.000000000 +0000 @@ -1,7 +1,7 @@ #!/usr/bin/env sh # Latest libraries. -_ZLIB_ARCHIVE="zlib-1.2.8.tar.xz" +_ZLIB_ARCHIVE="zlib-1.2.11.tar.xz" _EXPAT_ARCHIVE="expat-2.2.0.tar.bz2" _LIBTOOL_ARCHIVE="libtool-2.4.6.tar.xz" @@ -9,7 +9,7 @@ _LIBXML2_ARCHIVE="libxml2-2.9.4.tar.gz" _GETTEXT_ARCHIVE="gettext-0.19.8.1.tar.xz" -_LIBCURL_ARCHIVE="curl-7.50.3.tar.bz2" +_LIBCURL_ARCHIVE="curl-7.52.1.tar.bz2" _OPENSSL_ARCHIVE="openssl-1.0.2j.tar.gz" _LIBISDS_ARCHIVE="libisds-0.10.6.tar.xz" diff -Nru datovka-4.7.0/scripts/make-win.bat datovka-4.7.1/scripts/make-win.bat --- datovka-4.7.0/scripts/make-win.bat 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/scripts/make-win.bat 2017-01-19 09:29:26.000000000 +0000 @@ -70,6 +70,7 @@ copy "AUTHORS" %DATOVKAPATH% copy "COPYING" %DATOVKAPATH% copy "Changelog" %DATOVKAPATH% +copy "scripts\datovka-log.bat" %DATOVKAPATH% xcopy "dlls\*" %DATOVKAPATH% /E copy "locale\datovka_cs.qm" "%DATOVKAPATH%\locale" set SEARCHTEXT="VERSIONXXX" @@ -118,6 +119,7 @@ copy "AUTHORS" %DATOVKAPORTPATH% copy "COPYING" %DATOVKAPORTPATH% copy "Changelog" %DATOVKAPORTPATH% +copy "scripts\datovka-log.bat" %DATOVKAPORTPATH% xcopy "dlls\*" %DATOVKAPORTPATH% /E copy "locale\datovka_cs.qm" "%DATOVKAPORTPATH%\locale" @echo Run 7-ZIP and create ZIP archive of portable Datovka ... diff -Nru datovka-4.7.0/src/common.cpp datovka-4.7.1/src/common.cpp --- datovka-4.7.0/src/common.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/common.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -519,3 +519,66 @@ } return b64size * 3 / 4 - cnt; } + +/* ========================================================================= */ +/* + * True if selected account is WebDatovka (MojeId) account. + */ +bool isWebDatovkaAccount(const QString &userName) +/* ========================================================================= */ +{ + return userName.contains(DB_MOJEID_NAME_PREFIX); +} + +/* ========================================================================= */ +/* + * Get/create WebDatovka (MojeId) username. + */ +QString getWebDatovkaUsername(const QString &userId, const QString &accountId) +/* ========================================================================= */ +{ + return DB_MOJEID_NAME_PREFIX + userId + "-" + accountId; +} + +/* ========================================================================= */ +/* + * Get account id from username of WebDatovka account. + */ +int getWebDatovkaAccountId(const QString &userName) +/* ========================================================================= */ +{ + if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { + return -1; + } + + const QString aID = userName.split("-").at(2); + return aID.toInt(); +} + +/* ========================================================================= */ +/* + * Get user id from username of WebDatovka account. + */ +int getWebDatovkaUserId(const QString &userName) +/* ========================================================================= */ +{ + if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { + return -1; + } + const QString uID = userName.split("-").at(1); + return uID.toInt(); +} + +/* ========================================================================= */ +/* + * Get name prefix of tag database from username (WebDatovka). + */ +QString getWebDatovkaTagDbPrefix(const QString &userName) +/* ========================================================================= */ +{ + if (!userName.contains(DB_MOJEID_NAME_PREFIX)) { + return QString(); + } + + return DB_MOJEID_NAME_PREFIX + userName.split("-").at(1); +} diff -Nru datovka-4.7.0/src/common.h datovka-4.7.1/src/common.h --- datovka-4.7.0/src/common.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/common.h 2017-01-19 09:29:26.000000000 +0000 @@ -62,6 +62,18 @@ #define DATOVKA_DOWNLOAD_URL "https://labs.nic.cz/cs/datovka.html" #define PWD_EXPIRATION_NOTIFICATION_DAYS 7 // show expiration date dialog before xx days +#define DB_MOJEID_NAME_PREFIX "mojeid-" + +/* return values of Datovka login methods */ +typedef enum { + USER_NAME = 0, + CERTIFICATE = 1, + USER_CERTIFICATE = 2, + HOTP = 3, + TOTP = 4, + MOJEID = 5 +} LoginMethodsIndex; + /* return values of Datovka message state */ enum MessageProcessState { @@ -243,4 +255,28 @@ */ int base64RealSize(const QByteArray &b64); +/*! + * @brief Test if selected account is WebDatovka (MojeId) account. + */ +bool isWebDatovkaAccount(const QString &userName); + +/*! + * @brief Get/create WebDatovka (MojeId) username. + */ +QString getWebDatovkaUsername(const QString &userId, const QString &accountId); + +/*! + * Get account id from username of WebDatovka account. + */ +int getWebDatovkaAccountId(const QString &userName); + +/*! + * Get user id from username of WebDatovka account. + */ +int getWebDatovkaUserId(const QString &userName); + +/*! + * Get name prefix of tag database from username (WebDatovka). + */ +QString getWebDatovkaTagDbPrefix(const QString &userName); #endif /* _COMMON_H_ */ diff -Nru datovka-4.7.0/src/delegates/tag_item.cpp datovka-4.7.1/src/delegates/tag_item.cpp --- datovka-4.7.0/src/delegates/tag_item.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/delegates/tag_item.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -21,11 +21,11 @@ * the two. */ -#include /* TODO -- Remove this include. */ #include #include #include "src/delegates/tag_item.h" +#include "src/dimensions/dimensions.h" #include "src/log/log.h" #define DFLT_COLOUR "ffffff" @@ -49,9 +49,6 @@ return (id >= 0) && !name.isEmpty() && (6 == colour.size()); } -#define PADDING 5 /* Horizontal padding in pixels. */ -#define MARGIN 2 /* Vertical and horizontal margin. */ - int TagItem::paint(class QPainter *painter, const QStyleOptionViewItem &option) const { @@ -61,22 +58,29 @@ painter->save(); - int width = sizeHint(option).width(); - int height = rect.height() - (2 * MARGIN); + const QSize hint(sizeHint(option)); + int border = (rect.height() - hint.height()) / 2; + + int width = hint.width(); + int height = hint.height(); - QRectF drawnRect(0, MARGIN, width - (2 * MARGIN), height); + QRectF drawnRect(0, border, width, height); QPainterPath path; - int rounding = (int) (0.15 * height); + int rounding = (int)(0.15 * height); path.addRoundedRect(drawnRect, rounding, rounding, Qt::AbsoluteSize); if (option.state & QStyle::State_Selected) { - painter->fillRect(option.rect, option.palette.highlight()); + painter->fillRect(rect, option.palette.highlight()); } painter->setRenderHint(QPainter::Antialiasing, true); painter->translate(rect.x(), rect.y()); + const int margin = Dimensions::margin(option); + + painter->translate(margin, 0); + QColor rectColour("#" + colour); if (!rectColour.isValid()) { logWarningNL("Invalid tag colour '%s'. Using 'ffffff'", @@ -85,8 +89,6 @@ Q_ASSERT(rectColour.isValid()); } - painter->translate(MARGIN, 0); - QPen pen(rectColour, 1); painter->setPen(pen); painter->fillPath(path, rectColour); @@ -99,19 +101,20 @@ painter->restore(); - return width; + return width + margin; } QSize TagItem::sizeHint(const QStyleOptionViewItem &option) const { const QFont &font(option.font); + int height = QFontMetrics(font).height(); + const int padding = Dimensions::padding(height); + int width = QFontMetrics(font).width(name); - width += 2 * PADDING; - width += 2 * MARGIN; + width += 2 * padding; - int height = QFontMetrics(font).height(); - height += 2 * PADDING; + height += 2 * padding; return QSize(width, height); } @@ -172,11 +175,13 @@ QSize TagItemList::sizeHint(const QStyleOptionViewItem &option) const { int width = 0; + const int margin = Dimensions::margin(option); foreach (const TagItem &tag, *this) { width += tag.sizeHint(option).width(); + width += 2 * margin; } - width += MARGIN; + width += margin; /* Don't care about vertical dimensions here. */ return QSize(width, 1); diff -Nru datovka-4.7.0/src/dimensions/dimensions.cpp datovka-4.7.1/src/dimensions/dimensions.cpp --- datovka-4.7.0/src/dimensions/dimensions.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/dimensions/dimensions.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/dimensions/dimensions.h" + +const qreal Dimensions::m_margin = 0.4; +const qreal Dimensions::m_padding = 0.1; +const qreal Dimensions::m_lineHeight = 1.5; +const qreal Dimensions::m_screenRatio = 0.8; + +/*! + * @brief Obtain default widget font height. + * + * @param[in] widget Pointer to widget. + * @return Font heigh in pixels. + */ +static inline +int fontHeight(const QWidget *widget) +{ + Q_ASSERT(0 != widget); + + QStyleOption option; + option.initFrom(widget); + return option.fontMetrics.height(); +} + +int Dimensions::margin(const QStyleOptionViewItem &option) +{ + return QFontMetrics(option.font).height() * m_margin; +} + +int Dimensions::padding(int height) +{ + return height * m_padding; +} + +int Dimensions::tableLineHeight(const QStyleOptionViewItem &option) +{ + return QFontMetrics(option.font).height() * m_lineHeight; +} + +QSize Dimensions::windowSize(const QWidget *widget, qreal wr, qreal hr) +{ + if (widget == 0 || wr <= 0.0 || hr <= 0.0) { + return QSize(); + } + + int height = fontHeight(widget); + int w = height * wr; + int h = height * hr; + + /* Reduce window with if it exceeds screen width. */ + QRect screenRect(QApplication::desktop()->screenGeometry()); + + if (screenRect.width() < w) { + qreal ratio = + (qreal)w / ((qreal)screenRect.width() * m_screenRatio); + w /= ratio; + h *= ratio; + } + + return QSize(w, h); +} + +QRect Dimensions::windowDimensions(const QWidget *widget, qreal wr, qreal hr) +{ + if (widget == 0 || wr <= 0.0 || hr <= 0.0) { + return QRect(40, 40, 400, 300); + } + + int height = fontHeight(widget); + int w = height * wr; + int h = height * hr; + + /* Reduce dimensions with if they exceed screen width. */ + QRect screenRect(QApplication::desktop()->screenGeometry()); + + if (screenRect.width() < w) { + w = screenRect.width() * m_screenRatio; + } + if (screenRect.height() < h) { + h = screenRect.height() * m_screenRatio; + } + + /* Compute centred window position. */ + int x = (screenRect.width() - w) / 2; + int y = (screenRect.height() - h) / 2; + + return QRect(x, y, w, h); +} diff -Nru datovka-4.7.0/src/dimensions/dimensions.h datovka-4.7.1/src/dimensions/dimensions.h --- datovka-4.7.0/src/dimensions/dimensions.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/dimensions/dimensions.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _DIMENSIONS_H_ +#define _DIMENSIONS_H_ + +#include + +/*! + * @brief Defines some basic dimensions. + */ +class Dimensions { + +public: + /*! + * @brief Returns margin as function of font dimensions. + * + * @param[in] option Style options. + * @return Margin width in pixels. + */ + static + int margin(const QStyleOptionViewItem &option); + + /*! + * @brief Returns padding as function of supplied dimensions. + * + * @param[in] height Font height. + * @return Padding width in pixels. + */ + static + int padding(int height); + + /*! + * @brief Return default line height to table views and widgets. + * + * @param[in] option Style options. + * @return Line height pixels. + */ + static + int tableLineHeight(const QStyleOptionViewItem &option); + + /*! + * @brief Returns size of dialogue specified as the ratio of the + * detected font height. + * + * @param[in] widget Widget to obtain font metrics from. + * @param[in] wr Width ratio relative to font height. + * @param[in] hr Height ratio relative to font height. + * @return Window size. + */ + static + QSize windowSize(const QWidget *widget, qreal wr, qreal hr); + + /*! + * @brief Returns dimensions of window specified as the ratio of the + * detected font height. + * + * @param[in] widget Widget to obtain font metrics from. + * @param[in] wr Width ratio relative to font height. + * @param[in] hr Height ratio relative to font height. + * @return Window dimensions. + */ + static + QRect windowDimensions(const QWidget *widget, qreal wr, qreal hr); + +private: + /*! + * @brief Constructor. + * + * @note Prohibit any class instance. + */ + Dimensions(void); + + static + const qreal m_margin; /*!< Text margin as ratio of text height. */ + + static + const qreal m_padding; /*!< Text padding as ratio of text height. */ + + static + const qreal m_lineHeight; /*!< Height of line as ration of text height. */ + + static + const qreal m_screenRatio; /*!< Ratio of screen dimensions to use. */ +}; + +#endif /* _DIMENSIONS_H_ */ diff -Nru datovka-4.7.0/src/gui/datovka.cpp datovka-4.7.1/src/gui/datovka.cpp --- datovka-4.7.0/src/gui/datovka.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/datovka.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -47,14 +47,17 @@ #include "src/common.h" #include "src/crypto/crypto_funcs.h" #include "src/delegates/tags_delegate.h" +#include "src/dimensions/dimensions.h" #include "src/gui/dlg_about.h" #include "src/gui/dlg_change_pwd.h" #include "src/gui/dlg_account_from_db.h" #include "src/gui/dlg_create_account.h" +#include "src/gui/dlg_login_mojeid.h" #include "src/gui/dlg_signature_detail.h" #include "src/gui/dlg_change_directory.h" #include "src/gui/dlg_correspondence_overview.h" #include "src/gui/dlg_ds_search.h" +#include "src/gui/dlg_search_mojeid.h" #include "src/gui/dlg_msg_search.h" #include "src/gui/dlg_preferences.h" #include "src/gui/dlg_proxysets.h" @@ -71,10 +74,13 @@ #include "src/io/isds_helper.h" #include "src/io/isds_login.h" #include "src/io/isds_sessions.h" +#include "src/io/wd_sessions.h" #include "src/io/filesystem.h" #include "src/io/message_db_single.h" #include "src/io/message_db_set_container.h" #include "src/io/tag_db.h" +#include "src/model_interaction/attachment_interaction.h" +#include "src/io/tag_db_container.h" #include "src/models/files_model.h" #include "src/views/table_home_end_filter.h" #include "src/views/table_key_press_filter.h" @@ -84,9 +90,17 @@ #include "src/worker/task_erase_message.h" #include "src/worker/task_download_message.h" #include "src/worker/task_download_message_list.h" +#include "src/worker/task_download_message_list_mojeid.h" +#include "src/worker/task_download_message_mojeid.h" +#include "src/worker/task_sync_mojeid.h" +#include "src/worker/task_tag_sync_mojeid.h" +#include "src/worker/task_download_owner_info.h" +#include "src/worker/task_download_password_info.h" +#include "src/worker/task_download_user_info.h" #include "src/worker/task_import_zfo.h" #include "src/worker/task_vacuum_db_set.h" #include "src/worker/task_verify_message.h" +#include "src/worker/task_get_account_list_mojeid.h" #include "ui_datovka.h" @@ -104,6 +118,11 @@ */ #define DISABLE_ALL_TABLE 1 +/* + * If defined then adding of mojeID account will be inaccessible. + */ +#define DISABLE_MOJEID_ACCOUNT_ADDING 1 + /*! * @brief Returns QModelIndex of the currently selected account model node. */ @@ -123,6 +142,115 @@ #define currentFrstColMessageIndexes() \ (ui->messageList->selectionModel()->selectedRows(0)) +/*! + * @brief Returns QModelIndexList containing first column indexes of selected + * attachment model rows. + */ +#define currentFrstColAttachmentIndexes() \ + (ui->messageAttachmentList->selectionModel()->selectedRows(0)) + +/*! + * @brief Message identifier from index. + * + * @param[in] msgIdx Index into the message table view. + * @return Message identifier. + */ +static inline +qint64 msgIdentifier(const QModelIndex &msgIdx) +{ + Q_ASSERT(msgIdx.isValid()); + if (msgIdx.column() == DbMsgsTblModel::DMID_COL) { + return msgIdx.data().toLongLong(); + } else { + return msgIdx.sibling(msgIdx.row(), DbMsgsTblModel::DMID_COL) + .data().toLongLong(); + } +} + +/*! + * @brief Message time from index. + * + * @param[in] msgIdx Index into the message table view. + * @return Delivery time. + */ +static inline +QDateTime msgDeliveryTime(const QModelIndex &msgIdx) +{ + QModelIndex deliveryIdx( + msgIdx.sibling(msgIdx.row(), DbMsgsTblModel::DELIVERY_COL)); + Q_ASSERT(deliveryIdx.isValid()); + + return dateTimeFromDbFormat( + deliveryIdx.data(ROLE_PLAIN_DISPLAY).toString()); +} + +/*! + * @brief Returns a full message identifier from index. + * + * @param[in] msgIdx Index into the message table view. + * @return Full message identifier. + */ +static inline +MessageDb::MsgId msgMsgId(const QModelIndex &msgIdx) +{ + Q_ASSERT(msgIdx.isValid()); + return MessageDb::MsgId(msgIdentifier(msgIdx), msgDeliveryTime(msgIdx)); +} + +/*! + * @brief Returns list of full message identifiers. + * + * @param[in] msgIdxs List of indexes. + * @return List if message identifiers. + */ +static inline +QList msgMsgIds(const QModelIndexList &msgIdxs) +{ + QList msgIds; + foreach (const QModelIndex &idx, msgIdxs) { + if (!idx.isValid()) { + Q_ASSERT(0); + return QList(); + } + MessageDb::MsgId msgId(msgMsgId(idx)); + Q_ASSERT(msgId.dmId >= 0); + msgIds.append(msgId); + } + return msgIds; +} + +/*! + * @brief Returns whether we are working with sent or received messages. + * + * @param[in] acntIdx Account model index. + * @param[in] dfltDirect Default direction to be returned. + * @return Message direction identifier. + */ +static +enum MessageDirection messageDirection(const QModelIndex &acntIdx, + enum MessageDirection dfltDirect) +{ + enum MessageDirection ret = dfltDirect; + + switch (AccountModel::nodeType(acntIdx)) { + case AccountModel::nodeRecentReceived: + case AccountModel::nodeReceived: + case AccountModel::nodeReceivedYear: + ret = MSG_RECEIVED; + break; + case AccountModel::nodeRecentSent: + case AccountModel::nodeSent: + case AccountModel::nodeSentYear: + ret = MSG_SENT; + break; + default: + Q_ASSERT(0); + break; + } + + return ret; +} + /* ========================================================================= */ MainWindow::MainWindow(QWidget *parent) /* ========================================================================= */ @@ -175,6 +303,12 @@ SLOT(collectDownloadMessageStatus(QString, qint64, QDateTime, int, QString, bool))); connect(&globMsgProcEmitter, + SIGNAL(downloadMessageFinishedMojeId(QString, qint64, int, + QString, bool)), + this, + SLOT(collectDownloadMessageMojeId(QString, qint64, int, + QString, bool))); + connect(&globMsgProcEmitter, SIGNAL(downloadMessageListFinished(QString, int, int, QString, bool, int, int, int, int)), this, SLOT(collectDownloadMessageListStatus(QString, int, int, QString, @@ -189,6 +323,13 @@ QString, QString, bool, qint64)), this, SLOT(collectSendMessageStatus(QString, QString, int, QString, QString, QString, bool, qint64))); + connect(&globMsgProcEmitter, + SIGNAL(sendMessageMojeIdFinished(QString, QStringList, QString)), this, + SLOT(sendMessageMojeIdAction(QString, QStringList, QString))); + connect(&globMsgProcEmitter, + SIGNAL(refreshAccountList(QString)), this, + SLOT(refreshAccountList(QString))); + connect(&globWorkPool, SIGNAL(assignedFinished()), this, SLOT(backgroundWorkersFinished())); @@ -261,7 +402,7 @@ SLOT(attachmentItemRightClicked(QPoint))); connect(ui->messageAttachmentList, SIGNAL(doubleClicked(QModelIndex)), this, - SLOT(openSelectedAttachment())); + SLOT(openSelectedAttachment(QModelIndex))); ui->messageAttachmentList->installEventFilter(new TableHomeEndFilter(this)); /* It fires when any column was resized. */ @@ -391,7 +532,7 @@ QByteArray bytes = reply->readAll(); QString vstr = QString::fromUtf8(bytes.data(), bytes.size()); vstr.remove(QRegExp("[\n\t\r]")); - if (vstr > VERSION) { + if (vstr > QCoreApplication::applicationVersion()) { showStatusTextWithTimeout( tr("New version of Datovka is available:") + " " + vstr); @@ -399,7 +540,8 @@ int res = QMessageBox::information(this, tr("New version of Datovka"), tr("New version of Datovka is available.") +"\n\n"+ - tr("Current version is %1").arg(VERSION) + tr("Current version is %1"). + arg(QCoreApplication::applicationVersion()) + "\n" + tr("New version is %1").arg(vstr) + + "\n\n" + @@ -414,7 +556,8 @@ QMessageBox::information(this, tr("New version of Datovka"), tr("New version of Datovka is available.") +"\n\n"+ - tr("Current version is \"%1\"").arg(VERSION) + tr("Current version is \"%1\""). + arg(QCoreApplication::applicationVersion()) + "\n" + tr("New version is \"%1\"").arg(vstr) + "\n\n" + @@ -482,8 +625,15 @@ void MainWindow::updateProgressBar(const QString &label, int value) /* ========================================================================= */ { + if (value == -1) { + mui_statusProgressBar->setMaximum(0); + mui_statusProgressBar->setMinimum(0); + } else { + mui_statusProgressBar->setMaximum(100); + mui_statusProgressBar->setMinimum(0); + mui_statusProgressBar->setValue(value); + } mui_statusProgressBar->setFormat(label); - mui_statusProgressBar->setValue(value); mui_statusProgressBar->repaint(); } @@ -542,7 +692,7 @@ /* ========================================================================= */ /* - * Proxy setting dialog. + * Proxy settings dialogue. */ void MainWindow::proxySettings(void) /* ========================================================================= */ @@ -592,7 +742,8 @@ /* Decouple model and show banner page. */ ui->messageList->setModel(0); ui->messageStackedWidget->setCurrentIndex(0); - ui->accountTextInfo->setHtml(createDatovkaBanner(VERSION)); + ui->accountTextInfo->setHtml(createDatovkaBanner( + QCoreApplication::applicationVersion())); ui->accountTextInfo->setReadOnly(true); return; } @@ -947,26 +1098,16 @@ menu->addAction(ui->actionImport_ZFO_file_into_database); } else { menu->addAction(ui->actionAdd_account); + menu->addAction(ui->actionAdd_mojeID_account); +#ifdef DISABLE_MOJEID_ACCOUNT_ADDING + ui->actionAdd_mojeID_account->setVisible(false); +#endif /* DISABLE_MOJEID_ACCOUNT_ADDING */ } menu->exec(QCursor::pos()); menu->deleteLater(); } -/*! - * @brief Gets message time from selected index. - */ -static inline -QDateTime msgDeliveryTime(const QModelIndex &msgIdx) -{ - QModelIndex deliveryIdx(msgIdx.sibling(msgIdx.row(), DbMsgsTblModel::DELIVERY_COL)); - Q_ASSERT(deliveryIdx.isValid()); - - QDateTime deliveryTime = dateTimeFromDbFormat(deliveryIdx.data(ROLE_PLAIN_DISPLAY).toString()); - - return deliveryTime; -} - /* ========================================================================= */ /* * Sets contents of widgets according to selected messages. @@ -1026,89 +1167,92 @@ ui->messageStateCombo->setEnabled(received); - if (1 == firstColumnIdxs.size()) { - const QModelIndex &index = firstColumnIdxs.first(); + if (1 != firstColumnIdxs.size()) { + /* Multiple messages selected - stop here. */ + return; + } - MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); - if (0 == dbSet) { - Q_ASSERT(0); - return; - } - qint64 msgId = index.data().toLongLong(); - /* Remember last selected message. */ - messageItemStoreSelection(msgId); + MessageDbSet *dbSet = accountDbSet( + m_accountModel.userName(currentAccountModelIndex()), this); + if (0 == dbSet) { + Q_ASSERT(0); + return; + } - QDateTime deliveryTime = msgDeliveryTime(index); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, - false); - if (0 == messageDb) { - Q_ASSERT(0); - return; - } + MessageDb::MsgId msgId(msgMsgId(firstColumnIdxs.first())); - /* Mark message locally read. */ - if (!messageDb->smsgdtLocallyRead(msgId)) { - if (globPref.message_mark_as_read_timeout >= 0) { - qDebug() << "Starting timer to mark as " - "read for message" << msgId; - m_messageMarker.setSingleShot(true); - m_messageMarker.start( - globPref.message_mark_as_read_timeout); - } - } else { - m_messageMarker.stop(); + /* Remember last selected message. */ + messageItemStoreSelection(msgId.dmId); + + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); + if (0 == messageDb) { + Q_ASSERT(0); + return; + } + + /* Mark message locally read. */ + if (!messageDb->smsgdtLocallyRead(msgId.dmId)) { + if (globPref.message_mark_as_read_timeout >= 0) { + qDebug() << "Starting timer to mark as read for message" + << msgId.dmId; + m_messageMarker.setSingleShot(true); + m_messageMarker.start( + globPref.message_mark_as_read_timeout); } + } else { + m_messageMarker.stop(); + } - /* Generate and show message information. */ - ui->messageInfo->setHtml(messageDb->descriptionHtml(msgId, 0)); - ui->messageInfo->setReadOnly(true); + /* Generate and show message information. */ + ui->messageInfo->setHtml(messageDb->descriptionHtml(msgId.dmId, 0)); + ui->messageInfo->setReadOnly(true); - if (received) { - int msgState = messageDb->msgGetProcessState(msgId); + if (received) { + int msgState = messageDb->msgGetProcessState(msgId.dmId); - /* msgState is -1 if message is not in database */ - if (msgState >= 0) { - ui->messageStateCombo->setCurrentIndex( - msgState); - } else { - /* insert message state into database */ - messageDb->msgSetProcessState(msgId, UNSETTLED, - true); - ui->messageStateCombo->setCurrentIndex( - UNSETTLED); - } + /* msgState is -1 if message is not in database */ + if (msgState >= 0) { + ui->messageStateCombo->setCurrentIndex(msgState); } else { + /* insert message state into database */ + messageDb->msgSetProcessState(msgId.dmId, UNSETTLED, + true); ui->messageStateCombo->setCurrentIndex(UNSETTLED); } + } else { + ui->messageStateCombo->setCurrentIndex(UNSETTLED); + } - /* Show files related to message message. */ - QAbstractTableModel *fileTblMdl = messageDb->flsModel(msgId); - Q_ASSERT(0 != fileTblMdl); - //qDebug() << "Setting files"; - ui->messageAttachmentList->setModel(fileTblMdl); - /* First three columns contain hidden data. */ - ui->messageAttachmentList->setColumnHidden( - DbFlsTblModel::ATTACHID_COL, true); - ui->messageAttachmentList->setColumnHidden( - DbFlsTblModel::MSGID_COL, true); - ui->messageAttachmentList->setColumnHidden( - DbFlsTblModel::CONTENT_COL, true); + /* Show files related to message message. */ + QAbstractTableModel *fileTblMdl = messageDb->flsModel(msgId.dmId); + Q_ASSERT(0 != fileTblMdl); + ui->messageAttachmentList->setModel(fileTblMdl); + /* First three columns contain hidden data. */ + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::ATTACHID_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::MSGID_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::CONTENT_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::MIME_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::FPATH_COL, true); - if (ui->messageAttachmentList->model()->rowCount() > 0) { - ui->actionSave_all_attachments->setEnabled(true); - } + if (ui->messageAttachmentList->model()->rowCount() > 0) { + ui->actionSave_all_attachments->setEnabled(true); + } - ui->messageAttachmentList->resizeColumnToContents( - DbFlsTblModel::FNAME_COL); + ui->messageAttachmentList->resizeColumnToContents( + DbFlsTblModel::FNAME_COL); - /* Connect new slot. */ - connect(ui->messageAttachmentList->selectionModel(), - SIGNAL(selectionChanged(QItemSelection, QItemSelection)), - this, - SLOT(attachmentItemsSelectionChanged(QItemSelection, - QItemSelection))); - } + /* Connect new slot. */ + connect(ui->messageAttachmentList->selectionModel(), + SIGNAL(selectionChanged(QItemSelection, QItemSelection)), + this, + SLOT(attachmentItemsSelectionChanged(QItemSelection, + QItemSelection))); } @@ -1136,18 +1280,18 @@ return; } - qint64 msgId = index.sibling(index.row(), 0).data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(index); + const MessageDb::MsgId msgId(msgMsgId(index)); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } /* Get message state from database and toggle the value. */ - bool isRead = messageDb->smsgdtLocallyRead(msgId); - messageDb->smsgdtSetLocallyRead(msgId, !isRead); + bool isRead = messageDb->smsgdtLocallyRead(msgId.dmId); + messageDb->smsgdtSetLocallyRead(msgId.dmId, !isRead); /* * Mark message as read without reloading @@ -1157,7 +1301,7 @@ m_messageListProxyModel.sourceModel()); Q_ASSERT(0 != messageModel); - messageModel->overrideRead(msgId, !isRead); + messageModel->overrideRead(msgId.dmId, !isRead); /* * Reload/update account model only for @@ -1214,6 +1358,9 @@ menu->addAction(ui->actionDownload_message_signed); if (singleSelected) { menu->addAction(ui->actionReply); + } + menu->addAction(ui->actionForward_message); + if (singleSelected) { menu->addAction(ui->actionCreate_message_from_template); } menu->addSeparator(); @@ -1268,17 +1415,8 @@ debugSlotCall(); QModelIndex msgIndex; - { - QModelIndexList msgIndexes; - - QItemSelectionModel *selectionModel = - ui->messageList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - msgIndexes = selectionModel->selectedRows(0); + QModelIndexList msgIndexes(currentFrstColMessageIndexes()); if (msgIndexes.size() != 1) { /* Do nothing when multiple messages selected. */ @@ -1297,38 +1435,39 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - qint64 dmId = msgIndex.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(msgIndex)); + MessageDb::MsgId msgId(msgMsgId(msgIndex)); + Q_ASSERT(msgId.dmId >= 0); MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } - QByteArray msgRaw(messageDb->msgsMessageRaw(dmId)); + QByteArray msgRaw(messageDb->msgsMessageRaw(msgId.dmId)); if (msgRaw.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - msgRaw = messageDb->msgsMessageRaw(dmId); + msgRaw = messageDb->msgsMessageRaw(msgId.dmId); if (msgRaw.isEmpty()) { Q_ASSERT(0); return; @@ -1720,18 +1859,8 @@ Q_UNUSED(selected); Q_UNUSED(deselected); - QModelIndexList selectedIndexes; - { - QItemSelectionModel *selectionModel = - ui->messageAttachmentList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - selectedIndexes = selectionModel->selectedRows(0); - } - - setAttachmentActionVisibility(selectedIndexes.size()); + setAttachmentActionVisibility( + currentFrstColAttachmentIndexes().size()); } @@ -1753,22 +1882,12 @@ } } - QModelIndexList selectedIndexes; - { - QItemSelectionModel *selectionModel = - ui->messageAttachmentList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - selectedIndexes = selectionModel->selectedRows(0); - } - - Q_ASSERT(selectedIndexes.size() > 0); + QModelIndexList attachmentIndexes(currentFrstColAttachmentIndexes()); + Q_ASSERT(attachmentIndexes.size() > 0); QMenu *menu = new QMenu; - if (selectedIndexes.size() == 1) { + if (attachmentIndexes.size() == 1) { menu->addAction(ui->actionOpen_attachment); } menu->addAction(ui->actionSave_selected_attachments); @@ -1789,16 +1908,7 @@ { debugSlotCall(); - QModelIndexList attachmentIndexes; - { - QItemSelectionModel *selectionModel = - ui->messageAttachmentList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - attachmentIndexes = selectionModel->selectedRows(0); - } + QModelIndexList attachmentIndexes(currentFrstColAttachmentIndexes()); QModelIndex messageIndex(currentSingleMessageIndex()); if (!messageIndex.isValid()) { @@ -1806,37 +1916,39 @@ return; } + const QString userName( + m_accountModel.userName(currentAccountModelIndex())); + Q_ASSERT(!userName.isEmpty()); + + const MessageDb::MsgId msgId(msgMsgId(messageIndex)); + foreach (const QModelIndex &attachmentIndex, attachmentIndexes) { - saveAttachmentToFile(messageIndex, attachmentIndex); + saveAttachmentToFile(userName, msgId, attachmentIndex); } } -/* ========================================================================= */ -void MainWindow::saveAttachmentToFile(const QModelIndex &messageIndex, - const QModelIndex &attachmentIndex) -/* ========================================================================= */ +QString MainWindow::attachmentFilePath(const QString &userName, + const MessageDb::MsgId &msgId, QModelIndex attIdx) { - if (!attachmentIndex.isValid()) { + if (userName.isEmpty() || !msgId.isValid() || !attIdx.isValid()) { Q_ASSERT(0); - showStatusTextWithTimeout(tr("Saving attachment of message to " - "files was not successful!")); - return; + return QString(); } - qint64 dmId = messageIndex.sibling( - messageIndex.row(), 0).data().toLongLong(); + if (attIdx.column() != DbFlsTblModel::FNAME_COL) { + attIdx = attIdx.sibling(attIdx.row(), DbFlsTblModel::FNAME_COL); + if (!attIdx.isValid()) { + Q_ASSERT(0); + return QString(); + } + } + Q_ASSERT(attIdx.column() == DbFlsTblModel::FNAME_COL); - QModelIndex fileNameIndex = attachmentIndex.sibling( - attachmentIndex.row(), DbFlsTblModel::FNAME_COL); - Q_ASSERT(fileNameIndex.isValid()); - if(!fileNameIndex.isValid()) { - showStatusTextWithTimeout(tr("Saving attachment of message " - "\"%1\" to files was not successful!").arg(dmId)); - return; + QString fileName(attIdx.data().toString()); + if (fileName.isEmpty()) { + Q_ASSERT(0); + return QString(); } - QString fileName = fileNameIndex.data().toString(); - Q_ASSERT(!fileName.isEmpty()); - /* TODO -- Remember directory? */ QString saveAttachPath; if (globPref.use_global_paths) { @@ -1845,240 +1957,270 @@ saveAttachPath = m_save_attach_dir; } - const QString userName( - m_accountModel.userName(currentAccountModelIndex())); - Q_ASSERT(!userName.isEmpty()); - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); - return; + return QString(); } - QDateTime deliveryTime = msgDeliveryTime(messageIndex); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); - if (0 == messageDb) { + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); + if (Q_NULLPTR == messageDb) { Q_ASSERT(0); - return; + return QString(); } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); QString dbId = globAccountDbPtr->dbId(userName + "___True"); fileName = fileNameFromFormat(globPref.attachment_filename_format, - dmId, dbId, userName, fileName, entry.dmDeliveryTime, + msgId.dmId, dbId, userName, fileName, entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); - - fileName = QFileDialog::getSaveFileName(this, - tr("Save attachment"), - saveAttachPath + QDir::separator() + fileName); - if (fileName.isEmpty()) { - return; - } - - if (!globPref.use_global_paths) { - m_save_attach_dir = - QFileInfo(fileName).absoluteDir().absolutePath(); - storeExportPath(); + return QString(); } + return saveAttachPath + QDir::separator() + fileName; +} - /* Get data from base64. */ - QModelIndex dataIndex = attachmentIndex.sibling(attachmentIndex.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { +void MainWindow::saveAttachmentToFile(const QString &userName, + const MessageDb::MsgId &msgId, const QModelIndex &attIdx) +{ + if (!attIdx.isValid()) { Q_ASSERT(0); - showStatusTextWithTimeout(tr("Saving attachment of message " - "\"%1\" to files was not successful!").arg(dmId)); return; } - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); + QModelIndex fileNameIndex(attIdx.sibling(attIdx.row(), + DbFlsTblModel::FNAME_COL)); + Q_ASSERT(fileNameIndex.isValid()); + if(!fileNameIndex.isValid()) { + showStatusTextWithTimeout( + tr("Saving attachment of message '%1' to files was not successful!") + .arg(msgId.dmId)); + return; + } + QString fileName(attachmentFilePath(userName, msgId, attIdx)); - enum WriteFileState ret = writeFile(fileName, data); - if (WF_SUCCESS == ret) { - showStatusTextWithTimeout(tr("Saving attachment of message " - "\"%1\" to file was successful.").arg(dmId)); + QString savedFileName(AttachmentInteraction::saveAttachmentToFile(this, + attIdx, fileName)); + if (!savedFileName.isEmpty()) { + showStatusTextWithTimeout(tr( + "Saving attachment of message '%1' to file was successful.") + .arg(msgId.dmId)); + if (!globPref.use_global_paths) { + m_save_attach_dir = + QFileInfo(fileName).absoluteDir().absolutePath(); + storeExportPath(); + } } else { - showStatusTextWithTimeout(tr("Saving attachment of message " - "\"%1\" to file was not successful!").arg(dmId)); - QMessageBox::warning(this, - tr("Error saving attachment of message '%1'.").arg(dmId), - tr("Cannot write file '%1'.").arg(fileName), - QMessageBox::Ok); + showStatusTextWithTimeout(tr( + "Saving attachment of message '%1' to file was not successful!") + .arg(msgId.dmId)); } } - -/* ========================================================================= */ -/* - * Save all attachments to dir. - */ void MainWindow::saveAllAttachmentsToDir(void) -/* ========================================================================= */ { debugSlotCall(); - QModelIndex messageIndex(currentSingleMessageIndex()); + MessageDb::MsgId msgId; + { + const QModelIndex messageIndex(currentSingleMessageIndex()); + msgId = msgMsgId(messageIndex); + } - qint64 dmId = messageIndex.sibling( - messageIndex.row(), 0).data().toLongLong(); + DbFlsTblModel *attachModel = qobject_cast( + ui->messageAttachmentList->model()); + /* + * Download missing message. + * TODO -- Make this a separate function and reuse it wherever possible. + */ + if ((!msgId.deliveryTime.isValid()) || + (attachModel == Q_NULLPTR) || (attachModel->rowCount() == 0)) { + const QModelIndex acntIdx(currentAccountModelIndex()); + const QString userName(m_accountModel.userName(acntIdx)); + enum MessageDb::MessageType type; + if (AccountModel::nodeTypeIsReceived(acntIdx)) { + type = MessageDb::TYPE_RECEIVED; + } else if (AccountModel::nodeTypeIsSent(acntIdx)) { + type = MessageDb::TYPE_SENT; + } else { + Q_ASSERT(0); + return; + } - QString saveAttachPath; - if (globPref.use_global_paths) { - saveAttachPath = globPref.save_attachments_path; - } else { - saveAttachPath = m_save_attach_dir; - } + /* No data in attachment model present. */ + const QModelIndex messageIndex(currentSingleMessageIndex()); + msgId = msgMsgId(messageIndex); - QString newDir = QFileDialog::getExistingDirectory(this, - tr("Save attachments"), saveAttachPath, - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (!messageMissingOfferDownload(msgId, + tr("Message export error!"))) { + return; + } - if (newDir.isEmpty()) { - return; + /* Navigate to message. */ + messageItemFromSearchSelection(userName, msgId.dmId, + msgId.deliveryTime.toString("yyyy"), type); + /* Process all pending events. */ + QCoreApplication::processEvents(); } - if (!globPref.use_global_paths) { - m_save_attach_dir = newDir; - storeExportPath(); - } - - bool unspecifiedFailed = false; - QList unsuccessfullFiles; - - const QString userName( - m_accountModel.userName(currentAccountModelIndex())); - Q_ASSERT(!userName.isEmpty()); - - MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { - Q_ASSERT(0); - return; - } - QDateTime deliveryTime = msgDeliveryTime(messageIndex); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); - if (0 == messageDb) { + attachModel = qobject_cast( + ui->messageAttachmentList->model()); + if ((attachModel == Q_NULLPTR) || (attachModel->rowCount() == 0)) { Q_ASSERT(0); return; } - MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); - QString dbId = globAccountDbPtr->dbId(userName + "___True"); - - QList attachList = - messageDb->getFilesFromMessage(dmId); - if (attachList.isEmpty()) { - - if (!messageMissingOfferDownload(dmId, deliveryTime, - tr("Message export error!"))) { + /* Generate list of indexes into all rows. */ + QModelIndexList attIdxs; + for (int row = 0; row < attachModel->rowCount(); ++row) { + QModelIndex idx(attachModel->index(row, + DbFlsTblModel::FNAME_COL)); + if (!idx.isValid()) { + Q_ASSERT(0); return; } + attIdxs.append(idx); + } + Q_ASSERT(attIdxs.size() == attachModel->rowCount()); - messageDb = dbSet->accessMessageDb(deliveryTime, false); - if (0 == messageDb) { + QString attSaveDir; + if (globPref.use_global_paths) { + attSaveDir = globPref.save_attachments_path; + } else { + attSaveDir = m_save_attach_dir; + } + + attSaveDir = QFileDialog::getExistingDirectory(this, + tr("Save attachments"), attSaveDir, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (attSaveDir.isEmpty()) { + return; + } + + /* + * TODO -- This ridiculous asking for mostly irrelevant data and + * generating of stupendous file names must be reworked. + */ + const QString userName( + m_accountModel.userName(currentAccountModelIndex())); + Q_ASSERT(!userName.isEmpty()); + const QString dbId(globAccountDbPtr->dbId(userName + "___True")); + MessageDb::FilenameEntry entry; + { + MessageDbSet *dbSet = accountDbSet(userName, this); + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); return; } - - attachList = messageDb->getFilesFromMessage(dmId); - if (attachList.isEmpty()) { + MessageDb *messageDb = dbSet->accessMessageDb( + msgId.deliveryTime, false); + if (Q_NULLPTR == messageDb) { Q_ASSERT(0); return; } + entry = messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); } - foreach (const MessageDb::FileData &attach, attachList) { - QString fileName(attach.dmFileDescr); + QList unsuccessfulAtts; + bool existenceWarningDisplayed = false; /* Display only once. */ + + foreach (const QModelIndex &attIdx, attIdxs) { + Q_ASSERT(attIdx.column() == DbFlsTblModel::FNAME_COL); + const QString attName(attIdx.data().toString()); + QString fileName(attName); if (fileName.isEmpty()) { - unspecifiedFailed = true; Q_ASSERT(0); continue; } fileName = fileNameFromFormat( globPref.attachment_filename_format, - dmId, dbId, userName, fileName, entry.dmDeliveryTime, + msgId.dmId, dbId, userName, fileName, entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); - fileName = newDir + QDir::separator() + fileName; + fileName = attSaveDir + QDir::separator() + fileName; - QByteArray data( - QByteArray::fromBase64(attach.dmEncodedContent)); - - if (WF_SUCCESS != - writeFile(nonconflictingFileName(fileName), data)) { - unsuccessfullFiles.append(fileName); + bool fileExists = QFileInfo::exists(fileName); + if (fileExists) { + if (!existenceWarningDisplayed) { + QMessageBox::warning(this, + tr("Error saving attachment."), + tr("Some files already exist."), + QMessageBox::Ok); + existenceWarningDisplayed = true; + } + } + QString savedFileName( + AttachmentInteraction::saveAttachmentToFile(this, attIdx, + fileName, fileExists)); + if (savedFileName.isEmpty()) { + unsuccessfulAtts.append(fileName); continue; } if (globPref.delivery_info_for_every_file) { if (globPref.all_attachments_save_zfo_delinfo) { - exportDeliveryInfoAsZFO(newDir, attach.dmFileDescr, + exportDeliveryInfoAsZFO(attSaveDir, attName, globPref.delivery_filename_format_all_attach, - userName, dmId, deliveryTime, false); + userName, msgId, false); } if (globPref.all_attachments_save_pdf_delinfo) { - exportDeliveryInfoAsPDF(newDir, attach.dmFileDescr, - globPref.delivery_filename_format_all_attach, - userName, dmId, deliveryTime, false); + exportDeliveryInfoAsPDF(attSaveDir, attName, + globPref.delivery_filename_format_all_attach, + userName, msgId, false); } } } + if ((!globPref.use_global_paths) && (!attSaveDir.isEmpty())) { + m_save_attach_dir = attSaveDir; + storeExportPath(); + } + if (globPref.all_attachments_save_zfo_msg) { - exportMessageAsZFO(newDir, userName, dmId, deliveryTime, false); + exportMessageAsZFO(attSaveDir, userName, msgId, false); } if (globPref.all_attachments_save_pdf_msgenvel) { - exportMessageEnvelopeAsPDF(newDir, userName, dmId, deliveryTime, - false); + exportMessageEnvelopeAsPDF(attSaveDir, userName, msgId, false); } if (!globPref.delivery_info_for_every_file) { if (globPref.all_attachments_save_zfo_delinfo) { - exportDeliveryInfoAsZFO(newDir, "", + exportDeliveryInfoAsZFO(attSaveDir, QString(), globPref.delivery_filename_format, - userName, dmId, deliveryTime, false); + userName, msgId, false); } if (globPref.all_attachments_save_pdf_delinfo) { - exportDeliveryInfoAsPDF(newDir, "", + exportDeliveryInfoAsPDF(attSaveDir, QString(), globPref.delivery_filename_format, - userName, dmId, deliveryTime, false); + userName, msgId, false); } } - if (unspecifiedFailed) { - showStatusTextWithTimeout(tr("Some attachments of " - "message \"%1\" were not saved to disk!").arg(dmId)); - QMessageBox::warning(this, - tr("Error saving attachments of message '%1'.").arg(dmId), - tr("Could not save all attachments of message '%1'.") - .arg(dmId), - QMessageBox::Ok); - } else if (!unsuccessfullFiles.isEmpty()) { - showStatusTextWithTimeout(tr("Some attachments of " - "message \"%1\" were not saved to disk!").arg(dmId)); - QString warnMsg = + if (!unsuccessfulAtts.isEmpty()) { + showStatusTextWithTimeout( + tr("Some attachments of message '%1' were not saved to disk!") + .arg(msgId.dmId)); + QString warnMsg( tr("In total %1 attachment files could not be written.") - .arg(unsuccessfullFiles.size()); - warnMsg += "\n" + - tr("These are:").arg(unsuccessfullFiles.size()) + "\n"; + .arg(unsuccessfulAtts.size())); + warnMsg += "\n" + tr("These are:") + "\n"; int i; - for (i = 0; i < (unsuccessfullFiles.size() - 1); ++i) { - warnMsg += " '" + unsuccessfullFiles.at(i) + "'\n"; + for (i = 0; i < (unsuccessfulAtts.size() - 1); ++i) { + warnMsg += " '" + unsuccessfulAtts.at(i) + "'\n"; } - warnMsg += " '" + unsuccessfullFiles.at(i) + "'."; + warnMsg += " '" + unsuccessfulAtts.at(i) + "'."; QMessageBox::warning(this, - tr("Error saving attachments of message '%1'.").arg(dmId), + tr("Error saving attachments of message '%1'.") + .arg(msgId.dmId), warnMsg, QMessageBox::Ok); } else { - showStatusTextWithTimeout(tr("All attachments of " - "message \"%1\" were saved.").arg(dmId)); + showStatusTextWithTimeout( + tr("All attachments of message '%1' were saved.") + .arg(msgId.dmId)); } } @@ -2087,77 +2229,24 @@ /* * Open attachment in default application. */ -void MainWindow::openSelectedAttachment(void) +void MainWindow::openSelectedAttachment(const QModelIndex &index) /* ========================================================================= */ { debugSlotCall(); - QModelIndex selectedIndex; - - { - QModelIndexList attachmentIndexes; - - QItemSelectionModel *selectionModel = - ui->messageAttachmentList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - attachmentIndexes = selectionModel->selectedRows(0); - - if (attachmentIndexes.size() != 1) { - Q_ASSERT(0); - return; - } - - selectedIndex = attachmentIndexes[0]; - } - - if (!selectedIndex.isValid()) { - Q_ASSERT(0); - return; - } - - QModelIndex fileNameIndex = selectedIndex.sibling(selectedIndex.row(), - DbFlsTblModel::FNAME_COL); - Q_ASSERT(fileNameIndex.isValid()); - if(!fileNameIndex.isValid()) { - return; - } - QString attachName = fileNameIndex.data().toString(); - Q_ASSERT(!attachName.isEmpty()); - if (attachName.isEmpty()) { - return; - } - attachName.replace(QRegExp("\\s"), "_").replace( - QRegExp("[^a-zA-Z\\d\\.\\-_]"), "x"); - /* TODO -- Add message id into file name? */ - QString fileName = TMP_ATTACHMENT_PREFIX + attachName; - - /* Get data from base64. */ - QModelIndex dataIndex = selectedIndex.sibling(selectedIndex.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { - Q_ASSERT(0); - return; - } - - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); + QString attachName; + QString tmpPath; - fileName = writeTemporaryFile(fileName, data); - if (!fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Attachment '%1' stored to " - "temporary file '%2'.").arg(attachName).arg(fileName)); - QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); - /* TODO -- Handle openUrl() return value. */ + if (AttachmentInteraction::openAttachment(this, + *ui->messageAttachmentList, index, + &attachName, &tmpPath)) { + showStatusTextWithTimeout(tr( + "Attachment '%1' stored into temporary file '%2'.") + .arg(attachName).arg(tmpPath)); } else { - showStatusTextWithTimeout(tr("Attachment '%1' couldn't be " - "stored to temporary file.").arg(attachName)); - QMessageBox::warning(this, - tr("Error opening attachment."), - tr("Cannot write file '%1'.").arg(fileName), - QMessageBox::Ok); + showStatusTextWithTimeout(tr( + "Attachment '%1' couldn't be stored into temporary file.") + .arg(attachName)); } } @@ -2242,6 +2331,48 @@ } } +void MainWindow::collectDownloadMessageMojeId(const QString &usrName, + qint64 msgId, int result, const QString &errDesc, bool listScheduled) +{ + debugSlotCall(); + + if (TaskDownloadMessageMojeId::DM_SUCCESS == result) { + /* Refresh account and attachment list. */ + refreshAccountList(usrName); + + if (0 <= msgId) { + postDownloadSelectedMessageAttachments(usrName, msgId); + } + } else { + /* Notify the user. */ + if (!listScheduled) { + QMessageBox msgBox(this); + + showStatusTextWithTimeout(tr("It was not possible download " + "complete message \"%1\" from webdatovka server.").arg(msgId)); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(tr("Download message error")); + msgBox.setText(tr("It was not possible to download a complete " + "message \"%1\" from webdatovka server.").arg(msgId)); + if (!errDesc.isEmpty()) { + msgBox.setInformativeText(tr("Webdatovka: ") + errDesc); + } else { + msgBox.setInformativeText(tr("A connection error " + "occurred or the message has already been deleted " + "from the server.")); + } + + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.exec(); + } else { + showStatusTextWithTimeout( + tr("Couldn't download message '%1'.").arg(msgId)); + } + } +} + + void MainWindow::collectDownloadMessageListStatus(const QString &usrName, int direction, int result, const QString &errDesc, bool add, int rt, int rn, int st, int sn) @@ -2259,16 +2390,16 @@ QString errorMessage = (MSG_RECEIVED == direction) ? tr("It was not possible download received message list from" - " ISDS server.") : + " server.") : tr("It was not possible download sent message list from" - " ISDS server."); + " server."); showStatusTextWithTimeout(errorMessage); msgBox.setIcon(QMessageBox::Warning); msgBox.setWindowTitle(tr("Download message list error")); msgBox.setText(errorMessage); if (!errDesc.isEmpty()) { - msgBox.setInformativeText(tr("ISDS: ") + errDesc); + msgBox.setInformativeText(tr("Server: ") + errDesc); } else { msgBox.setInformativeText( tr("A connection error occurred.")); @@ -2322,7 +2453,7 @@ debugFuncCall(); showStatusTextWithTimeout(tr("Message \"%1\" " - " was downloaded from ISDS server.").arg(dmId)); + " was downloaded from server.").arg(dmId)); const QString currentUserName( m_accountModel.userName(currentAccountModelIndex())); @@ -2363,9 +2494,7 @@ ui->messageList->selectionModel()->select(storedMsgSelection, QItemSelectionModel::ClearAndSelect); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - if (1 != firstMsgColumnIdxs.size()) { + if (1 != currentFrstColMessageIndexes().size()) { return; } @@ -2412,6 +2541,10 @@ DbFlsTblModel::MSGID_COL, true); ui->messageAttachmentList->setColumnHidden( DbFlsTblModel::CONTENT_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::MIME_COL, true); + ui->messageAttachmentList->setColumnHidden( + DbFlsTblModel::FPATH_COL, true); if (ui->messageAttachmentList->model()->rowCount() > 0) { ui->actionSave_all_attachments->setEnabled(true); @@ -2842,9 +2975,7 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetReadStatus(firstMsgColumnIdxs, true); + messageItemsSetReadStatus(currentFrstColMessageIndexes(), true); } @@ -2857,9 +2988,7 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetReadStatus(firstMsgColumnIdxs, false); + messageItemsSetReadStatus(currentFrstColMessageIndexes(), false); } @@ -2872,9 +3001,7 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetProcessStatus(firstMsgColumnIdxs, UNSETTLED); + messageItemsSetProcessStatus(currentFrstColMessageIndexes(), UNSETTLED); } @@ -2887,9 +3014,7 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetProcessStatus(firstMsgColumnIdxs, IN_PROGRESS); + messageItemsSetProcessStatus(currentFrstColMessageIndexes(), IN_PROGRESS); } @@ -2902,27 +3027,19 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetProcessStatus(firstMsgColumnIdxs, SETTLED); + messageItemsSetProcessStatus(currentFrstColMessageIndexes(), SETTLED); } /* ========================================================================= */ /* - * Delete selected message from local database and ISDS. + * Delete selected message from local database and ISDS/Webdatovka. */ void MainWindow::deleteMessage(void) /* ========================================================================= */ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - if (firstMsgColumnIdxs.isEmpty()) { - return; - } - const QString userName( m_accountModel.userName(currentAccountModelIndex())); if (userName.isEmpty()) { @@ -2930,6 +3047,17 @@ return; } + if (isWebDatovkaAccount(userName)) { + deleteMessageWebdatovka(userName); + return; + } + + QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); + + if (firstMsgColumnIdxs.isEmpty()) { + return; + } + QString dlgTitleText, questionText, checkBoxText, detailText; int msgIdxCnt = firstMsgColumnIdxs.size(); @@ -2947,7 +3075,7 @@ checkBoxText = tr("Delete these messages also from server ISDS"); detailText = tr("Warning: If you delete selected messages " - "from ISDS then these message will be lost forever."); + "from ISDS then these messages will be lost forever."); } QDialog *yesNoCheckDlg = new YesNoCheckboxDialog(dlgTitleText, @@ -2967,6 +3095,86 @@ return; } + /* Save current account index */ + QModelIndex selectedAcntIndex(currentAccountModelIndex()); + + foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { + if (eraseMessage(userName, id, delMsgIsds)) { + /* + * Hiding selected line in the message model actually + * does not help. The model contains all the old data + * and causes problems. Therefore the model must be + * regenerated. + */ + if (selectedAcntIndex.isValid()) { + accountItemCurrentChanged(selectedAcntIndex); + } + /* + * TODO -- Remove the year on account list if last + * message was removed. + */ + + /* Delete all tags from message_tags table. + * Tag in the tag table are kept. + */ + globTagDbPtr->removeAllTagsFromMsg(userName, id.dmId); + } + } + + /* Refresh account list. */ + refreshAccountList(userName); +} + + +/* ========================================================================= */ +/* + * Func: Delete selected message from local database and Webdatovka. + */ +void MainWindow::deleteMessageWebdatovka(const QString &userName) +/* ========================================================================= */ +{ + debugFuncCall(); + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + showWebDatovkaInfoDialog(userName, + tr("You have to be logged into the Webdatovka " + "if you want to delete message(s).")); + return; + } + + QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); + if (firstMsgColumnIdxs.isEmpty()) { + return; + } + + QString dlgTitleText, questionText, detailText; + int msgIdxCnt = firstMsgColumnIdxs.size(); + + if (1 == msgIdxCnt) { + qint64 dmId = firstMsgColumnIdxs.first().data().toLongLong(); + dlgTitleText = tr("Delete message %1").arg(dmId); + questionText = tr("Do you want to delete " + "message '%1'?").arg(dmId); + detailText = tr("Warning: If you delete the message " + "from Webdatovka then this message will be lost forever."); + } else { + dlgTitleText = tr("Delete messages"); + questionText = tr("Do you want to delete selected messages?"); + detailText = tr("Warning: If you delete selected messages " + "from Webdatovka then these messages will be lost forever."); + } + + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Question); + msgBox.setWindowTitle(dlgTitleText); + msgBox.setText(questionText); + msgBox.setInformativeText(detailText); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + if (QMessageBox::No == msgBox.exec()) { + return; + } + QList msgIds; foreach (const QModelIndex &idx, firstMsgColumnIdxs) { msgIds.append(MessageDb::MsgId(idx.data().toLongLong(), @@ -2976,9 +3184,27 @@ /* Save current account index */ QModelIndex selectedAcntIndex(currentAccountModelIndex()); + MessageDbSet *dbSet = accountDbSet(userName, this); + if (Q_NULLPTR == dbSet) { + Q_ASSERT(0); + return; + } + + QString errStr; foreach (const MessageDb::MsgId &id, msgIds) { - if (eraseMessage(userName, id.dmId, id.deliveryTime, - delMsgIsds)) { + MessageDb *messageDb = + dbSet->accessMessageDb(id.deliveryTime, false); + if (messageDb == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + if (!jsonlayer.deleteMessage(userName, + messageDb->getWebDatokaId(id.dmId), errStr)) { + qDebug() << "WD_DELETE_MESSAGE_ERROR:" << id.dmId + << errStr; + continue; + } + if (eraseMessage(userName, id, false)) { /* * Hiding selected line in the message model actually * does not help. The model contains all the old data @@ -2996,7 +3222,9 @@ /* Delete all tags from message_tags table. * Tag in the tag table are kept. */ - globTagDbPtr->removeAllTagsFromMsg(userName, id.dmId); + TagDb *tagDb = + globWebDatovkaTagDbPtr->accessTagDb(userName); + tagDb->removeAllTagsFromMsg(userName, id.dmId); } } @@ -3010,8 +3238,8 @@ * Delete message from long term storage in ISDS and * local database - based on action parameter. */ -bool MainWindow::eraseMessage(const QString &userName, qint64 dmId, - const QDateTime &deliveryTime, bool delFromIsds) +bool MainWindow::eraseMessage(const QString &userName, + const MessageDb::MsgId &msgId, bool delFromIsds) /* ========================================================================= */ { debugFuncCall(); @@ -3024,39 +3252,22 @@ return false; } - bool incoming = true; - { - QModelIndex acntIdx(currentAccountModelIndex()); - - switch (AccountModel::nodeType(acntIdx)) { - case AccountModel::nodeRecentReceived: - case AccountModel::nodeReceived: - case AccountModel::nodeReceivedYear: - incoming = true; - break; - case AccountModel::nodeRecentSent: - case AccountModel::nodeSent: - case AccountModel::nodeSentYear: - incoming = false; - break; - default: - break; - } - } + enum MessageDirection msgDirect = + messageDirection(currentAccountModelIndex(), MSG_RECEIVED); if (delFromIsds && !globIsdsSessions.isConnectedToIsds(userName) && !connectToIsds(userName)) { logErrorNL( "Couldn't connect to ISDS when erasing message '%" PRId64 "'.", - dmId); + msgId.dmId); return false; } QString errorStr, longErrorStr; TaskEraseMessage *task; - task = new (std::nothrow) TaskEraseMessage(userName, dbSet, dmId, - deliveryTime, incoming, delFromIsds); + task = new (std::nothrow) TaskEraseMessage(userName, dbSet, msgId, + msgDirect, delFromIsds); task->setAutoDelete(false); globWorkPool.runSingle(task); @@ -3067,43 +3278,45 @@ switch (result) { case TaskEraseMessage::NOT_DELETED: - logErrorNL("Message '%" PRId64 "' couldn't be deleted.", dmId); + logErrorNL("Message '%" PRId64 "' couldn't be deleted.", + msgId.dmId); showStatusTextWithTimeout(tr("Message \"%1\" was not deleted.") - .arg(dmId)); + .arg(msgId.dmId)); return false; break; case TaskEraseMessage::DELETED_ISDS: logWarning("Message '%" PRId64 "' deleted only from ISDS.\n", - dmId); + msgId.dmId); showStatusTextWithTimeout(tr( - "Message \"%1\" was deleted only from ISDS.").arg(dmId)); + "Message \"%1\" was deleted only from ISDS.") + .arg(msgId.dmId)); return false; break; case TaskEraseMessage::DELETED_LOCAL: if (delFromIsds) { logWarning( "Message '%" PRId64 "' deleted only from local database.\n", - dmId); + msgId.dmId); showStatusTextWithTimeout(tr( "Message \"%1\" was deleted only from local database.") - .arg(dmId)); + .arg(msgId.dmId)); } else { logInfo( "Message '%" PRId64 "' deleted from local database.\n", - dmId); + msgId.dmId); showStatusTextWithTimeout(tr( "Message \"%1\" was deleted from local database.") - .arg(dmId)); + .arg(msgId.dmId)); } return true; break; case TaskEraseMessage::DELETED_ISDS_LOCAL: logInfo( "Message '%" PRId64 "' deleted from ISDS and local database.\n", - dmId); + msgId.dmId); showStatusTextWithTimeout(tr( "Message \"%1\" was deleted from ISDS and local database.") - .arg(dmId)); + .arg(msgId.dmId)); return true; break; default: @@ -3177,6 +3390,13 @@ continue; } + // webdatovka sync + if (isWebDatovkaAccount(userName)) { + synchroniseSelectedAccount(userName); + continue; + } + + /* Try connecting to ISDS, just to generate log-in dialogue. */ if (!globIsdsSessions.isConnectedToIsds(userName) && !connectToIsds(userName)) { @@ -3215,6 +3435,12 @@ userName = m_accountModel.userName(currentAccountModelIndex()); Q_ASSERT(!userName.isEmpty()); } + + // webdatovka sync + if (isWebDatovkaAccount(userName)) { + return wdSyncAccount(userName); + } + MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { return false; @@ -3290,69 +3516,70 @@ { debugSlotCall(); - enum MessageDirection msgDirection = MSG_RECEIVED; - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (firstMsgColumnIdxs.isEmpty()) { return; } - QList msgIds; - foreach (const QModelIndex &idx, firstMsgColumnIdxs) { - msgIds.append(MessageDb::MsgId(idx.data().toLongLong(), - msgDeliveryTime(idx))); - } - - QString userName; - { - QModelIndex accountIndex(currentAccountModelIndex()); - Q_ASSERT(accountIndex.isValid()); - - switch (AccountModel::nodeType(accountIndex)) { - case AccountModel::nodeRecentReceived: - case AccountModel::nodeReceived: - case AccountModel::nodeReceivedYear: - msgDirection = MSG_RECEIVED; - break; - case AccountModel::nodeRecentSent: - case AccountModel::nodeSent: - case AccountModel::nodeSentYear: - msgDirection = MSG_SENT; - break; - default: - break; - } - - userName = m_accountModel.userName(accountIndex); - } - - /* Try connecting to ISDS, just to generate log-in dialogue. */ + const QModelIndex acntIdx(currentAccountModelIndex()); + enum MessageDirection msgDirect = + messageDirection(acntIdx, MSG_RECEIVED); + const QString userName(m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return; } - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return; - } - ui->actionSync_all_accounts->setEnabled(false); - ui->actionGet_messages->setEnabled(false); + if (isWebDatovkaAccount(userName)) { + if (!wdSessions.isConnectedToWebdatovka(userName)) { + loginToMojeId(userName); + } - foreach (const MessageDb::MsgId &id, msgIds) { - /* Using prepend() just to outrun other jobs. */ - TaskDownloadMessage *task; + if (!wdSessions.isConnectedToWebdatovka(userName)) { + showWebDatovkaInfoDialog(userName, + tr("You have to be logged into the WebDatovka " + "if you want to download complete message.")); + return; + } - task = new (std::nothrow) TaskDownloadMessage( - userName, dbSet, msgDirection, id.dmId, id.deliveryTime, - false); - task->setAutoDelete(true); - globWorkPool.assignLo(task, WorkerPool::PREPEND); + foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { + /* Using prepend() just to outrun other jobs. */ + MessageDb *messageDb = dbSet->accessMessageDb(id.deliveryTime, false); + if (messageDb == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + int mId = messageDb->getWebDatokaId(id.dmId); + TaskDownloadMessageMojeId *task; + + task = new (std::nothrow) TaskDownloadMessageMojeId( + userName, dbSet, msgDirect, mId, id.dmId, false); + task->setAutoDelete(true); + globWorkPool.assignLo(task, WorkerPool::PREPEND); + } + } else { + + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return; + } + + ui->actionSync_all_accounts->setEnabled(false); + ui->actionGet_messages->setEnabled(false); + + foreach (const MessageDb::MsgId &id, msgMsgIds(firstMsgColumnIdxs)) { + /* Using prepend() just to outrun other jobs. */ + TaskDownloadMessage *task; + + task = new (std::nothrow) TaskDownloadMessage( + userName, dbSet, msgDirect, id, false); + task->setAutoDelete(true); + globWorkPool.assignLo(task, WorkerPool::PREPEND); + } } } @@ -3372,10 +3599,17 @@ html.append(indentDivStart); html.append("

"); - if (AccountModel::globAccounts[userName].isTestAccount()) { - html.append(tr("Test account")); + + if (isWebDatovkaAccount(userName)) { + html.append(tr("MojeID account")); + html.append("
\"mojeID\""); } else { - html.append(tr("Standard account")); + if (AccountModel::globAccounts[userName].isTestAccount()) { + html.append(tr("Test account")); + } else { + html.append(tr("Standard account")); + } + html.append("
\"ISDS\""); } html.append("

"); @@ -4009,8 +4243,6 @@ } -#define W_OFFS 2 -#define H_OFFS 22 #define SH_OFFS 50 /* Menu bar + top tool-bar. */ /* ========================================================================= */ /* @@ -4020,11 +4252,16 @@ /* ========================================================================= */ { /* Window geometry. */ + QRect defaultDimensions(Dimensions::windowDimensions(this, 76.0, 48.0)); - int x = settings.value("window_position/x", 0).toInt() + W_OFFS; - int y = settings.value("window_position/y", 0).toInt() + H_OFFS; - int w = settings.value("window_position/w", 800).toInt(); - int h = settings.value("window_position/h", 600).toInt(); + int x = settings.value(WIN_POSITION_HEADER "/" WIN_POSITION_X, + defaultDimensions.x()).toInt(); + int y = settings.value(WIN_POSITION_HEADER "/" WIN_POSITION_Y, + defaultDimensions.y()).toInt(); + int w = settings.value(WIN_POSITION_HEADER "/" WIN_POSITION_W, + defaultDimensions.width()).toInt(); + int h = settings.value(WIN_POSITION_HEADER "/" WIN_POSITION_H, + defaultDimensions.height()).toInt(); this->setGeometry(x, y, w, h); /* Splitter geometry. */ @@ -4103,6 +4340,8 @@ /* Separator. */ connect(ui->actionAdd_account, SIGNAL(triggered()), this, SLOT(addNewAccount())); + connect(ui->actionAdd_mojeID_account, SIGNAL(triggered()), + this, SLOT(addNewMojeIDAccount())); connect(ui->actionDelete_account, SIGNAL(triggered()), this, SLOT(deleteSelectedAccount())); /* Separator. */ @@ -4157,6 +4396,8 @@ this, SLOT(downloadSelectedMessageAttachments())); connect(ui->actionReply, SIGNAL(triggered()), this, SLOT(createAndSendMessageReply())); + connect(ui->actionForward_message, SIGNAL(triggered()), + this, SLOT(createAndSendMessageWithZfos())); connect(ui->actionCreate_message_from_template, SIGNAL(triggered()), this, SLOT(createAndSendMessageFromTmpl())); /* Separator. */ @@ -4304,6 +4545,7 @@ ui->actionDownload_message_signed->setEnabled(numSelected > 0); ui->actionReply->setEnabled(numSelected == 1); + ui->actionForward_message->setEnabled(numSelected > 0); ui->actionCreate_message_from_template->setEnabled(numSelected == 1); /* Separator. */ ui->actionSignature_detail->setEnabled(numSelected == 1); @@ -4369,18 +4611,18 @@ /* Window geometry. */ - settings.beginGroup("window_position"); + settings.beginGroup(WIN_POSITION_HEADER); - value = this->geometry().x() - W_OFFS; + value = this->geometry().x(); value = (value < 0) ? 0 : value; - settings.setValue("x", value); + settings.setValue(WIN_POSITION_X, value); - value = this->geometry().y() - H_OFFS; + value = this->geometry().y(); value = (value < 0) ? 0 : value; - settings.setValue("y", value); + settings.setValue(WIN_POSITION_Y, value); - settings.setValue("w", this->geometry().width()); - settings.setValue("h", this->geometry().height()); + settings.setValue(WIN_POSITION_W, this->geometry().width()); + settings.setValue(WIN_POSITION_H, this->geometry().height()); settings.endGroup(); @@ -4395,14 +4637,12 @@ settings.endGroup(); } -#undef W_OFFS -#undef H_OFFS #undef SH_OFFS /* ========================================================================= */ /* - * Load and apply setting from configuration file. + * Load and apply settings from configuration file. */ void MainWindow::loadSettings(void) /* ========================================================================= */ @@ -4675,7 +4915,7 @@ /* ========================================================================= */ /*! - * @brief Store current setting to configuration file. + * @brief Store current settings to configuration file. */ void MainWindow::saveSettings(void) const /* ========================================================================= */ @@ -4744,6 +4984,11 @@ openSendMessageDialog(DlgSendMessage::ACT_REPLY); } +void MainWindow::createAndSendMessageWithZfos(void) +{ + debugSlotCall(); + openSendMessageDialog(DlgSendMessage::ACT_FORWARD); +} /* ========================================================================= */ /* @@ -4766,8 +5011,7 @@ debugFuncCall(); QList messageDbList; - qint64 msgId = -1; - QDateTime deliveryTime; + QList msgIds; /* get username of selected account */ const QString userName( @@ -4796,21 +5040,47 @@ messageDbList.append(Task::AccountDescr(userName, dbSet)); } - /* if is reply or template, ID of selected message is required */ - if (DlgSendMessage::ACT_REPLY == action || - DlgSendMessage::ACT_NEW_FROM_TMP == action) { - const QAbstractItemModel *tableModel = - ui->messageList->model(); - Q_ASSERT(0 != tableModel); - QModelIndex index = tableModel->index( - currentSingleMessageIndex().row(), 0); - msgId = tableModel->itemData(index).first().toLongLong(); - deliveryTime = msgDeliveryTime(index); + QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); + + switch (action) { + case DlgSendMessage::ACT_NEW: + break; + case DlgSendMessage::ACT_REPLY: + case DlgSendMessage::ACT_NEW_FROM_TMP: + Q_ASSERT(firstMsgColumnIdxs.size() == 1); + /* No break here. */ + case DlgSendMessage::ACT_FORWARD: + Q_ASSERT(firstMsgColumnIdxs.size() > 0); + foreach (const QModelIndex &msgIdx, firstMsgColumnIdxs) { + MessageDb::MsgId msgId(msgMsgId(msgIdx)); + + /* Check whether full messages are present. */ + MessageDbSet *dbSet = accountDbSet(userName, this); + Q_ASSERT(0 != dbSet); + + MessageDb *messageDb = + dbSet->accessMessageDb(msgId.deliveryTime, false); + if (0 == messageDb) { + Q_ASSERT(0); + return; + } + + if (!messageDb->msgsStoredWhole(msgId.dmId)) { + messageMissingOfferDownload(msgId, + tr("Full message not present!")); + } + + msgIds.append(msgId); + } + break; + default: + Q_ASSERT(0); + return; + break; } QDialog *sendMsgDialog = new DlgSendMessage(messageDbList, - (DlgSendMessage::Action) action, msgId, deliveryTime, - userName, this); + (DlgSendMessage::Action) action, msgIds, userName, this); showStatusTextWithTimeout(tr("Create and send a message.")); @@ -4820,7 +5090,6 @@ sendMsgDialog->setAttribute(Qt::WA_DeleteOnClose, true); sendMsgDialog->show(); - } @@ -4875,6 +5144,19 @@ /* ========================================================================= */ /* + * Add mojeID account action and dialog. + */ +void MainWindow::addNewMojeIDAccount(void) +/* ========================================================================= */ +{ + debugSlotCall(); + + loginToMojeId(QString()); +} + + +/* ========================================================================= */ +/* * Slot: Delete selected account */ void MainWindow::deleteSelectedAccount(void) @@ -4885,6 +5167,19 @@ const QString userName( m_accountModel.userName(currentAccountModelIndex())); + deleteAccount(userName); +} + + +/* ========================================================================= */ +/* + * Slot: Delete account. + */ +void MainWindow::deleteAccount(const QString &userName) +/* ========================================================================= */ +{ + debugSlotCall(); + if (userName.isEmpty()) { Q_ASSERT(0); return; @@ -4935,7 +5230,17 @@ .arg(accountName)); } - globTagDbPtr->removeAllMsgTagsFromAccount(userName); + if (isWebDatovkaAccount(userName)) { + TagDb *tagDbWd = globWebDatovkaTagDbPtr->accessTagDb( + getWebDatovkaTagDbPrefix(userName)); + if (!existsAnotherMojeIdAccountWithSameUserId(userName)) { + globWebDatovkaTagDbPtr->deleteDb(tagDbWd); + } else { + tagDbWd->removeAllMsgTagsFromAccount(userName); + } + } else { + globTagDbPtr->removeAllMsgTagsFromAccount(userName); + } if ((YesNoCheckboxDialog::YesChecked == retVal) || (YesNoCheckboxDialog::YesUnchecked == retVal)) { @@ -5206,9 +5511,22 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return; + if (!isWebDatovkaAccount(userName)) { + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return; + } + } else { + if (!wdSessions.isConnectedToWebdatovka(userName)) { + loginToMojeId(userName); + } + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + showWebDatovkaInfoDialog(userName, + tr("You have to be logged into the WebDatovka " + "if you want to find databox.")); + return; + } } /* Method connectToIsds() acquires account information. */ @@ -5226,10 +5544,18 @@ showStatusTextWithTimeout(tr("Find databoxes from account \"%1\".") .arg(AccountModel::globAccounts[userName].accountName())); - QDialog *dsSearch = new DlgDsSearch(DlgDsSearch::ACT_BLANK, 0, - dbType, dbEffectiveOVM, dbOpenAddressing, this, userName); - dsSearch->exec(); - dsSearch->deleteLater(); + if (isWebDatovkaAccount(userName)) { + QDialog *dsSearch = + new DlgDsSearchMojeId(DlgDsSearchMojeId::ACT_BLANK, 0, + dbType, dbEffectiveOVM, this, userName); + dsSearch->exec(); + dsSearch->deleteLater(); + } else { + QDialog *dsSearch = new DlgDsSearch(DlgDsSearch::ACT_BLANK, 0, + dbType, dbEffectiveOVM, dbOpenAddressing, this, userName); + dsSearch->exec(); + dsSearch->deleteLater(); + } } @@ -5535,7 +5861,7 @@ void MainWindow::refreshAccountList(const QString &userName) /* ========================================================================= */ { - debugFuncCall(); + debugSlotCall(); if (userName.isEmpty()) { logWarning("%s\n", @@ -5931,16 +6257,19 @@ const QString userName( m_accountModel.userName(currentAccountModelIndex())); - qint64 dmId = -1; - QDateTime deliveryTime; - { - QModelIndex msgIdx = firstMsgColumnIdxs.first(); - dmId = msgIdx.sibling(msgIdx.row(), 0).data().toLongLong(); - deliveryTime = msgDeliveryTime(msgIdx); + + if (isWebDatovkaAccount(userName)) { + showWebDatovkaInfoDialog(userName, ""); + return; } + + MessageDb::MsgId msgId(msgMsgId(firstMsgColumnIdxs.first())); Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); - Q_ASSERT(deliveryTime.isValid()); + Q_ASSERT(msgId.dmId >= 0); + if (!msgId.deliveryTime.isValid()) { + Q_ASSERT(0); + return; + } MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { @@ -5957,10 +6286,8 @@ return; } - TaskVerifyMessage *task; - - task = new (std::nothrow) TaskVerifyMessage(userName, dbSet, dmId, - deliveryTime); + TaskVerifyMessage *task = new (std::nothrow) TaskVerifyMessage(userName, + dbSet, msgId); task->setAutoDelete(false); globWorkPool.runSingle(task); @@ -6087,6 +6414,14 @@ { debugSlotCall(); + const QString userName = + m_accountModel.userName(currentAccountModelIndex()); + + if (isWebDatovkaAccount(userName)) { + showWebDatovkaInfoDialog(userName, ""); + return; + } + QDialog *importZfo = new ImportZFODialog(this); connect(importZfo, SIGNAL(returnZFOAction(enum ImportZFODialog::ZFOtype, @@ -6451,14 +6786,13 @@ * Export message into as ZFO file dialogue. */ void MainWindow::exportMessageAsZFO(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation) + const QString &userName, MessageDb::MsgId msgId, bool askLocation) /* ========================================================================= */ { debugFuncCall(); Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); /* Delivery time can be invalid. */ MessageDbSet *dbSet = accountDbSet(userName, this); @@ -6466,33 +6800,35 @@ Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); QString dbId = globAccountDbPtr->dbId(userName + "___True"); - QByteArray base64 = messageDb->msgsMessageBase64(dmId); + QByteArray base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - base64 = messageDb->msgsMessageBase64(dmId); + base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { Q_ASSERT(0); return; @@ -6500,7 +6836,7 @@ } QString fileName = fileNameFromFormat(globPref.message_filename_format, - dmId, dbId, userName, "", entry.dmDeliveryTime, + msgId.dmId, dbId, userName, "", entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); if (attachPath.isEmpty()) { @@ -6519,8 +6855,9 @@ } if (fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message \"%1\" to " - "ZFO was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message \"%1\" to ZFO was not successful!") + .arg(msgId.dmId)); return; } @@ -6535,13 +6872,15 @@ enum WriteFileState ret = writeFile(fileName, data); if (WF_SUCCESS == ret) { - showStatusTextWithTimeout(tr("Export of message \"%1\" to " - "ZFO was successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message \"%1\" to ZFO was successful!") + .arg(msgId.dmId)); } else { - showStatusTextWithTimeout(tr("Export of message \"%1\" to " - "ZFO was not successful.").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message \"%1\" to ZFO was not successful.") + .arg(msgId.dmId)); QMessageBox::warning(this, - tr("Error exporting message '%1'.").arg(dmId), + tr("Error exporting message '%1'.").arg(msgId.dmId), tr("Cannot write file '%1'.").arg(fileName), QMessageBox::Ok); } @@ -6552,75 +6891,95 @@ /* * Download complete message synchronously without worker and thread */ -bool MainWindow::downloadCompleteMessage(qint64 dmId, - QDateTime &deliveryTime) +bool MainWindow::downloadCompleteMessage(MessageDb::MsgId &msgId) /* ========================================================================= */ { debugFuncCall(); /* selection().indexes() ? */ - enum MessageDirection msgDirect = MSG_RECEIVED; - - QModelIndex acntIndex(currentAccountModelIndex()); - switch (AccountModel::nodeType(acntIndex)) { - case AccountModel::nodeRecentReceived: - case AccountModel::nodeReceived: - case AccountModel::nodeReceivedYear: - msgDirect = MSG_RECEIVED; - break; - case AccountModel::nodeRecentSent: - case AccountModel::nodeSent: - case AccountModel::nodeSentYear: - msgDirect = MSG_SENT; - break; - default: - break; - } - - const QString userName(m_accountModel.userName(acntIndex)); + const QModelIndex acntIdx(currentAccountModelIndex()); + enum MessageDirection msgDirect = + messageDirection(acntIdx, MSG_RECEIVED); + const QString userName(m_accountModel.userName(acntIdx)); Q_ASSERT(!userName.isEmpty()); - if (!globIsdsSessions.isConnectedToIsds(userName) && - !connectToIsds(userName)) { - return false; - } MessageDbSet *dbSet = accountDbSet(userName, this); - if (0 == dbSet) { + if (Q_NULLPTR == dbSet) { Q_ASSERT(0); return false; } bool ret = false; - TaskDownloadMessage *task; - task = new (std::nothrow) TaskDownloadMessage( - userName, dbSet, msgDirect, dmId, deliveryTime, false); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - ret = TaskDownloadMessage::DM_SUCCESS == task->m_result; - if (ret) { - deliveryTime = task->m_mId.deliveryTime; + if (isWebDatovkaAccount(userName)) { + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + loginToMojeId(userName); + } + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + showWebDatovkaInfoDialog(userName, + tr("You have to be logged into the WebDatovka " + "if you want to download complete message.")); + return ret; + } + + MessageDb *messageDb = + dbSet->accessMessageDb(msgId.deliveryTime, false); + if (messageDb == Q_NULLPTR) { + Q_ASSERT(0); + return false; + } + int mId = messageDb->getWebDatokaId(msgId.dmId); + TaskDownloadMessageMojeId *task; + + task = new (std::nothrow) TaskDownloadMessageMojeId( + userName, dbSet, msgDirect, mId, msgId.dmId, false); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + ret = TaskDownloadMessageMojeId::DM_SUCCESS == task->m_result; + delete task; + + } else { + + if (!globIsdsSessions.isConnectedToIsds(userName) && + !connectToIsds(userName)) { + return false; + } + TaskDownloadMessage *task; + + task = new (std::nothrow) TaskDownloadMessage( + userName, dbSet, msgDirect, msgId, false); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + ret = TaskDownloadMessage::DM_SUCCESS == task->m_result; + if (ret) { + msgId.deliveryTime = task->m_mId.deliveryTime; + } + + delete task; } - delete task; + /* Process all pending events. */ + QCoreApplication::processEvents(); return ret; } -bool MainWindow::messageMissingOfferDownload(qint64 dmId, - QDateTime &deliveryTime, const QString &title) +bool MainWindow::messageMissingOfferDownload(MessageDb::MsgId &msgId, + const QString &title) { debugFuncCall(); QMessageBox msgBox(this); msgBox.setWindowTitle(title); - msgBox.setText(tr("Complete message '%1' is missing.").arg(dmId)); + msgBox.setText(tr("Complete message '%1' is missing.").arg(msgId.dmId)); msgBox.setIcon(QMessageBox::Warning); msgBox.setInformativeText( - tr("First you must download the complete message before export.") + + tr("First you must download the complete message to continue with the action.") + "\n\n" + tr("Do you want to download the complete message now?")); @@ -6628,15 +6987,15 @@ msgBox.setDefaultButton(QMessageBox::Yes); if ((QMessageBox::Yes == msgBox.exec()) && - downloadCompleteMessage(dmId, deliveryTime)) { + downloadCompleteMessage(msgId)) { showStatusTextWithTimeout( tr("Complete message '%1' has been downloaded."). - arg(dmId)); + arg(msgId.dmId)); return true; } else { showStatusTextWithTimeout( tr("Complete message '%1' has not been downloaded."). - arg(dmId)); + arg(msgId.dmId)); return false; } } @@ -6647,14 +7006,14 @@ */ void MainWindow::exportDeliveryInfoAsZFO(const QString &attachPath, const QString &attachFileName, const QString &formatString, - const QString &userName, qint64 dmId, QDateTime deliveryTime, + const QString &userName, MessageDb::MsgId msgId, bool askLocation) /* ========================================================================= */ { debugFuncCall(); Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); /* Delivery time can be invalid. */ MessageDbSet *dbSet = accountDbSet(userName, this); @@ -6662,40 +7021,40 @@ Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); return; } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); QString dbId = globAccountDbPtr->dbId(userName + "___True"); - QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(dmId); + QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Delivery info export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL("Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - base64 = messageDb->msgsGetDeliveryInfoBase64(dmId); + base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { Q_ASSERT(0); return; } } - QString fileName = fileNameFromFormat(formatString, dmId, dbId, + QString fileName = fileNameFromFormat(formatString, msgId.dmId, dbId, userName, attachFileName, entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); @@ -6715,8 +7074,9 @@ } if (fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message delivery " - "info \"%1\" to ZFO was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message delivery info \"%1\" to ZFO was not successful!") + .arg(msgId.dmId)); return; } @@ -6731,14 +7091,16 @@ enum WriteFileState ret = writeFile(fileName, data); if (WF_SUCCESS == ret) { - showStatusTextWithTimeout(tr("Export of message delivery " - "info \"%1\" to ZFO was successful.").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message delivery info \"%1\" to ZFO was successful.") + .arg(msgId.dmId)); } else { - showStatusTextWithTimeout(tr("Export of message delivery " - "info \"%1\" to ZFO was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message delivery info \"%1\" to ZFO was not successful!") + .arg(msgId.dmId)); QMessageBox::warning(this, tr("Error exporting message delivery info '%1'.") - .arg(dmId), + .arg(msgId.dmId), tr("Cannot write file '%1'.").arg(fileName), QMessageBox::Ok); } @@ -6751,14 +7113,13 @@ */ void MainWindow::exportDeliveryInfoAsPDF(const QString &attachPath, const QString &attachFileName, const QString &formatString, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation) + const QString &userName, MessageDb::MsgId msgId, bool askLocation) /* ========================================================================= */ { debugFuncCall(); Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); /* Delivery time can be invalid. */ MessageDbSet *dbSet = accountDbSet(userName, this); @@ -6766,40 +7127,41 @@ Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); return; } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); QString dbId = globAccountDbPtr->dbId(userName + "___True"); - QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(dmId); + QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Delivery info export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - base64 = messageDb->msgsGetDeliveryInfoBase64(dmId); + base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { Q_ASSERT(0); return; } } - QString fileName = fileNameFromFormat(formatString, dmId, dbId, + QString fileName = fileNameFromFormat(formatString, msgId.dmId, dbId, userName, attachFileName, entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); @@ -6814,12 +7176,12 @@ fileName = QFileDialog::getSaveFileName(this, tr("Save delivery info as PDF file"), fileName, tr("PDF file (*.pdf)")); - //, QString(), 0, QFileDialog::DontUseNativeDialog); } if (fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message delivery " - "info \"%1\" to PDF was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message delivery info \"%1\" to PDF was not successful!") + .arg(msgId.dmId)); return; } @@ -6831,18 +7193,20 @@ } QTextDocument doc; - doc.setHtml(messageDb->deliveryInfoHtmlToPdf(dmId)); + doc.setHtml(messageDb->deliveryInfoHtmlToPdf(msgId.dmId)); - showStatusTextPermanently(tr("Printing of delivery info \"%1\" to " - "PDF. Please wait...").arg(dmId)); + showStatusTextPermanently( + tr("Printing of delivery info \"%1\" to PDF. Please wait...") + .arg(msgId.dmId)); QPrinter printer; printer.setOutputFileName(fileName); printer.setOutputFormat(QPrinter::PdfFormat); doc.print(&printer); - showStatusTextWithTimeout(tr("Export of message delivery info " - "\"%1\" to PDF was successful.").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message delivery info \"%1\" to PDF was successful.") + .arg(msgId.dmId)); } @@ -6851,14 +7215,13 @@ * Export selected message envelope as PDF file dialog. */ void MainWindow::exportMessageEnvelopeAsPDF(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation) + const QString &userName, MessageDb::MsgId msgId, bool askLocation) /* ========================================================================= */ { debugFuncCall(); Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); /* Delivery time can be invalid. */ MessageDbSet *dbSet = accountDbSet(userName, this); @@ -6866,33 +7229,35 @@ Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); QString dbId = globAccountDbPtr->dbId(userName + "___True"); - QByteArray base64 = messageDb->msgsMessageBase64(dmId); + QByteArray base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - base64 = messageDb->msgsMessageBase64(dmId); + base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { Q_ASSERT(0); return; @@ -6900,7 +7265,7 @@ } QString fileName = fileNameFromFormat(globPref.message_filename_format, - dmId, dbId, userName, "", entry.dmDeliveryTime, + msgId.dmId, dbId, userName, "", entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); if (attachPath.isEmpty()) { @@ -6917,8 +7282,9 @@ } if (fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message " - "envelope \"%1\" to PDF was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was not successful!") + .arg(msgId.dmId)); return; } @@ -6933,24 +7299,28 @@ globAccountDbPtr->getUserDataboxInfo(userName + "___True"); if (accountData.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message " - "envelope \"%1\" to PDF was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was not successful!") + .arg(msgId.dmId)); return; } QTextDocument doc; - doc.setHtml(messageDb->envelopeInfoHtmlToPdf(dmId, accountData.at(0))); + doc.setHtml(messageDb->envelopeInfoHtmlToPdf(msgId.dmId, + accountData.at(0))); - showStatusTextPermanently(tr("Printing of message envelope \"%1\" to " - "PDF. Please wait...").arg(dmId)); + showStatusTextPermanently( + tr("Printing of message envelope \"%1\" to PDF. Please wait...") + .arg(msgId.dmId)); QPrinter printer; printer.setOutputFileName(fileName); printer.setOutputFormat(QPrinter::PdfFormat); doc.print(&printer); - showStatusTextWithTimeout(tr("Export of message envelope \"%1\" to " - "PDF was successful.").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was successful.") + .arg(msgId.dmId)); } @@ -6959,8 +7329,7 @@ * Export selected message envelope as PDF and attachment files */ void MainWindow::exportMessageEnvelopeAttachments(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation) + const QString &userName, MessageDb::MsgId msgId, bool askLocation) /* ========================================================================= */ { debugFuncCall(); @@ -6968,45 +7337,48 @@ QString newAttachPath; Q_ASSERT(!userName.isEmpty()); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); /* Delivery time can be invalid. */ QString dbId = globAccountDbPtr->dbId(userName + "___True"); QDir dir(attachPath); - dir.mkdir(QString::number(dmId)); + dir.mkdir(QString::number(msgId.dmId)); - newAttachPath = attachPath + QDir::separator() + QString::number(dmId); + newAttachPath = attachPath + QDir::separator() + + QString::number(msgId.dmId); MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } - QList attachList = - messageDb->getFilesFromMessage(dmId); + QList attachList( + messageDb->getFilesFromMessage(msgId.dmId)); if (attachList.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - attachList = messageDb->getFilesFromMessage(dmId); + attachList = messageDb->getFilesFromMessage(msgId.dmId); if (attachList.isEmpty()) { Q_ASSERT(0); return; @@ -7014,7 +7386,7 @@ } MessageDb::FilenameEntry entry = - messageDb->msgsGetAdditionalFilenameEntry(dmId); + messageDb->msgsGetAdditionalFilenameEntry(msgId.dmId); foreach (const MessageDb::FileData &attach, attachList) { QString fileName(attach.dmFileDescr); @@ -7025,7 +7397,7 @@ fileName = fileNameFromFormat( globPref.attachment_filename_format, - dmId, dbId, userName, fileName, entry.dmDeliveryTime, + msgId.dmId, dbId, userName, fileName, entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); fileName = newAttachPath + QDir::separator() + fileName; @@ -7040,7 +7412,7 @@ } QString fileName = fileNameFromFormat(globPref.message_filename_format, - dmId, dbId, userName, "", entry.dmDeliveryTime, + msgId.dmId, dbId, userName, "", entry.dmDeliveryTime, entry.dmAcceptanceTime, entry.dmAnnotation, entry.dmSender); if (newAttachPath.isEmpty()) { @@ -7057,8 +7429,9 @@ } if (fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message " - "envelope \"%1\" to PDF was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was not successful!") + .arg(msgId.dmId)); return; } @@ -7073,25 +7446,28 @@ globAccountDbPtr->getUserDataboxInfo(userName + "___True"); if (accountData.isEmpty()) { - showStatusTextWithTimeout(tr("Export of message " - "envelope \"%1\" to PDF was not successful!").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was not successful!") + .arg(msgId.dmId)); return; } QTextDocument doc; - doc.setHtml(messageDb->descriptionHtml(dmId, 0) + - messageDb->fileListHtmlToPdf(dmId)); + doc.setHtml(messageDb->descriptionHtml(msgId.dmId, 0) + + messageDb->fileListHtmlToPdf(msgId.dmId)); - showStatusTextPermanently(tr("Printing of message envelope \"%1\" to " - "PDF. Please wait...").arg(dmId)); + showStatusTextPermanently( + tr("Printing of message envelope \"%1\" to PDF. Please wait...") + .arg(msgId.dmId)); QPrinter printer; printer.setOutputFileName(fileName); printer.setOutputFormat(QPrinter::PdfFormat); doc.print(&printer); - showStatusTextWithTimeout(tr("Export of message envelope \"%1\" to " - "PDF was successful.").arg(dmId)); + showStatusTextWithTimeout( + tr("Export of message envelope \"%1\" to PDF was successful.") + .arg(msgId.dmId)); } @@ -7171,8 +7547,9 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7180,18 +7557,9 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { - Q_ASSERT(0); - return; - } - - qint64 dmId = frstIdx.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(frstIdx)); - - exportMessageAsZFO(QString(), userName, dmId, deliveryTime, - true); + foreach (const MessageDb::MsgId &msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); + exportMessageAsZFO(QString(), userName, msgId, true); } } @@ -7199,8 +7567,9 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7208,19 +7577,17 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { - Q_ASSERT(0); - return; - } - qint64 dmId = frstIdx.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(frstIdx)); + if (isWebDatovkaAccount(userName)) { + /* TODO - will be supported later */ + showWebDatovkaInfoDialog(userName, ""); + return; + } + foreach (const MessageDb::MsgId &msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); exportDeliveryInfoAsZFO(QString(), QString(), - globPref.delivery_filename_format, userName, dmId, - deliveryTime, true); + globPref.delivery_filename_format, userName, msgId, true); } } @@ -7228,8 +7595,9 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7237,19 +7605,16 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { - Q_ASSERT(0); - return; - } - - qint64 dmId = frstIdx.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(frstIdx)); + if (isWebDatovkaAccount(userName)) { + /* TODO - will be supported later */ + showWebDatovkaInfoDialog(userName, ""); + return; + } + foreach (const MessageDb::MsgId &msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); exportDeliveryInfoAsPDF(QString(), QString(), - globPref.delivery_filename_format, userName, dmId, - deliveryTime, true); + globPref.delivery_filename_format, userName, msgId, true); } } @@ -7257,8 +7622,9 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7266,28 +7632,19 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { - Q_ASSERT(0); - return; - } - - qint64 dmId = frstIdx.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(frstIdx)); - - exportMessageEnvelopeAsPDF(QString(), userName, dmId, - deliveryTime, true); + foreach (const MessageDb::MsgId &msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); + exportMessageEnvelopeAsPDF(QString(), userName, msgId, true); } } - void MainWindow::exportSelectedMessageEnvelopeAttachments(void) { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7303,30 +7660,20 @@ return; } - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { - Q_ASSERT(0); - return; - } - - qint64 dmId = frstIdx.data().toLongLong(); - Q_ASSERT(dmId >= 0); - QDateTime deliveryTime(msgDeliveryTime(frstIdx)); - - exportMessageEnvelopeAttachments(newDir, userName, dmId, - deliveryTime, false); + foreach (const MessageDb::MsgId &msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); + exportMessageEnvelopeAttachments(newDir, userName, msgId, + false); } } - - - void MainWindow::sendMessagesZfoEmail(void) { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7336,14 +7683,13 @@ QDateTime::currentDateTimeUtc().toString( "dd.MM.yyyy-HH:mm:ss.zzz")); - QString subject = (1 == firstMsgColumnIdxs.size()) ? - tr("Data message") : tr("Data messages"); + QString subject((1 == msgIds.size()) ? + tr("Data message") : tr("Data messages")); - subject += " " + firstMsgColumnIdxs.first().data().toString(); - if (firstMsgColumnIdxs.size() > 1) { - for (int i = 1; i < firstMsgColumnIdxs.size(); ++i) { - subject += ", " + - firstMsgColumnIdxs.at(i).data().toString(); + subject += " " + QString::number(msgIds.first().dmId); + if (msgIds.size() > 1) { + for (int i = 1; i < msgIds.size(); ++i) { + subject += ", " + QString::number(msgIds.at(i).dmId); } } @@ -7353,52 +7699,49 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - QDateTime deliveryTime(msgDeliveryTime(firstMsgColumnIdxs.first())); - MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); - if (0 == messageDb) { - Q_ASSERT(0); - return; - } - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { + foreach (MessageDb::MsgId msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); + + MessageDb *messageDb = dbSet->accessMessageDb( + msgId.deliveryTime, false); + if (0 == messageDb) { Q_ASSERT(0); return; } - qint64 dmId = frstIdx.data().toLongLong(); - - QByteArray base64 = messageDb->msgsMessageBase64(dmId); + QByteArray base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - base64 = messageDb->msgsMessageBase64(dmId); + base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { Q_ASSERT(0); return; } } - QString attachName(QString("DDZ_%1.zfo").arg(dmId)); - + QString attachName(dzPrefix(messageDb, msgId.dmId) + + QString("DZ_%1.zfo").arg(msgId.dmId)); if (attachName.isEmpty()) { Q_ASSERT(0); return; @@ -7423,8 +7766,9 @@ { debugSlotCall(); - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - if (0 == firstMsgColumnIdxs.size()) { + const QList msgIds( + msgMsgIds(currentFrstColMessageIndexes())); + if (0 == msgIds.size()) { return; } @@ -7434,14 +7778,13 @@ QDateTime::currentDateTimeUtc().toString( "dd.MM.yyyy-HH:mm:ss.zzz")); - QString subject = (1 == firstMsgColumnIdxs.size()) ? - tr("Attachments of message") : tr("Attachments of messages"); + QString subject((1 == msgIds.size()) ? + tr("Attachments of message") : tr("Attachments of messages")); - subject += " " + firstMsgColumnIdxs.first().data().toString(); - if (firstMsgColumnIdxs.size() > 1) { - for (int i = 1; i < firstMsgColumnIdxs.size(); ++i) { - subject += ", " + - firstMsgColumnIdxs.at(i).data().toString(); + subject += " " + QString::number(msgIds.first().dmId); + if (msgIds.size() > 1) { + for (int i = 1; i < msgIds.size(); ++i) { + subject += ", " + QString::number(msgIds.at(i).dmId); } } @@ -7451,45 +7794,42 @@ m_accountModel.userName(currentAccountModelIndex())); Q_ASSERT(!userName.isEmpty()); - QDateTime deliveryTime(msgDeliveryTime(firstMsgColumnIdxs.first())); - MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); - if (0 == messageDb) { - Q_ASSERT(0); - return; - } - foreach (const QModelIndex &frstIdx, firstMsgColumnIdxs) { - if (!frstIdx.isValid()) { + foreach (MessageDb::MsgId msgId, msgIds) { + Q_ASSERT(msgId.dmId >= 0); + + MessageDb *messageDb = dbSet->accessMessageDb( + msgId.deliveryTime, false); + if (0 == messageDb) { Q_ASSERT(0); return; } - qint64 dmId = frstIdx.data().toLongLong(); - QList attachList = - messageDb->getFilesFromMessage(dmId); + messageDb->getFilesFromMessage(msgId.dmId); if (attachList.isEmpty()) { - if (!messageMissingOfferDownload(dmId, deliveryTime, + if (!messageMissingOfferDownload(msgId, tr("Message export error!"))) { return; } - messageDb = dbSet->accessMessageDb(deliveryTime, false); + messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); - logErrorNL("Could not access database of " - "freshly downloaded message '%" PRId64 "'.", dmId); + logErrorNL( + "Could not access database of freshly downloaded message '%" PRId64 "'.", + msgId.dmId); return; } - attachList = messageDb->getFilesFromMessage(dmId); + attachList = messageDb->getFilesFromMessage(msgId.dmId); if (attachList.isEmpty()) { Q_ASSERT(0); return; @@ -7520,16 +7860,7 @@ { debugSlotCall(); - QModelIndexList attachmentIndexes; - { - QItemSelectionModel *selectionModel = - ui->messageAttachmentList->selectionModel(); - if (0 == selectionModel) { - Q_ASSERT(0); - return; - } - attachmentIndexes = selectionModel->selectedRows(0); - } + QModelIndexList attachmentIndexes(currentFrstColAttachmentIndexes()); qint64 dmId = -1; { @@ -7589,13 +7920,12 @@ return; } - const QModelIndex &msgIdx = firstMsgColumnIdxs.first(); - qint64 dmId = msgIdx.data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(msgIdx); - Q_ASSERT(deliveryTime.isValid()); - - Q_ASSERT(msgIdx.isValid()); - if (!msgIdx.isValid()) { + const MessageDb::MsgId msgId(msgMsgId(firstMsgColumnIdxs.first())); + if (msgId.dmId < 0) { + Q_ASSERT(0); + return; + } + if (!msgId.deliveryTime.isValid()) { return; } @@ -7605,17 +7935,18 @@ Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } - QByteArray base64 = messageDb->msgsMessageBase64(dmId); + QByteArray base64 = messageDb->msgsMessageBase64(msgId.dmId); if (base64.isEmpty()) { QMessageBox msgBox(this);; msgBox.setWindowTitle(tr("Datovka - Export error!")); - msgBox.setText(tr("Cannot export the message ") + dmId); + msgBox.setText(tr("Cannot export the message ") + msgId.dmId); msgBox.setIcon(QMessageBox::Warning); msgBox.setInformativeText( tr("First you must download message before its export...")); @@ -7623,11 +7954,11 @@ return; } - QString fileName = - QString(TMP_ATTACHMENT_PREFIX "DDZ_%1.zfo").arg(dmId); - Q_ASSERT(!fileName.isEmpty()); - + QString fileName(TMP_ATTACHMENT_PREFIX + + dzPrefix(messageDb, msgId.dmId) + + QString("DZ_%1.zfo").arg(msgId.dmId)); if (fileName.isEmpty()) { + Q_ASSERT(0); return; } @@ -7635,15 +7966,17 @@ fileName = writeTemporaryFile(fileName, data); if (!fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Message '%1' stored to " - "temporary file '%2'.").arg(dmId).arg(fileName)); + showStatusTextWithTimeout( + tr("Message '%1' stored to temporary file '%2'.") + .arg(msgId.dmId).arg(fileName)); QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); /* TODO -- Handle openUrl() return value. */ } else { - showStatusTextWithTimeout(tr("Message '%1' couldn't be " - "stored to temporary file.").arg(dmId)); + showStatusTextWithTimeout( + tr("Message '%1' couldn't be stored to temporary file.") + .arg(msgId.dmId)); QMessageBox::warning(this, - tr("Error opening message '%1'.").arg(dmId), + tr("Error opening message '%1'.").arg(msgId.dmId), tr("Cannot write file '%1'.").arg(fileName), QMessageBox::Ok); } @@ -7659,39 +7992,47 @@ { debugSlotCall(); + const QString userName = + m_accountModel.userName(currentAccountModelIndex()); + + if (isWebDatovkaAccount(userName)) { + /* TODO - will be supported later */ + showWebDatovkaInfoDialog(userName, ""); + return; + } + /* First column. */ QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); if (1 != firstMsgColumnIdxs.size()) { return; } - const QModelIndex &msgIdx = firstMsgColumnIdxs.first(); - qint64 dmId = msgIdx.data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(msgIdx); - Q_ASSERT(deliveryTime.isValid()); - - Q_ASSERT(msgIdx.isValid()); - if (!msgIdx.isValid()) { + const MessageDb::MsgId msgId(msgMsgId(firstMsgColumnIdxs.first())); + if (msgId.dmId < 0) { + Q_ASSERT(0); + return; + } + if (!msgId.deliveryTime.isValid()) { return; } - MessageDbSet *dbSet = accountDbSet( - m_accountModel.userName(currentAccountModelIndex()), this); + MessageDbSet *dbSet = accountDbSet(userName, this); if (0 == dbSet) { Q_ASSERT(0); return; } - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return; } - QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(dmId); + QByteArray base64 = messageDb->msgsGetDeliveryInfoBase64(msgId.dmId); if (base64.isEmpty()) { QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Datovka - Export error!")); - msgBox.setText(tr("Cannot export the message ") + dmId); + msgBox.setText(tr("Cannot export the message ") + msgId.dmId); msgBox.setIcon(QMessageBox::Warning); msgBox.setInformativeText( tr("First you must download message before its export...")); @@ -7699,11 +8040,11 @@ return; } - QString fileName = - QString(TMP_ATTACHMENT_PREFIX "DDZ_%1_info.zfo").arg(dmId); - Q_ASSERT(!fileName.isEmpty()); - + QString fileName(TMP_ATTACHMENT_PREFIX + + dzPrefix(messageDb, msgId.dmId) + + QString("DZ_%1_info.zfo").arg(msgId.dmId)); if (fileName.isEmpty()) { + Q_ASSERT(0); return; } @@ -7711,16 +8052,17 @@ fileName = writeTemporaryFile(fileName, data); if (!fileName.isEmpty()) { - showStatusTextWithTimeout(tr("Message delivery information " - "'%1' stored to temporary file '%2'.").arg(dmId) - .arg(fileName)); + showStatusTextWithTimeout( + tr("Message delivery information '%1' stored to temporary file '%2'.") + .arg(msgId.dmId).arg(fileName)); QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); /* TODO -- Handle openUrl() return value. */ } else { - showStatusTextWithTimeout(tr("Message delivery information " - "'%1' couldn't be stored to temporary file.").arg(dmId)); + showStatusTextWithTimeout( + tr("Message delivery information '%1' couldn't be stored to temporary file.") + .arg(msgId.dmId)); QMessageBox::warning(this, - tr("Error opening message '%1'.").arg(dmId), + tr("Error opening message '%1'.").arg(msgId.dmId), tr("Cannot write file '%1'.").arg(fileName), QMessageBox::Ok); } @@ -7742,15 +8084,12 @@ return; } - const QModelIndex &msgIdx = firstMsgColumnIdxs.first(); - qint64 dmId = msgIdx.data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(msgIdx); - if (!deliveryTime.isValid()) { + const MessageDb::MsgId msgId(msgMsgId(firstMsgColumnIdxs.first())); + if (msgId.dmId < 0) { + Q_ASSERT(0); return; } - - if (!msgIdx.isValid()) { - Q_ASSERT(0); + if (!msgId.deliveryTime.isValid()) { return; } @@ -7761,8 +8100,7 @@ return; } - QDialog *signature_detail = new DlgSignatureDetail(*dbSet, dmId, - deliveryTime, this); + QDialog *signature_detail = new DlgSignatureDetail(*dbSet, msgId, this); signature_detail->exec(); signature_detail->deleteLater(); } @@ -8252,9 +8590,7 @@ break; } - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); - - messageItemsSetProcessStatus(firstMsgColumnIdxs, procSt); + messageItemsSetProcessStatus(currentFrstColMessageIndexes(), procSt); } @@ -8289,24 +8625,23 @@ for (QModelIndexList::const_iterator it = firstMsgColumnIdxs.begin(); it != firstMsgColumnIdxs.end(); ++it) { - qint64 dmId = it->data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(*it); - Q_ASSERT(deliveryTime.isValid()); + const MessageDb::MsgId msgId(msgMsgId(*it)); + Q_ASSERT(msgId.deliveryTime.isValid()); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, - false); + MessageDb *messageDb = dbSet->accessMessageDb( + msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); continue; } - messageDb->smsgdtSetLocallyRead(dmId, read); + messageDb->smsgdtSetLocallyRead(msgId.dmId, read); /* * Mark message as read without reloading * the whole model. */ - messageModel->overrideRead(dmId, read); + messageModel->overrideRead(msgId.dmId, read); } ui->messageList->selectionModel()->select(storedMsgSelection, @@ -8351,24 +8686,23 @@ for (QModelIndexList::const_iterator it = firstMsgColumnIdxs.begin(); it != firstMsgColumnIdxs.end(); ++it) { - qint64 dmId = it->data().toLongLong(); - QDateTime deliveryTime = msgDeliveryTime(*it); - Q_ASSERT(deliveryTime.isValid()); + const MessageDb::MsgId msgId(msgMsgId(*it)); + Q_ASSERT(msgId.deliveryTime.isValid()); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, - false); + MessageDb *messageDb = dbSet->accessMessageDb( + msgId.deliveryTime, false); if (0 == messageDb) { Q_ASSERT(0); continue; } - messageDb->msgSetProcessState(dmId, state, false); + messageDb->msgSetProcessState(msgId.dmId, state, false); /* * Mark message as read without reloading * the whole model. */ - messageModel->overrideProcessing(dmId, state); + messageModel->overrideProcessing(msgId.dmId, state); } ui->messageList->selectionModel()->select(storedMsgSelection, @@ -8715,7 +9049,7 @@ return; } - QList msgIdList = dbSet->getAllMessageIDsFromDB(); + QList msgIdList(dbSet->getAllMessageIDsFromDB()); msgCnt = msgIdList.count(); foreach (const MessageDb::MsgId &mId, msgIdList) { @@ -8838,8 +9172,7 @@ } foreach (const MessageDb::MsgId &mId, expirMsgIds) { - exportMessageAsZFO(newDir, userName, mId.dmId, - mId.deliveryTime, false); + exportMessageAsZFO(newDir, userName, mId, false); } } @@ -8931,6 +9264,14 @@ { debugSlotCall(); + const QString userName = + m_accountModel.userName(currentAccountModelIndex()); + + if (isWebDatovkaAccount(userName)) { + showWebDatovkaInfoDialog(userName, ""); + return; + } + QMessageBox msgBox(this); msgBox.setIcon(QMessageBox::Question); msgBox.setWindowTitle(tr("Import of mesages from database")); @@ -8961,8 +9302,7 @@ m_on_import_database_dir_activate = QFileInfo(files.at(0)).absoluteDir().absolutePath(); - doMsgsImportFromDatabase(files, - m_accountModel.userName(currentAccountModelIndex())); + doMsgsImportFromDatabase(files, userName); } @@ -9065,8 +9405,8 @@ QString dboxId = globAccountDbPtr->dbId(userName + "___True"); /* get all messages from source single database */ - QList msgIdList = - srcDbSingle->getAllMessageIDsFromDB(); + QList msgIdList( + srcDbSingle->getAllMessageIDsFromDB()); /* get database set for selected account */ MessageDbSet *dstDbSet = accountDbSet(userName, this); @@ -9558,6 +9898,9 @@ void MainWindow::setUpUi(void) { ui->setupUi(this); + /* Set default line height for table views/widgets. */ + ui->messageList->setNarrowedLineHeight(); + ui->messageAttachmentList->setNarrowedLineHeight(); /* Window title. */ setWindowTitle( @@ -9610,7 +9953,8 @@ /* Show banner. */ ui->messageStackedWidget->setCurrentIndex(0); - ui->accountTextInfo->setHtml(createDatovkaBanner(VERSION)); + ui->accountTextInfo->setHtml(createDatovkaBanner( + QCoreApplication::applicationVersion())); ui->accountTextInfo->setReadOnly(true); } @@ -9673,6 +10017,10 @@ } /* Separator. */ ui->actionAdd_account->isEnabled(); + ui->actionAdd_mojeID_account->isEnabled(); +#ifdef DISABLE_MOJEID_ACCOUNT_ADDING + ui->actionAdd_mojeID_account->setVisible(false); +#endif /* DISABLE_MOJEID_ACCOUNT_ADDING */ ui->actionDelete_account->isEnabled(); /* Separator. */ ui->actionImport_database_directory->isEnabled(); @@ -9737,7 +10085,18 @@ ico.addFile(QStringLiteral(":/icons/32x32/datovka-message-reply.png"), QSize(), QIcon::Normal, QIcon::Off); ui->actionReply->setIcon(ico); } - ui->actionCreate_message_from_template->isEnabled(); + { + QIcon ico; + ico.addFile(QStringLiteral(":/icons/16x16/datovka-message.png"), QSize(), QIcon::Normal, QIcon::Off); + ico.addFile(QStringLiteral(":/icons/32x32/datovka-message.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionForward_message->setIcon(ico); + } + { + QIcon ico; + ico.addFile(QStringLiteral(":/icons/16x16/datovka-message.png"), QSize(), QIcon::Normal, QIcon::Off); + ico.addFile(QStringLiteral(":/icons/32x32/datovka-message.png"), QSize(), QIcon::Normal, QIcon::Off); + ui->actionCreate_message_from_template->setIcon(ico); + } /* Separator. */ { QIcon ico; @@ -9810,7 +10169,6 @@ ui->actionEmail_selected_attachments->isEnabled(); } - /* ========================================================================= */ /* * Slot: Show tags manager dialog for tags settings. @@ -9820,15 +10178,14 @@ { debugSlotCall(); - QDialog *tagsDlg = new DlgTags(this); - tagsDlg->exec(); - tagsDlg->deleteLater(); + modifyTags(m_accountModel.userName(currentAccountModelIndex()), + QList(), QList()); } /* ========================================================================= */ /* - * Slot: Add/detele tags to/from selected messages. + * Slot: Add/delete tags to/from selected messages. */ void MainWindow::addOrDeleteMsgTags(void) /* ========================================================================= */ @@ -9836,29 +10193,37 @@ debugSlotCall(); QList msgIdList; + QList msgIdWebDatovkaList; - QModelIndexList firstMsgColumnIdxs(currentFrstColMessageIndexes()); + const QString userName( + m_accountModel.userName(currentAccountModelIndex())); + const bool webdatovkaAccount = isWebDatovkaAccount(userName); + MessageDbSet *dbSet = Q_NULLPTR; + if (webdatovkaAccount) { + dbSet = accountDbSet(userName, this); + if (Q_NULLPTR == dbSet) { + Q_ASSERT(0); + return; + } + } - foreach (const QModelIndex &idx, firstMsgColumnIdxs) { + foreach (const QModelIndex &idx, currentFrstColMessageIndexes()) { msgIdList.append(idx.data().toLongLong()); + if (webdatovkaAccount) { + Q_ASSERT(Q_NULLPTR != dbSet); + QDateTime deliveryTime(msgDeliveryTime(idx)); + MessageDb *messageDb = + dbSet->accessMessageDb(deliveryTime, false); + if (messageDb == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + qint64 mId = messageDb->getWebDatokaId(idx.data().toLongLong()); + msgIdWebDatovkaList.append(mId); + } } - /* - * FIXME -- The tags dialogue as it now exixts is not suitable for - * adding tags to messages. - */ - - const QString userName = - m_accountModel.userName(currentAccountModelIndex()); - - QDialog *tagsDlg = new DlgTags(userName, msgIdList, this); - tagsDlg->exec(); - tagsDlg->deleteLater(); - - DbMsgsTblModel *messageModel = dynamic_cast( - m_messageListProxyModel.sourceModel()); - Q_ASSERT(0 != messageModel); - messageModel->refillTagsColumn(userName, msgIdList, -1); + modifyTags(userName, msgIdList, msgIdWebDatovkaList); } @@ -9950,3 +10315,405 @@ delete task; } + +void MainWindow::modifyTags(const QString &userName, QList msgIdList, + QList msgIdWebDatovkaList) +{ + TagDb *tagDb = Q_NULLPTR; + + if (isWebDatovkaAccount(userName)) { + if (!wdSessions.isConnectedToWebdatovka(userName)) { + loginToMojeId(userName); + } + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + showWebDatovkaInfoDialog(userName, + tr("You have to be logged into the WebDatovka if you want to modify tags.")); + return; + } + + tagDb = globWebDatovkaTagDbPtr->accessTagDb( + getWebDatovkaTagDbPrefix(userName)); + } else { + tagDb = globTagDbPtr; + } + if (tagDb == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + + QDialog *tagsDlg = Q_NULLPTR; + + if (msgIdList.isEmpty() && msgIdWebDatovkaList.isEmpty()) { + tagsDlg = new DlgTags(userName, tagDb, this); + } else if (!msgIdList.isEmpty() && !msgIdWebDatovkaList.isEmpty()) { + Q_ASSERT(0); + return; + } else if ((!userName.isEmpty() && !msgIdList.isEmpty()) || + (!userName.isEmpty() && !msgIdWebDatovkaList.isEmpty())) { + /* + * FIXME -- The tags dialogue as it now exists is not suitable + * for adding tags to messages. + */ + tagsDlg = new DlgTags(userName, tagDb, msgIdList, + msgIdWebDatovkaList, this); + } else { + Q_ASSERT(0); + return; + } + if (tagsDlg == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + + int dlgRet = tagsDlg->exec(); + tagsDlg->deleteLater(); + + if (userName.isEmpty() || (dlgRet == DlgTags::NO_ACTION)) { + /* Nothing else to do. */ + return; + } + + DbMsgsTblModel *messageModel = qobject_cast( + m_messageListProxyModel.sourceModel()); + if (messageModel == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + + if (dlgRet == DlgTags::TAGS_CHANGED) { + /* May affect all rows. */ + msgIdList.clear(); + for (int row = 0; row < messageModel->rowCount(); ++row) { + msgIdList.append(messageModel->index(row, + DbMsgsTblModel::DMID_COL).data().toLongLong()); + } + } + + if (msgIdList.isEmpty()) { + return; + } + + messageModel->refillTagsColumn(userName, msgIdList, -1); +} + +/* ========================================================================= */ +/* + * Func: Download and update all accounts from webdatovka. + */ +bool MainWindow::wdGetAccountList(const QString &userName, + const QNetworkCookie &sessionid, bool syncWithAll) +/* ========================================================================= */ +{ + debugFuncCall(); + + bool ret = false; + QStringList deletedAccounts; + deletedAccounts.clear(); + + /* list of accounts task */ + TaskGetAccountListMojeId *task; + task = new (std::nothrow) TaskGetAccountListMojeId(userName, sessionid, + syncWithAll, &m_accountModel, deletedAccounts); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + + QString msgBoxTitle = tr("Add account(s) error"); + if (!userName.isEmpty()) { + msgBoxTitle = + AccountModel::globAccounts[userName].accountName() + " : " + + userName; + } + + QMessageBox msgBox(this); + QString msgBoxText = task->m_error; + TaskGetAccountListMojeId::Result retVal = task->m_return; + QString delAcntName = "\n"; + + delete task; + + switch (retVal) { + case TaskGetAccountListMojeId::ACNTLIST_WEBDAT_ERR: + showStatusTextWithTimeout(msgBoxText); + QMessageBox::warning(this, msgBoxTitle, msgBoxText, + QMessageBox::Ok); + break; + case TaskGetAccountListMojeId::ACNTLIST_NONEXIST: + msgBoxText = tr("There aren't any Webdatovka accounts for this " + "mojeID identity."); + showStatusTextWithTimeout(msgBoxText); + QMessageBox::warning(this, msgBoxTitle, msgBoxText, + QMessageBox::Ok); + break; + case TaskGetAccountListMojeId::ACNTLIST_WRONGUSER: + msgBoxText = tr("You are login into wrong mojeID identity."); + showStatusTextWithTimeout(msgBoxText); + QMessageBox::warning(this, msgBoxTitle, + msgBoxText + " " + tr("Please enter correct mojeID " + "login for account '%1'."). + arg(AccountModel::globAccounts[userName].accountName()), + QMessageBox::Ok); + break; + case TaskGetAccountListMojeId::ACNTLIST_WU_HAS_ACNT: + msgBoxText = tr("You are login into wrong mojeID identity."); + showStatusTextWithTimeout(msgBoxText); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(msgBoxTitle); + msgBox.setText(msgBoxText + " " + + tr("New mojeID identity has some account(s).")); + msgBox.setInformativeText(tr("Do you want to add account(s) " + "for this mojeID identity to Datovka?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + if (QMessageBox::Yes == msgBox.exec()) { + ret = wdGetAccountList(QString(), sessionid, syncWithAll); + } + break; + case TaskGetAccountListMojeId::ACNTLIST_DELETE_ACNT: + foreach (const QString &username, deletedAccounts) { + delAcntName.append("\n"); + delAcntName.append(AccountModel::globAccounts[username] + .accountName()); + delAcntName.append(" (" + username + ")"); + } + msgBoxText = tr("Some account(s) were removed from Webdatovka " + "for this mojeID identity."); + showStatusTextWithTimeout(msgBoxText); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(msgBoxTitle); + msgBox.setText(msgBoxText + delAcntName); + msgBox.setInformativeText(tr("Do you want to also " + "remove these accounts from Datovka?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + if (QMessageBox::Yes == msgBox.exec()) { + foreach (const QString &username, deletedAccounts) { + deleteAccount(username); + } + } + ret = true; + break; + default: + ret = true; + break; + } + + return ret; +} + + +/* ========================================================================= */ +/* + * Func: Download all messsages for selected account from webdatovka. + */ +bool MainWindow::wdGetMessageList(const QString &userName) +/* ========================================================================= */ +{ + debugFuncCall(); + + if (!isWebDatovkaAccount(userName)) { + return false; + } + + /* list of tags task */ + TaskTagSyncAccount *tagtask; + tagtask = new (std::nothrow) TaskTagSyncAccount(userName); + tagtask->setAutoDelete(true); + globWorkPool.assignHi(tagtask); + + int accountID = getWebDatovkaAccountId(userName); + + MessageDbSet *dbSet = accountDbSet(userName, this); + if (0 == dbSet) { + Q_ASSERT(0); + return false; + } + + /* list of received messages task */ + TaskDownloadMessageListMojeID *task; + task = new (std::nothrow) TaskDownloadMessageListMojeID(userName, dbSet, + MSG_RECEIVED, globPref.auto_download_whole_messages, + MESSAGE_LIST_LIMIT, + accountID, 0); + task->setAutoDelete(true); + globWorkPool.assignLo(task); + + /* list of sent messages task */ + task = new (std::nothrow) TaskDownloadMessageListMojeID(userName, dbSet, + MSG_SENT, globPref.auto_download_whole_messages, + MESSAGE_LIST_LIMIT, + accountID, 0); + task->setAutoDelete(true); + globWorkPool.assignLo(task); + + return true; +} + + +/* ========================================================================= */ +/* + * Func: Sync selected account in webdatovka server. + */ +bool MainWindow::wdSyncAccount(const QString &userName) +/* ========================================================================= */ +{ + debugFuncCall(); + + if (!isWebDatovkaAccount(userName)) { + return false; + } + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + loginToMojeId(userName); + } + + if (!wdSessions.isConnectedToWebdatovka(userName)) { + return false; + } + + int accountID = getWebDatovkaAccountId(userName); + + /* sync account task */ + TaskSyncAccount *task; + task = new (std::nothrow) TaskSyncAccount(userName, accountID); + task->setAutoDelete(true); + globWorkPool.assignHi(task); + + return wdGetMessageList(userName); +} + + +/* ========================================================================= */ +/* + * Func: Show dialog for webdatovka account, that action is not supported. + */ +void MainWindow::showWebDatovkaInfoDialog(const QString &userName, QString txt) +/* ========================================================================= */ +{ + debugFuncCall(); + + if (txt.isEmpty()) { + txt = tr("This action is not supported for MojeID account " + "'%1'").arg(AccountModel::globAccounts[userName].accountName()); + } + showStatusTextWithTimeout(txt); + QMessageBox::warning(this, + AccountModel::globAccounts[userName].accountName() + " : " + + userName, txt, QMessageBox::Ok); +} + + +/* ========================================================================= */ +/* + * Slot: Performs action depending on webdatovka message send outcome. + */ +void MainWindow::sendMessageMojeIdAction(const QString &userName, + const QStringList &result, const QString &error) +/* ========================================================================= */ +{ + debugSlotCall(); + + if (!error.isEmpty()) { + qDebug() << error; + return; + } + + if (result.isEmpty()) { + MessageDbSet *dbSet = accountDbSet(userName, this); + if (0 == dbSet) { + return; + } + + TaskDownloadMessageListMojeID *task; + task = new (std::nothrow) TaskDownloadMessageListMojeID( + userName, dbSet, MSG_SENT, + globPref.auto_download_whole_messages, MESSAGE_LIST_LIMIT, + getWebDatovkaAccountId(userName), 0); + task->setAutoDelete(true); + globWorkPool.assignLo(task); + } +} + + +/* ========================================================================= */ +/* + * Slot: Login to MojeID - first step. + */ +void MainWindow::loginToMojeId(const QString &userName) +/* ========================================================================= */ +{ + debugSlotCall(); + + QUrl lastUrl; + jsonlayer.startLoginToWebDatovka(lastUrl); + + QDialog *mojeIDLoginDialog = new DlgLoginToMojeId(userName, + lastUrl.toString(), this); + + connect(mojeIDLoginDialog, SIGNAL(callMojeId(QString, QString, QString, + QString, QString, QString, bool, QString)), + this, SLOT(callMojeId(QString, + QString, QString, QString, QString, QString, bool, QString))); + + mojeIDLoginDialog->exec(); +} + + +/* ========================================================================= */ +/* + * Slot: Login to MojeID - second step. + */ +void MainWindow::callMojeId(const QString &user, + const QString &lastUrl, const QString &token, + QString userName, QString pwd, QString otp, bool syncALL, + const QString &certPath) +/* ========================================================================= */ +{ + debugSlotCall(); + + QString error; + + QNetworkCookie sessionid; + + if (!jsonlayer.loginToMojeID(lastUrl, token, userName, pwd, otp, + certPath, error, sessionid)) { + showStatusTextWithTimeout(error); + QMessageBox::critical(this, tr("Login problem"), + error, QMessageBox::Ok); + return; + } else { + mui_statusOnlineLabel->setText(tr("Mode: online")); + } + + wdGetAccountList(user, sessionid, syncALL); + + if (ui->accountList->model()->rowCount() > 0) { + activeAccountMenuAndButtons(true); + } +} + + +/* ========================================================================= */ +/* + * Func: Test if exists another mojeID account with same userId + * when we delete any mojeID acccount. + */ +bool MainWindow::existsAnotherMojeIdAccountWithSameUserId( + const QString &userName) +/* ========================================================================= */ +{ + AccountsMap::iterator i; + int cnt = 0; + int userId = getWebDatovkaUserId(userName); + + for (i = m_accountModel.globAccounts.begin(); + i != m_accountModel.globAccounts.end(); ++i) { + if (isWebDatovkaAccount(i->userName())) { + if (userId == getWebDatovkaUserId(i->userName())) { + cnt++; + } + } + } + + return (cnt > 1); +} diff -Nru datovka-4.7.0/src/gui/datovka.h datovka-4.7.1/src/gui/datovka.h --- datovka-4.7.0/src/gui/datovka.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/datovka.h 2017-01-19 09:29:26.000000000 +0000 @@ -46,6 +46,7 @@ #include "src/models/sort_filter_proxy_model.h" #include "src/settings/preferences.h" #include "src/single/single_instance.h" +#include "src/web/json.h" #include "src/worker/task.h" /* TODO -- remove this header file. */ /* Forward declaration as we don;t wan to pull-in all header file content. */ @@ -89,6 +90,30 @@ static MessageDbSet *accountDbSet(const QString &userName, MainWindow *mw); + /*! + * @brief Get data about logged in user and his box. + */ + static + bool getOwnerInfoFromLogin(const QString &userName); + + /*! + * @brief Get information about password expiration date. + */ + static + bool getPasswordInfoFromLogin(const QString &userName); + + /*! + * @brief Get data about logged in user. + */ + static + bool getUserInfoFromLogin(const QString &userName); + + /*! + * @brief Get account list from Webdatovka. + */ + bool wdGetAccountList(const QString &userName, + const QNetworkCookie &sessionid, bool syncWithAll); + protected: /*! * Check if some worker is working on the background and show @@ -97,7 +122,18 @@ void closeEvent(QCloseEvent *event); +public slots: + + /*! + * @brief Login to mojeID. + */ + void loginToMojeId(const QString &userName); + private slots: + /*! + * @brief Refresh AccountList. + */ + void refreshAccountList(const QString &userName); /*! * @brief Processes messages from single instance emitter. @@ -118,6 +154,14 @@ bool listScheduled); /*! + * @brief Performs action depending on message download outcome + * for webdatovka. + */ + void collectDownloadMessageMojeId(const QString &usrName, + qint64 msgId, int result, const QString &errDesc, + bool listScheduled); + + /*! * @brief Performs action depending on message list download outcome. */ void collectDownloadMessageListStatus(const QString &usrName, @@ -133,6 +177,12 @@ bool isPDZ, qint64 dmId); /*! + * @brief Performs action depending on webdatovka message send outcome. + */ + void sendMessageMojeIdAction(const QString &userName, + const QStringList &result, const QString &error); + + /*! * @brief Version response slot. */ void datovkaVersionResponce(QNetworkReply* reply); @@ -223,7 +273,7 @@ /*! * @brief Open attachment in default application. */ - void openSelectedAttachment(void); + void openSelectedAttachment(const QModelIndex &index = QModelIndex()); /*! * @brief Mark all received messages in the current working account. @@ -341,6 +391,11 @@ void deleteMessage(void); /*! + * @brief Delete selected message(s) from local database and Webdatovka. + */ + void deleteMessageWebdatovka(const QString &userName); + + /*! * @brief Downloads new messages from server for all accounts. */ void synchroniseAllAccounts(void); @@ -371,6 +426,12 @@ void createAndSendMessageReply(void); /*! + * @nrief Create a message containing as attachment the selected + * messages on ZFO format. + */ + void createAndSendMessageWithZfos(void); + + /*! * @brief Create message from the template (selected message). */ void createAndSendMessageFromTmpl(void); @@ -401,11 +462,21 @@ void addNewAccount(void); /*! + * @brief Add mojeID account action and dialog. + */ + void addNewMojeIDAccount(void); + + /*! * @brief Deletion confirmation dialog. */ void deleteSelectedAccount(void); /*! + * @brief Delete account. + */ + void deleteAccount(const QString &userName); + + /*! * @brief Show import database directory dialog. */ void showImportDatabaseDialog(void); @@ -421,7 +492,7 @@ void prepareMsgsImportFromDatabase(void); /*! - * @brief Proxy setting dialog. + * @brief Proxy settings dialogue. */ void proxySettings(void); @@ -676,13 +747,48 @@ */ void vacuumMsgDbSlot(void); + void callMojeId(const QString &user, const QString &lastUrl, + const QString &token, QString userName, QString pwd, QString otp, + bool syncALL, const QString &certPath); + private: QTimer m_timerSyncAccounts; int m_timeoutSyncAccounts; + /*! + * @brief Shows tag editing dialogue. + * + * @no If no message identifiers are supplied then just the tags are + * edited. + * + * @param[in] userName Account login string. Must be supplied when + * message identifiers are passed. + * @param[in] msgIdList Messages whose tags should be edited. + * @param[in] msgIdWebDatovkaList Webdatovka messages whose tags should + * be edited. + */ + void modifyTags(const QString &userName, QList msgIdList, + QList msgIdWebDatovkaList); + + /*! + * @brief Get message list from webdatovka server. + */ + bool wdGetMessageList(const QString &userName); + + /*! + * @brief Do sync of account in the webdatovka server. + */ + bool wdSyncAccount(const QString &userName); + + /*! + * @brief Show status bar text with timeout. + */ void showStatusTextWithTimeout(const QString &qStr); + /*! + * @brief Show status bar text permanently. + */ void showStatusTextPermanently(const QString &qStr); /*! @@ -703,15 +809,14 @@ * @brief Export message into ZFO file dialogue. */ void exportMessageAsZFO(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation); + const QString &userName, MessageDb::MsgId msgId, bool askLocation); /*! * @brief Export delivery information as ZFO file dialogue. */ void exportDeliveryInfoAsZFO(const QString &attachPath, const QString &attachFileName, const QString &formatString, - const QString &userName, qint64 dmId, QDateTime deliveryTime, + const QString &userName, MessageDb::MsgId msgId, bool askLocation); /*! @@ -719,22 +824,19 @@ */ void exportDeliveryInfoAsPDF(const QString &attachPath, const QString &attachFileName, const QString &formatString, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation); + const QString &userName, MessageDb::MsgId msgId, bool askLocation); /*! * @brief Export selected message envelope as PDF file dialogue. */ void exportMessageEnvelopeAsPDF(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation); + const QString &userName, MessageDb::MsgId msgId, bool askLocation); /*! * @brief Export selected message envelope as PDF and attachment files. */ void exportMessageEnvelopeAttachments(const QString &attachPath, - const QString &userName, qint64 dmId, QDateTime deliveryTime, - bool askLocation); + const QString &userName, MessageDb::MsgId msgId, bool askLocation); /*! * @brief Set info status bar from worker. @@ -743,21 +845,22 @@ int rt, int rn, int st, int sn); /*! - * @brief Refresh AccountList. - */ - void refreshAccountList(const QString &userName); - - /*! * @brief Set tablewidget when message download worker is done. */ void postDownloadSelectedMessageAttachments(const QString &userName, qint64 dmId); /*! + * @brief Generates file path where sto store attachment into. + */ + QString attachmentFilePath(const QString &userName, + const MessageDb::MsgId &msgId, QModelIndex attIdx); + + /*! * @brief Save attachment identified by indexes to file. */ - void saveAttachmentToFile(const QModelIndex &messageIndex, - const QModelIndex &attachmentIndex); + void saveAttachmentToFile(const QString &userName, + const MessageDb::MsgId &msgId, const QModelIndex &attIdx); /*! * @brief Return index for yearly entry with given properties. @@ -848,12 +951,12 @@ void activeAccountMenuAndButtons(bool action) const; /*! - * @brief Load and apply setting from configuration file. + * @brief Load and apply settings from configuration file. */ void loadSettings(void); /*! - * @brief Store current setting to configuration file. + * @brief Store current settings to configuration file. */ void saveSettings(void) const; @@ -990,8 +1093,8 @@ * * @return True if message has been removed from local database. */ - bool eraseMessage(const QString &userName, qint64 dmId, - const QDateTime &deliveryTime, bool delFromIsds); + bool eraseMessage(const QString &userName, + const MessageDb::MsgId &msgId, bool delFromIsds); /*! * @brief Authenticate message from ZFO file. @@ -1028,9 +1131,11 @@ * without worker and thread. * * @note Delivery time may change if invalid given. + * + * @param[in,out] msgId Message identifier. + * @return True on success. */ - bool downloadCompleteMessage(qint64 dmId, - QDateTime &deliveryTime); + bool downloadCompleteMessage(MessageDb::MsgId &msgId); /*! * @brief Shows notification dialogue and offers downloading of @@ -1038,10 +1143,11 @@ * * @note Delivery time may change if invalid given. * + * @param[in,out] msgId Message identifier. * @return True on success. */ - bool messageMissingOfferDownload(qint64 dmId, - QDateTime &deliveryTime, const QString &title); + bool messageMissingOfferDownload(MessageDb::MsgId &msgId, + const QString &title); /*! * @brief Set read status to messages with given indexes. @@ -1115,6 +1221,22 @@ bool setBackOriginDb(MessageDbSet *dbset, const QString &dbDir, const QString &userName); + /*! + * @brief Show dialog for webdatovka account + * that action is not implemented. + * @param[in] userName - account username. + * @param[in] txt additional info text. + */ + void showWebDatovkaInfoDialog(const QString &userName, QString txt); + + /*! + * @brief Test if exists another mojeID account with same userId + * when we delete any mojeID acccount. + * + * @param[in] userName - account username. + * @return true if any account exists + */ + bool existsAnotherMojeIdAccountWithSameUserId(const QString &userName); QString m_confDirName; /*!< Configuration directory location. */ QString m_confFileName; /*!< Configuration file location. */ @@ -1184,7 +1306,6 @@ * @brief Sets action icons. */ void setMenuActionIcons(void); - }; diff -Nru datovka-4.7.0/src/gui/dlg_contacts.cpp datovka-4.7.1/src/gui/dlg_contacts.cpp --- datovka-4.7.0/src/gui/dlg_contacts.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_contacts.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -44,6 +44,8 @@ m_userName(userName) { setupUi(this); + /* Set default line height for table views/widgets. */ + contactTableWidget->setNarrowedLineHeight(); this->contactTableWidget->setColumnWidth(0,20); this->contactTableWidget->setColumnWidth(1,60); diff -Nru datovka-4.7.0/src/gui/dlg_correspondence_overview.cpp datovka-4.7.1/src/gui/dlg_correspondence_overview.cpp --- datovka-4.7.0/src/gui/dlg_correspondence_overview.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_correspondence_overview.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -593,7 +593,7 @@ fileName = exportDir + QDir::separator() + fileName + ".zfo"; if (!exportMessageAsZFO(mId, fileName, false)) { - qDebug() << "DDZ" << mId.dmId + qDebug() << "DZ" << mId.dmId << "export error"; errorText = tr("Message '%1' does not " "contain data necessary for ZFO " @@ -625,7 +625,7 @@ fileName = exportDir + QDir::separator() + fileName + ".zfo"; if (!exportMessageAsZFO(mId, fileName, false)) { - qDebug() << "DDZ" << mId.dmId + qDebug() << "DZ" << mId.dmId << "export error"; errorText = tr("Message '%1' does not " "contain data necessary for ZFO " @@ -664,7 +664,7 @@ fileName = exportDir + QDir::separator() + fileName + ".zfo"; if (!exportMessageAsZFO(mId, fileName, true)) { - qDebug() << "DDZ" << mId.dmId + qDebug() << "DZ" << mId.dmId << "export error"; errorText = tr("Message '%1' does not " "contain deivery info data " @@ -696,7 +696,7 @@ fileName = exportDir + QDir::separator() + fileName + ".zfo"; if (!exportMessageAsZFO(mId, fileName, true)) { - qDebug() << "DDZ" << mId.dmId + qDebug() << "DZ" << mId.dmId << "export error"; errorText = tr("Message '%1' does not " "contain deivery info data " diff -Nru datovka-4.7.0/src/gui/dlg_create_account.cpp datovka-4.7.1/src/gui/dlg_create_account.cpp --- datovka-4.7.0/src/gui/dlg_create_account.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_create_account.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -55,6 +55,17 @@ m_loginmethod = loginMethodIdx; switch (m_loginmethod) { + case MOJEID: + this->certificateLabel->setEnabled(false); + this->addCertificateButton->setEnabled(false); + this->passwordLabel->setEnabled(false); + this->passwordLineEdit->setEnabled(false); + this->rememberPswcheckBox->setEnabled(false); + this->usernameLineEdit->setEnabled(false); + this->accountLineEdit->setEnabled(false); + this->testAccountCheckBox->setEnabled(false); + this->loginmethodComboBox->setEnabled(false); + break; case CERTIFICATE: this->certificateLabel->setEnabled(true); this->addCertificateButton->setEnabled(true); @@ -88,6 +99,12 @@ bool buttonEnabled; switch (m_loginmethod) { + case MOJEID: + buttonEnabled = true; + if (m_action == ACT_EDIT) { + this->accountLineEdit->setEnabled(true); + } + break; case CERTIFICATE: buttonEnabled = !this->accountLineEdit->text().isEmpty() && !this->usernameLineEdit->text().isEmpty() @@ -222,9 +239,13 @@ case AcntSettings::LIM_UNAME_PWD_TOTP: itemIdx = TOTP; break; + case AcntSettings::LIM_MOJE_ID: + this->loginmethodComboBox->addItem(tr("mojeID")); + itemIdx = MOJEID; + break; default: Q_ASSERT(0); - itemIdx = TOTP; + itemIdx = USER_NAME; break; } @@ -247,6 +268,7 @@ checkInputFields(); } + AcntSettings DlgCreateAccount::getContent(void) const { AcntSettings newAccountSettings; diff -Nru datovka-4.7.0/src/gui/dlg_create_account.h datovka-4.7.1/src/gui/dlg_create_account.h --- datovka-4.7.0/src/gui/dlg_create_account.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_create_account.h 2017-01-19 09:29:26.000000000 +0000 @@ -46,7 +46,8 @@ CERTIFICATE = 1, USER_CERTIFICATE = 2, HOTP = 3, - TOTP = 4 + TOTP = 4, + MOJEID = 5 }; /*! diff -Nru datovka-4.7.0/src/gui/dlg_ds_search.cpp datovka-4.7.1/src/gui/dlg_ds_search.cpp --- datovka-4.7.0/src/gui/dlg_ds_search.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_ds_search.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -46,6 +46,9 @@ m_showInfoLabel(false) { setupUi(this); + /* Set default line height for table views/widgets. */ + resultsTableWidget->setNarrowedLineHeight(); + initSearchWindow(); } diff -Nru datovka-4.7.0/src/gui/dlg_login_mojeid.cpp datovka-4.7.1/src/gui/dlg_login_mojeid.cpp --- datovka-4.7.0/src/gui/dlg_login_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_login_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "dlg_login_mojeid.h" +#include "src/log/log.h" +#include "src/web/json.h" + +DlgLoginToMojeId::DlgLoginToMojeId(const QString &userName, + const QString &lastUrl, QWidget *parent) + : QDialog(parent), + m_loginmethod(0), + m_certPath(""), + m_userName(userName), + m_lastUrl(lastUrl), + m_token(QString()) +{ + setupUi(this); + initAccountDialog(); +} + + +/* ========================================================================= */ +/* + * Init dialog + */ +void DlgLoginToMojeId::initAccountDialog(void) +/* ========================================================================= */ +{ + this->loginmethodComboBox->addItem(tr("Password")); + this->loginmethodComboBox->addItem(tr("Certificate")); + this->loginmethodComboBox->addItem(tr("Password + Secure code")); + this->certificateLabel->setEnabled(false); + this->otpLineEdit->setEnabled(false); + this->accountButtonBox->button( + QDialogButtonBox::Ok)->setEnabled(false); + this->addCertificateButton->setEnabled(false); + connect(this->loginmethodComboBox, SIGNAL(currentIndexChanged (int)), + this, SLOT(setActiveButton(int))); + connect(this->addCertificateButton, SIGNAL(clicked()), this, + SLOT(addCertificateFromFile())); + connect(this->accountButtonBox, SIGNAL(accepted()), this, + SLOT(sendData(void))); + connect(this->usernameLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(checkInputFields())); + connect(this->passwordLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(checkInputFields())); + connect(this->otpLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(checkInputFields())); + + if (!m_userName.isEmpty()) { + this->synchroCheckBox->setEnabled(false); + this->setWindowTitle(tr("Login to account: %1").arg(m_userName)); + } + + /* USERNAME+PWD is set as default login method in the Webdatovka */ + jsonlayer.loginMethodChanged(USER_NAME, m_lastUrl, m_token); +} + + +/* ========================================================================= */ +/* + * Open load dialog and set certificate file path + */ +void DlgLoginToMojeId::addCertificateFromFile(void) +/* ========================================================================= */ +{ + QString certFileName = QFileDialog::getOpenFileName(this, + tr("Open Certificate"), "", + tr("Certificate Files (*.p12 *.pem)")); + if (!certFileName.isEmpty()) { + this->addCertificateButton->setText(certFileName); + this->addCertificateButton->setIcon(QIcon(ICON_3PARTY_PATH + + QString("key_16.png"))); + m_certPath = certFileName; + checkInputFields(); + } +} + + +/* ========================================================================= */ +/* + * Check content of mandatory items in dialog and activate save button + */ +void DlgLoginToMojeId::checkInputFields(void) +/* ========================================================================= */ +{ + bool buttonEnabled; + if (m_loginmethod == CERTIFICATE) { + buttonEnabled = !m_certPath.isEmpty(); + } else if (m_loginmethod == USER_NAME) { + buttonEnabled = !this->usernameLineEdit->text().isEmpty() + && !this->passwordLineEdit->text().isEmpty(); + } else { + buttonEnabled = !this->usernameLineEdit->text().isEmpty() + && !this->passwordLineEdit->text().isEmpty() + && !this->otpLineEdit->text().isEmpty(); + } + + this->accountButtonBox->button(QDialogButtonBox::Ok)-> + setEnabled(buttonEnabled); +} + + +/* ========================================================================= */ +/* + * Set active/inactive buttons based on login method + */ +void DlgLoginToMojeId::setActiveButton(int itemindex) +/* ========================================================================= */ +{ + this->usernameLineEdit->setEnabled(true); + + if (itemindex == CERTIFICATE) { + this->certificateLabel->setEnabled(true); + this->addCertificateButton->setEnabled(true); + this->passwordLabel->setEnabled(false); + this->passwordLineEdit->setEnabled(false); + this->otpLineEdit->setEnabled(false); + this->otpLineEdit->clear(); + this->passwordLineEdit->clear(); + } else if (itemindex == USER_NAME) { + this->certificateLabel->setEnabled(false); + this->addCertificateButton->setEnabled(false); + this->passwordLabel->setEnabled((true)); + this->passwordLineEdit->setEnabled((true)); + this->otpLineEdit->setEnabled(false); + this->otpLineEdit->clear(); + } else { + this->certificateLabel->setEnabled(false); + this->addCertificateButton->setEnabled(false); + this->passwordLabel->setEnabled((true)); + this->passwordLineEdit->setEnabled((true)); + this->otpLineEdit->setEnabled(true); + } + + m_loginmethod = itemindex; + + jsonlayer.loginMethodChanged(m_loginmethod, m_lastUrl, m_token); + + checkInputFields(); +} + + +/* ========================================================================= */ +/* + * Login to mojeID. + */ +void DlgLoginToMojeId::sendData(void) +/* ========================================================================= */ +{ + debugSlotCall(); + + emit callMojeId(m_userName, m_lastUrl, + m_token, this->usernameLineEdit->text(), + this->passwordLineEdit->text(), this->otpLineEdit->text(), + this->synchroCheckBox->isChecked(), m_certPath); +} diff -Nru datovka-4.7.0/src/gui/dlg_login_mojeid.h datovka-4.7.1/src/gui/dlg_login_mojeid.h --- datovka-4.7.0/src/gui/dlg_login_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_login_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#ifndef _DLG_LOGIN_MOJEID_H_ +#define _DLG_LOGIN_MOJEID_H_ + +#include + +#include "src/common.h" +#include "ui_dlg_login_mojeid.h" + +class DlgLoginToMojeId : public QDialog, public Ui::LoginToMojeId { + Q_OBJECT + +public: + + DlgLoginToMojeId(const QString &userName, const QString &lastUrl, + QWidget *parent = 0); + +private slots: + void setActiveButton(int); + void addCertificateFromFile(void); + void sendData(void); + void checkInputFields(void); + +signals: + void callMojeId(QString, QString, QString, + QString, QString, QString, bool, QString); + +private: + void initAccountDialog(void); + + int m_loginmethod; + QString m_certPath; + QString m_userName; + QString m_lastUrl; + QString m_token; +}; + +#endif /* _DLG_LOGIN_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/gui/dlg_msg_search.cpp datovka-4.7.1/src/gui/dlg_msg_search.cpp --- datovka-4.7.0/src/gui/dlg_msg_search.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_msg_search.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -47,6 +47,9 @@ m_userName(userName) { setupUi(this); + /* Set default line height for table views/widgets. */ + resultsTableWidget->setNarrowedLineHeight(); + initSearchWindow(); } diff -Nru datovka-4.7.0/src/gui/dlg_preferences.cpp datovka-4.7.1/src/gui/dlg_preferences.cpp --- datovka-4.7.0/src/gui/dlg_preferences.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_preferences.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -23,7 +23,8 @@ #include -#include "dlg_preferences.h" +#include "src/dimensions/dimensions.h" +#include "src/gui/dlg_preferences.h" #include "src/settings/preferences.h" #include "ui_dlg_preferences.h" @@ -31,6 +32,13 @@ : QDialog(parent) { setupUi(this); + { + /* Adjust window size according to font size. */ + QSize newSize = Dimensions::windowSize(this, 46.0, 44.0); + if (newSize.isValid()) { + this->resize(newSize); + } + } initPrefDialog(); } diff -Nru datovka-4.7.0/src/gui/dlg_search_mojeid.cpp datovka-4.7.1/src/gui/dlg_search_mojeid.cpp --- datovka-4.7.0/src/gui/dlg_search_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_search_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,283 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#include +#include + +#include "src/gui/dlg_search_mojeid.h" +#include "src/views/table_home_end_filter.h" +#include "src/views/table_space_selection_filter.h" +#include "src/web/json.h" + +DlgDsSearchMojeId::DlgDsSearchMojeId(Action action, + QTableWidget *recipientTableWidget, const QString &dbType, + bool dbEffectiveOVM, QWidget *parent, const QString &userName) + : QDialog(parent), + m_action(action), + m_recipientTableWidget(recipientTableWidget), + m_dbType(dbType), + m_dbEffectiveOVM(dbEffectiveOVM), + m_userName(userName), + m_limit(0) +{ + setupUi(this); + initSearchWindow(); +} + + +/* ========================================================================= */ +/* + * Init ISDS search dialog + */ +void DlgDsSearchMojeId::initSearchWindow(void) +/* ========================================================================= */ +{ + this->resultsTableWidget->setColumnHidden(5, true); + + this->accountInfo->setText("" + m_userName + + "" + " - " + m_dbType); + + this->resultsTableWidget->setColumnWidth(0,20); + this->resultsTableWidget->setColumnWidth(1,60); + this->resultsTableWidget->setColumnWidth(2,120); + + connect(this->resultsTableWidget, + SIGNAL(itemSelectionChanged()), this, + SLOT(setFirtsColumnActive())); + + connect(this->keywordLineEdit, SIGNAL(textChanged(QString)), + this, SLOT(checkInputFields())); + connect(this->resultsTableWidget,SIGNAL(itemClicked(QTableWidgetItem*)), + this, SLOT(enableOkButton())); + connect(this->resultsTableWidget, + SIGNAL(itemChanged(QTableWidgetItem*)), this, + SLOT(enableOkButton())); + connect(this->buttonBox, SIGNAL(accepted()), this, + SLOT(insertDsItems())); + connect(this->searchPushButton, SIGNAL(clicked()), this, + SLOT(searchDataBox())); + connect(this->resultsTableWidget, SIGNAL(doubleClicked(QModelIndex)), + this, SLOT(contactItemDoubleClicked(QModelIndex))); + + this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + this->resultsTableWidget-> + setEditTriggers(QAbstractItemView::NoEditTriggers); + + this->resultsTableWidget->installEventFilter( + new TableHomeEndFilter(this)); + this->resultsTableWidget->installEventFilter( + new TableSpaceSelectionFilter(this)); + + checkInputFields(); +} + + +/* ========================================================================= */ +/* + * Set first column with checkbox active if item was changed + */ +void DlgDsSearchMojeId::setFirtsColumnActive(void) +/* ========================================================================= */ +{ + this->resultsTableWidget->selectColumn(0); + this->resultsTableWidget->selectRow( + this->resultsTableWidget->currentRow()); +} + + +/* ========================================================================= */ +/* + * Check input fields in the dialog + */ +void DlgDsSearchMojeId::checkInputFields(void) +/* ========================================================================= */ +{ + this->searchPushButton->setEnabled(false); + if (this->keywordLineEdit->text().length() > 0) { + this->searchPushButton->setEnabled(true); + } + this->searchPushButton->setText(tr("Search")); + m_limit = 0; +} + + +/* ========================================================================= */ +/* + * Call ISDS and find data boxes with given criteria + */ +void DlgDsSearchMojeId::searchDataBox(void) +/* ========================================================================= */ +{ + if (m_limit == 0) { + this->resultsTableWidget->setRowCount(0); + } + this->resultsTableWidget->setEnabled(false); + + QList rList; + bool hasMore = false; + QString errStr; + + int accountID = getWebDatovkaAccountId(m_userName); + + JsonLayer jsonLayer; + jsonLayer.searchRecipient(m_userName, accountID, + this->keywordLineEdit->text(), m_limit, rList, hasMore, errStr); + + if (rList.isEmpty()) { + return; + } + + this->resultsTableWidget->setEnabled(true); + foreach (const JsonLayer::Recipient &recipient, rList) { + int row = this->resultsTableWidget->rowCount(); + this->resultsTableWidget->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem; + item->setCheckState(Qt::Unchecked); + this->resultsTableWidget->setItem(row,0,item); + item = new QTableWidgetItem; + item->setText(recipient.recipientDbId); + this->resultsTableWidget->setItem(row,1,item); + item = new QTableWidgetItem; + item->setText(recipient.recipientName); + this->resultsTableWidget->setItem(row,2,item); + item = new QTableWidgetItem; + item->setText(recipient.recipientAddress); + this->resultsTableWidget->setItem(row,3,item); + } + + if (this->resultsTableWidget->rowCount() > 0) { + this->resultsTableWidget->selectColumn(0); + this->resultsTableWidget->selectRow(0); + } + + if (hasMore) { + this->searchPushButton->setText(tr("Search next")); + m_limit++; + } +} + + +/* ========================================================================= */ +/* + * Enable action button + */ +void DlgDsSearchMojeId::enableOkButton(void) +/* ========================================================================= */ +{ + this->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + for (int i = 0; i < this->resultsTableWidget->rowCount(); i++) { + if (this->resultsTableWidget->item(i,0)->checkState()) { + this->buttonBox->button(QDialogButtonBox::Ok)-> + setEnabled(true); + } + } +} + + +/* ========================================================================= */ +/* + * Test if the selected item is not in recipient list + */ +bool DlgDsSearchMojeId::isInRecipientTable(const QString &idDs) const +/* ========================================================================= */ +{ + Q_ASSERT(0 != m_recipientTableWidget); + + for (int i = 0; i < this->m_recipientTableWidget->rowCount(); i++) { + if (this->m_recipientTableWidget->item(i,0)->text() == idDs) { + return true; + } + } + return false; +} + + +/* ========================================================================= */ +/* + * Insert selected contacts into recipient list of the sent message dialog. + */ +void DlgDsSearchMojeId::insertDsItems(void) +/* ========================================================================= */ +{ + if (ACT_ADDNEW == m_action) { + Q_ASSERT(0 != m_recipientTableWidget); + for (int i = 0; i < this->resultsTableWidget->rowCount(); i++) { + if (this->resultsTableWidget->item(i,0)->checkState()) { + insertContactToRecipentTable(i); + } + } + } +} + + +/* ========================================================================= */ +/* + * Doubleclick of selected contact. + */ +void DlgDsSearchMojeId::contactItemDoubleClicked(const QModelIndex &index) +/* ========================================================================= */ +{ + if (ACT_ADDNEW == m_action) { + + if (!index.isValid()) { + this->close(); + return; + } + + insertContactToRecipentTable(index.row()); + + this->close(); + } +} + + +/* ========================================================================= */ +/* + * Insert contact into recipient list of the sent message dialog. + */ +void DlgDsSearchMojeId::insertContactToRecipentTable(int selRow) +/* ========================================================================= */ +{ + if (!isInRecipientTable( + this->resultsTableWidget->item(selRow, 1)->text())) { + + int row = m_recipientTableWidget->rowCount(); + m_recipientTableWidget->insertRow(row); + QTableWidgetItem *item = new QTableWidgetItem; + item->setText(this->resultsTableWidget-> + item(selRow, 1)->text()); + this->m_recipientTableWidget->setItem(row,0,item); + item = new QTableWidgetItem; + item->setText(this->resultsTableWidget-> + item(selRow, 2)->text()); + this->m_recipientTableWidget->setItem(row,1,item); + item = new QTableWidgetItem; + item->setText(this->resultsTableWidget->item(selRow, 3)->text()); + this->m_recipientTableWidget->setItem(row, 2, item); + item = new QTableWidgetItem; + item->setText(""); + item->setTextAlignment(Qt::AlignCenter); + this->m_recipientTableWidget->setItem(row, 3, item); + } +} diff -Nru datovka-4.7.0/src/gui/dlg_search_mojeid.h datovka-4.7.1/src/gui/dlg_search_mojeid.h --- datovka-4.7.0/src/gui/dlg_search_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_search_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#ifndef _DLG_SEARCH_MOJEID_H_ +#define _DLG_SEARCH_MOJEID_H_ + + +#include +#include + +#include "src/common.h" +#include "ui_dlg_search_mojeid.h" + + +class DlgDsSearchMojeId : public QDialog, public Ui::DsSearchMojeId { + Q_OBJECT + +public: + enum Action { + ACT_BLANK, + ACT_ADDNEW + }; + + DlgDsSearchMojeId(Action action, QTableWidget *recipientTableWidget, + const QString &dbType, bool dbEffectiveOVM, + QWidget *parent = 0, const QString &userName = QString()); + +private slots: + void checkInputFields(void); + void insertDsItems(void); + void enableOkButton(void); + void searchDataBox(void); + void setFirtsColumnActive(void); + void contactItemDoubleClicked(const QModelIndex &index); + +private: + + bool isInRecipientTable(const QString &idDs) const; + void initSearchWindow(void); + void addContactsToTable(const QList< QVector > &contactList); + void insertContactToRecipentTable(int selRow); + + Action m_action; + QTableWidget *m_recipientTableWidget; + QString m_dbType; + bool m_dbEffectiveOVM; + const QString m_userName; + int m_limit; +}; + + +#endif /* _DLG_SEARCH_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/gui/dlg_send_message.cpp datovka-4.7.1/src/gui/dlg_send_message.cpp --- datovka-4.7.0/src/gui/dlg_send_message.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_send_message.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -21,8 +21,6 @@ * the two. */ - -#include #include #include #include @@ -33,23 +31,48 @@ #include "src/gui/dlg_change_pwd.h" #include "src/gui/dlg_contacts.h" #include "src/gui/dlg_ds_search.h" +#include "src/model_interaction/attachment_interaction.h" +#include "src/gui/dlg_search_mojeid.h" #include "src/models/accounts_model.h" #include "src/io/account_db.h" #include "src/io/dbs.h" -#include "src/io/filesystem.h" #include "src/io/isds_sessions.h" +#include "src/io/wd_sessions.h" #include "src/io/message_db.h" #include "src/log/log.h" #include "src/settings/preferences.h" -#include "src/views/attachment_table_widget.h" +#include "src/views/attachment_table_view.h" #include "src/views/table_home_end_filter.h" #include "src/worker/message_emitter.h" #include "src/worker/pool.h" #include "src/worker/task_download_credit_info.h" #include "src/worker/task_keep_alive.h" #include "src/worker/task_send_message.h" +#include "src/worker/task_send_message_mojeid.h" #include "ui_dlg_send_message.h" +const QString &dzPrefix(MessageDb *messageDb, qint64 dmId) +{ + const static QString nothing; + const static QString received(QLatin1String("D")); + const static QString sent(QLatin1String("0")); + + if (0 == messageDb || dmId < 0) { + return nothing; + } + + switch (messageDb->msgMessageType(dmId)) { + case MessageDb::TYPE_RECEIVED: + return received; + break; + case MessageDb::TYPE_SENT: + return sent; + break; + default: + return nothing; + break; + } +} /* * Column indexes into recipient table widget. @@ -62,13 +85,12 @@ DlgSendMessage::DlgSendMessage( const QList &messageDbSetList, - Action action, qint64 msgId, const QDateTime &deliveryTime, + Action action, const QList &msgIds, const QString &userName, class MainWindow *mv, QWidget *parent) : QDialog(parent), m_keepAliveTimer(), m_messageDbSetList(messageDbSetList), - m_msgID(msgId), - m_deliveryTime(deliveryTime), + m_msgIds(msgIds), m_dbId(""), m_senderName(""), m_action(action), @@ -81,12 +103,21 @@ m_dmType(""), m_dmSenderRefNumber(""), m_mv(mv), + m_dbSet(0), m_isLogged(false), + m_attachmentModel(), + m_isWebDatovkaAccount(false), m_transactIds(), m_sentMsgResultList() { setupUi(this); + /* Set default line height for table views/widgets. */ + recipientTableWidget->setNarrowedLineHeight(); + attachmentTableView->setNarrowedLineHeight(); + initNewMessageDialog(); + + Q_ASSERT(0 != m_dbSet); } /* ========================================================================= */ @@ -104,15 +135,47 @@ void DlgSendMessage::initNewMessageDialog(void) /* ========================================================================= */ { + if (isWebDatovkaAccount(m_userName)) { + m_isWebDatovkaAccount = true; + } + this->recipientTableWidget->setColumnWidth(0,70); this->recipientTableWidget->setColumnWidth(1,180); this->recipientTableWidget->setColumnWidth(2,240); - this->attachmentTableWidget->setColumnWidth(0,150); - this->attachmentTableWidget->setColumnWidth(1,40); - this->attachmentTableWidget->setColumnWidth(2,120); + m_attachmentModel.setHeader(); + + this->attachmentTableView->setModel(&m_attachmentModel); + + this->attachmentTableView->setColumnWidth(DbFlsTblModel::FNAME_COL, 150); + this->attachmentTableView->setColumnWidth(DbFlsTblModel::MIME_COL, 120); - this->attachmentTableWidget->setColumnHidden(5, true); + this->attachmentTableView->setColumnHidden(DbFlsTblModel::ATTACHID_COL, true); + this->attachmentTableView->setColumnHidden(DbFlsTblModel::MSGID_COL, true); + this->attachmentTableView->setColumnHidden(DbFlsTblModel::CONTENT_COL, true); + +#if 0 + this->attachmentTableView->setAcceptDrops(true); + this->attachmentTableView->setDragEnabled(false); + this->attachmentTableView->setDragDropOverwriteMode(false); + this->attachmentTableView->setDropIndicatorShown(true); + this->attachmentTableView->setDragDropMode(QAbstractItemView::InternalMove); +// this->attachmentTableView->setDefaultDropAction(Qt::MoveAction); +#endif +#if 0 + this->attachmentTableView->setAcceptDrops(true); + this->attachmentTableView->setDragEnabled(true); + this->attachmentTableView->setDragDropOverwriteMode(false); + this->attachmentTableView->setDropIndicatorShown(true); + this->attachmentTableView->setDragDropMode(QAbstractItemView::DragDrop); + this->attachmentTableView->setDefaultDropAction(Qt::MoveAction); +#endif + this->attachmentTableView->setAcceptDrops(true); + this->attachmentTableView->setDragEnabled(true); + this->attachmentTableView->setDragDropOverwriteMode(false); + this->attachmentTableView->setDropIndicatorShown(true); + this->attachmentTableView->setDragDropMode(QAbstractItemView::DragDrop); + this->attachmentTableView->setDefaultDropAction(Qt::CopyAction); this->replyLabel->hide(); this->replyLabel->setEnabled(false); @@ -162,15 +225,14 @@ connect(this->removeAttachment, SIGNAL(clicked()), this, SLOT(deleteSelectedAttachmentFiles())); connect(this->openAttachment, SIGNAL(clicked()), this, - SLOT(openAttachmentFile())); + SLOT(openSelectedAttachment())); connect(this->recipientTableWidget, SIGNAL(itemClicked(QTableWidgetItem *)), this, SLOT(recItemSelect())); - connect(this->attachmentTableWidget, - SIGNAL(itemDoubleClicked(QTableWidgetItem *)), - this, SLOT(tableItemDoubleClicked(QTableWidgetItem *))); + connect(this->attachmentTableView, SIGNAL(doubleClicked(QModelIndex)), + this, SLOT(openSelectedAttachment(QModelIndex))); connect(this->enterDbIdpushButton, SIGNAL(clicked()), this, SLOT(addDbIdToRecipientList())); @@ -178,27 +240,27 @@ connect(this->subjectText, SIGNAL(textChanged(QString)), this, SLOT(checkInputFields())); - connect(this->attachmentTableWidget->model(), + connect(&m_attachmentModel, SIGNAL(rowsInserted(QModelIndex, int, int)), this, SLOT(checkInputFields())); - connect(this->attachmentTableWidget->model(), + connect(&m_attachmentModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this, SLOT(checkInputFields())); - connect(this->attachmentTableWidget->model(), + connect(&m_attachmentModel, SIGNAL(dataChanged(QModelIndex, QModelIndex, QVector)), this, SLOT(attachmentDataChanged(QModelIndex, QModelIndex, QVector))); - connect(this->attachmentTableWidget->selectionModel(), + connect(this->attachmentTableView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), this, SLOT(attachmentSelectionChanged(QItemSelection, QItemSelection))); this->recipientTableWidget-> setEditTriggers(QAbstractItemView::NoEditTriggers); - this->attachmentTableWidget-> + this->attachmentTableView-> setEditTriggers(QAbstractItemView::NoEditTriggers); this->recipientTableWidget->installEventFilter( new TableHomeEndFilter(this)); - this->attachmentTableWidget->installEventFilter( + this->attachmentTableView->installEventFilter( new TableHomeEndFilter(this)); connect(this->sendButton, SIGNAL(clicked()), this, SLOT(sendMessage())); @@ -207,11 +269,17 @@ QString, QString, bool, qint64)), this, SLOT(collectSendMessageStatus(QString, QString, int, QString, QString, QString, bool, qint64))); + connect(&globMsgProcEmitter, + SIGNAL(sendMessageMojeIdFinished(QString, QStringList, QString)), this, + SLOT(sendMessageMojeIdAction(QString, QStringList, QString))); - connect(&m_keepAliveTimer, SIGNAL(timeout()), this, - SLOT(pingIsdsServer())); m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); + if (!m_isWebDatovkaAccount) { + connect(&m_keepAliveTimer, SIGNAL(timeout()), this, + SLOT(pingIsdsServer())); + } + this->attachmentSizeInfo->setText( tr("Total size of attachments is %1 B").arg(0)); @@ -235,6 +303,8 @@ this->payRecipient->hide(); if (ACT_NEW_FROM_TMP == m_action) { fillDlgFromTmpMsg(); + } else if (ACT_FORWARD == m_action) { + fillDlgAsForward(); } } @@ -265,32 +335,42 @@ m_userName = userName; } - struct isds_ctx *session = NULL; + if (isWebDatovkaAccount(m_userName)) { + m_isWebDatovkaAccount = true; + } - m_isLogged = true; + if (!m_isWebDatovkaAccount) { - m_keepAliveTimer.stop(); - { - TaskKeepAlive *task; - task = new (std::nothrow) TaskKeepAlive(m_userName); - task->setAutoDelete(false); - globWorkPool.runSingle(task); - - m_isLogged = task->m_isAlive; - - delete task; - } - if (!m_isLogged) { - if (m_mv) { - m_isLogged = m_mv->connectToIsds(m_userName); + struct isds_ctx *session = NULL; + m_isLogged = true; + m_keepAliveTimer.stop(); + { + TaskKeepAlive *task; + task = new (std::nothrow) TaskKeepAlive(m_userName); + task->setAutoDelete(false); + globWorkPool.runSingle(task); + + m_isLogged = task->m_isAlive; + + delete task; } - } - m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); + if (!m_isLogged) { + if (m_mv) { + m_isLogged = m_mv->connectToIsds(m_userName); + } + } + m_keepAliveTimer.start(DLG_ISDS_KEEPALIVE_MS); - session = globIsdsSessions.session(m_userName); - if (NULL == session) { - logErrorNL("%s", "Missing ISDS session."); - m_isLogged = false; + session = globIsdsSessions.session(m_userName); + if (NULL == session) { + logErrorNL("%s", "Missing ISDS session."); + m_isLogged = false; + } + } else { + if (!wdSessions.isConnectedToWebdatovka(m_userName)) { + m_mv->loginToMojeId(m_userName); + } + m_isLogged = true; } foreach (const Task::AccountDescr &acnt, m_messageDbSetList) { @@ -317,8 +397,11 @@ } else { m_lastAttAddPath = accountInfo.lastAttachAddPath(); } - if (m_dbOpenAddressing) { - m_pdzCredit = getPDZCreditFromISDS(m_userName, m_dbId); + + if (!m_isWebDatovkaAccount) { + if (m_dbOpenAddressing) { + m_pdzCredit = getPDZCreditFromISDS(m_userName, m_dbId); + } } QString dbOpenAddressingText = ""; @@ -340,7 +423,6 @@ } - /* ========================================================================= */ /* * Func: Return remaining PDZ credit. @@ -370,21 +452,6 @@ /* ========================================================================= */ /* - * Slot is fired when user double clicked on attachment item - open file. - */ -void DlgSendMessage::tableItemDoubleClicked(QTableWidgetItem *item) -/* ========================================================================= */ -{ - debugSlotCall(); - - Q_UNUSED(item); - - openAttachmentFile(); -} - - -/* ========================================================================= */ -/* * Whenever any data in attachment table change. */ void DlgSendMessage::attachmentDataChanged(const QModelIndex &topLeft, @@ -415,12 +482,13 @@ QModelIndexList selectedIndexes; { QItemSelectionModel *selectionModel = - this->attachmentTableWidget->selectionModel(); + this->attachmentTableView->selectionModel(); if (0 == selectionModel) { Q_ASSERT(0); return; } - selectedIndexes = selectionModel->selectedRows(0); + selectedIndexes = + selectionModel->selectedRows(DbFlsTblModel::FNAME_COL); } this->removeAttachment->setEnabled(selectedIndexes.size() > 0); @@ -437,15 +505,23 @@ { debugFuncCall(); + if (m_msgIds.size() != 1) { + logWarningNL("%s", + "Expected one message to generate reply from."); + return; + } + const MessageDb::MsgId &msgId(m_msgIds.first()); + bool hideOptionalWidget = true; this->fromComboBox->setEnabled(false); - MessageDb *messageDb = m_dbSet->accessMessageDb(m_deliveryTime, false); + MessageDb *messageDb = + m_dbSet->accessMessageDb(msgId.deliveryTime, false); Q_ASSERT(0 != messageDb); MessageDb::PartialEnvelopeData envData = - messageDb->msgsReplyData(m_msgID); + messageDb->msgsReplyData(msgId.dmId); m_dmType = envData.dmType; m_dmSenderRefNumber = envData.dmRecipientRefNumber; @@ -517,6 +593,42 @@ this->recipientTableWidget->setItem(row, RTW_PDZ, item); } +void DlgSendMessage::fillDlgAsForward(void) +{ + debugFuncCall(); + + if (m_msgIds.size() == 0) { + logWarningNL("%s", + "Expected at lease one message to generate reply from."); + return; + } + + /* Fill attachments with messages. */ + foreach (const MessageDb::MsgId &msgId, m_msgIds) { + MessageDb *messageDb = + m_dbSet->accessMessageDb(msgId.deliveryTime, false); + if (0 == messageDb) { + Q_ASSERT(0); + continue; + } + + /* If only a single message if forwarded. */ + if (m_msgIds.size() == 1) { + MessageDb::PartialEnvelopeData envData( + messageDb->msgsReplyData(msgId.dmId)); + + this->subjectText->setText("Fwd: " + envData.dmAnnotation); + } + + QByteArray msgBase64(messageDb->msgsMessageBase64(msgId.dmId)); + if (msgBase64.isEmpty()) { + continue; + } + + m_attachmentModel.appendAttachmentEntry(msgBase64, + dzPrefix(messageDb, msgId.dmId) + QString("DZ_%1.zfo").arg(msgId.dmId)); + } +} /* ========================================================================= */ /* @@ -527,13 +639,21 @@ { debugFuncCall(); + if (m_msgIds.size() != 1) { + logWarningNL("%s", + "Expected one message to generate reply from."); + return; + } + const MessageDb::MsgId &msgId(m_msgIds.first()); + bool hideOptionalWidget = true; - MessageDb *messageDb = m_dbSet->accessMessageDb(m_deliveryTime, false); + MessageDb *messageDb = + m_dbSet->accessMessageDb(msgId.deliveryTime, false); Q_ASSERT(0 != messageDb); MessageDb::PartialEnvelopeData envData = - messageDb->msgsReplyData(m_msgID); + messageDb->msgsReplyData(msgId.dmId); m_dmType = envData.dmType; m_dmSenderRefNumber = envData.dmRecipientRefNumber; @@ -621,30 +741,11 @@ /* fill attachments from template message */ QList msgFileList = - messageDb->getFilesFromMessage(m_msgID); + messageDb->getFilesFromMessage(msgId.dmId); foreach (const MessageDb::FileData &fileData, msgFileList) { - int row = this->attachmentTableWidget->rowCount(); - this->attachmentTableWidget->insertRow(row); - QTableWidgetItem *item = new QTableWidgetItem; - item->setText(fileData.dmFileDescr); - this->attachmentTableWidget->setItem(row, ATW_FILE, item); - item = new QTableWidgetItem; - item->setText(""); - this->attachmentTableWidget->setItem(row, ATW_TYPE, item); - item = new QTableWidgetItem; - item->setText(tr("unknown")); - this->attachmentTableWidget->setItem(row, ATW_MIME, item); - item = new QTableWidgetItem; - item->setText(QString::number( - base64RealSize(fileData.dmEncodedContent))); - this->attachmentTableWidget->setItem(row, ATW_SIZE, item); - item = new QTableWidgetItem; - item->setText(tr("local database")); - this->attachmentTableWidget->setItem(row, ATW_PATH, item); - item = new QTableWidgetItem; - item->setData(Qt::DisplayRole, fileData.dmEncodedContent); - this->attachmentTableWidget->setItem(row, ATW_DATA, item); + m_attachmentModel.appendAttachmentEntry( + fileData.dmEncodedContent, fileData.dmFileDescr); } } @@ -686,8 +787,10 @@ } foreach (const QString &fileName, fileNames) { - int fileSize = this->attachmentTableWidget->addFile(fileName); + int fileSize = m_attachmentModel.insertAttachmentFile(fileName, + m_attachmentModel.rowCount()); if (fileSize <= 0) { + /* TODO -- Generate some warning message. */ continue; } } @@ -772,7 +875,7 @@ /* ========================================================================= */ { QModelIndexList firstMsgColumnIdxs = - this->attachmentTableWidget->selectionModel()->selectedRows(0); + this->attachmentTableView->selectionModel()->selectedRows(0); for (int i = firstMsgColumnIdxs.size() - 1; i >= 0; --i) { /* @@ -780,7 +883,7 @@ * indexes. */ int row = firstMsgColumnIdxs.at(i).row(); - this->attachmentTableWidget->removeRow(row); + m_attachmentModel.removeRow(row); } checkInputFields(); @@ -796,22 +899,23 @@ { int aSize = 0; - for (int i = 0; i < this->attachmentTableWidget->rowCount(); i++) { - QTableWidgetItem *item = - this->attachmentTableWidget->item(i, ATW_SIZE); - if (0 != item) { - aSize += item->text().toInt(); + for (int i = 0; i < m_attachmentModel.rowCount(); ++i) { + QModelIndex idx( + m_attachmentModel.index(i, DbFlsTblModel::FSIZE_COL)); + + if (idx.isValid()) { + aSize += idx.data().toInt(); } } this->attachmentSizeInfo->setStyleSheet("QLabel { color: black }"); - if (this->attachmentTableWidget->rowCount() > MAX_ATTACHMENT_FILES) { + if (m_attachmentModel.rowCount() > MAX_ATTACHMENT_FILES) { this->attachmentSizeInfo-> setStyleSheet("QLabel { color: red }"); - this->attachmentSizeInfo->setText( - tr("Warning: The permitted amount (%1) of attachments has " - "been exceeded.").arg(QString::number(MAX_ATTACHMENT_FILES))); + this->attachmentSizeInfo->setText(tr( + "Warning: The permitted amount (%1) of attachments has been exceeded.") + .arg(QString::number(MAX_ATTACHMENT_FILES))); return false; } @@ -825,15 +929,14 @@ this->attachmentSizeInfo-> setStyleSheet("QLabel { color: red }"); this->attachmentSizeInfo->setText( - tr("Warning: Total size of attachments " - "is larger than %1 MB!"). - arg(QString::number( + tr("Warning: Total size of attachments is larger than %1 MB!") + .arg(QString::number( MAX_ATTACHMENT_SIZE_MB))); return false; } } else { - this->attachmentSizeInfo->setText( - tr("Total size of attachments is ~%1 B").arg(aSize)); + this->attachmentSizeInfo->setText(tr( + "Total size of attachments is ~%1 B").arg(aSize)); } } else { this->attachmentSizeInfo->setText( @@ -852,9 +955,9 @@ /* ========================================================================= */ { bool buttonEnabled = calculateAndShowTotalAttachSize() - && !this->subjectText->text().isEmpty() - && (this->recipientTableWidget->rowCount() > 0) - && (this->attachmentTableWidget->rowCount() > 0); + && !this->subjectText->text().isEmpty() + && (this->recipientTableWidget->rowCount() > 0) + && (m_attachmentModel.rowCount() > 0); if (this->payReply->isChecked()) { if (this->dmSenderRefNumber->text().isEmpty()) { @@ -887,70 +990,30 @@ /* ========================================================================= */ /* - * Find recipent in the ISDS. + * Find recipient in the ISDS. */ void DlgSendMessage::findAndAddRecipient(void) /* ========================================================================= */ { - QDialog *dsSearch = new DlgDsSearch(DlgDsSearch::ACT_ADDNEW, - this->recipientTableWidget, m_dbType, m_dbEffectiveOVM, - m_dbOpenAddressing, this, m_userName); + QDialog *dsSearch = NULL; + if (!m_isWebDatovkaAccount) { + dsSearch = new DlgDsSearch(DlgDsSearch::ACT_ADDNEW, + this->recipientTableWidget, m_dbType, m_dbEffectiveOVM, + m_dbOpenAddressing, this, m_userName); + } else { + dsSearch = new DlgDsSearchMojeId(DlgDsSearchMojeId::ACT_ADDNEW, + this->recipientTableWidget, m_dbType, m_dbEffectiveOVM, + this, m_userName); + } dsSearch->exec(); } - -/* ========================================================================= */ -/* - * Open attachment in default application. - */ -void DlgSendMessage::openAttachmentFile(void) -/* ========================================================================= */ +void DlgSendMessage::openSelectedAttachment(const QModelIndex &index) { - QModelIndex selectedIndex = - this->attachmentTableWidget->currentIndex(); - - Q_ASSERT(selectedIndex.isValid()); - if (!selectedIndex.isValid()) { - return; - } - - QModelIndex fileNameIndex = - selectedIndex.sibling(selectedIndex.row(), ATW_FILE); - Q_ASSERT(fileNameIndex.isValid()); - if(!fileNameIndex.isValid()) { - return; - } - QString attachName = fileNameIndex.data().toString(); - Q_ASSERT(!attachName.isEmpty()); - if (attachName.isEmpty()) { - return; - } - attachName.replace(QRegExp("\\s"), "_").replace( - QRegExp("[^a-zA-Z\\d\\.\\-_]"), "x"); - /* TODO -- Add message id into file name? */ - QString fileName = TMP_ATTACHMENT_PREFIX + attachName; - - /* Get data from base64. */ - QModelIndex dataIndex = selectedIndex.sibling(selectedIndex.row(), - ATW_DATA); - Q_ASSERT(dataIndex.isValid()); - if (!dataIndex.isValid()) { - return; - } - - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); + debugSlotCall(); - fileName = writeTemporaryFile(fileName, data); - if (!fileName.isEmpty()) { - QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); - /* TODO -- Handle openUrl() return value. */ - } else { - QMessageBox::warning(this, - tr("Error opening attachment."), - tr("Cannot write file '%1'.").arg(fileName), - QMessageBox::Ok); - } + AttachmentInteraction::openAttachment(this, *this->attachmentTableView, + index); } @@ -995,13 +1058,18 @@ bool DlgSendMessage::buildDocuments(QList &documents) const { /* Load attachments. */ - for (int i = 0; i < this->attachmentTableWidget->rowCount(); ++i) { + for (int row = 0; row < m_attachmentModel.rowCount(); ++row) { IsdsDocument document; + QModelIndex index; document.isXml = false; - document.dmFileDescr = this->attachmentTableWidget-> - item(i, ATW_FILE)->text(); + index = m_attachmentModel.index(row, DbFlsTblModel::FNAME_COL); + if (!index.isValid()) { + Q_ASSERT(0); + continue; + } + document.dmFileDescr = index.data().toString(); /* * First document must have dmFileMetaType set to @@ -1014,11 +1082,16 @@ * be filled up on the ISDS server. It allows sending files * with special mime types without recognition by application. */ - document.dmMimeType = ""; + document.dmMimeType = QStringLiteral(""); + index = + m_attachmentModel.index(row, DbFlsTblModel::CONTENT_COL); + if (!index.isValid()) { + Q_ASSERT(0); + continue; + } document.data = QByteArray::fromBase64( - this->attachmentTableWidget->item(i, ATW_DATA)-> - data(Qt::DisplayRole).toByteArray()); + index.data(Qt::DisplayRole).toByteArray()); documents.append(document); } @@ -1089,6 +1162,74 @@ return true; } + +bool DlgSendMessage::buildEnvelopeWebDatovka(JsonLayer::Envelope &envelope) const +{ + /* Set mandatory fields of envelope. */ + envelope.dmAnnotation = this->subjectText->text(); + + /* Set optional fields. */ + envelope.dmSenderIdent = this->dmSenderIdent->text(); + envelope.dmRecipientIdent = this->dmRecipientIdent->text(); + envelope.dmSenderRefNumber = this->dmSenderRefNumber->text(); + envelope.dmRecipientRefNumber = this->dmRecipientRefNumber->text(); + envelope.dmLegalTitleLaw = this->dmLegalTitleLaw->text(); + envelope.dmLegalTitleYear = this->dmLegalTitleYear->text(); + envelope.dmLegalTitleSect = this->dmLegalTitleSect->text(); + envelope.dmLegalTitlePar = this->dmLegalTitlePar->text(); + envelope.dmLegalTitlePoint = this->dmLegalTitlePoint->text(); + envelope.dmPersonalDelivery = this->dmPersonalDelivery->isChecked(); + envelope.dmPublishOwnID = this->dmPublishOwnID->isChecked(); + envelope.dmOVM = m_dbEffectiveOVM; + + /* Only OVM can change. */ + if (convertDbTypeToInt(m_dbType) > DBTYPE_OVM_REQ) { + envelope.dmAllowSubstDelivery = true; + } else { + envelope.dmAllowSubstDelivery = + this->dmAllowSubstDelivery->isChecked(); + } + + return true; +} + + +/* ========================================================================= */ +/* + * Load attachments into json for sending via webdatovka. + */ +bool DlgSendMessage::buildFileListWebDatovka(QList &fileList) + const +/* ========================================================================= */ +{ + QModelIndex index; + + for (int row = 0; row < m_attachmentModel.rowCount(); ++row) { + + index = m_attachmentModel.index(row, DbFlsTblModel::FNAME_COL); + if (!index.isValid()) { + Q_ASSERT(0); + continue; + } + + JsonLayer::File file; + file.fName = index.data().toString(); + + index = + m_attachmentModel.index(row, DbFlsTblModel::CONTENT_COL); + if (!index.isValid()) { + Q_ASSERT(0); + continue; + } + + file.fContent = index.data(Qt::DisplayRole).toByteArray(); + fileList.append(file); + } + + return true; +} + + /* ========================================================================= */ /* * Send message/multiple message. @@ -1098,6 +1239,39 @@ { debugSlotCall(); + if (m_isWebDatovkaAccount) { + + /* Get account ID */ + int accountID = getWebDatovkaAccountId(m_userName); + + /* Create recipient list. */ + JsonLayer::Recipient recipient; + QList recipientList; + for (int row = 0; row < this->recipientTableWidget->rowCount(); ++row) { + recipient.recipientDbId = + this->recipientTableWidget->item(row, RTW_ID)->text(); + recipient.toHands = this->dmToHands->text(); + recipient.recipientName = + this->recipientTableWidget->item(row, RTW_NAME)->text(); + recipient.recipientAddress = + this->recipientTableWidget->item(row, RTW_ADDR)->text(); + recipientList.append(recipient); + } + + JsonLayer::Envelope envelope; + buildEnvelopeWebDatovka(envelope); + QList fileList; + buildFileListWebDatovka(fileList); + + TaskSendMessageMojeId *task; + task = new (std::nothrow) TaskSendMessageMojeId(m_userName, accountID, + recipientList, envelope, fileList); + task->setAutoDelete(true); + globWorkPool.assignHi(task); + + return; + } + QString detailText; /* List of unique identifiers. */ @@ -1337,3 +1511,54 @@ this->recipientTableWidget->setItem(row, RTW_PDZ, item); } } + + +/* ========================================================================= */ +/* + * Slot: Performs action depending on webdatovka message send outcome. + */ +void DlgSendMessage::sendMessageMojeIdAction(const QString &userName, + const QStringList &result, const QString &error) +/* ========================================================================= */ +{ + debugSlotCall(); + + Q_UNUSED(error); + + QString detailText; + + if (result.isEmpty()) { + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Information); + msgBox.setWindowTitle(tr("Message sent")); + msgBox.setText("" + + tr("Message has successfully been sent to all recipients.") + + ""); + msgBox.setStandardButtons(QMessageBox::Ok); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.exec(); + this->accept(); /* Set return code to accepted. */ + emit doActionAfterSentMsgSignal(userName, m_lastAttAddPath); + } else { + for (int i = 0; i < result.count(); ++i) { + QString msg = result.at(i); + detailText += msg.replace("§", ": "); + } + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle(tr("Message sending error")); + msgBox.setText("" + + tr("Message has NOT been sent to all recipients.") + + ""); + detailText += "

" + + tr("Do you want to close the Send message form?") + ""; + msgBox.setInformativeText(detailText); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + if (msgBox.exec() == QMessageBox::Yes) { + this->close(); /* Set return code to closed. */ + emit doActionAfterSentMsgSignal(userName, + m_lastAttAddPath); + } + } +} diff -Nru datovka-4.7.0/src/gui/dlg_send_message.h datovka-4.7.1/src/gui/dlg_send_message.h --- datovka-4.7.0/src/gui/dlg_send_message.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_send_message.h 2017-01-19 09:29:26.000000000 +0000 @@ -27,16 +27,31 @@ #include #include #include +#include #include #include #include #include "src/common.h" +#include "src/io/message_db.h" #include "src/io/message_db_set.h" +#include "src/models/files_model.h" #include "src/worker/task.h" #include "src/worker/task_send_message.h" +#include "src/web/json.h" #include "ui_dlg_send_message.h" +/*! + * @brief Returns message prefix depending on whether it is sent ore received. + * + * @param[in] messageDb Message database. + * @param[in] dmId Message identifier number. + * @return Prefix. + * + * @todo Move this function somewhere else + * (and clean up the code of the following dialogue. + */ +const QString &dzPrefix(MessageDb *messageDb, qint64 dmId); class DlgSendMessage : public QDialog, public Ui::SendMessage { Q_OBJECT @@ -45,11 +60,12 @@ enum Action { ACT_NEW, ACT_REPLY, + ACT_FORWARD, ACT_NEW_FROM_TMP }; DlgSendMessage(const QList &messageDbSetList, - Action action, qint64 msgId, const QDateTime &deliveryTime, + Action action, const QList &msgIds, const QString &userName, class MainWindow *mv, QWidget *parent = 0); signals: @@ -61,7 +77,14 @@ void showOptionalFormAndSet(int); void addAttachmentFile(void); void deleteSelectedAttachmentFiles(void); - void openAttachmentFile(void); + + /* + * @brief Open attachment in default application. + * + * @param index Index identifying the line. If invalid index passed then + * selected item is taken from the selection model. + */ + void openSelectedAttachment(const QModelIndex &index = QModelIndex()); void addRecipientFromLocalContact(void); void deleteRecipientData(void); void findAndAddRecipient(void); @@ -72,9 +95,10 @@ const QString &transactId, int result, const QString &resultDesc, const QString &dbIDRecipient, const QString &recipientName, bool isPDZ, qint64 dmId); + void sendMessageMojeIdAction(const QString &userName, + const QStringList &result, const QString &error); void pingIsdsServer(void); void addDbIdToRecipientList(void); - void tableItemDoubleClicked(QTableWidgetItem *item); void attachmentDataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector &roles); void attachmentSelectionChanged(const QItemSelection &selected, @@ -84,11 +108,10 @@ private: QTimer m_keepAliveTimer; const QList m_messageDbSetList; - qint64 m_msgID; - QDateTime m_deliveryTime; + const QList m_msgIds; QString m_dbId; QString m_senderName; - Action m_action; + const Action m_action; QString m_userName; QString m_dbType; bool m_dbEffectiveOVM; @@ -100,6 +123,8 @@ class MainWindow *m_mv; MessageDbSet *m_dbSet; bool m_isLogged; + DbFlsTblModel m_attachmentModel; /*!< Attachment model. */ + bool m_isWebDatovkaAccount; /* Used to collect sending results. */ QSet m_transactIds; @@ -108,11 +133,14 @@ void initNewMessageDialog(void); bool calculateAndShowTotalAttachSize(void); void fillDlgAsReply(void); + void fillDlgAsForward(void); void fillDlgFromTmpMsg(void); int showInfoAboutPDZ(int pdzCnt); bool buildDocuments(QList &documents) const; bool buildEnvelope(IsdsEnvelope &envelope) const; + bool buildEnvelopeWebDatovka(JsonLayer::Envelope &envelope) const; + bool buildFileListWebDatovka(QList &fileList) const; static QString getPDZCreditFromISDS(const QString &userName, diff -Nru datovka-4.7.0/src/gui/dlg_signature_detail.cpp datovka-4.7.1/src/gui/dlg_signature_detail.cpp --- datovka-4.7.0/src/gui/dlg_signature_detail.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_signature_detail.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -39,8 +39,8 @@ /* * Constructor. */ -DlgSignatureDetail::DlgSignatureDetail(const MessageDbSet &dbSet, qint64 dmId, - const QDateTime &deliveryTime, QWidget *parent) +DlgSignatureDetail::DlgSignatureDetail(const MessageDbSet &dbSet, + const MessageDb::MsgId &msgId, QWidget *parent) /* ========================================================================= */ : QDialog(parent), m_msgDER(), @@ -50,15 +50,15 @@ dSize() { /* Obtain raw message and time stamp. */ - Q_ASSERT(dmId >= 0); - Q_ASSERT(deliveryTime.isValid()); - MessageDb *messageDb = dbSet.constAccessMessageDb(deliveryTime); + Q_ASSERT(msgId.dmId >= 0); + Q_ASSERT(msgId.deliveryTime.isValid()); + MessageDb *messageDb = dbSet.constAccessMessageDb(msgId.deliveryTime); Q_ASSERT(0 != messageDb); - if (messageDb->msgsVerificationAttempted(dmId)) { - m_msgDER = messageDb->msgsMessageRaw(dmId); + if (messageDb->msgsVerificationAttempted(msgId.dmId)) { + m_msgDER = messageDb->msgsMessageRaw(msgId.dmId); } - m_tstDER = messageDb->msgsTimestampRaw(dmId); - m_dbIsVerified = messageDb->msgsVerified(dmId); + m_tstDER = messageDb->msgsTimestampRaw(msgId.dmId); + m_dbIsVerified = messageDb->msgsVerified(msgId.dmId); setupUi(this); diff -Nru datovka-4.7.0/src/gui/dlg_signature_detail.h datovka-4.7.1/src/gui/dlg_signature_detail.h --- datovka-4.7.0/src/gui/dlg_signature_detail.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_signature_detail.h 2017-01-19 09:29:26.000000000 +0000 @@ -29,6 +29,7 @@ #include #include +#include "src/io/message_db.h" #include "src/io/message_db_set.h" #include "ui_dlg_signature_detail.h" @@ -37,8 +38,8 @@ Q_OBJECT public: - DlgSignatureDetail(const MessageDbSet &dbSet, qint64 dmId, - const QDateTime &deliveryTime, QWidget *parent = 0); + DlgSignatureDetail(const MessageDbSet &dbSet, + const MessageDb::MsgId &msgId, QWidget *parent = 0); DlgSignatureDetail(const void *msgDER, size_t msgSize, const void *tstDER, size_t tstSize, QWidget *parent = 0); diff -Nru datovka-4.7.0/src/gui/dlg_tag.cpp datovka-4.7.1/src/gui/dlg_tag.cpp --- datovka-4.7.0/src/gui/dlg_tag.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_tag.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -25,20 +25,27 @@ #include #include "src/gui/dlg_tag.h" -#include "src/io/tag_db.h" +#include "src/web/json.h" -DlgTag::DlgTag(QWidget *parent) +DlgTag::DlgTag(const QString &userName, TagDb *tagDb, + bool isWebDatovkaAccount, QWidget *parent) : QDialog(parent), + m_userName(userName), + m_tagDbPtr(tagDb), + m_isWebDatovkaAccount(isWebDatovkaAccount), m_tagItem() { setupUi(this); initDlg(); - } -DlgTag::DlgTag(const TagItem &tag, QWidget *parent) +DlgTag::DlgTag(const QString &userName, TagDb *tagDb, + bool isWebDatovkaAccount, const TagItem &tag, QWidget *parent) : QDialog(parent), + m_userName(userName), + m_tagDbPtr(tagDb), + m_isWebDatovkaAccount(isWebDatovkaAccount), m_tagItem(tag) { setupUi(this); @@ -88,17 +95,62 @@ Q_ASSERT(TagItem::isValidColourStr(m_tagItem.colour)); + JsonLayer jsLayer; + QString errStr; + QMessageBox msgBox; + msgBox.setIcon(QMessageBox::Critical); + if (m_tagItem.id >= 0) { - globTagDbPtr->updateTag(m_tagItem.id, m_tagItem.name, m_tagItem.colour); + + if (m_isWebDatovkaAccount) { + Q_ASSERT(!m_userName.isEmpty()); + if (!jsLayer.updateTag(m_userName, m_tagItem.id, + m_tagItem.name, m_tagItem.colour, errStr)) { + msgBox.setWindowTitle(tr("Tag update error")); + msgBox.setText(tr("Tag with name '%1'' wasn't " + "updated in the WebDatovka database.").arg( + m_tagItem.name)); + msgBox.setInformativeText(errStr); + msgBox.exec(); + return; + } + } + m_tagDbPtr->updateTag(m_tagItem.id, m_tagItem.name, + m_tagItem.colour); + } else { - if (!globTagDbPtr->insertTag(m_tagItem.name, m_tagItem.colour)) { - QMessageBox msgBox; - msgBox.setIcon(QMessageBox::Critical); - msgBox.setWindowTitle(tr("Tag error")); - msgBox.setText(tr("Tag with name '%1'' already " - "exists in database.").arg(m_tagItem.name)); - msgBox.setInformativeText(tr("Tag wasn't created again.")); - msgBox.exec(); + if (m_isWebDatovkaAccount) { + Q_ASSERT(!m_userName.isEmpty()); + int tagId = jsLayer.createTag(m_userName, + m_tagItem.name, m_tagItem.colour, errStr); + if (tagId <= 0) { + msgBox.setWindowTitle(tr("Tag insert error")); + msgBox.setText(tr("Tag with name '%1'' wasn't'" + " created in WebDatovka database.").arg( + m_tagItem.name)); + msgBox.setInformativeText(errStr); + msgBox.exec(); + return; + } + if (!m_tagDbPtr->insertUpdateWebDatovkaTag(tagId, + m_tagItem.name, m_tagItem.colour)) { + msgBox.setWindowTitle(tr("Tag error")); + msgBox.setText(tr("Tag with name '%1'' already " + "exists in database.").arg(m_tagItem.name)); + msgBox.setInformativeText( + tr("Tag wasn't created again.")); + msgBox.exec(); + } + } else { + if (!m_tagDbPtr->insertTag(m_tagItem.name, + m_tagItem.colour)) { + msgBox.setWindowTitle(tr("Tag error")); + msgBox.setText(tr("Tag with name '%1'' already " + "exists in database.").arg(m_tagItem.name)); + msgBox.setInformativeText( + tr("Tag wasn't created again.")); + msgBox.exec(); + } } } } diff -Nru datovka-4.7.0/src/gui/dlg_tag.h datovka-4.7.1/src/gui/dlg_tag.h --- datovka-4.7.0/src/gui/dlg_tag.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_tag.h 2017-01-19 09:29:26.000000000 +0000 @@ -21,7 +21,6 @@ * the two. */ - #ifndef _DLG_TAG_H_ #define _DLG_TAG_H_ @@ -30,6 +29,7 @@ #include "src/delegates/tag_item.h" #include "ui_dlg_tag.h" +#include "src/io/tag_db.h" /*! * @brief Create new tag dialogue. @@ -41,20 +41,26 @@ /*! * @brief Constructor. * - * @param[in] parent Parent widget. + * @param[in] userName Account user name. + * @param[in] isWebDatovka is Webdatovka account. + * @param[in] parent Parent widget. */ - explicit DlgTag(QWidget *parent = 0); + explicit DlgTag(const QString &userName, TagDb *tagDb, + bool isWebDatovkaAccount, QWidget *parent = Q_NULLPTR); /*! * @brief Constructor. * - * @param[in] tag Tag. - * @param[in] parent Parent widget. - */ - explicit DlgTag(const TagItem &tag, QWidget *parent = 0); + * @param[in] userName Account user name. + * @param[in] isWebDatovka is Webdatovka account. + * @param[in] tag Tag. + * @param[in] parent Parent widget. + */ + explicit DlgTag(const QString &userName, TagDb *tagDb, + bool isWebDatovkaAccount, const TagItem &tag, + QWidget *parent = Q_NULLPTR); private slots: - /*! * @brief Insert or update tag data into database. */ @@ -66,7 +72,6 @@ void chooseNewColor(void); private: - /*! * @brief Initialises new tag dialogue. */ @@ -77,6 +82,9 @@ */ void setPreviewButtonColor(void); + const QString m_userName; /*!< Account username. */ + TagDb *m_tagDbPtr; /*!< Tag db pointer. */ + const bool m_isWebDatovkaAccount; /*!< is WebDatovka account. */ TagItem m_tagItem; /*!< Created tag. */ }; diff -Nru datovka-4.7.0/src/gui/dlg_tags.cpp datovka-4.7.1/src/gui/dlg_tags.cpp --- datovka-4.7.0/src/gui/dlg_tags.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_tags.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -24,32 +24,42 @@ #include #include +#include "src/common.h" #include "src/delegates/tags_delegate.h" #include "src/gui/dlg_tag.h" #include "src/gui/dlg_tags.h" -#include "src/io/tag_db.h" +#include "src/io/tag_db_container.h" #include "src/models/tags_model.h" #define WRONG_TAG_ID -1 /** TODO -- Remove. */ -DlgTags::DlgTags(QWidget *parent) +DlgTags::DlgTags(const QString &userName, TagDb *tagDb, QWidget *parent) : QDialog(parent), - m_userName(), + m_userName(userName), + m_tagDbPtr(tagDb), m_msgIdList(), - m_tagsDelegate(0), - m_tagsModel(0) + m_msgIdWebDatovkaList(), + m_tagsDelegate(Q_NULLPTR), + m_tagsModel(Q_NULLPTR), + m_retCode(NO_ACTION), + m_isWebDatovkaAccount(false) { setupUi(this); initDlg(); } -DlgTags::DlgTags(const QString &userName, const QList &msgIdList, - QWidget *parent) +DlgTags::DlgTags(const QString &userName, TagDb *tagDb, + const QList &msgIdList, + const QList &msgIdWebDatovkaList, QWidget *parent) : QDialog(parent), m_userName(userName), + m_tagDbPtr(tagDb), m_msgIdList(msgIdList), - m_tagsDelegate(0), - m_tagsModel(0) + m_msgIdWebDatovkaList(msgIdWebDatovkaList), + m_tagsDelegate(Q_NULLPTR), + m_tagsModel(Q_NULLPTR), + m_retCode(NO_ACTION), + m_isWebDatovkaAccount(false) { setupUi(this); initDlg(); @@ -58,17 +68,25 @@ DlgTags::~DlgTags(void) { - if (0 != m_tagsDelegate) { + if (Q_NULLPTR != m_tagsDelegate) { delete m_tagsDelegate; } - if (0 != m_tagsModel) { + if (Q_NULLPTR != m_tagsModel) { delete m_tagsModel; } } +int DlgTags::exec(void) +{ + QDialog::exec(); + + return m_retCode; +} + void DlgTags::addTag(void) { - QDialog *tagDlg = new DlgTag(this); + QDialog *tagDlg = new DlgTag(m_userName, m_tagDbPtr, + m_isWebDatovkaAccount, this); tagDlg->exec(); tagDlg->deleteLater(); @@ -77,13 +95,19 @@ void DlgTags::updateTag(void) { - TagItem tagItem(globTagDbPtr->getTagData( + TagItem tagItem(m_tagDbPtr->getTagData( getTagIdFromIndex(tagListView->selectionModel()->currentIndex()))); - QDialog *tagDlg = new DlgTag(tagItem, this); - tagDlg->exec(); + QDialog *tagDlg = new DlgTag(m_userName, m_tagDbPtr, + m_isWebDatovkaAccount, tagItem, this); + int retVal = tagDlg->exec(); tagDlg->deleteLater(); + if (retVal == QDialog::Accepted) { + /* Existing tag has very likely just been changed. */ + m_retCode = TAGS_CHANGED; + } + fillTagsToListView(); } @@ -91,10 +115,25 @@ { QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); + if (slctIdxs.isEmpty()) { + /* Nothing to do. */ + return; + } + foreach (const QModelIndex &idx, slctIdxs) { - globTagDbPtr->deleteTag(getTagIdFromIndex(idx)); + + if (m_isWebDatovkaAccount) { + if (!m_jsonsLayer.deleteTag(m_userName, + getTagIdFromIndex(idx), m_errStr)) { + continue; + } + } + m_tagDbPtr->deleteTag(getTagIdFromIndex(idx)); } + /* Existing tags have been removed. */ + m_retCode = TAGS_CHANGED; + fillTagsToListView(); } @@ -102,36 +141,112 @@ { QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); + if (slctIdxs.isEmpty()) { + /* Nothing to do. */ + return; + } + Q_ASSERT(!m_userName.isEmpty()); - foreach (const qint64 &msgId, m_msgIdList) { - foreach (const QModelIndex &idx, slctIdxs) { - globTagDbPtr->assignTagToMsg(m_userName, - getTagIdFromIndex(idx), msgId); + if (m_isWebDatovkaAccount) { + if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { + return; + } + for (int i = 0; i < m_msgIdList.count(); ++i) { + foreach (const QModelIndex &idx, slctIdxs) { + if (!m_jsonsLayer.assignTag(m_userName, + getTagIdFromIndex(idx), + m_msgIdWebDatovkaList.at(i), m_errStr)) { + continue; + } + m_tagDbPtr->assignTagToMsg(m_userName, + getTagIdFromIndex(idx), + m_msgIdList.at(i)); + } + + } + } else { + foreach (const qint64 &msgId, m_msgIdList) { + foreach (const QModelIndex &idx, slctIdxs) { + m_tagDbPtr->assignTagToMsg(m_userName, + getTagIdFromIndex(idx), msgId); + } } } + + /* Tag assignment was changed. */ + if (m_retCode != TAGS_CHANGED) { + m_retCode = ASSIGMENT_CHANGED; + } } void DlgTags::removeSelectedTagsFromMsgs(void) { QModelIndexList slctIdxs(tagListView->selectionModel()->selectedRows()); + if (slctIdxs.isEmpty()) { + /* Nothing to do. */ + return; + } + Q_ASSERT(!m_userName.isEmpty()); - foreach (const qint64 &msgId, m_msgIdList) { - foreach (const QModelIndex &idx, slctIdxs) { - globTagDbPtr->removeTagFromMsg(m_userName, - getTagIdFromIndex(idx), msgId); + if (m_isWebDatovkaAccount) { + if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { + return; + } + for (int i = 0; i < m_msgIdList.count(); ++i) { + foreach (const QModelIndex &idx, slctIdxs) { + if (!m_jsonsLayer.removeTag(m_userName, + getTagIdFromIndex(idx), + m_msgIdWebDatovkaList.at(i), m_errStr)) { + continue; + } + m_tagDbPtr->removeTagFromMsg(m_userName, + getTagIdFromIndex(idx), m_msgIdList.at(i)); + } + + } + } else { + foreach (const qint64 &msgId, m_msgIdList) { + foreach (const QModelIndex &idx, slctIdxs) { + m_tagDbPtr->removeTagFromMsg(m_userName, + getTagIdFromIndex(idx), msgId); + } } } + + /* Tag assignment was changed. */ + if (m_retCode != TAGS_CHANGED) { + m_retCode = ASSIGMENT_CHANGED; + } } void DlgTags::removeAllTagsFromMsgs(void) { Q_ASSERT(!m_userName.isEmpty()); - foreach (const qint64 &msgId, m_msgIdList) { - globTagDbPtr->removeAllTagsFromMsg(m_userName, msgId); + if (m_isWebDatovkaAccount) { + if (m_msgIdList.count() != m_msgIdWebDatovkaList.count()) { + return; + } + for (int i = 0; i < m_msgIdList.count(); ++i) { + if (!m_jsonsLayer.removeAllTags(m_userName, + m_msgIdWebDatovkaList.at(i), m_errStr)) { + continue; + } + m_tagDbPtr->removeAllTagsFromMsg(m_userName, + m_msgIdList.at(i)); + } + } else { + foreach (const qint64 &msgId, m_msgIdList) { + m_tagDbPtr->removeAllTagsFromMsg(m_userName, msgId); + } + } + + /* Tag assignment was changed. */ + if (m_retCode != TAGS_CHANGED) { + m_retCode = ASSIGMENT_CHANGED; } } @@ -158,13 +273,15 @@ void DlgTags::fillTagsToListView(void) { - TagItemList tagList(globTagDbPtr->getAllTags()); + TagItemList tagList(m_tagDbPtr->getAllTags()); m_tagsModel->setTagList(tagList); } void DlgTags::initDlg(void) { + m_isWebDatovkaAccount = isWebDatovkaAccount(m_userName); + m_tagsDelegate = new TagsDelegate(this); m_tagsModel = new TagsModel(this); @@ -233,7 +350,7 @@ const qint64 id = getTagIdFromIndex(idx); foreach (const qint64 &msgId, m_msgIdList) { const TagItemList tags = - globTagDbPtr->getMessageTags(m_userName, msgId); + m_tagDbPtr->getMessageTags(m_userName, msgId); foreach (const TagItem &tag, tags) { if (tag.id == id) { tagListView->selectionModel()->select( diff -Nru datovka-4.7.0/src/gui/dlg_tags.h datovka-4.7.1/src/gui/dlg_tags.h --- datovka-4.7.0/src/gui/dlg_tags.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_tags.h 2017-01-19 09:29:26.000000000 +0000 @@ -28,36 +28,60 @@ #include #include "ui_dlg_tags.h" +#include "src/io/tag_db.h" +#include "src/web/json.h" /*! * @brief Tags management dialogue. */ -class DlgTags : public QDialog , public Ui::TagsDialog { +class DlgTags : public QDialog, public Ui::TagsDialog { Q_OBJECT public: /*! - * @brief Constructor. - * - * @param[in] parent Parent widget. + * Describes the action the dialogue has performed. */ - explicit DlgTags(QWidget *parent = 0); + enum ReturnCode { + NO_ACTION, /*!< Nothing happened. */ + ASSIGMENT_CHANGED, /*!< Assignment of tags to messages have changed. */ + TAGS_CHANGED /*!< Actual tags have been deleted or changed. */ + }; /*! * @brief Constructor. * * @param[in] userName Account user name. - * @param[in] msgIdList List of message ids. * @param[in] parent Parent widget. */ - explicit DlgTags(const QString &userName, - const QList &msgIdList, QWidget *parent = 0); + explicit DlgTags(const QString &userName, TagDb *tagDb, + QWidget *parent = Q_NULLPTR); + + /*! + * @brief Constructor. + * + * @param[in] userName Account user name. + * @param[in] msgIdList List of message ids. + * @param[in] msgIdWebDatovkaList List of message ids. + * @param[in] parent Parent widget. + */ + explicit DlgTags(const QString &userName, TagDb *tagDb, + const QList &msgIdList, + const QList &msgIdWebDatovkaList, QWidget *parent = Q_NULLPTR); /*! * @brief Destructor. */ ~DlgTags(void); +public slots: + /*! + * @brief Shows the dialogue as a modal dialogue. + * + * @return Method returns ReturnCode. + */ + virtual + int exec(void) Q_DECL_OVERRIDE; + private slots: /*! * @brief Add tag (insert into database). @@ -120,10 +144,19 @@ */ void selectAllAssingedTagsFromMsgs(void); - QString m_userName; /*!< Account username. */ - QList m_msgIdList; /*!< List of message identifiers. */ + const QString m_userName; /*!< Account username. */ + TagDb *m_tagDbPtr; /*!< Tag db pointer. */ + const QList m_msgIdList; /*!< List of message identifiers. */ + QList m_msgIdWebDatovkaList; /*!< List of message identifiers of WebDatovka. */ + class TagsDelegate *m_tagsDelegate; /*!< Responsible for painting. */ class TagsModel *m_tagsModel; /*!< Tags model. */ + + enum ReturnCode m_retCode; /*!< Dialogue return code. */ + bool m_isWebDatovkaAccount; /*!< is WebDatovka account. */ + + QString m_errStr; + JsonLayer m_jsonsLayer; }; #endif /* _DLG_TAGS_H_ */ diff -Nru datovka-4.7.0/src/gui/dlg_view_zfo.cpp datovka-4.7.1/src/gui/dlg_view_zfo.cpp --- datovka-4.7.0/src/gui/dlg_view_zfo.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_view_zfo.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -21,16 +21,13 @@ * the two. */ - #include -#include #include #include #include #include #include #include -#include #include "src/crypto/crypto_funcs.h" #include "src/gui/dlg_import_zfo.h" @@ -40,6 +37,7 @@ #include "src/io/filesystem.h" #include "src/io/isds_sessions.h" #include "src/log/log.h" +#include "src/model_interaction/attachment_interaction.h" #include "src/settings/preferences.h" #include "src/views/table_home_end_filter.h" @@ -49,6 +47,8 @@ m_attachmentModel(this) { setupUi(this); + /* Set default line height for table views/widgets. */ + attachmentTable->setNarrowedLineHeight(); /* Load message ZFO. */ parseZfoFile(zfoFileName); @@ -105,18 +105,18 @@ QMenu *menu = new QMenu(this); /* Detects selection of multiple attachments. */ - QModelIndexList indexes = selectedAttachmentIndexes(); + QModelIndexList indexes( + AttachmentInteraction::selectedColumnIndexes(*attachmentTable, + DbFlsTblModel::FNAME_COL)); if (index.isValid()) { - //attachmentItemSelectionChanged(index); - menu->addAction(QIcon(ICON_3PARTY_PATH "folder_16.png"), tr("Open attachment"), this, SLOT(openSelectedAttachment()))-> setEnabled(indexes.size() == 1); menu->addAction(QIcon(ICON_3PARTY_PATH "save_16.png"), tr("Save attachment"), this, - SLOT(saveSelectedAttachmentToFile()))-> + SLOT(saveSelectedAttachmentsToFile()))-> setEnabled(indexes.size() == 1); menu->addAction(QIcon(ICON_3PARTY_PATH "save_16.png"), tr("Save attachments"), this, @@ -128,159 +128,29 @@ menu->exec(QCursor::pos()); } -void DlgViewZfo::saveSelectedAttachmentToFile(void) +void DlgViewZfo::saveSelectedAttachmentsToFile(void) { - QModelIndex selectedIndex = selectedAttachmentIndex(); - - if (!selectedIndex.isValid()) { - Q_ASSERT(0); - return; - } - - QString fileName = selectedIndex.data().toString(); - if (fileName.isEmpty()) { - Q_ASSERT(0); - return; - } - /* TODO -- Remember directory? */ - fileName = QFileDialog::getSaveFileName(this, - tr("Save attachment"), fileName); + debugSlotCall(); - if (fileName.isEmpty()) { - return; - } - - QModelIndex dataIndex = selectedIndex.sibling(selectedIndex.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { - Q_ASSERT(0); - return; - } - - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); - - if (WF_SUCCESS != writeFile(fileName, data)) { - QMessageBox::warning(this, - tr("Error saving attachment."), - tr("Cannot write file '%1'.").arg(fileName), - QMessageBox::Ok); - } + AttachmentInteraction::saveAttachmentsToFile(this, *attachmentTable); } void DlgViewZfo::saveSelectedAttachmentsIntoDirectory(void) { - QModelIndexList selectedIndexes = selectedAttachmentIndexes(); - - if (selectedIndexes.isEmpty()) { - Q_ASSERT(0); - return; - } - - QString newDir = QFileDialog::getExistingDirectory(this, - tr("Save attachments"), NULL, - QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); - - if (newDir.isNull() || newDir.isEmpty()) { - return; - } - /* TODO -- Remember directory? */ - - bool unspecifiedFailed = false; - QList unsuccessfullFiles; - - foreach (QModelIndex idx, selectedIndexes) { - if (!idx.isValid()) { - Q_ASSERT(0); - unspecifiedFailed = true; - continue; - } - - QString fileName = idx.data().toString(); - if (fileName.isEmpty()) { - Q_ASSERT(0); - unspecifiedFailed = true; - continue; - } - - fileName = newDir + QDir::separator() + fileName; - - QModelIndex dataIndex = idx.sibling(idx.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { - Q_ASSERT(0); - continue; - } - - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); + debugSlotCall(); - if (WF_SUCCESS != writeFile(fileName, data)) { - unsuccessfullFiles.append(fileName); - continue; - } - } - - if (unspecifiedFailed) { - QMessageBox::warning(this, - tr("Error saving attachments."), - tr("Could not save all attachments."), - QMessageBox::Ok); - } else if (!unsuccessfullFiles.isEmpty()) { - QString warnMsg = - tr("In total %1 attachment files could not be written.") - .arg(unsuccessfullFiles.size()); - warnMsg += "\n" + - tr("These are:").arg(unsuccessfullFiles.size()) + "\n"; - int i; - for (i = 0; i < (unsuccessfullFiles.size() - 1); ++i) { - warnMsg += " '" + unsuccessfullFiles.at(i) + "'\n"; - } - warnMsg += " '" + unsuccessfullFiles.at(i) + "'."; - QMessageBox::warning(this, tr("Error saving attachments."), - warnMsg, QMessageBox::Ok); - } + AttachmentInteraction::saveAttachmentsToDirectory(this, + *this->attachmentTable, + AttachmentInteraction::selectedColumnIndexes(*attachmentTable, + DbFlsTblModel::FNAME_COL)); } -void DlgViewZfo::openSelectedAttachment(void) +void DlgViewZfo::openSelectedAttachment(const QModelIndex &index) { - QModelIndex selectedIndex = selectedAttachmentIndex(); - - if (!selectedIndex.isValid()) { - Q_ASSERT(0); - return; - } + debugSlotCall(); - QString attachName = selectedIndex.data().toString(); - if (attachName.isEmpty()) { - Q_ASSERT(0); - return; - } - attachName.replace(QRegExp("\\s"), "_").replace( - QRegExp("[^a-zA-Z\\d\\.\\-_]"), "x"); - /* TODO -- Add message id into file name? */ - QString fileName = TMP_ATTACHMENT_PREFIX + attachName; - - QModelIndex dataIndex = selectedIndex.sibling(selectedIndex.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { - Q_ASSERT(0); - return; - } - - QByteArray data = - QByteArray::fromBase64(dataIndex.data().toByteArray()); - - fileName = writeTemporaryFile(fileName, data); - if (!fileName.isEmpty()) { - QDesktopServices::openUrl(QUrl::fromLocalFile(fileName)); - /* TODO -- Handle openUrl() return value. */ - } else { - QMessageBox::warning(this, - tr("Error opening attachment."), - tr("Cannot write file '%1'.").arg(fileName), - QMessageBox::Ok); - } + AttachmentInteraction::openAttachment(this, *this->attachmentTable, + index); } void DlgViewZfo::showSignatureDetails(void) @@ -368,6 +238,7 @@ this->attachmentTable->setEnabled(true); this->attachmentTable->show(); m_attachmentModel.setMessage(m_message); + m_attachmentModel.setHeader(); envelopeTextEdit->setHtml( messageDescriptionHtml(m_attachmentModel.rowCount(), m_message->raw, m_message->raw_length, @@ -384,6 +255,10 @@ true); attachmentTable->setColumnHidden(DbFlsTblModel::CONTENT_COL, true); + attachmentTable->setColumnHidden(DbFlsTblModel::MIME_COL, + true); + attachmentTable->setColumnHidden(DbFlsTblModel::FPATH_COL, + true); attachmentTable->resizeColumnToContents( DbFlsTblModel::FNAME_COL); @@ -391,7 +266,7 @@ connect(attachmentTable, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(attachmentItemRightClicked(QPoint))); connect(attachmentTable, SIGNAL(doubleClicked(QModelIndex)), - this, SLOT(openSelectedAttachment())); + this, SLOT(openSelectedAttachment(QModelIndex))); attachmentTable->installEventFilter(new TableHomeEndFilter(this)); } @@ -401,35 +276,6 @@ SLOT(showSignatureDetails())); } -QModelIndex DlgViewZfo::selectedAttachmentIndex(void) const -{ - if (0 == attachmentTable->selectionModel()) { - Q_ASSERT(0); - return QModelIndex(); - } - - QModelIndex selectedIndex = - attachmentTable->selectionModel()->currentIndex(); - - if (!selectedIndex.isValid()) { - Q_ASSERT(0); - return QModelIndex(); - } - - return selectedIndex.sibling(selectedIndex.row(), - DbFlsTblModel::FNAME_COL); -} - -QModelIndexList DlgViewZfo::selectedAttachmentIndexes(void) const -{ - if (0 == attachmentTable->selectionModel()) { - Q_ASSERT(0); - return QModelIndexList(); - } - - return attachmentTable->selectionModel()->selectedRows(0); -} - QString DlgViewZfo::messageDescriptionHtml(int attachmentCount, const void *msgDER, size_t msgSize, const void *tstDER, size_t tstSize) const diff -Nru datovka-4.7.0/src/gui/dlg_view_zfo.h datovka-4.7.1/src/gui/dlg_view_zfo.h --- datovka-4.7.0/src/gui/dlg_view_zfo.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/dlg_view_zfo.h 2017-01-19 09:29:26.000000000 +0000 @@ -73,7 +73,7 @@ /*! * @brief Saves selected attachment to file. */ - void saveSelectedAttachmentToFile(void); + void saveSelectedAttachmentsToFile(void); /*! * @brief Saves selected attachments to directory. @@ -83,7 +83,7 @@ /*! * @brief Open attachment in default application. */ - void openSelectedAttachment(void); + void openSelectedAttachment(const QModelIndex &index = QModelIndex()); /*! * @brief View signature details. @@ -111,16 +111,6 @@ void setUpDialogue(void); /*! - * @brief Returns selected attachment index. - */ - QModelIndex selectedAttachmentIndex(void) const; - - /*! - * @brief Returns all selected indexes. - */ - QModelIndexList selectedAttachmentIndexes(void) const; - - /*! * @brief Generate description from supplied message. * * @param[in] attachmentCount Number of attached files. diff -Nru datovka-4.7.0/src/gui/ui/datovka.ui datovka-4.7.1/src/gui/ui/datovka.ui --- datovka-4.7.0/src/gui/ui/datovka.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/datovka.ui 2017-01-19 09:29:26.000000000 +0000 @@ -80,9 +80,6 @@ QAbstractScrollArea::AdjustToContents - - 1 - 100 @@ -135,10 +132,13 @@ Qt::Vertical - + false + + false + false @@ -151,9 +151,6 @@ false - - 20 - false @@ -338,6 +335,9 @@ false + + false + false @@ -347,9 +347,6 @@ false - - 20 - false @@ -383,6 +380,7 @@ + @@ -429,6 +427,7 @@ + @@ -538,6 +537,9 @@ Add new account + + Add new data box account + QAction::NoRole @@ -568,6 +570,9 @@ Proxy settings + + Proxy settings + QAction::NoRole @@ -595,6 +600,9 @@ Quit + + Quit the application + Ctrl+Q @@ -610,6 +618,9 @@ Create account from database + + Create account from database + QAction::NoRole @@ -658,6 +669,9 @@ Mark all as read + + Mark all messages as read + QAction::NoRole @@ -763,22 +777,13 @@ User manual + + User manual + QAction::NoRole - - - - :/icons/3party/present_16.png:/icons/3party/present_16.png - - - Datovka update - - - Update Datovka application - - @@ -787,6 +792,9 @@ Find Data Box + + Find data box + QAction::NoRole @@ -799,6 +807,9 @@ Authenticate message file + + Verify message authenticity + QAction::NoRole @@ -811,6 +822,9 @@ View message from ZFO file + + View content of a ZFO file + QAction::NoRole @@ -823,6 +837,9 @@ Export correspondence overview + + Create a correspondence overview + QAction::NoRole @@ -1035,6 +1052,9 @@ Import messages from ZFO files + + Import a message from ZFO file into the database + QAction::NoRole @@ -1042,7 +1062,7 @@ - :/icons/16x16/datovka-message.png:/icons/16x16/datovka-message.png + :/icons/16x16/datovka.png:/icons/16x16/datovka.png Use message as template @@ -1080,6 +1100,9 @@ Time stamp expiration check + + Check whether the message time stamp is not expired or expiring + QAction::NoRole @@ -1092,6 +1115,9 @@ Homepage + + Open the home page of the application + QAction::NoRole @@ -1104,6 +1130,9 @@ Import messages from database + + Import messages into database from an external database file + QAction::NoRole @@ -1116,6 +1145,9 @@ Split database by years + + Messages are going to be stored into separate database files according to years + QAction::NoRole @@ -1149,6 +1181,9 @@ Creates an e-mail containing selected attachments + + QAction::NoRole + @@ -1158,6 +1193,9 @@ Edit tags + + Edit tags + QAction::NoRole @@ -1170,6 +1208,39 @@ Vacuum message database + + This may reduce the database file size and optimise the access speed + + + QAction::NoRole + + + + + + :/icons/16x16/datovka.png:/icons/16x16/datovka.png + + + Forward message + + + Forward message + + + QAction::NoRole + + + + + + :/mojeid.png:/mojeid.png + + + Add mojeID account + + + Add new mojeID account + QAction::NoRole @@ -1181,6 +1252,11 @@ QTableView
attachment_table_view.h
+ + LoweredTableView + QTableView +
lowered_table_view.h
+
diff -Nru datovka-4.7.0/src/gui/ui/dlg_contacts.ui datovka-4.7.1/src/gui/ui/dlg_contacts.ui --- datovka-4.7.0/src/gui/ui/dlg_contacts.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_contacts.ui 2017-01-19 09:29:26.000000000 +0000 @@ -51,7 +51,7 @@ - + QAbstractItemView::AnyKeyPressed|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed|QAbstractItemView::SelectedClicked @@ -64,6 +64,9 @@ true + + false + false @@ -73,15 +76,9 @@ false - - 18 - false - - 18 - @@ -116,6 +113,13 @@
+ + + LoweredTableWidget + QTableWidget +
lowered_table_widget.h
+
+
diff -Nru datovka-4.7.0/src/gui/ui/dlg_ds_search.ui datovka-4.7.1/src/gui/ui/dlg_ds_search.ui --- datovka-4.7.0/src/gui/ui/dlg_ds_search.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_ds_search.ui 2017-01-19 09:29:26.000000000 +0000 @@ -176,7 +176,7 @@
- + false @@ -189,6 +189,9 @@ true + + false + false @@ -198,15 +201,9 @@ false - - 18 - false - - 18 - @@ -251,6 +248,13 @@ + + + LoweredTableWidget + QTableWidget +
lowered_table_widget.h
+
+
diff -Nru datovka-4.7.0/src/gui/ui/dlg_login_mojeid.ui datovka-4.7.1/src/gui/ui/dlg_login_mojeid.ui --- datovka-4.7.0/src/gui/ui/dlg_login_mojeid.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_login_mojeid.ui 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,261 @@ + + + LoginToMojeId + + + + 0 + 0 + 413 + 322 + + + + + 0 + 0 + + + + + 16777215 + 322 + + + + Add a new mojeID account(s) + + + + :/icons/3party/plus_16.png:/icons/3party/plus_16.png + + + + + + + + + + + :/mojeid.png + + + + + + + Please select login method and enter credentials for mojeID. + + + Qt::AlignCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Qt::Horizontal + + + + + + + Login method: + + + + + + + Select authorization method for login into your databox + + + + + + + Username: + + + + + + + Enter your username + + + + + + + Password: + + + + + + + Enter your password + + + QLineEdit::Password + + + + + + + Qt::Horizontal + + + + + + + Certificate file: + + + + + + + + + Select a certificate + + + Add + + + + :/icons/3party/plus_16.png:/icons/3party/plus_16.png + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + + + + Security code (OTP): + + + + + + + + + Qt::Horizontal + + + + + + + Account will be included into synchronisation +process of all accounts on the background + + + Synchronise account(s) when "Synchronise all" is activated + + + true + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + accountButtonBox + accepted() + LoginToMojeId + accept() + + + 248 + 254 + + + 157 + 274 + + + + + accountButtonBox + rejected() + LoginToMojeId + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff -Nru datovka-4.7.0/src/gui/ui/dlg_msg_search.ui datovka-4.7.1/src/gui/ui/dlg_msg_search.ui --- datovka-4.7.0/src/gui/ui/dlg_msg_search.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_msg_search.ui 2017-01-19 09:29:26.000000000 +0000 @@ -355,7 +355,7 @@ - + false @@ -386,15 +386,9 @@ false - - 18 - false - - 18 - @@ -409,6 +403,13 @@ + + + LoweredTableWidget + QTableWidget +
lowered_table_widget.h
+
+
diff -Nru datovka-4.7.0/src/gui/ui/dlg_preferences.ui datovka-4.7.1/src/gui/ui/dlg_preferences.ui --- datovka-4.7.0/src/gui/ui/dlg_preferences.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_preferences.ui 2017-01-19 09:29:26.000000000 +0000 @@ -35,9 +35,6 @@ Qt::ElideNone - - false - false @@ -930,7 +927,7 @@ - Note: toolbar setting will not apllied until you restart the application. + Note: toolbar settings will not be applied until you restart the application. @@ -1877,7 +1874,7 @@ - Note: language setting will not apllied until you restart the application. + Note: language settings will not be applied until you restart the application. diff -Nru datovka-4.7.0/src/gui/ui/dlg_proxysets.ui datovka-4.7.1/src/gui/ui/dlg_proxysets.ui --- datovka-4.7.0/src/gui/ui/dlg_proxysets.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_proxysets.ui 2017-01-19 09:29:26.000000000 +0000 @@ -122,10 +122,10 @@ - Manual proxy setting + Manual proxy settings - Manual proxy setting + Manual proxy settings @@ -336,10 +336,10 @@ - Manual proxy setting + Manual proxy settings - Manual proxy setting + Manual proxy settings diff -Nru datovka-4.7.0/src/gui/ui/dlg_search_mojeid.ui datovka-4.7.1/src/gui/ui/dlg_search_mojeid.ui --- datovka-4.7.0/src/gui/ui/dlg_search_mojeid.ui 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_search_mojeid.ui 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,200 @@ + + + DsSearchMojeId + + + + 0 + 0 + 514 + 365 + + + + Search recipient + + + + :/icons/3party/plus_16.png:/icons/3party/plus_16.png + + + + + + + + Current account: + + + + + + + n/a + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + + + + + QFormLayout::AllNonFixedFieldsGrow + + + + + Keyword: + + + + + + + + + + + + false + + + Search + + + + :/icons/3party/search_16.png:/icons/3party/search_16.png + + + + + + + Qt::Horizontal + + + + + + + false + + + QAbstractItemView::SelectRows + + + false + + + true + + + false + + + true + + + false + + + 18 + + + false + + + 18 + + + + + + + + + ID + + + + + Name + + + + + Address + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + + + + buttonBox + accepted() + DsSearchMojeId + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DsSearchMojeId + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff -Nru datovka-4.7.0/src/gui/ui/dlg_send_message.ui datovka-4.7.1/src/gui/ui/dlg_send_message.ui --- datovka-4.7.0/src/gui/ui/dlg_send_message.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_send_message.ui 2017-01-19 09:29:26.000000000 +0000 @@ -492,7 +492,7 @@ - + QAbstractItemView::SelectRows @@ -502,12 +502,12 @@ true + + false + false - - 1 - true @@ -517,15 +517,9 @@ false - - 18 - false - - 18 - Id @@ -750,7 +744,7 @@ - + QAbstractItemView::SelectRows @@ -760,14 +754,14 @@ true + + false + false - - 1 - - true + false true @@ -775,57 +769,6 @@ false - - 18 - - - false - - - 18 - - - - File - - - File name - - - - - Type - - - - - MimeType - - - MIME type of file - - - - - Size - - - Size of file in bytes - - - - - FilePath - - - Absolute path of file - - - - - Base64 - - @@ -900,9 +843,14 @@ - AttachmentTableWidget + AttachmentTableView + QTableView +
attachment_table_view.h
+
+ + LoweredTableWidget QTableWidget -
attachment_table_widget.h
+
lowered_table_widget.h
@@ -929,7 +877,7 @@ removeAttachment openAttachment recipientTableWidget - attachmentTableWidget + attachmentTableView diff -Nru datovka-4.7.0/src/gui/ui/dlg_view_zfo.ui datovka-4.7.1/src/gui/ui/dlg_view_zfo.ui --- datovka-4.7.0/src/gui/ui/dlg_view_zfo.ui 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/gui/ui/dlg_view_zfo.ui 2017-01-19 09:29:26.000000000 +0000 @@ -30,6 +30,9 @@ false + + false + false @@ -39,9 +42,6 @@ false - - 18 - false diff -Nru datovka-4.7.0/src/io/dbs.cpp datovka-4.7.1/src/io/dbs.cpp --- datovka-4.7.0/src/io/dbs.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/dbs.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -41,9 +41,10 @@ const QString dbDateTimeFormat("yyyy-MM-dd HH:mm:ss.zzz"); static const QString dbShortDateTimeFormat("yyyy-MM-dd HH:mm:ss"); - static const QString dbDateFormat("yyyy-MM-dd"); +static +const QString dbDateIsoFormat("yyyy-MM-ddThh:mm:ss.zzzZ"); /* ========================================================================= */ @@ -140,7 +141,6 @@ return ret; } - /* ========================================================================= */ /* * Converts time to QDateTime. @@ -224,3 +224,26 @@ return ret; } + + +/* ========================================================================= */ +/* + * Converts iso datetime to format to be stored in database. + */ +QString fromIsoDatetimetoDbformat(const QString &dateTimeStr) +/* ========================================================================= */ +{ + QDateTime dateTime = QDateTime::fromString(dateTimeStr, dbDateIsoFormat); + return dateTime.toString(dbDateTimeFormat); +} + + +/* ========================================================================= */ +/* + * Converts iso datetime to datetime. + */ +QDateTime fromIsoDatetimetoDateTime(const QString &dateTimeStr) +/* ========================================================================= */ +{ + return QDateTime::fromString(dateTimeStr, dbDateIsoFormat); +} diff -Nru datovka-4.7.0/src/io/dbs.h datovka-4.7.1/src/io/dbs.h --- datovka-4.7.0/src/io/dbs.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/dbs.h 2017-01-19 09:29:26.000000000 +0000 @@ -85,5 +85,14 @@ */ QString qDateTimeToDbFormat(const QDateTime &dateTime); +/*! + * @brief Converts iso datetime to format to be stored in database. + */ +QString fromIsoDatetimetoDbformat(const QString &dateTimeStr); + +/*! + * @brief Converts iso datetime to datetime. + */ +QDateTime fromIsoDatetimetoDateTime(const QString &dateTimeStr); #endif /* _DBS_H_ */ diff -Nru datovka-4.7.0/src/io/message_db.cpp datovka-4.7.1/src/io/message_db.cpp --- datovka-4.7.0/src/io/message_db.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/message_db.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -54,6 +54,10 @@ #include "src/log/log.h" #include "src/settings/preferences.h" +/* Attachment size is computed from actual data. */ +static +const QVector fileItemIdsNoSize = {"id", "message_id", + "dmEncodedContent", "_dmFileDescr", "_dmMimeType", "0"}; const QVector MessageDb::msgPrintedAttribs = {"dmSenderIdent", "dmSenderRefNumber", "dmRecipientIdent", "dmRecipientRefNumber", @@ -67,12 +71,8 @@ "dmAcceptanceTime", "dmMessageStatus"}; const QVector MessageDb::fileItemIds = {"id", "message_id", - "dmEncodedContent", "_dmFileDescr", "LENGTH(dmEncodedContent)"}; - -/* Attachment size is computed from actual data. */ -static -const QVector fileItemIdsNoData = {"id", "message_id", - "dmEncodedContent", "_dmFileDescr", "0"}; + "dmEncodedContent", "_dmFileDescr", "_dmMimeType", + "LENGTH(dmEncodedContent)"}; MessageDb::MessageDb(const QString &connectionName) : SQLiteDb(connectionName), @@ -587,6 +587,34 @@ return PartialEnvelopeData(); } +int MessageDb::msgMessageType(qint64 dmId) const +{ + QSqlQuery query(m_db); + QString queryStr; + + queryStr = "SELECT " + "message_type" + " FROM supplementary_message_data WHERE " + "message_id = :dmId"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + goto fail; + } + query.bindValue(":dmId", dmId); + if (query.exec() && query.isActive() && + query.first() && query.isValid()) { + return query.value(0).toInt(); + } else { + logErrorNL( + "Cannot execute SQL query and/or read SQL data: %s.", + query.lastError().text().toUtf8().constData()); + goto fail; + } + +fail: + return -1; +} /* ========================================================================= */ /* @@ -1791,10 +1819,10 @@ int i; QSqlQuery query(m_db); QString queryStr = "SELECT "; - for (i = 0; i < (fileItemIdsNoData.size() - 1); ++i) { - queryStr += fileItemIdsNoData[i] + ", "; + for (i = 0; i < (fileItemIdsNoSize.size() - 1); ++i) { + queryStr += fileItemIdsNoSize[i] + ", "; } - queryStr += fileItemIdsNoData.last(); + queryStr += fileItemIdsNoSize.last(); queryStr += " FROM files WHERE " "message_id = :msgId"; if (!query.prepare(queryStr)) { @@ -1812,20 +1840,7 @@ /* First three columns ought to be hidden. */ m_sqlFilesModel.setQuery(query); - for (i = 0; i < fileItemIds.size(); ++i) { - /* Description. */ - m_sqlFilesModel.setHeaderData(i, Qt::Horizontal, - flsTbl.attrProps.value(fileItemIds[i]).desc, - Qt::DisplayRole); - /* Data type. */ - m_sqlFilesModel.setHeaderData(i, Qt::Horizontal, - flsTbl.attrProps.value(fileItemIds[i]).type, - ROLE_MSGS_DB_ENTRY_TYPE); - } - - /* Rename last column to file size. */ - m_sqlFilesModel.setHeaderData(i - 1, Qt::Horizontal, - QObject::tr("File Size"), Qt::DisplayRole); + m_sqlFilesModel.setHeader(); return &m_sqlFilesModel; @@ -2495,7 +2510,6 @@ } } - //qDebug() << queryStr; /* prepare query string */ if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", @@ -2571,7 +2585,6 @@ queryStr += "m.dmID LIKE '%'||:dmId||'%'"; - //qDebug() << queryStr; /* prepare query string */ if (!query.prepare(queryStr)) { logErrorNL("Cannot prepare SQL query: %s.", @@ -2590,8 +2603,6 @@ } } - //qDebug() << queryStr; - if (query.exec() && query.isActive() && query.first() && query.isValid()) { while (query.isValid()) { @@ -3504,6 +3515,33 @@ } +/* ========================================================================= */ +/* + * Get id of message in webdatovka db form ISDS msgId. + */ +int MessageDb::getWebDatokaId(qint64 msgId) +/* ========================================================================= */ +{ + QSqlQuery query(m_db); + QString queryStr = "SELECT _origin FROM messages WHERE dmID = :dmId"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return -1; + } + query.bindValue(":dmId", msgId); + if (query.exec() && query.isActive() && + query.first() && query.isValid()) { + return query.value(0).toInt(); + } else { + logErrorNL( + "Cannot execute SQL query and/or read SQL data: %s.", + query.lastError().text().toUtf8().constData()); + return -1; + } +} + + /* ========================================================================= */ /* * Insert raw (DER) delivery info into raw_delivery_info_data table. diff -Nru datovka-4.7.0/src/io/message_db.h datovka-4.7.1/src/io/message_db.h --- datovka-4.7.0/src/io/message_db.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/message_db.h 2017-01-19 09:29:26.000000000 +0000 @@ -90,6 +90,24 @@ ~MsgId(void) { } + MsgId &operator=(const MsgId &other) Q_DECL_NOTHROW + { + dmId = other.dmId; + deliveryTime = other.deliveryTime; + return *this; + } + +#ifdef Q_COMPILER_RVALUE_REFS + inline + MsgId &operator=(MsgId &&other) Q_DECL_NOTHROW + { + /* qSwap() is obsolete */ + std::swap(dmId, other.dmId); + std::swap(deliveryTime, other.deliveryTime); + return *this; + } +#endif /* Q_COMPILER_RVALUE_REFS */ + bool isValid(void) const { return (dmId >= 0) && (deliveryTime.isValid()); @@ -110,6 +128,11 @@ SoughtMsg(void) : mId(), type(0), dmAnnotation(), dmSender(), dmRecipient() { } + SoughtMsg(const SoughtMsg &msg) + : mId(msg.mId), type(msg.type), + dmAnnotation(msg.dmAnnotation), dmSender(msg.dmSender), + dmRecipient(msg.dmRecipient) + { } SoughtMsg(const MsgId &id, int t, const QString &annot, const QString &sen, const QString &rec) : mId(id), type(t), dmAnnotation(annot), @@ -124,6 +147,30 @@ ~SoughtMsg(void) { } + SoughtMsg &operator=(const SoughtMsg &other) Q_DECL_NOTHROW + { + mId = other.mId; + type = other.type; + dmAnnotation = other.dmAnnotation; + dmSender = other.dmSender; + dmRecipient = other.dmRecipient; + return *this; + } + +#ifdef Q_COMPILER_RVALUE_REFS + inline + SoughtMsg &operator=(SoughtMsg &&other) Q_DECL_NOTHROW + { + /* qSwap() is obsolete */ + std::swap(mId, other.mId); + std::swap(type, other.type); + std::swap(dmAnnotation, other.dmAnnotation); + std::swap(dmSender, other.dmSender); + std::swap(dmRecipient, other.dmRecipient); + return *this; + } +#endif /* Q_COMPILER_RVALUE_REFS */ + bool isValid(void) const { return mId.isValid() && @@ -238,6 +285,14 @@ PartialEnvelopeData msgsReplyData(qint64 dmId) const; /*! + * @brief Return message type (sent or received). + * + * @param[in] dmId Message id. + * @return Message type value, negative value on error. + */ + int msgMessageType(qint64 dmId) const; + + /*! * @brief Returns true if verification attempt was performed. * * @param[in] dmId Message id. @@ -659,6 +714,14 @@ bool copyRelevantMsgsToNewDb(const QString &newDbFileName, const QString &year); + /*! + * @brief Get id of message in webdatovka db form ISDS msgId. + * + * @param[in] msgId Message identifier. + * @return Internal id of message in webdatovka db. + */ + int getWebDatokaId(qint64 msgId); + protected: /* These function are used from within a database container. */ /*! * @brief Return all received messages model. @@ -966,6 +1029,10 @@ DbMsgsTblModel m_sqlMsgsModel; /*!< Model of displayed messages. */ +public: + static + const QVector fileItemIds; + private: static const QVector msgPrintedAttribs; @@ -973,8 +1040,6 @@ const QVector msgDeliveryBoolAttribs; static const QVector msgStatus; - static - const QVector fileItemIds; DbFlsTblModel m_sqlFilesModel; /*!< Model of displayed files. */ diff -Nru datovka-4.7.0/src/io/tag_db_container.cpp datovka-4.7.1/src/io/tag_db_container.cpp --- datovka-4.7.0/src/io/tag_db_container.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/io/tag_db_container.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#include +#include +#include + +#include "src/io/tag_db_container.h" +#include "src/models/accounts_model.h" +#include "src/settings/preferences.h" + +/* ========================================================================= */ +TagDbContainer::TagDbContainer(const QString &connectionName) +/* ========================================================================= */ + : QMap(), + m_connectionName(connectionName) +{ +} + + +/* ========================================================================= */ +TagDbContainer::~TagDbContainer(void) +/* ========================================================================= */ +{ + QMap::iterator i; + + for (i = this->begin(); i != this->end(); ++i) { + delete i.value(); + } +} + +/* ========================================================================= */ +/* + * Access/create+open message database related to item. + */ +TagDb *TagDbContainer::accessTagDb(const QString &key) +/* ========================================================================= */ +{ + TagDb *db = NULL; + bool open_ret; + + QString dbTagName = constructDbTagName(key); + + + /* Already opened. */ + if (this->find(dbTagName) != this->end()) { + return (*this)[dbTagName]; + } + + db = new(std::nothrow) TagDb(dbTagName); + if (NULL == db) { + Q_ASSERT(0); + return NULL; + } + + open_ret = db->openDb(dbTagName); + if (!open_ret) { + delete db; + return NULL; + } + + this->insert(dbTagName, db); + + return db; +} + + +/* ========================================================================= */ +/* + * Delete message db. + */ +bool TagDbContainer::deleteDb(TagDb *db) +/* ========================================================================= */ +{ + if (0 == db) { + Q_ASSERT(0); + return false; + } + + /* Find entry. */ + QMap::iterator it = this->begin(); + while ((it != this->end()) && (it.value() != db)) { + ++it; + } + /* Must exist. */ + if (this->end() == it) { + Q_ASSERT(0); + return false; + } + + /* Remove from container. */ + this->erase(it); + + /* Get file name. */ + QString fileName = db->fileName(); + + /* Close database. */ + delete db; + + if (fileName == TagDb::memoryLocation) { + return true; + } + + /* Delete file. */ + if (!QFile::remove(fileName)) { + return false; + } + + return true; +} + + +/* ========================================================================= */ +/* + * Creates the database name from supplied information. + */ +QString TagDbContainer::constructDbTagName(const QString &primaryKey) +/* ========================================================================= */ +{ + /* get current db file location */ + AcntSettings &itemSettings(AccountModel::globAccounts[primaryKey]); + QString dbDir = itemSettings.dbDir(); + if (dbDir.isEmpty()) { + dbDir = globPref.confDir(); + } + + return dbDir + QDir::separator() + primaryKey + "-tag.db"; +} + + +TagDbContainer * globWebDatovkaTagDbPtr = 0; diff -Nru datovka-4.7.0/src/io/tag_db_container.h datovka-4.7.1/src/io/tag_db_container.h --- datovka-4.7.0/src/io/tag_db_container.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/io/tag_db_container.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TAG_DB_CONTAINER_H_ +#define _TAG_DB_CONTAINER_H_ + + +#include +#include + +#include "src/io/tag_db.h" + +/*! + * @brief Database container. + * + * TODO -- Should there be a single globally accessible instance? + * (Actually no singleton.) + */ +class TagDbContainer : private QMap { +public: + explicit TagDbContainer(const QString &connectionName); + ~TagDbContainer(void); + + /*! + * @brief Access/create+open message database set related to item. + * + * @param[in] primaryKey Part of database file name, usually the login. + * @return Pointer to database, zero pointer on error. + */ + TagDb *accessTagDb(const QString &key); + + /*! + * @brief Delete tag database. + * + * @param db Deleted database. + * @return True on success. + */ + bool deleteDb(TagDb *db); + + /*! + * @brief Creates the database name from supplied information. + * + * @param[in] key user name. + * @return Path to database file. + */ + static + QString constructDbTagName(const QString &key); + + const QString m_connectionName; +}; + +/*! + * @brief Global database container. + */ +extern TagDbContainer * globWebDatovkaTagDbPtr; + +#endif /* _TAG_DB_CONTAINER_H_ */ diff -Nru datovka-4.7.0/src/io/tag_db.cpp datovka-4.7.1/src/io/tag_db.cpp --- datovka-4.7.0/src/io/tag_db.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/tag_db.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -83,6 +83,34 @@ return true; } +bool TagDb::insertUpdateWebDatovkaTag(int id, + const QString &tagName, const QString &tagColor) +{ + QSqlQuery query(m_db); + + QString queryStr = "INSERT OR REPLACE INTO tag (id, tag_name, tag_color) " + "VALUES (:tag_id, :tag_name, :tag_color)"; + + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + query.bindValue(":tag_id", id); + query.bindValue(":tag_name", tagName); + query.bindValue(":tag_color", tagColor); + + if (!query.exec()) { + logErrorNL("Cannot execute SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; +} + + bool TagDb::updateTag(int id, const QString &tagName, const QString &tagColor) { QSqlQuery query(m_db); @@ -142,6 +170,27 @@ return true; } + +bool TagDb::deleteAllTags(void) +{ + QSqlQuery query(m_db); + + QString queryStr = "DELETE FROM tag"; + if (!query.prepare(queryStr)) { + logErrorNL("Cannot prepare SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + if (!query.exec()) { + logErrorNL("Cannot execute SQL query: %s.", + query.lastError().text().toUtf8().constData()); + return false; + } + + return true; +} + + TagItem TagDb::getTagData(int id) { QSqlQuery query(m_db); diff -Nru datovka-4.7.0/src/io/tag_db.h datovka-4.7.1/src/io/tag_db.h --- datovka-4.7.0/src/io/tag_db.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/io/tag_db.h 2017-01-19 09:29:26.000000000 +0000 @@ -61,6 +61,17 @@ bool insertTag(const QString &tagName, const QString &tagColor); /*! + * @brief Insert new or update webdatovka tag into database file. + * + * @param[in] id id of tag form webdatovka. + * @param[in] tagName text label of tag. + * @param[in] tagColor color of tag in HEX format. + * @return True on success, false on any error. + */ + bool insertUpdateWebDatovkaTag(int id, const QString &tagName, + const QString &tagColor); + + /*! * @brief Update tag in database file. * * @param[in] id id of tag. @@ -79,6 +90,13 @@ bool deleteTag(int id); /*! + * @brief Delete all tags from database file. + * + * @return True on success, false on any error. + */ + bool deleteAllTags(void); + + /*! * @brief Get tag data from database file. * * @param[in] id id of tag. diff -Nru datovka-4.7.0/src/io/wd_sessions.cpp datovka-4.7.1/src/io/wd_sessions.cpp --- datovka-4.7.0/src/io/wd_sessions.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/io/wd_sessions.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#include +#include + +#include "src/io/wd_sessions.h" +#include "src/log/log.h" + +GlobWDSessions wdSessions; + +/* ========================================================================= */ +GlobWDSessions::GlobWDSessions(void) +/* ========================================================================= */ + : m_wdSessions() +{ +} + + +/* ========================================================================= */ +GlobWDSessions::~GlobWDSessions(void) +/* ========================================================================= */ +{ + m_wdSessions.clear(); +} + + +/* ========================================================================= */ +bool GlobWDSessions::holdsSession(const QString &userName) const +/* ========================================================================= */ +{ + return m_wdSessions.contains(userName); +} + + +/* ========================================================================= */ +/* + * Is connect to databox given by account index + */ +bool GlobWDSessions::isConnectedToWebdatovka(const QString &userName) +/* ========================================================================= */ +{ + if (!holdsSession(userName)) { + return false; + } else { + if (m_wdSessions.value(userName).name().isEmpty()) { + return false; + } + if (m_wdSessions.value(userName).value().isEmpty()) { + return false; + } + } + return true; +} + + +/* ========================================================================= */ +/* + * Creates new session. + */ +void GlobWDSessions::createCleanSession(const QString &userName) +/* ========================================================================= */ +{ + m_wdSessions.insert(userName, QNetworkCookie()); +} + + +/* ========================================================================= */ +/* + * Set cookie to session associated to user name. + */ +bool GlobWDSessions::setSessionCookie(const QString &userName, + const QNetworkCookie &cookie) +/* ========================================================================= */ +{ + m_wdSessions.insert(userName, cookie); + return true; +} + + +/* ========================================================================= */ +/* + * Returns associated session. + */ +QNetworkCookie GlobWDSessions::sessionCookie(const QString &userName) const +/* ========================================================================= */ +{ + return m_wdSessions.value(userName); +} diff -Nru datovka-4.7.0/src/io/wd_sessions.h datovka-4.7.1/src/io/wd_sessions.h --- datovka-4.7.0/src/io/wd_sessions.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/io/wd_sessions.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#ifndef _WEBDATOVKA_SESSIONS_H_ +#define _WEBDATOVKA_SESSIONS_H_ + +#include +#include +#include + + +/*! + * @brief Holds the webdatovka context structures. + */ +class GlobWDSessions { + +public: + GlobWDSessions(void); + ~GlobWDSessions(void); + + /*! + * @brief Returns true is active session exists. + */ + bool holdsSession(const QString &userName) const; + + /*! + * @brief Returns associated session cookie. + */ + QNetworkCookie sessionCookie(const QString &userName) const; + + /*! + * @brief Ping of webdatovka. Test if connection is active. + */ + bool isConnectedToWebdatovka(const QString &userName); + + /*! + * @brief Creates new session. + */ + void createCleanSession(const QString &userName); + + /*! + * @brief Set cookie to session associated to user name. + * + * @return True on success. + */ + bool setSessionCookie(const QString &userName, + const QNetworkCookie &cookie); + +private: + QMap m_wdSessions; +}; + +/* Global webdatovka context container instance. */ +extern GlobWDSessions wdSessions; + +#endif /* _WEBDATOVKA_SESSIONS_H_ */ diff -Nru datovka-4.7.0/src/log/log.cpp datovka-4.7.1/src/log/log.cpp --- datovka-4.7.0/src/log/log.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/log/log.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -56,6 +56,9 @@ switch (type) { case QtDebugMsg: +#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) + case QtInfoMsg: +#endif /* >= Qt-5.5 */ case QtWarningMsg: case QtCriticalMsg: if (globLog.logVerbosity() > 0) { @@ -543,6 +546,11 @@ case QtDebugMsg: return LOG_DEBUG; break; +#if (QT_VERSION >= QT_VERSION_CHECK(5, 5, 0)) + case QtInfoMsg: + return LOG_INFO; + break; +#endif /* >= Qt-5.5 */ case QtWarningMsg: return LOG_WARNING; break; @@ -551,9 +559,11 @@ break; case QtFatalMsg: return LOG_EMERG; /* System is unusable. */ + break; default: Q_ASSERT(0); return -1; + break; } } diff -Nru datovka-4.7.0/src/main.cpp datovka-4.7.1/src/main.cpp --- datovka-4.7.0/src/main.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/main.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -43,6 +43,7 @@ #include "src/io/filesystem.h" #include "src/io/message_db_set_container.h" #include "src/io/tag_db.h" +#include "src/io/tag_db_container.h" #include "src/io/sqlite/db.h" #include "src/log/log.h" #include "src/models/accounts_model.h" @@ -636,6 +637,13 @@ globPref.tagDbPath().toUtf8().constData()); return EXIT_FAILURE; } + + /* Create tag DB container. */ + globWebDatovkaTagDbPtr = new (std::nothrow) TagDbContainer("tagDbWebDatovka"); + if (0 == globWebDatovkaTagDbPtr) { + logErrorNL("%s", "Cannot allocate webdatovka tag db container."); + return EXIT_FAILURE; + } } @@ -653,6 +661,12 @@ globWorkPool.start(); logInfo("%s\n", "Worker pool started."); +#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0)) + // https://blog.qt.io/blog/2016/01/26/high-dpi-support-in-qt-5-6/ + //logInfoNL("%s", "Enabling high DPI scaling."); + //QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#endif /* >= Qt-5.6 */ + if (runMode == RUN_MODE_CLI) { delete splash; ret = doCLI(serList, parser); @@ -695,6 +709,12 @@ delete globTagDbPtr; globTagDbPtr = 0; } + + if (0 != globWebDatovkaTagDbPtr) { + delete globWebDatovkaTagDbPtr; + globWebDatovkaTagDbPtr = 0; + } + if (0 != globMessageDbsPtr) { delete globMessageDbsPtr; globMessageDbsPtr = 0; diff -Nru datovka-4.7.0/src/model_interaction/attachment_interaction.cpp datovka-4.7.1/src/model_interaction/attachment_interaction.cpp --- datovka-4.7.0/src/model_interaction/attachment_interaction.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/model_interaction/attachment_interaction.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,378 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include +#include +#include + +#include "src/io/filesystem.h" +#include "src/io/message_db_set_container.h" +#include "src/model_interaction/attachment_interaction.h" +#include "src/models/files_model.h" + +/*! + * @brief Returns single line selection index. + * + * @param[in] view View to ask for selected indexes. + * @param[in] column Number of column to receive indexes with. + * @return Valid selected index, or invalid index if no selection or error. + */ +static +QModelIndex selectedSingleIndex(const AttachmentTableView &view, int column) +{ + QModelIndex index; + + QModelIndexList indexes( + AttachmentInteraction::selectedColumnIndexes(view, column)); + if (indexes.size() == 1) { + return indexes.at(0); + } + + return QModelIndex(); +} + +/*! + * @brief Creates a temporary file for data stored in attachment. + * + * @param[in] index Index identifying the attachment data. + * @return Path to written temporary file, empty string on error. + */ +static +QString createTemporaryFile(QModelIndex index) +{ + if (!index.isValid()) { + Q_ASSERT(0); + return QString(); + } + + if (index.column() != DbFlsTblModel::FNAME_COL) { + index = index.sibling(index.row(), DbFlsTblModel::FNAME_COL); + if (!index.isValid()) { + Q_ASSERT(0); + return QString(); + } + } + Q_ASSERT(index.column() == DbFlsTblModel::FNAME_COL); + + QString attachName(index.data().toString()); + if (attachName.isEmpty()) { + Q_ASSERT(0); + return QString(); + } + + attachName.replace(QRegExp("\\s"), "_").replace( + QRegExp("[^a-zA-Z\\d\\.\\-_]"), "x"); + /* TODO -- Add message id into file name? */ + QString fileName(TMP_ATTACHMENT_PREFIX + attachName); + + QByteArray data; + { + /* Get data from base64. */ + QModelIndex dataIndex( + index.sibling(index.row(), DbFlsTblModel::CONTENT_COL)); + if (!dataIndex.isValid()) { + Q_ASSERT(0); + return QString(); + } + data = QByteArray::fromBase64(dataIndex.data().toByteArray()); + } + + return writeTemporaryFile(fileName, data); +} + +bool AttachmentInteraction::openAttachment(QWidget *parent, + const AttachmentTableView &view, QModelIndex index, + QString *attName, QString *tmpPath) +{ + if (attName != Q_NULLPTR) { + attName->clear(); + } + if (tmpPath != Q_NULLPTR) { + tmpPath->clear(); + } + + if (index.isValid()) { + if (index.column() != DbFlsTblModel::FNAME_COL) { + index = index.sibling(index.row(), + DbFlsTblModel::FNAME_COL); + } + } else { + /* Determine selection. */ + index = selectedSingleIndex(view, DbFlsTblModel::FNAME_COL); + if (!index.isValid()) { + return false; + } + } + + if (!index.isValid()) { + return false; + } + Q_ASSERT(index.column() == DbFlsTblModel::FNAME_COL); + + QString attachName(index.data().toString()); + if (attachName.isEmpty()) { + Q_ASSERT(0); + return false; + } + if (attName != Q_NULLPTR) { + *attName = attachName; + } + + /* Obtain plain file name from model if contains a file name. */ + QString fileName( + index.sibling(index.row(), + DbFlsTblModel::FPATH_COL).data(ROLE_PLAIN_DISPLAY).toString()); + if (fileName.isEmpty()) { + fileName = createTemporaryFile(index); + } + if (!fileName.isEmpty()) { + if (tmpPath != Q_NULLPTR) { + *tmpPath = fileName; + } + return QDesktopServices::openUrl( + QUrl::fromLocalFile(fileName)); + } else { + QMessageBox::warning(parent, + tr("Error storing attachment."), + tr("Cannot write temporary file for attachment '%1'.") + .arg(attachName), + QMessageBox::Ok); + return false; + } +} + +QString AttachmentInteraction::saveAttachmentToFile(QWidget *parent, + QModelIndex index, const QString &suggestedFilePath, bool askLocation) +{ + if (!index.isValid()) { + return QString(); + } + + if (index.column() != DbFlsTblModel::FNAME_COL) { + index = index.sibling(index.row(), DbFlsTblModel::FNAME_COL); + } + + if (!index.isValid()) { + Q_ASSERT(0); + return QString(); + } + Q_ASSERT(index.column() == DbFlsTblModel::FNAME_COL); + + QString fileName; + if (suggestedFilePath.isEmpty()) { + fileName = index.data().toString(); + if (fileName.isEmpty()) { + Q_ASSERT(0); + return QString(); + } + } else { + fileName = suggestedFilePath; + } + + if (askLocation) { + fileName = QFileDialog::getSaveFileName(parent, + tr("Save attachment"), fileName); + } + if (fileName.isEmpty()) { + return QString(); + } + /* TODO -- Remember directory? */ + + QModelIndex dataIndex(index.sibling(index.row(), + DbFlsTblModel::CONTENT_COL)); + if (!dataIndex.isValid()) { + Q_ASSERT(0); + return QString(); + } + + QByteArray data(QByteArray::fromBase64(dataIndex.data().toByteArray())); + + if (WF_SUCCESS != writeFile(fileName, data)) { + QMessageBox::warning(parent, + tr("Error saving attachment."), + tr("Cannot write file '%1'.").arg(fileName), + QMessageBox::Ok); + return QString(); + } + + return fileName; +} + +void AttachmentInteraction::saveAttachmentsToFile(QWidget *parent, + const AttachmentTableView &view, QModelIndexList indexList) +{ + if (indexList.isEmpty()) { + indexList = selectedColumnIndexes(view, + DbFlsTblModel::FNAME_COL); + } + + if (indexList.isEmpty()) { + return; + } + + foreach (const QModelIndex &index, indexList) { + saveAttachmentToFile(parent, index); + } +} + +/*! + * @brief Generates a list of unique (within supplied list) attachment names. + * + * @param[in] indexList List of indexes referring to selected rows. + * @return List of index-name pairs, empty list on error. + */ +static +QList< QPair > renameAttachments( + const QModelIndexList &indexList) +{ + typedef QPair ListContent; + typedef QList ListType; + ListType pairList; + QSet attNames; + + foreach (const QModelIndex &index, indexList) { + QString attName; + if (index.column() == DbFlsTblModel::FNAME_COL) { + attName = index.data().toString(); + } else { + attName = index.sibling(index.row(), + DbFlsTblModel::FNAME_COL).data().toString(); + } + if (attName.isEmpty()) { + Q_ASSERT(0); + return ListType(); + } + + if (attNames.contains(attName)) { + int cntr = 0; + QFileInfo fi(attName); + + const QString baseName(fi.baseName()); + const QString suffix(fi.completeSuffix()); + + do { + ++cntr; + attName = baseName + "_" + + QString::number(cntr) + "." + suffix; + } while (attNames.contains(attName)); + Q_ASSERT(!attName.isEmpty()); + } + + attNames.insert(attName); + pairList.append(ListContent(index, attName)); + } + + return pairList; +} + +QString AttachmentInteraction::saveAttachmentsToDirectory(QWidget *parent, + const AttachmentTableView &view, QModelIndexList indexList, + QString suggestedDirPath) +{ + if (indexList.isEmpty()) { + indexList = selectedColumnIndexes(view, + DbFlsTblModel::FNAME_COL); + } + + if (indexList.isEmpty()) { + return QString(); + } + + typedef QPair ListContent; + typedef QList ListType; + + /* Sorted index list with unique attachment names. */ + ListType atts(renameAttachments( + DbFlsTblModel::sortedUniqueLineIndexes(indexList, + DbFlsTblModel::FNAME_COL))); + if (atts.isEmpty()) { + return QString(); + } + + suggestedDirPath = QFileDialog::getExistingDirectory(parent, + tr("Save attachments"), suggestedDirPath, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); + if (suggestedDirPath.isEmpty()) { + return QString(); + } + + ListType unsuccessfulAtts; + bool existenceWarningDisplayed = false; /* Display only once. */ + + foreach (const ListContent &att, atts) { + const QModelIndex &idx(att.first); + QString fileName(att.second); + + fileName = suggestedDirPath + QDir::separator() + fileName; + + bool fileExists = QFileInfo::exists(fileName); + if (fileExists) { + if (!existenceWarningDisplayed) { + QMessageBox::warning(parent, + tr("Error saving attachment."), + tr("Some files already exist."), + QMessageBox::Ok); + existenceWarningDisplayed = true; + } + /* Ask for file name. */ + fileName = QFileDialog::getSaveFileName(parent, + tr("Save attachment"), fileName); + if (fileName.isEmpty()) { + unsuccessfulAtts.append(att); + continue; + } + } + + QModelIndex contIdx(idx.sibling(idx.row(), + DbFlsTblModel::CONTENT_COL)); + + QByteArray content( + QByteArray::fromBase64(contIdx.data().toByteArray())); + + if (WF_SUCCESS != writeFile(fileName, content)) { + unsuccessfulAtts.append(att); + continue; + } + } + + if (!unsuccessfulAtts.isEmpty()) { + QString warnMsg( + tr("In total %1 attachment files could not be written."). + arg(unsuccessfulAtts.size())); + warnMsg += "\n" + tr("These are:") + "\n"; + int i; + for (i = 0; i < (unsuccessfulAtts.size() - 1); ++i) { + warnMsg += " '" + unsuccessfulAtts.at(i).second + "'\n"; + } + warnMsg += " '" + unsuccessfulAtts.at(i).second + "'."; + QMessageBox::warning(parent, tr("Error saving attachments."), + warnMsg, QMessageBox::Ok); + } + + if (atts.size() == unsuccessfulAtts.size()) { + return QString(); + } + + return suggestedDirPath; +} diff -Nru datovka-4.7.0/src/model_interaction/attachment_interaction.h datovka-4.7.1/src/model_interaction/attachment_interaction.h --- datovka-4.7.0/src/model_interaction/attachment_interaction.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/model_interaction/attachment_interaction.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _ATTACHMENT_INTERACTION_H_ +#define _ATTACHMENT_INTERACTION_H_ + +#include /* Q_DECLARE_TR_FUNCTIONS */ +#include + +#include "src/views/attachment_table_view.h" + +/*! + * @brief Provides a namespace for convenience functions dealing with the + * attachment model. + * + * @note These functions are not part of the attachment model code because + * mostly they require some sort of QUI interaction and require Qt widgets + * to be compiled. + */ +class AttachmentInteraction { + Q_DECLARE_TR_FUNCTIONS(AttachmentInteraction) + +private: + /*! + * @brief Private constructor. + */ + AttachmentInteraction(void); + +public: + /*! + * @brief Returns list of indexes into selected rows. + * + * @param[in] view View to ask for selected indexes. + * @param[in] column Number of column to receive indexes with. + * @return List of indexes. + */ + static inline + QModelIndexList selectedColumnIndexes(const AttachmentTableView &view, + int column) + { + return view.selectionModel()->selectedRows(column); + } + + /*! + * @brief Open attachment file in associated application. + * + * @param[in,out] parent Parent widget to call dialogues from. + * @param[in] view Table view to determine selection from. + * @param[in] index Selection index, if invalid then selection is + * determined. + * @param[out] attName Set to attachment name if can be determined. + * @param[out] tmpPath Set to temporary file path if can be + * determined. + * @return True on success, false else. + */ + static + bool openAttachment(QWidget *parent, const AttachmentTableView &view, + QModelIndex index = QModelIndex(), QString *attName = Q_NULLPTR, + QString *tmpPath = Q_NULLPTR); + + /*! + * @brief Save attachment to file. + * + * @param[in,out] parent Parent widget to call dialogues from. + * @param[in] index Selection index, must be valid. + * @param[in] suggestedFilePath File with path to store data into, + * attachment name is taken if empty. + * @param[in] askLocation If true then dialogue asking for file + * location will be generated. + * @return Path to file where data were stored, empty string on error. + */ + static + QString saveAttachmentToFile(QWidget *parent, QModelIndex index, + const QString &suggestedFilePath = QString(), + bool askLocation = true); + + /*! + * @brief Save all selected attachments + * + * @param[in,out] parent Parent widget to call dialogues from. + * @param[in] view Table view to determine selection from. + * @param[in] indexList Selection indexes, if empty then selection + * is determined. + */ + static + void saveAttachmentsToFile(QWidget *parent, + const AttachmentTableView &view, + QModelIndexList indexList = QModelIndexList()); + + /*! + * @brief Save selected attachments into a single directory. + * + * @param[in,out] parent Parent widget to call dialogues from. + * @param[in] view Table view to determine selection from. + * @param[in] indexList Selection indexes, if empty then selection + * is determined. + * @param[in] suggestedDirPath Suggested directory where data + * should be stored. + * @return Directory where data were stores, empty string if no data + * stored. + */ + static + QString saveAttachmentsToDirectory(QWidget *parent, + const AttachmentTableView &view, + QModelIndexList indexList = QModelIndexList(), + QString suggestedDirPath = QString()); +}; + +#endif /* _ATTACHMENT_INTERACTION_H_ */ diff -Nru datovka-4.7.0/src/models/accounts_model.cpp datovka-4.7.1/src/models/accounts_model.cpp --- datovka-4.7.0/src/models/accounts_model.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/accounts_model.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -306,8 +306,12 @@ case Qt::DecorationRole: switch (type) { case nodeAccountTop: - return QIcon(ICON_3PARTY_PATH + - QStringLiteral("letter_16.png")); + if (isWebDatovkaAccount(uName)) { + return QIcon(":/mojeid.png"); + } else { + return QIcon(ICON_3PARTY_PATH + + QStringLiteral("letter_16.png")); + } break; case nodeRecentReceived: case nodeReceived: diff -Nru datovka-4.7.0/src/models/accounts_model.h datovka-4.7.1/src/models/accounts_model.h --- datovka-4.7.0/src/models/accounts_model.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/accounts_model.h 2017-01-19 09:29:26.000000000 +0000 @@ -32,8 +32,17 @@ #include #include + #include "src/settings/accounts.h" +/* Login method descriptors. */ +#define LIM_USERNAME "username" +#define LIM_CERT "certificate" +#define LIM_USER_CERT "user_certificate" +#define LIM_HOTP "hotp" +#define LIM_TOTP "totp" +#define LIM_MOJEID "mojeid" + /*! * @brief Account hierarchy. */ diff -Nru datovka-4.7.0/src/models/files_model.cpp datovka-4.7.1/src/models/files_model.cpp --- datovka-4.7.0/src/models/files_model.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/files_model.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -21,39 +21,343 @@ * the two. */ +#include /* std::sort */ +#include +#include +#include +#include +#include +#include +#include + #include "src/common.h" +#include "src/io/db_tables.h" +#include "src/io/filesystem.h" #include "src/io/isds_sessions.h" +#include "src/io/message_db.h" #include "src/log/log.h" #include "src/models/files_model.h" +#define LOCAL_DATABASE_STR QLatin1String("local database") + DbFlsTblModel::DbFlsTblModel(QObject *parent) : TblModel(parent) { + /* Fixed column count. */ + m_columnCount = MAX_COL; +} + +/*! + * @brief Check whether file exists and is readable. + * + * @param[in] filePath Path to file. + * @return True if file is readable. + */ +static +bool fileReadable(const QString &filePath) +{ + if (filePath.isEmpty()) { + return false; + } + QFileInfo fileInfo(filePath); + return fileInfo.exists() && fileInfo.isReadable(); +} + +/*! + * @brief Read file size. + * + * @param[in] filePath Path to file. + * @return File size or negative number if cannot determine. + */ +static +qint64 getFileSize(const QString &filePath) + { + QFileInfo fileInfo(filePath); + if (fileInfo.exists() && fileInfo.isReadable()) { + return fileInfo.size(); + } + return -1; +} + +/*! + * @brief Read file content and encode it into base64. + * + * @param[in] filePath Path to file. + * @return Base64-encoded file content. + */ +static +QByteArray getFileBase64(const QString &filePath) + { + QFile file(filePath); + if (file.exists()) { + if (!file.open(QIODevice::ReadOnly)) { + logErrorNL("Could not open file '%s'.", + filePath.toUtf8().constData()); + goto fail; + } + return file.readAll().toBase64(); + } +fail: + return QByteArray(); } QVariant DbFlsTblModel::data(const QModelIndex &index, int role) const { - if ((Qt::DisplayRole == role) && (FSIZE_COL == index.column())) { - /* Compute attachment size from base64 length. */ - QByteArray b64 = _data(index.sibling(index.row(), CONTENT_COL), - role).toByteArray(); - return base64RealSize(b64); - } else { + switch (role) { + case Qt::DisplayRole: + /* Continue with code. */ + break; + case ROLE_PLAIN_DISPLAY: + /* Explicitly asking associated file path. */ + if (index.column() == FPATH_COL) { + const QString fPath(_data(index.row(), FPATH_COL, + Qt::DisplayRole).toString()); + QByteArray b64(_data(index.row(), CONTENT_COL, + Qt::DisplayRole).toByteArray()); + + if ((fPath == LOCAL_DATABASE_STR) && !b64.isEmpty()) { + return QVariant(); /* No file present. */ + } else if (fileReadable(fPath)) { + return fPath; /* File present. */ + } else { + return QVariant(); + } + } + return QVariant(); + break; + default: + return _data(index, role); + break; + } + + switch (index.column()) { + case CONTENT_COL: + { + const QString fPath(_data(index.row(), FPATH_COL, + role).toString()); + + if (fPath == LOCAL_DATABASE_STR) { + /* Data should be in the model. */ + return _data(index, role); + } else if (fileReadable(fPath)) { + /* Read file. */ + return getFileBase64(fPath); + } else { + /* + * This fallback is used when filling model + * with zfo content. + */ + return _data(index, role); + } + } + break; + case FSIZE_COL: + { + const QString fPath(_data(index.row(), FPATH_COL, + role).toString()); + QByteArray b64(_data(index.row(), CONTENT_COL, + role).toByteArray()); + + if (fPath == LOCAL_DATABASE_STR) { + /* Get attachment size from base64 length. */ + return base64RealSize(b64); + } else if (fileReadable(fPath)) { + /* File size. */ + return getFileSize(fPath); + } else { + /* + * This fallback is used when filling model + * with zfo content. + */ + return base64RealSize(b64); + } + } + break; + case FPATH_COL: + { + const QString fPath(_data(index).toString()); + return (fPath == LOCAL_DATABASE_STR) ? + tr("local database") : fPath; + } + break; + default: return _data(index, role); + break; } } +Qt::DropActions DbFlsTblModel::DbFlsTblModel::supportedDropActions(void) const +{ + /* The model must provide removeRows() to be able to use move action. */ + return Qt::CopyAction | Qt::MoveAction; +} + Qt::ItemFlags DbFlsTblModel::flags(const QModelIndex &index) const { Qt::ItemFlags defaultFlags = TblModel::flags(index); if (index.isValid()) { - defaultFlags |= Qt::ItemIsDragEnabled; + /* Don't allow drops on items. */ + defaultFlags |= Qt::ItemIsDragEnabled; // | Qt::ItemIsDropEnabled; + } else { + defaultFlags |= Qt::ItemIsDropEnabled; } return defaultFlags; } +QStringList DbFlsTblModel::mimeTypes(void) const +{ + return QStringList(QStringLiteral("text/uri-list")); +} + +/*! + * @brief Converts list of absolute file names to list of URLs. + * + * @param[in] fileNames List of absolute file names. + * @return List of URLs or empty list on error. + */ +static +QList fileUrls(const QStringList &fileNames) +{ + QList uriList; + + foreach (const QString &fileName, fileNames) { + uriList.append(QUrl::fromLocalFile(fileName)); + } + + return uriList; +} + +QMimeData *DbFlsTblModel::mimeData(const QModelIndexList &indexes) const +{ + QModelIndexList lineIndexes = sortedUniqueLineIndexes(indexes, + FNAME_COL); + if (lineIndexes.isEmpty()) { + return Q_NULLPTR; + } + + /* Create temporary directory. Automatic remove is on by default. */ + QTemporaryDir dir(QDir::tempPath() + QDir::separator() + TMP_DIR_NAME); + if (!dir.isValid()) { + logErrorNL("%s", "Could not create a temporary directory."); + return Q_NULLPTR; + } + /* + * Automatic removal cannot be set because his removes the files + * before actual copying of the file. + * + * TODO -- Represent the copied data in a different way than an URL. + */ + dir.setAutoRemove(false); + + QStringList fileNames(accessibleFiles(dir.path(), lineIndexes)); + if (fileNames.isEmpty()) { + logErrorNL("%s", "Could not write temporary files."); + return Q_NULLPTR; + } + + QMimeData *mimeData = new (std::nothrow) QMimeData; + if (Q_NULLPTR == mimeData) { + return Q_NULLPTR; + } + QList urlList = fileUrls(fileNames); + mimeData->setUrls(urlList); + + return mimeData; +} + +bool DbFlsTblModel::canDropMimeData(const QMimeData *data, + Qt::DropAction action, int row, int column, + const QModelIndex &parent) const +{ + Q_UNUSED(action); + Q_UNUSED(row); + Q_UNUSED(column); + Q_UNUSED(parent); + + if (Q_NULLPTR == data) { + return false; + } + + return data->hasUrls(); +} + +/*! + * @brief Convert a list of URLs to a list of absolute file paths. + * + * @param[in] uriList List of file URLs. + * @return List of absolute file paths or empty list on error. + */ +static +QStringList filePaths(const QList &uriList) +{ + QStringList filePaths; + + foreach (const QUrl &uri, uriList) { + if (!uri.isValid()) { + logErrorNL("Dropped invalid URL '%s'.", + uri.toString().toUtf8().constData()); + return QList(); + } + + if (!uri.isLocalFile()) { + logErrorNL("Dropped URL '%s' is not a local file.", + uri.toString().toUtf8().constData()); + return QList(); + } + + filePaths.append(uri.toLocalFile()); + } + + return filePaths; +} + +bool DbFlsTblModel::dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, const QModelIndex &parent) +{ + if (!canDropMimeData(data, action, row, column, parent)) { + return false; + } + + /* data->hasUrls() tested in canDropMimeData() */ + QStringList paths(filePaths(data->urls())); + + if (parent.isValid()) { + /* Non-root node; append data. */ + row = rowCount(); + } + + foreach (const QString &filePath, paths) { + insertAttachmentFile(filePath, row); + row++; /* Move to next row. */ + } + + return true; +} + +void DbFlsTblModel::setHeader(void) +{ + int i; + + for (i = 0; i < MessageDb::fileItemIds.size(); ++i) { + /* Description. */ + setHeaderData(i, Qt::Horizontal, + flsTbl.attrProps.value(MessageDb::fileItemIds[i]).desc, + Qt::DisplayRole); + /* Data type. */ + setHeaderData(i, Qt::Horizontal, + flsTbl.attrProps.value(MessageDb::fileItemIds[i]).type, + ROLE_MSGS_DB_ENTRY_TYPE); + } + + /* Columns with missing names. */ + setHeaderData(FSIZE_COL, Qt::Horizontal, tr("File size"), + Qt::DisplayRole); + setHeaderData(FPATH_COL, Qt::Horizontal, tr("File path"), + Qt::DisplayRole); +} + bool DbFlsTblModel::setMessage(const struct isds_message *message) { if (NULL == message) { @@ -61,16 +365,158 @@ return false; } + beginResetModel(); m_data.clear(); m_rowsAllocated = 0; m_rowCount = 0; + endResetModel(); - m_columnCount = MAX_COL; + /* m_columnCount = MAX_COL; */ + + return appendMessageData(message); +} + +void DbFlsTblModel::setQuery(QSqlQuery &query) +{ + beginResetModel(); + m_data.clear(); + m_rowsAllocated = 0; + m_rowCount = 0; + endResetModel(); + + /* Looks like empty results have column count set. */ + /* m_columnCount = MAX_COL; */ + if ((query.record().count() + 1) != m_columnCount) { + Q_ASSERT(0); + return; + } + + appendQueryData(query); +} + +bool DbFlsTblModel::appendQueryData(QSqlQuery &query) +{ + if ((query.record().count() + 1) != m_columnCount) { + return false; + } + + query.first(); + while (query.isActive() && query.isValid()) { + + QVector row(m_columnCount); + + queryToVector(row, query); + row[FPATH_COL] = LOCAL_DATABASE_STR; + + /* Don't check data duplicity! */ + insertVector(row, rowCount(), false); + + query.next(); + } + + return true; +} + +/* File content will be held within model. */ +//#define HOLD_FILE_CONTENT + +int DbFlsTblModel::insertAttachmentFile(const QString &filePath, int row) +{ + QFile attFile(filePath); + + int fileSize = attFile.size(); + if (0 == fileSize) { + logWarning("Ignoring file '%s' with zero size.\n", + filePath.toUtf8().constData()); + return 0; + } + + QString fileName(QFileInfo(attFile.fileName()).fileName()); + QMimeType mimeType(QMimeDatabase().mimeTypeForFile(attFile)); + + for (int i = 0; i < rowCount(); ++i) { + if (_data(i, FPATH_COL).toString() == filePath) { + /* Already in table. */ + logWarning("File '%s' already in table.\n", + filePath.toUtf8().constData()); + return -1; + } + } + + QVector rowVect(m_columnCount); + + //rowVect[ATTACHID_COL] = QVariant(); + //rowVect[MSGID_COL] = QVariant(); +#if defined HOLD_FILE_CONTENT + rowVect[CONTENT_COL] = getFileBase64(filePath); +#else /* !defined HOLD_FILE_CONTENT */ + rowVect[CONTENT_COL] = QByteArray(); +#endif /* defined HOLD_FILE_CONTENT */ + rowVect[FNAME_COL] = fileName; + rowVect[MIME_COL] = mimeType.name(); + rowVect[FSIZE_COL] = fileSize; // QString::number(fileSize) + rowVect[FPATH_COL] = filePath; + + /* Check data duplicity. */ + if (insertVector(rowVect, row, true)) { + return fileSize; + } else { + return -1; + } +} + +bool DbFlsTblModel::appendAttachmentEntry(const QByteArray &base64content, + const QString &fName) +{ + if (base64content.isEmpty() || fName.isEmpty()) { + return false; + } + + QVector rowVect(m_columnCount); + + //rowVect[ATTACHID_COL] = QVariant(); + //rowVect[MSGID_COL] = QVariant(); + rowVect[CONTENT_COL] = base64content; + rowVect[FNAME_COL] = fName; + rowVect[MIME_COL] = tr("unknown"); + rowVect[FSIZE_COL] = base64RealSize(base64content); // QString::number() + rowVect[FPATH_COL] = LOCAL_DATABASE_STR; + + /* Check data duplicity. */ + return insertVector(rowVect, rowCount(), true); +} + +/*! + * @brief Used for sorting index lists. + */ +class IndexRowLess { +public: + bool operator()(const QModelIndex &a, const QModelIndex &b) const + { + return a < b; + } +}; + +QModelIndexList DbFlsTblModel::sortedUniqueLineIndexes( + const QModelIndexList &indexes, int dfltCoumn) +{ + QSet lines; + QModelIndexList uniqueLines; + + foreach (const QModelIndex &index, indexes) { + if (lines.contains(index.row())) { + continue; + } + uniqueLines.append(index.sibling(index.row(), dfltCoumn)); + lines.insert(index.row()); + } - return addMessageData(message); + ::std::sort(uniqueLines.begin(), uniqueLines.end(), IndexRowLess()); + + return uniqueLines; } -bool DbFlsTblModel::addMessageData(const struct isds_message *message) +bool DbFlsTblModel::appendMessageData(const struct isds_message *message) { const struct isds_list *docListItem; const struct isds_document *doc; @@ -80,8 +526,6 @@ return false; } - beginResetModel(); - docListItem = message->documents; if (NULL == docListItem) { logWarning("%s\n", "Message has no documents."); @@ -90,15 +534,9 @@ doc = (struct isds_document *) docListItem->data; if (NULL == doc) { Q_ASSERT(0); - endResetModel(); return false; } - if (m_rowCount == m_rowsAllocated) { - m_rowsAllocated += m_rowAllocationIncrement; - m_data.resize(m_rowsAllocated); - } - QVector row(m_columnCount); row[CONTENT_COL] = QVariant( @@ -107,12 +545,170 @@ row[FNAME_COL] = QVariant(QString(doc->dmFileDescr)); row[FSIZE_COL] = QVariant(0); - m_data[m_rowCount++] = row; + /* Don't check data duplicity! */ + insertVector(row, rowCount(), false); docListItem = docListItem->next; } - endResetModel(); + return true; +} + +bool DbFlsTblModel::insertVector(const QVector &rowVect, + int row, bool insertUnique) +{ + if (rowVect.size() != m_columnCount) { + return false; + } + + if ((row < 0) || (row > rowCount())) { + /* + * -1 is passed when dropping directly on index which may be + * invalid for root node. + */ + row = rowCount(); + } + + if (insertUnique && nameAndContentPresent(rowVect.at(CONTENT_COL), + rowVect.at(FNAME_COL), rowVect.at(FPATH_COL))) { + /* Fail if data present. */ + logWarningNL("Same data '%s' already attached.", + rowVect.at(FNAME_COL).toString().toUtf8().constData()); + return false; + } + + Q_ASSERT((0 <= row) && (row <= rowCount())); + + beginInsertRows(QModelIndex(), row, row); + + reserveSpace(); + + if (row == rowCount()) { + m_data[m_rowCount++] = rowVect; + } else { + m_data.insert(row, rowVect); + m_rowCount++; + } + + endInsertRows(); return true; } + +bool DbFlsTblModel::nameAndContentPresent(const QVariant &base64content, + const QVariant &fName, const QVariant &fPath) const +{ + /* Cannot use foreach (), because contains pre-allocated empty lines. */ + for (int row = 0; row < rowCount(); ++row) { + const QVector &rowEntry = m_data.at(row); + if ((rowEntry.at(FNAME_COL) == fName) && + (rowEntry.at(FPATH_COL) == fPath) && + (rowEntry.at(CONTENT_COL) == base64content)) { + return true; + } + } + + return false; +} + +/*! + * @brief Creates temporary files related to selected view items. + * + * @param[in] tmpDirPath Temporary directory path. + * @param[in] index Index identifying line. + * @param[in] fileNumber Number identifying the file. + * @return Absolute file name or empty string on error. + */ +static +QString temporaryFile(const QString &tmpDirPath, const QModelIndex &index, + int fileNumber) +{ + if (tmpDirPath.isEmpty()) { + Q_ASSERT(0); + return QString(); + } + + QString subirPath(tmpDirPath + QDir::separator() + + QString::number(fileNumber++)); + { + /* + * Create a separate subdirectory because the files + * may have equal names. + */ + QDir dir(tmpDirPath); + if (!dir.mkpath(subirPath)) { + logError("Could not create directory '%s'.", + subirPath.toUtf8().constData()); + return QString(); + } + } + QString attachAbsPath(subirPath + QDir::separator()); + { + /* Determine full file path. */ + QModelIndex fileNameIndex = index.sibling(index.row(), + DbFlsTblModel::FNAME_COL); + if(!fileNameIndex.isValid()) { + Q_ASSERT(0); + return QString(); + } + QString attachFileName(fileNameIndex.data().toString()); + if (attachFileName.isEmpty()) { + Q_ASSERT(0); + return QString(); + } + attachAbsPath += attachFileName; + } + QByteArray attachData; + { + /* Obtain data. */ + QModelIndex dataIndex = index.sibling(index.row(), + DbFlsTblModel::CONTENT_COL); + if (!dataIndex.isValid()) { + Q_ASSERT(0); + return QString(); + } + attachData = QByteArray::fromBase64( + dataIndex.data().toByteArray()); + if (attachData.isEmpty()) { + Q_ASSERT(0); + return QString(); + } + } + if (WF_SUCCESS != writeFile(attachAbsPath, attachData, false)) { + return QString(); + } + + return attachAbsPath; +} + +QStringList DbFlsTblModel::accessibleFiles(const QString &tmpDirPath, + const QModelIndexList &indexes) const +{ + QStringList accessibleFileList; + int fileNumber = 0; + + foreach (const QModelIndex &idx, indexes) { + fileNumber++; + const QString fPath(_data(idx.row(), FPATH_COL, + Qt::DisplayRole).toString()); + + QString fileName; + + if (fPath == LOCAL_DATABASE_STR) { + fileName = temporaryFile(tmpDirPath, idx, fileNumber); + } else if (fileReadable(fPath)) { + fileName = fPath; + } else { + /* This fallback should not be used. */ + fileName = temporaryFile(tmpDirPath, idx, fileNumber); + } + + if (fileName.isEmpty()) { + return QStringList(); + } + + accessibleFileList.append(fileName); + } + + return accessibleFileList; +} diff -Nru datovka-4.7.0/src/models/files_model.h datovka-4.7.1/src/models/files_model.h --- datovka-4.7.0/src/models/files_model.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/files_model.h 2017-01-19 09:29:26.000000000 +0000 @@ -48,8 +48,10 @@ MSGID_COL = 1, /* Message identifier. */ CONTENT_COL = 2, /* Base64-encoded attachment content. */ FNAME_COL = 3, /* Attachment file name. */ - FSIZE_COL = 4, /* Attachment file size (base64-decoded). */ - MAX_COL = 5 /* Number of columns. */ + MIME_COL = 4, /* Mime type description. */ + FSIZE_COL = 5, /* Attachment file size (base64-decoded). */ + FPATH_COL = 6, /* Path to origin. */ + MAX_COL = 7 /* Number of columns. */ }; /*! @@ -57,7 +59,7 @@ * * @param[in] parent Parent object. */ - DbFlsTblModel(QObject *parent = 0); + explicit DbFlsTblModel(QObject *parent = Q_NULLPTR); /*! * @brief Returns the data stored under the given role. @@ -71,6 +73,14 @@ int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; /*! + * @brief Returns the drop actions supported by this model. + * + * @return Supported drop actions. + */ + virtual + Qt::DropActions supportedDropActions(void) const Q_DECL_OVERRIDE; + + /*! * @brief Used to set items draggable. * * @param[in] index Index which to obtain flags for. @@ -79,6 +89,59 @@ Qt::ItemFlags flags(const QModelIndex &index) const Q_DECL_OVERRIDE; /*! + * @brief Returns the list of allowed MIME types. + * + * @return List of MIME types. + */ + virtual + QStringList mimeTypes(void) const Q_DECL_OVERRIDE; + + /*! + * @brief Returns object containing serialised attachment data. + * + * @param[in] indexes List of indexes. + * @return Pointer to newly allocated mime data object, 0 on error. + */ + virtual + QMimeData *mimeData( + const QModelIndexList &indexes) const Q_DECL_OVERRIDE; + + /*! + * @brief Returns whether the model accepts drops of given mime data. + * + * @param[in] data Data to be dropped. + * @param[in] action Type of drop action. + * @param[in] row Target row. + * @param[in] column Target column. + * @param[in] parent Parent index. + * @return True if drop is accepted. + */ + virtual + bool canDropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, + const QModelIndex &parent) const Q_DECL_OVERRIDE; + + /*! + * @brief Handles data supplied by drop operation. + * + * @param[in] data Data to be dropped. + * @param[in] action Type of drop action. + * @param[in] row Target row. + * @param[in] column Target column. + * @param[in] parent Parent index. + * @return True if data are handled by the model. + */ + virtual + bool dropMimeData(const QMimeData *data, Qt::DropAction action, + int row, int column, + const QModelIndex &parent) Q_DECL_OVERRIDE; + + /*! + * @brief Sets default header. + */ + void setHeader(void); + + /*! * @brief Sets the content of the model according to the supplied * message. * @@ -87,14 +150,95 @@ */ bool setMessage(const struct isds_message *message); + /*! + * @brief Sets the content of the model according to the supplied query. + * + * @param[in,out] qyery SQL query result. + */ + virtual + void setQuery(QSqlQuery &query) Q_DECL_OVERRIDE; + + /*! + * @brief Appends data from the supplied query to the model. + * + * @param[in,out] query SQL query result. + * @return True on success. + */ + virtual + bool appendQueryData(QSqlQuery &query) Q_DECL_OVERRIDE; + + /*! + * @brief Adds attachment file. + * + * @param[in] filePath Path to attachment file. + * @param[in] row Row to insert the data into. + * @return Positive size of added file, 0 or -1 on error. + */ + int insertAttachmentFile(const QString &filePath, int row); + + /*! + * @brief Append attachment data line. + * + * @param[in] base64content Base64-encoded attachment content. + * @param[in] fName Attachment name. + * @param True when attachment data successfully added. + */ + bool appendAttachmentEntry(const QByteArray &base64content, + const QString &fName); + + /*! + * @brief Generate sorted list containing only one index per line each. + * + * @param[in] indexes Indexes identifying lines. + * @return List of indexes with unique row numbers. + */ + static + QModelIndexList sortedUniqueLineIndexes(const QModelIndexList &indexes, + int dfltCoumn); + private: /*! * @brief Appends data from the supplied message. * * @param[in] message Message structure. - * @return True on success. + * @return True when message data successfully added. + */ + bool appendMessageData(const struct isds_message *message); + + /*! + * @brief Insert supplied vector. + * + * @param[in] rowVect Vector containing a model row. + * @param[in] row Row to insert the data into. + * @param[in] insertUnique true if only unique file should be added. + * @return True when attachment data successfully added. + */ + bool insertVector(const QVector &rowVect, int row, + bool insertUnique); + + /*! + * @brief Check whether file name and content combination already + * exists. + * + * @param[in] base64content Base64-encoded attachment content. + * @param[in] fName Attachment name. + * @param[in] fPath File path. + * @return True if content with name exists in model. + */ + bool nameAndContentPresent(const QVariant &base64content, + const QVariant &fName, const QVariant &fPath) const; + + /*! + * @brief Returns list of file paths for lines given in indexes. + * + * @note FIles are created if no files are held within the model. + * + * @param[in] tmpDirPath Temporary directory path. + * @param[in] indexes Indexes identifying the attachment entries. + * @return List of file paths, empty path list on error. */ - bool addMessageData(const struct isds_message *message); + QStringList accessibleFiles(const QString &tmpDirPath, + const QModelIndexList &indexes) const; }; #endif /* _FILES_MODEL_H_ */ diff -Nru datovka-4.7.0/src/models/messages_model.cpp datovka-4.7.1/src/models/messages_model.cpp --- datovka-4.7.0/src/models/messages_model.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/messages_model.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -29,7 +29,9 @@ #include "src/io/tag_db.h" /* Direct access to tag database, */ #include "src/io/db_tables.h" #include "src/io/dbs.h" +#include "src/io/tag_db_container.h" #include "src/models/messages_model.h" +#include "src/io/message_db.h" const int DbMsgsTblModel::rcvdMsgsColCnt(8); const int DbMsgsTblModel::sntMsgsColCnt(7); @@ -530,7 +532,16 @@ bool DbMsgsTblModel::fillTagsColumn(const QString &userName, int col) { - if (0 == globTagDbPtr) { + TagDb *tagDb = 0; + + if (isWebDatovkaAccount(userName)) { + tagDb = globWebDatovkaTagDbPtr-> + accessTagDb(getWebDatovkaTagDbPrefix(userName)); + } else { + tagDb = globTagDbPtr; + } + + if (0 == tagDb) { return false; } @@ -553,7 +564,7 @@ for (int row = 0; row < rowCount(); ++row) { qint64 dmId = TblModel::index(row, 0).data().toLongLong(); m_data[row][col] = QVariant::fromValue( - globTagDbPtr->getMessageTags(userName, dmId)); + tagDb->getMessageTags(userName, dmId)); } emit dataChanged(TblModel::index(0, col), @@ -565,7 +576,16 @@ bool DbMsgsTblModel::refillTagsColumn(const QString &userName, const QList &dmIds, int col) { - if (0 == globTagDbPtr) { + TagDb *tagDb = 0; + + if (isWebDatovkaAccount(userName)) { + tagDb = globWebDatovkaTagDbPtr-> + accessTagDb(getWebDatovkaTagDbPrefix(userName)); + } else { + tagDb = globTagDbPtr; + } + + if (0 == tagDb) { return false; } @@ -589,7 +609,7 @@ qint64 dmId = TblModel::index(row, 0).data().toLongLong(); if (dmIds.contains(dmId)) { m_data[row][col] = QVariant::fromValue( - globTagDbPtr->getMessageTags(userName, dmId)); + tagDb->getMessageTags(userName, dmId)); emit dataChanged(TblModel::index(row, col), TblModel::index(row, col)); } diff -Nru datovka-4.7.0/src/models/table_model.cpp datovka-4.7.1/src/models/table_model.cpp --- datovka-4.7.0/src/models/table_model.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/table_model.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -75,9 +75,11 @@ void TblModel::setQuery(QSqlQuery &query) { + beginResetModel(); m_data.clear(); m_rowsAllocated = 0; m_rowCount = 0; + endResetModel(); /* Looks like empty results have column count set. */ m_columnCount = query.record().count(); @@ -96,16 +98,11 @@ query.first(); while (query.isActive() && query.isValid()) { - if (m_rowCount == m_rowsAllocated) { - m_rowsAllocated += m_rowAllocationIncrement; - m_data.resize(m_rowsAllocated); - } + reserveSpace(); QVector row(m_columnCount); - for (int i = 0; i < m_columnCount; ++i) { - row[i] = query.value(i); - } + queryToVector(row, query); m_data[m_rowCount++] = row; @@ -117,6 +114,89 @@ return true; } +bool TblModel::moveRows(const QModelIndex &sourceParent, int sourceRow, + int count, const QModelIndex &destinationParent, int destinationChild) +{ + if (sourceParent.isValid() || destinationParent.isValid()) { + /* Only moves within root node are allowed. */ + return false; + } + + if ((sourceRow < 0) || (sourceRow >= rowCount()) || + (count < 0) || ((sourceRow + count) > rowCount()) || + (destinationChild < 0) || (destinationChild > rowCount())) { + /* Boundaries or location outside limits. */ + return false; + } + + if (count == 0) { + return true; + } + + if ((sourceRow <= destinationChild) && + (destinationChild <= (sourceRow + count))) { + /* Destination lies within source. */ + return true; + } + + int newPosition; /* Position after removal. */ + if (destinationChild < sourceRow) { + newPosition = destinationChild; + } else if (destinationChild > (sourceRow + count)) { + newPosition = destinationChild - count; + } else { + Q_ASSERT(0); + return false; + } + + beginMoveRows(sourceParent, sourceRow, sourceRow + count - 1, + destinationParent, destinationChild); + + QList< QVector > movedData; + for (int i = sourceRow; i < (sourceRow + count); ++i) { + movedData.append(m_data.takeAt(sourceRow)); + } + + for (int i = 0; i < count; ++i) { + m_data.insert(newPosition + i, movedData.takeAt(0)); + } + Q_ASSERT(movedData.isEmpty()); + + endMoveRows(); + + return true; +} + +bool TblModel::removeRows(int row, int count, const QModelIndex &parent) +{ + if ((row < 0) || (count < 0) || parent.isValid()) { + /* Return if not operating on model root. */ + return false; + } + + if (row >= rowCount()) { + return false; + } + + if (count > (rowCount() - row)) { + /* Adjust the count to fit the model. */ + count = rowCount() - row; + } + + int last = row + count - 1; + beginRemoveRows(parent, row, last); + + /* Work in reverse order. */ + for (int i = last; i >= row; --i) { + m_data.removeAt(i); + --m_rowCount; + } + + endRemoveRows(); + + return true; +} + QVariant TblModel::_data(const QModelIndex &index, int role) const { if (role != Qt::DisplayRole) { @@ -150,3 +230,18 @@ return m_headerData[section][role]; } + +void TblModel::reserveSpace(void) +{ + if (m_rowCount == m_rowsAllocated) { + m_rowsAllocated += m_rowAllocationIncrement; + m_data.resize(m_rowsAllocated); + } +} + +void TblModel::queryToVector(QVector &vect, const QSqlQuery &query) +{ + for (int i = 0; i < query.record().count(); ++i) { + vect[i] = query.value(i); + } +} diff -Nru datovka-4.7.0/src/models/table_model.h datovka-4.7.1/src/models/table_model.h --- datovka-4.7.0/src/models/table_model.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/models/table_model.h 2017-01-19 09:29:26.000000000 +0000 @@ -39,7 +39,7 @@ * * @param[in] parent Parent object. */ - TblModel(QObject *parent = 0); + explicit TblModel(QObject *parent = 0); /*! * @brief Returns number of rows under given parent. @@ -114,6 +114,33 @@ virtual bool appendQueryData(QSqlQuery &query); + /*! + * @brief Move rows. + * + * @param[in] sourceParent Source parent. + * @param[in] sourceRow Source row. + * @param[in] count Number of rows to be moved. + * @param[in] destinationParent Destination parent. + * @param[in] destinationChild Row to move data into. + * @return If move performed. + */ + virtual + bool moveRows(const QModelIndex &sourceParent, int sourceRow, + int count, const QModelIndex &destinationParent, + int destinationChild) Q_DECL_OVERRIDE; + + /*! + * @brief Remove rows. + * + * @param[in] row Starting row. + * @param[in] count Number of rows to be removed. + * @param[in] parent Parent item the row is relative to. + * @return True if the rows were successfully removed. + */ + virtual + bool removeRows(int row, int count, + const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE; + protected: /*! * @brief Returns raw data stored under the given role. @@ -146,6 +173,20 @@ QVariant _headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + /*! + * @brief Inflate data container. + */ + void reserveSpace(void); + + /*! + * @brief Copies query result into vector. + * + * @param[out] vect Vector to write data into. + * @param[in] query Query to copy data from. + */ + static + void queryToVector(QVector &vect, const QSqlQuery &query); + /* * Data are organised using a two-dimensional array. * The size of the array is incremented using several lines at once. diff -Nru datovka-4.7.0/src/settings/accounts.cpp datovka-4.7.1/src/settings/accounts.cpp --- datovka-4.7.0/src/settings/accounts.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/settings/accounts.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -60,6 +60,7 @@ static const QString uNamePwdCrt(QLatin1String("user_certificate")); static const QString uNamePwdHotp(QLatin1String("hotp")); static const QString uNamePwdTotp(QLatin1String("totp")); + static const QString uMojeId(QLatin1String("mojeid")); } /*! @@ -87,6 +88,9 @@ case AcntSettings::LIM_UNAME_PWD_TOTP: return AcntSettings::LIM_UNAME_PWD_TOTP; break; + case AcntSettings::LIM_MOJE_ID: + return AcntSettings::LIM_MOJE_ID; + break; case AcntSettings::LIM_UNKNOWN: default: return AcntSettings::LIM_UNKNOWN; @@ -113,11 +117,14 @@ return AcntSettings::LIM_UNAME_PWD_HOTP; } else if (str == MethodNames::uNamePwdTotp) { return AcntSettings::LIM_UNAME_PWD_TOTP; + } else if (str == MethodNames::uMojeId) { + return AcntSettings::LIM_MOJE_ID; } else { return AcntSettings::LIM_UNKNOWN; } } + /*! * @brief Converts login method identifier to string. * @@ -145,6 +152,9 @@ case AcntSettings::LIM_UNAME_PWD_TOTP: return MethodNames::uNamePwdTotp; break; + case AcntSettings::LIM_MOJE_ID: + return MethodNames::uMojeId; + break; case AcntSettings::LIM_UNKNOWN: default: Q_ASSERT(0); diff -Nru datovka-4.7.0/src/settings/accounts.h datovka-4.7.1/src/settings/accounts.h --- datovka-4.7.0/src/settings/accounts.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/settings/accounts.h 2017-01-19 09:29:26.000000000 +0000 @@ -66,7 +66,8 @@ LIM_UNAME_CRT, /*!< User name and certificate. */ LIM_UNAME_PWD_CRT, /*!< User name, password and certificate. */ LIM_UNAME_PWD_HOTP, /*!< User name, password and HOTP. */ - LIM_UNAME_PWD_TOTP /*!< User name, password and TOTP (SMS). */ + LIM_UNAME_PWD_TOTP, /*!< User name, password and TOTP (SMS). */ + LIM_MOJE_ID /*!< MOJEID. */ }; /*! diff -Nru datovka-4.7.0/src/settings/preferences.cpp datovka-4.7.1/src/settings/preferences.cpp --- datovka-4.7.0/src/settings/preferences.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/settings/preferences.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -40,6 +40,7 @@ /*! Account database file name. */ #define ACCOUNT_DB_FILE "messages.shelf.db" #define TAG_DB_FILE "tag.db" +#define TAG_WEBDATOVKA_DB_FILE "mojeid-tag.db" GlobPreferences::GlobPreferences(void) : confSubdir(DFLT_CONF_SUBDIR), @@ -47,6 +48,7 @@ saveToConf(DFLT_CONF_FILE), accountDbFile(ACCOUNT_DB_FILE), tagDbFile(TAG_DB_FILE), + tagWebDatovkaDbFile(TAG_WEBDATOVKA_DB_FILE), auto_download_whole_messages(false), default_download_signed(true), //store_passwords_on_disk(false), @@ -452,3 +454,7 @@ return confDir() + QDir::separator() + tagDbFile; } +QString GlobPreferences::tagWebDatovkaDbPath(void) const +{ + return confDir() + QDir::separator() + tagWebDatovkaDbFile; +} diff -Nru datovka-4.7.0/src/settings/preferences.h datovka-4.7.1/src/settings/preferences.h --- datovka-4.7.0/src/settings/preferences.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/settings/preferences.h 2017-01-19 09:29:26.000000000 +0000 @@ -63,6 +63,7 @@ QString saveToConf; /*!< Configuration file to save to. */ const QString accountDbFile; /*!< Account db file. */ const QString tagDbFile; /*!< Tag db file. */ + const QString tagWebDatovkaDbFile; /*!< Tag webdatovka db file. */ bool auto_download_whole_messages; bool default_download_signed; /*!< Default downloading method. */ //bool store_passwords_on_disk; @@ -143,6 +144,13 @@ * @return Whole path to tag database file. */ QString tagDbPath(void) const; + + /*! + * @brief Returns whole webdatovka tag db path. + * + * @return Whole path to webdatovka tag database file. + */ + QString tagWebDatovkaDbPath(void) const; }; /*! diff -Nru datovka-4.7.0/src/views/attachment_table_view.cpp datovka-4.7.1/src/views/attachment_table_view.cpp --- datovka-4.7.0/src/views/attachment_table_view.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/views/attachment_table_view.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2016 CZ.NIC * * 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 @@ -22,56 +22,153 @@ */ #include -#include +#include +#include + +#include "src/models/files_model.h" +#if 0 +#include #include #include #include #include -#include #include "src/common.h" -#include "src/io/filesystem.h" #include "src/log/log.h" #include "src/models/files_model.h" +#endif +#include "src/log/log.h" #include "src/views/attachment_table_view.h" +/*! + * @brief Style used to override default drop indicator. + */ +class AttachmentViewStyle : public QProxyStyle { +public: + /*! + * @brief Constructor. + */ + explicit AttachmentViewStyle(QStyle *style = Q_NULLPTR); + + /*! + * @brief Draws primitive element. + * + * @note Used to draw drop indicator as whole line through the entire + * row. + */ + virtual + void drawPrimitive(PrimitiveElement element, + const QStyleOption *option, QPainter *painter, + const QWidget *widget = Q_NULLPTR) const Q_DECL_OVERRIDE; +}; + +AttachmentViewStyle::AttachmentViewStyle(QStyle *style) + : QProxyStyle(style) +{ +} + +void AttachmentViewStyle::drawPrimitive(PrimitiveElement element, + const QStyleOption *option, QPainter *painter, const QWidget *widget) const +{ + if ((element == QStyle::PE_IndicatorItemViewItemDrop) && + (!option->rect.isNull())) { + QStyleOption opt(*option); + opt.rect.setLeft(0); + if (widget != Q_NULLPTR) { + opt.rect.setRight(widget->width()); + } + QProxyStyle::drawPrimitive(element, &opt, painter, widget); + return; + } + QProxyStyle::drawPrimitive(element, option, painter, widget); +} + AttachmentTableView::AttachmentTableView(QWidget *parent) - : QTableView(parent), - m_dragStartPosition() + : LoweredTableView(parent) { + /* Override default style. */ + setStyle(new AttachmentViewStyle(style())); + setDragEnabled(true); } -void AttachmentTableView::mouseMoveEvent(QMouseEvent *event) +#if 0 +void AttachmentTableView::dragEnterEvent(QDragEnterEvent *event) { if (0 == event) { Q_ASSERT(0); return; } - if (!(event->buttons() & Qt::LeftButton) || - (event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { - QTableView::mouseMoveEvent(event); + const QMimeData *mimeData = event->mimeData(); + if (0 == mimeData) { + Q_ASSERT(0); return; } - /* Create temporary directory. Automatic remove is on by default. */ - QTemporaryDir dir(QDir::tempPath() + QDir::separator() + TMP_DIR_NAME); - if (!dir.isValid()) { - logErrorNL("%s", "Could not create a temporary directory."); + if (mimeData->hasUrls()) { + event->acceptProposedAction(); + } else { + logInfo("Rejecting drag enter event with mime type '%s'.\n", + mimeData->formats().join(" ").toUtf8().constData()); + } +} +#endif + +#if 0 +void AttachmentTableView::dragMoveEvent(QDragMoveEvent *event) +{ + if (0 == event) { + Q_ASSERT(0); return; } + + event->acceptProposedAction(); +} +#endif + +void AttachmentTableView::dropEvent(QDropEvent *event) +{ /* - * Automatic removal cannot be set because his removes the files - * before actual copying of the file. - * - * TODO -- Represent the copied data in a different way than an URL. + * Don't know what's happening. + * The default view/mode behaviour is somewhat strange. + * When dragging data originating from the model, if the model + * signals elements added while processing the event then the original + * data are not removed. */ - dir.setAutoRemove(false); - QList tmpFileNames = temporaryFiles(dir); - if (tmpFileNames.isEmpty()) { - logErrorNL("%s", "Could not write temporary files."); + /* TODO -- Access the model in a more transparent way. */ + DbFlsTblModel *attachmentModel = qobject_cast(model()); + if (attachmentModel == Q_NULLPTR) { + return; + } + + bool dropOriginatesHere = (event->source() == this); + if (!dropOriginatesHere) { + LoweredTableView::dropEvent(event); + } else { + shuffleOnDrop(event); + } +} + +#if 0 +void AttachmentTableView::mouseMoveEvent(QMouseEvent *event) +{ + if (0 == event) { + Q_ASSERT(0); + return; + } + + if (!(event->buttons() & Qt::LeftButton) || + (event->pos() - m_dragStartPosition).manhattanLength() < QApplication::startDragDistance()) { + QTableView::mouseMoveEvent(event); + return; + } + + /* TODO -- Access the model in a more transparent way. */ + DbFlsTblModel *attachmentModel = + qobject_cast(model()); + if (0 == attachmentModel) { return; } @@ -80,14 +177,15 @@ return; } - QMimeData *mimeData = new (std::nothrow) QMimeData; - if (0 != mimeData) { - QList urlList = temporaryFileUrls(tmpFileNames); - mimeData->setUrls(urlList); - drag->setMimeData(mimeData); + QModelIndexList rowIdxs(this->selectionModel()->selectedRows(0)); + QMimeData *mimeData = attachmentModel->mimeData(rowIdxs); + if (0 == mimeData) { + delete drag; + return; } + drag->setMimeData(mimeData); - if (tmpFileNames.size() == 1) { + if (rowIdxs.size() == 1) { drag->setDragCursor( QPixmap(ICON_3PARTY_PATH "document_32.png"), Qt::MoveAction); @@ -106,7 +204,9 @@ /* Ignore the return value of the drop action. */ drag->exec(Qt::CopyAction | Qt::MoveAction); } +#endif +#if 0 void AttachmentTableView::mousePressEvent(QMouseEvent *event) { if (0 == event) { @@ -120,87 +220,160 @@ QTableView::mousePressEvent(event); } +#endif + +void AttachmentTableView::shuffleOnDrop(QDropEvent *event) +{ + Q_ASSERT(event->source() == this); + + /* TODO -- Access the model in a more transparent way. */ + DbFlsTblModel *attachmentModel = qobject_cast(model()); + if (attachmentModel == Q_NULLPTR) { + Q_ASSERT(0); + return; + } + + int row = -1; + int col = -1; + QModelIndex dropIndex; + if (!dropOn(event, &row, &col, &dropIndex)) { + return; + } + + if (dropIndex.isValid()) { + /* Must be dropped on root. */ + return; + } + + if (row < 0) { + /* Dropping on root is treated as dropping on end. */ + row = attachmentModel->rowCount(); + } + + const QModelIndexList selectedSorted( + DbFlsTblModel::sortedUniqueLineIndexes( + selectionModel()->selectedIndexes(), 0)); + + if (selectedSorted.isEmpty()) { + return; + } + + int firstRow = selectedSorted.first().row(); + int count = selectedSorted.size(); + int lastRow = selectedSorted.last().row(); + if ((lastRow - firstRow + 1) > count) { + /* TODO -- Allow discontinuous selection. */ + logWarningNL("%s", "Discontinuous selection, aborting."); + return; + } + + attachmentModel->moveRows(QModelIndex(), firstRow, count, + QModelIndex(), row); + +} -QList AttachmentTableView::temporaryFiles( - const QTemporaryDir &tmpDir) const +bool AttachmentTableView::droppingOnItself(QDropEvent *event, + const QModelIndex &index) { - QList tmpFileList; - int fileNumber = 0; - const QString tmpPath(tmpDir.path()); - - if (tmpPath.isEmpty()) { - Q_ASSERT(0); - return QList(); - } - - QModelIndexList firstMsgColumnIdxs = - this->selectionModel()->selectedRows(0); - - foreach (const QModelIndex &idx, firstMsgColumnIdxs) { - QString subirPath(tmpPath + QDir::separator() + - QString::number(fileNumber++)); - { - /* - * Create a separate subdirectory because the files - * may have equal names. - */ - QDir dir(tmpPath); - if (!dir.mkpath(subirPath)) { - logError("Could not create directory '%s'.", - subirPath.toUtf8().constData()); - return QList(); + Qt::DropAction dropAction = event->dropAction(); + if (dragDropMode() == QAbstractItemView::InternalMove) { + dropAction = Qt::MoveAction; + } + if ((event->source() == this) && + (event->possibleActions() & Qt::MoveAction) && + (dropAction == Qt::MoveAction)) { + QModelIndexList selectedIdxs = selectedIndexes(); + QModelIndex child = index; + while (child.isValid() && child != rootIndex()) { + if (selectedIdxs.contains(child)) { + return true; } + child = child.parent(); } - QString attachAbsPath(subirPath + QDir::separator()); - { - /* Determine full file path. */ - QModelIndex fileNameIndex = idx.sibling(idx.row(), - DbFlsTblModel::FNAME_COL); - if(!fileNameIndex.isValid()) { - Q_ASSERT(0); - return QList(); - } - QString attachFileName(fileNameIndex.data().toString()); - if (attachFileName.isEmpty()) { - Q_ASSERT(0); - return QList(); - } - attachAbsPath += attachFileName; + } + return false; +} + +bool AttachmentTableView::dropOn(QDropEvent *event, int *dropRow, int *dropCol, + QModelIndex *dropIndex) +{ + /* Inspired y Qt sources. */ + + if (event->isAccepted()) { + return false; + } + + QModelIndex index; + /* rootIndex() (i.e. the viewport) might be a valid index. */ + if (viewport()->rect().contains(event->pos())) { + index = indexAt(event->pos()); + if (!index.isValid() || !visualRect(index).contains(event->pos())) { + index = rootIndex(); } - QByteArray attachData; - { - /* Obtain data. */ - QModelIndex dataIndex = idx.sibling(idx.row(), - DbFlsTblModel::CONTENT_COL); - if (!dataIndex.isValid()) { - Q_ASSERT(0); - return QList(); - } - attachData = QByteArray::fromBase64( - dataIndex.data().toByteArray()); - if (attachData.isEmpty()) { - Q_ASSERT(0); - return QList(); + } + + /* If we are allowed to do the drop. */ + if (model()->supportedDropActions() & event->dropAction()) { + int row = -1; + int col = -1; + if (index != rootIndex()) { + //dropIndicatorPosition = position(event->pos(), visualRect(index), index); + //switch (dropIndicatorPosition) { + switch (position(event->pos(), visualRect(index), index)) { + case QAbstractItemView::AboveItem: + row = index.row(); + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::BelowItem: + row = index.row() + 1; + col = index.column(); + index = index.parent(); + break; + case QAbstractItemView::OnItem: + case QAbstractItemView::OnViewport: + break; } + } else { + //dropIndicatorPosition = QAbstractItemView::OnViewport; } - if (WF_SUCCESS != writeFile(attachAbsPath, attachData, false)) { - return QList(); + *dropIndex = index; + *dropRow = row; + *dropCol = col; + if (!droppingOnItself(event, index)) { + return true; } - - tmpFileList.append(attachAbsPath); } - - return tmpFileList; + return false; } -QList AttachmentTableView::temporaryFileUrls( - const QList &tmpFileNames) +QAbstractItemView::DropIndicatorPosition AttachmentTableView::position( + const QPoint &pos, const QRect &rect, const QModelIndex &index) const { - QList uriList; + QAbstractItemView::DropIndicatorPosition r = + QAbstractItemView::OnViewport; + if (!dragDropOverwriteMode()) { + const int margin = 2; + if (pos.y() - rect.top() < margin) { + r = QAbstractItemView::AboveItem; + } else if (rect.bottom() - pos.y() < margin) { + r = QAbstractItemView::BelowItem; + } else if (rect.contains(pos, true)) { + r = QAbstractItemView::OnItem; + } + } else { + QRect touchingRect = rect; + touchingRect.adjust(-1, -1, 1, 1); + if (touchingRect.contains(pos, false)) { + r = QAbstractItemView::OnItem; + } + } - foreach (const QString &fileName, tmpFileNames) { - uriList.append(QUrl::fromLocalFile(fileName)); + if ((r == QAbstractItemView::OnItem) && + (!(model()->flags(index) & Qt::ItemIsDropEnabled))) { + r = (pos.y() < rect.center().y()) ? + QAbstractItemView::AboveItem : QAbstractItemView::BelowItem; } - return uriList; + return r; } diff -Nru datovka-4.7.0/src/views/attachment_table_view.h datovka-4.7.1/src/views/attachment_table_view.h --- datovka-4.7.0/src/views/attachment_table_view.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/views/attachment_table_view.h 2017-01-19 09:29:26.000000000 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014-2015 CZ.NIC + * Copyright (C) 2014-2016 CZ.NIC * * 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 @@ -24,57 +24,104 @@ #ifndef _ATTACHMENT_TABLE_VIEW_H_ #define _ATTACHMENT_TABLE_VIEW_H_ +#if 0 #include #include #include -#include -#include #include +#endif + +#include "src/views/lowered_table_view.h" /*! * @brief Custom attachment table view class with dragging enabled. */ -class AttachmentTableView : public QTableView { +class AttachmentTableView : public LoweredTableView { Q_OBJECT public: /*! * @brief Constructor. + * + * @param[in] parent Parent widget. */ - AttachmentTableView(QWidget *parent = 0); + explicit AttachmentTableView(QWidget *parent = 0); protected: +#if 0 + /*! + * @brief Allows the drop. + */ + virtual + void dragEnterEvent(QDragEnterEvent *event) Q_DECL_OVERRIDE; +#endif + +#if 0 + /*! + * @brief Allow drag move. + */ + virtual + void dragMoveEvent(QDragMoveEvent *event) Q_DECL_OVERRIDE; +#endif + + /*! + * @brief Processes the drop. + * + * @param[in,out] event Drag event. + */ + virtual + void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE; + +#if 0 /*! * @brief Activates the drag. */ virtual - void mouseMoveEvent(QMouseEvent *event); + void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE; +#endif +#if 0 /* * @brief Used for storing the beginning position of the drag. */ virtual - void mousePressEvent(QMouseEvent *event); + void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE; +#endif private: /*! - * @brief Creates temporary files related to selected view items. + * @brief Preforms displayed data reordering according to drop data. * - * @param[in] tmpDir Temporary directory object. - * @return List of absolute file names or empty list on error. + * @param[in] event Drop event. + */ + void shuffleOnDrop(QDropEvent *event); + + /*! + * @brief Return true if this is a move from ourself and \a index is a + * child of the selection that is being moved. */ - QList temporaryFiles(const QTemporaryDir &tmpDir) const; + bool droppingOnItself(QDropEvent *event, const QModelIndex &index); /*! - * @brief Converts list of absolute file names to list of URLs. + * @brief If the event hasn't already been accepted, determines the + * index to drop on. + * + * if (row == -1 && col == -1) + * // append to this drop index + * else + * // place at row, col in drop index * - * @param[in] tmpFileNames List of absolute file names. - * @return List of URLs or empty list on error. + * If it returns \c true a drop can be done, and dropRow, dropCol + * and dropIndex reflects the position of the drop. */ - static - QList temporaryFileUrls(const QList &tmpFileNames); + bool dropOn(QDropEvent *event, int *dropRow, int *dropCol, + QModelIndex *dropIndex); - QPoint m_dragStartPosition /*!< Holds the starting drag point. */; + /*! + * @brief Determined drop indicator position. + */ + QAbstractItemView::DropIndicatorPosition position(const QPoint &pos, + const QRect &rect, const QModelIndex &index) const; }; #endif /* _ATTACHMENT_TABLE_VIEW_H_ */ diff -Nru datovka-4.7.0/src/views/attachment_table_widget.cpp datovka-4.7.1/src/views/attachment_table_widget.cpp --- datovka-4.7.0/src/views/attachment_table_widget.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/views/attachment_table_widget.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * 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 . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#include -#include -#include -#include - -#include "src/common.h" -#include "src/log/log.h" -#include "src/views/attachment_table_widget.h" - -AttachmentTableWidget::AttachmentTableWidget(QWidget *parent) - : QTableWidget(parent) -{ - setAcceptDrops(true); -} - -int AttachmentTableWidget::addFile(const QString &filePath) -{ - QFile attFile(filePath); - - int fileSize = attFile.size(); - if (0 == fileSize) { - logWarning("Ignoring file '%s' with zero size.\n", - filePath.toUtf8().constData()); - return 0; - } - - QString fileName(QFileInfo(attFile.fileName()).fileName()); - QMimeType mimeType = QMimeDatabase().mimeTypeForFile(attFile); - - int row = this->rowCount(); - - for (int i = 0; i < row; ++i) { - if (this->item(i, ATW_PATH)->text() == filePath) { - /* Already in table. */ - logWarning("File '%s' already in table.\n", - filePath.toUtf8().constData()); - return -1; - } - } - - this->insertRow(row); - - QTableWidgetItem *item = new QTableWidgetItem; - item->setText(fileName); - this->setItem(row, ATW_FILE, item); - item = new QTableWidgetItem; - item->setText(""); - this->setItem(row, ATW_TYPE, item); - item = new QTableWidgetItem; - item->setText(mimeType.name()); - this->setItem(row, ATW_MIME, item); - item = new QTableWidgetItem; - item->setText(QString::number(fileSize)); - this->setItem(row, ATW_SIZE, item); - item = new QTableWidgetItem; - item->setText(filePath); - this->setItem(row, ATW_PATH, item); - item = new QTableWidgetItem; - item->setData(Qt::DisplayRole, getFileBase64(filePath)); - this->setItem(row, ATW_DATA, item); - - return fileSize; -} - -void AttachmentTableWidget::dragEnterEvent(QDragEnterEvent *event) -{ - if (0 == event) { - Q_ASSERT(0); - return; - } - - const QMimeData *mimeData = event->mimeData(); - if (0 == mimeData) { - Q_ASSERT(0); - return; - } - - if (mimeData->hasUrls()) { - event->acceptProposedAction(); - } else { - logInfo("Rejecting drag enter event with mime type '%s'.\n", - mimeData->formats().join(" ").toUtf8().constData()); - } -} - -void AttachmentTableWidget::dragMoveEvent(QDragMoveEvent *event) -{ - if (0 == event) { - Q_ASSERT(0); - return; - } - - event->acceptProposedAction(); -} - -void AttachmentTableWidget::dropEvent(QDropEvent *event) -{ - if (0 == event) { - Q_ASSERT(0); - return; - } - - const QMimeData *mimeData = event->mimeData(); - if (0 == mimeData) { - Q_ASSERT(0); - return; - } - - if (!mimeData->hasUrls()) { - return; - } - - QList paths = filePaths(mimeData->urls()); - - foreach (const QString &filePath, paths) { - addFile(filePath); - } -} - -QList AttachmentTableWidget::filePaths(const QList &uriList) -{ - QList filePaths; - - foreach (const QUrl &uri, uriList) { - if (!uri.isValid()) { - logErrorNL("Dropped invalid URL '%s'.", - uri.toString().toUtf8().constData()); - return QList(); - } - - if (!uri.isLocalFile()) { - logErrorNL("Dropped URL '%s' is not a local file.", - uri.toString().toUtf8().constData()); - return QList(); - } - - filePaths.append(uri.toLocalFile()); - } - - return filePaths; -} - -QByteArray AttachmentTableWidget::getFileBase64(const QString &filePath) - { - QFile file(filePath); - if (file.exists()) { - if (!file.open(QIODevice::ReadOnly)) { - logErrorNL("Could not open file '%s'.", - filePath.toUtf8().constData()); - goto fail; - } - return file.readAll().toBase64(); - } -fail: - return QByteArray(); -} diff -Nru datovka-4.7.0/src/views/attachment_table_widget.h datovka-4.7.1/src/views/attachment_table_widget.h --- datovka-4.7.0/src/views/attachment_table_widget.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/views/attachment_table_widget.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,104 +0,0 @@ -/* - * Copyright (C) 2014-2015 CZ.NIC - * - * 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 . - * - * In addition, as a special exception, the copyright holders give - * permission to link the code of portions of this program with the - * OpenSSL library under certain conditions as described in each - * individual source file, and distribute linked combinations including - * the two. - */ - -#ifndef _ATTACHMENT_TABLE_WIDGET_H_ -#define _ATTACHMENT_TABLE_WIDGET_H_ - -#include -#include -#include -#include -#include -#include - -/* - * Column indexes into attachment table widget. - */ -#define ATW_FILE 0 -#define ATW_TYPE 1 -#define ATW_MIME 2 -#define ATW_SIZE 3 -#define ATW_PATH 4 -#define ATW_DATA 5 /* Base64 encoded and hidden. */ - -/*! - * @brief Custom attachment table widget class with dropping enabled. - */ -class AttachmentTableWidget : public QTableWidget { - Q_OBJECT - -public: - /*! - * @brief Constructor. - */ - AttachmentTableWidget(QWidget *parent = 0); - - /*! - * @brief Adds a file of not already present. - * - * @return File size or -1 on error. - */ - int addFile(const QString &filePath); - -protected: - /*! - * @brief Allows the drop. - */ - virtual - void dragEnterEvent(QDragEnterEvent *event); - - /*! - * @brief Allow drag move. - */ - virtual - void dragMoveEvent(QDragMoveEvent *event); - - /*! - * @brief Processes the drop. - */ - virtual - void dropEvent(QDropEvent *event); - -private: - /*! - * @brief Convert a list of URLs to a list of absolute file paths. - * - * @param[in] uriList List of file URLs. - * @return List of absolute file paths or empty list on error. - */ - static - QList filePaths(const QList &uriList); - - /*! - * @brief Read file content and encode it into base64. - * - * @param[in] filePath Path to file. - * @return Base64-encoded file content. - */ - static - QByteArray getFileBase64(const QString &filePath); - - /* TODO -- File size counter. */ -}; - -#endif /* _ATTACHMENT_TABLE_WIDGET_H_ */ diff -Nru datovka-4.7.0/src/views/lowered_table_view.cpp datovka-4.7.1/src/views/lowered_table_view.cpp --- datovka-4.7.0/src/views/lowered_table_view.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/views/lowered_table_view.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/dimensions/dimensions.h" +#include "src/views/lowered_table_view.h" + +LoweredTableView::LoweredTableView(QWidget *parent) + : QTableView(parent) +{ +} + +void LoweredTableView::setNarrowedLineHeight(void) const +{ + verticalHeader()->setDefaultSectionSize( + Dimensions::tableLineHeight(viewOptions())); +} diff -Nru datovka-4.7.0/src/views/lowered_table_view.h datovka-4.7.1/src/views/lowered_table_view.h --- datovka-4.7.0/src/views/lowered_table_view.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/views/lowered_table_view.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _LOWERED_TABLE_VIEW_H_ +#define _LOWERED_TABLE_VIEW_H_ + +#include + +/*! + * @brief Table view with lowered row height. + */ +class LoweredTableView : public QTableView { + Q_OBJECT + +public: + /*! + * @brief Constructor. + * + * @param[in] parent Parent widget. + */ + explicit LoweredTableView(QWidget *parent = 0); + + /*! + * @brief Sets narrowed row size. + */ + void setNarrowedLineHeight(void) const; +}; + +#endif /* _LOWERED_TABLE_VIEW_H_ */ diff -Nru datovka-4.7.0/src/views/lowered_table_widget.cpp datovka-4.7.1/src/views/lowered_table_widget.cpp --- datovka-4.7.0/src/views/lowered_table_widget.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/views/lowered_table_widget.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/dimensions/dimensions.h" +#include "src/views/lowered_table_widget.h" + +LoweredTableWidget::LoweredTableWidget(QWidget *parent) + : QTableWidget(parent) +{ +} + +void LoweredTableWidget::setNarrowedLineHeight(void) const +{ + verticalHeader()->setDefaultSectionSize( + Dimensions::tableLineHeight(viewOptions())); +} diff -Nru datovka-4.7.0/src/views/lowered_table_widget.h datovka-4.7.1/src/views/lowered_table_widget.h --- datovka-4.7.0/src/views/lowered_table_widget.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/views/lowered_table_widget.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _LOWERED_TABLE_WIDGET_H_ +#define _LOWERED_TABLE_WIDGET_H_ + +#include + +/*! + * @brief Table widget with lowered row height. + */ +class LoweredTableWidget : public QTableWidget { + Q_OBJECT + +public: + /*! + * @brief Constructor. + * + * @param[in] parent Parent widget. + */ + explicit LoweredTableWidget(QWidget *parent = 0); + + /*! + * @brief Sets narrowed row size. + */ + void setNarrowedLineHeight(void) const; +}; + +#endif /* _LOWERED_TABLE_WIDGET_H_ */ diff -Nru datovka-4.7.0/src/web/json.cpp datovka-4.7.1/src/web/json.cpp --- datovka-4.7.0/src/web/json.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/web/json.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,1321 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/common.h" +#include "src/web/json.h" +#include "src/web/net.h" +#include "src/io/wd_sessions.h" +#include "src/gui/dlg_login_mojeid.h" + +JsonLayer jsonlayer; + +JsonLayer::JsonLayer(QObject *parent) + : QObject(parent) +{ +} + +JsonLayer::~JsonLayer(void) +{ +} + +QNetworkCookie JsonLayer::fakeLoginWebDatovka(void) +{ + QUrl url(QString(WEBDATOVKA_SERVICE_URL) + "desktoplogin"); + QByteArray reply; + QNetworkCookie sessionid; + netmanager.createGetRequestWebDatovka(url, sessionid, reply); + + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_SESSION_ID) { + sessionid = cookieList.at(i); + } + } + + return sessionid; +} + + +bool JsonLayer::startLoginToWebDatovka(QUrl &lastUrl) +{ + QByteArray reply; + QNetworkCookie sessionid; + QByteArray postData; + + // STEP 1: call webdatovka for start login procedure (GET). + // We should obtain url for redirect + // and openconnect parameter list (postdata). + QUrl url(QString(WEBDATOVKA_SERVICE_URL) + "desktoplogin"); + netmanager.createPostRequestWebDatovka(url, sessionid, postData, reply); + lastUrl = url; + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + url.setUrl(jsonObject["url"].toString()); + if (!url.isValid()) { + return false; + } + + // Create formdata string from json + QJsonObject postdata = jsonObject["postdata"].toObject(); + QVariantMap map = postdata.toVariantMap(); + QVariantMap::iterator i; + for (i = map.begin(); i != map.end(); ++i) { + postData.append(i.key()).append("=").append(i.value().toString()).append("&"); + } + + // STEP 2: Call mojeID for starting of login procedure (POST). + // We send openconnect parameter list as postdata. + netmanager.createPostRequestMojeId(url, lastUrl, postData, reply); + lastUrl = url; + + return true; +} + + +bool JsonLayer::loginMethodChanged(int method, QString &lastUrl, QString &token) +{ + QByteArray reply; + QUrl url; + if (method == USER_NAME) { + url.setUrl(MOJEID_URL_PASSWORD); + } else if (method == CERTIFICATE) { + url.setUrl(MOJEID_URL_CERTIFICATE); + } else { + url.setUrl(MOJEID_URL_OTP); + } + + // STEP 3: Call to mojeID on new login endpoint (GET). + // We should obtain html page. From page we must get token. + netmanager.createGetRequestMojeId(url, QUrl(lastUrl), reply); + lastUrl = url.toString(); + + QString html(reply); + QRegularExpression exp("captured(1); + } + + return true; +} + +bool JsonLayer::loginToMojeID(const QString &lastUrl, + const QString &token, const QString &username, + const QString &pwd, const QString &otp, const QString &certPath, + QString &errStr, QNetworkCookie &sessionid) +{ + QByteArray reply; + QUrl lUrl(lastUrl); + QUrl url; + + errStr = tr("Login to mojeID failed. You must choose correct " + "login method and enter correct login data. Try again."); + + // STEP 4: Send credential to mojeID endpoint (POST). + // We send login data, csrfmiddlewaretoken + // and mojeid token as content. OTP or certificate data optionaly. + url.setUrl(MOJEID_URL_CERTIFICATE); + + QString str = "csrfmiddlewaretoken="; + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_CSRFTOKEN) { + str += cookieList.at(i).value(); + } + } + str += "&token=" + token; + str += "&username=" + username; + if (!pwd.isEmpty()) { + url.setUrl(MOJEID_URL_PASSWORD); + str += "&password=" + pwd; + } + if (!otp.isEmpty()) { + url.setUrl(MOJEID_URL_OTP); + str += "&otp_token=" + otp; + } + str += "&allow=prihlasit+se"; + QByteArray data; + data.append(str); + netmanager.createPostRequestMojeId(url, lUrl, data, reply); + lUrl = url; + + if (lUrl.toString() == MOJEID_URL_CERTIFICATE) { + + url.setUrl(MOJEID_URL_SSLLOGIN); + + QFile certFile(certPath); + if (!certFile.open(QIODevice::ReadOnly)) { + errStr = tr("Cannot open client certificate from path '%1'").arg(certPath); + return false; + } + + bool ok; + const QString passPhrase = QInputDialog::getText(0, + tr("Certificate password"), + tr("Enter certificate password:"), + QLineEdit::Password, NULL, &ok); + + QFileInfo finfo(certFile); + QString ext = finfo.suffix().toLower(); + if (ext == "pem") { + QByteArray certData = certFile.readAll(); + QSslCertificate cert(certData, QSsl::Pem); + QSslKey key(certData, QSsl::Rsa, QSsl::Pem, + QSsl::PrivateKey, passPhrase.toUtf8()); + netmanager.createPostRequestMojeIdCert(url, lUrl, + data, cert, key, reply); + } +#if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) + else if (ext == "p12" || ext == "pfx") { + // is PKCS12 format + QSslCertificate cert; + QSslKey key; + QList importedCerts; + if (QSslCertificate::importPkcs12(&certFile, &key, + &cert, &importedCerts, passPhrase.toUtf8())) { + netmanager.createPostRequestMojeIdCert(url, + lUrl, data, cert, key, reply); + } else { + errStr = tr("Cannot parse client certificate from path '%1'").arg(certPath); + return false; + } + } +#else /* < Qt-5.4 */ +#warning "Compiling against version < Qt-5.4 which does not have QSslCertificate::importPkcs12()." +#endif /* >= Qt-5.4 */ + lUrl = url; + } + + // STEP 5: send confiramtion to mojeID endpoint (POST). + // We send new csrfmiddlewaretoken + // and mojeid token and other values as content. + url.setUrl(MOJEID_URL_CONFIRM); + str = "csrfmiddlewaretoken="; + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_CSRFTOKEN) { + str += cookieList.at(i).value(); + } + } + str += "&token=" + token; + str += "&username=" + username; + str += "&first_name=first_name"; + str += "&last_name=last_name"; + str += "&email_default=email_default"; + str += "&allow=OK"; + data.clear(); + data.append(str); + netmanager.createPostRequestMojeId(url, lUrl, data, reply); + lUrl = url; + + /* TODO - repeat login proccess if confirmation failed */ + + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_SESSION_ID) { + sessionid = cookieList.at(i); + } + } + + // STEP 6: redirect mojeID responce to webdatovka (GET). + // We send mojeid parametrs in get url. + url.setUrl(netmanager.newUrl); + netmanager.createGetRequestWebDatovka(url, sessionid, reply); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + if (!jsonObject["errmsg"].toString().isEmpty()) { + errStr = jsonObject["errmsg"].toString(); + } + } else { + if (!jsonObject["warning"].toString().isEmpty()) { + errStr = jsonObject["warning"].toString(); + } + // Now, you are logged to webdatovka and you have sessionid cookie. + // Next requests/operations only via new sessionid. + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_SESSION_ID) { + sessionid = cookieList.at(i); + } + } + return true; + } + + return false; +} + + +bool JsonLayer::isLoggedToWebDatovka(const QString &userName, + QNetworkCookie &sessionid) +{ + sessionid = wdSessions.sessionCookie(userName); + if (sessionid.value().isEmpty()) { + return false; + } + + return true; +} + + +bool JsonLayer::updateSessionId(const QString &userName) +{ + QNetworkCookie sessionid; + + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_SESSION_ID) { + sessionid = cookieList.at(i); + } + } + + return wdSessions.setSessionCookie(userName, sessionid); +} + + +bool JsonLayer::pingServer(const QString &userName, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + netmanager.createGetRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "ping"), sessionid, reply); + + updateSessionId(userName); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::createAccount(const QString &userName,const QString &name, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["name"] = name; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "newaccount"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + /* TODO - parse new account data and store to db + * Here is not API implemented yet. + */ + + return true; +} + + +bool JsonLayer::renameAccount(const QString &userName, int accountID, + const QString &newName, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["account"] = accountID; + rootObj["name"] = newName; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "renameaccount"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::deleteAccount(const QString &userName, int accountID, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["account"] = accountID; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deleteaccount"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::getAccountList(const QNetworkCookie &sessionid, int &userId, + QList &accountList, QString &errStr) +{ + QByteArray reply; + + netmanager.createGetRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "accountlist"), sessionid, + reply); + + if (reply.isEmpty()) { + return false; + } + + return parseAccountList(reply, userId, accountList, errStr); +} + + +bool JsonLayer::getMessageList(const QString &userName, int accountID, + int messageType, int limit, int offset, + QList &messageList, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["account"] = accountID; + rootObj["folder"] = messageType; + rootObj["offset"] = offset; + rootObj["limit"] = limit; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "msgenvelopelist"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + return parseMessageList(reply, messageList, errStr); +} + + +bool JsonLayer::syncAccount(const QString &userName, int accountID, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["account"] = accountID; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "synchronize"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +QByteArray JsonLayer::downloadMessage(const QString &userName, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return QByteArray(); + } + + netmanager.createGetRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "downloadsigned/" + + QString::number(msgId)), sessionid, reply); + + updateSessionId(userName); + + return reply; +} + + +QByteArray JsonLayer::downloadFile(const QString &userName, int fileId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return QByteArray(); + } + + netmanager.createGetRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "downloadfile/" + + QString::number(fileId)), sessionid, reply); + + updateSessionId(userName); + + return reply; +} + + +bool JsonLayer::getTagList(const QString &userName, + QList &tagList, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "listtags"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + return parseTagList(reply, tagList, errStr); +} + + +int JsonLayer::createTag(const QString &userName, const QString &name, + const QString &color, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["name"] = name; + rootObj["color"] = color; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "newtag"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return -1; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return -1; + } + return jsonObject["id"].toInt(); +} + + +bool JsonLayer::updateTag(const QString &userName, int tagId, const QString &name, + const QString &color, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["id"] = tagId; + rootObj["name"] = name; + rootObj["color"] = color; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "edittag"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::deleteTag(const QString &userName, int tagId, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["id"] = tagId; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deletetag"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::assignTag(const QString &userName, int tagId, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["id"] = tagId; + rootObj["msgid"] = msgId; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/add"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::removeTag(const QString &userName, int tagId, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["id"] = tagId; + rootObj["msgid"] = msgId; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/remove"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::removeAllTags(const QString &userName, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["msgid"] = msgId; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "tagmsg/removeall"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::searchRecipient(const QString &userName, int accountID, + const QString &word, int position, + QList &resultList, bool &hasMore, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + rootObj["account"] = accountID; + rootObj["needle"] = word; + rootObj["position"] = position; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "searchrecipient"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + return parseSearchRecipient(reply, resultList, hasMore, errStr); +} + + +bool JsonLayer::sendMessage(const QString &userName, int accountID, + const QList &recipientList, + const JsonLayer::Envelope &envelope, + const QList &fileList, + QStringList &resultList, QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonArray recipienList; + foreach (const JsonLayer::Recipient &recipient, recipientList) { + QJsonObject recData; + recData["db_id_recipient"] = recipient.recipientDbId; + recData["name"] = recipient.recipientName; + recData["address"] = recipient.recipientAddress; + recData["dm_to_hands"] = recipient.toHands; + recipienList.append(recData); + } + + QJsonObject msgEnvelope; + msgEnvelope["dm_annotation"] = envelope.dmAnnotation; + if (!envelope.dmRecipientIdent.isEmpty()) { + msgEnvelope["dm_recipient_ident"] = envelope.dmRecipientIdent; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_recipient_ref_number"] = + envelope.dmRecipientRefNumber; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_sender_ident"] = envelope.dmSenderIdent; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_sender_ref_number"] = envelope.dmSenderRefNumber; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_legal_title_law"] = envelope.dmLegalTitleLaw; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_legal_title_par"] = envelope.dmLegalTitlePar; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_legal_title_point"] = envelope.dmLegalTitlePoint; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_legal_title_sect"] = envelope.dmLegalTitleSect; + } + if (!envelope.dmRecipientRefNumber.isEmpty()) { + msgEnvelope["dm_legal_title_year"] = envelope.dmLegalTitleYear; + } + msgEnvelope["dm_personal_delivery"] = envelope.dmPersonalDelivery; + msgEnvelope["dm_allow_subst_delivery"] = envelope.dmAllowSubstDelivery; + msgEnvelope["dm_publish_own_id"] = envelope.dmPublishOwnID; + msgEnvelope["dm_ovm"] = envelope.dmOVM; + msgEnvelope["account"] = accountID; + msgEnvelope["rcpt"] = recipienList; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "saveenvelope"), sessionid, + QJsonDocument(msgEnvelope).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + int draftId = jsonObject["draft_id"].toInt(); + + /* TODO - check returned bool */ + foreach (const JsonLayer::File &file, fileList) { + netmanager.createPostRequestWebDatovkaSendFile( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "uploadonefile"), + sessionid, draftId, file.fName, + QByteArray::fromBase64(file.fContent), reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + jsonResponse = QJsonDocument::fromJson(reply); + jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + } + + QJsonObject rootObj; + rootObj["draft_id"] = draftId; + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "senddraft"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + jsonResponse = QJsonDocument::fromJson(reply); + jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + QString result; + QJsonArray errorArray = jsonObject["errors"].toArray(); + foreach (const QJsonValue &value, errorArray) { + QJsonObject obj = value.toObject(); + result = obj["dbID"].toString() + "§" + obj["msg"].toString(); + resultList.append(result); + } + + return true; +} + + +bool JsonLayer::deleteMessage(const QString &userName, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + QJsonArray array; + array.append(msgId); + rootObj["msg_id"] = array; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "deletemessage"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + + +bool JsonLayer::markMessageAsRead(const QString &userName, int msgId, + QString &errStr) +{ + QByteArray reply; + QNetworkCookie sessionid; + + if (!isLoggedToWebDatovka(userName, sessionid)) { + errStr = tr("User is not logged to mojeID"); + return false; + } + + QJsonObject rootObj; + QJsonArray array; + array.append(msgId); + rootObj["msg_id"] = array; + + netmanager.createPostRequestWebDatovka( + QUrl(QString(WEBDATOVKA_SERVICE_URL) + "markasread"), sessionid, + QJsonDocument(rootObj).toJson(QJsonDocument::Compact), + reply); + + updateSessionId(userName); + + if (reply.isEmpty()) { + errStr = tr("Reply content missing"); + return false; + } + + QJsonDocument jsonResponse = QJsonDocument::fromJson(reply); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + return true; +} + +bool JsonLayer::parseAccountList(const QByteArray &content, int &userId, + QList &accountList, QString &errStr) +{ + QJsonDocument jsonResponse = QJsonDocument::fromJson(content); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + userId = jsonObject["userId"].toInt(); + QJsonArray jsonArray = jsonObject["accountsList"].toArray(); + + foreach (const QJsonValue &value, jsonArray) { + QJsonObject obj = value.toObject(); + JsonLayer::AccountData aData; + aData.userId = userId; + aData.accountId = obj["id"].toInt(); + aData.name = obj["name"].toString(); + QJsonObject owner = obj["owner"].toObject(); + QJsonObject user = obj["user"].toObject(); + + aData.ownerInfo.key = obj["id"].toString(); + aData.ownerInfo.dbID = owner["db_id"].toString(); + aData.ownerInfo.dbType = owner["db_type"].toString(); + aData.ownerInfo.ic = owner["ic_db"].toString().isEmpty() ? + NULL : owner["ic_db"].toString(); + aData.ownerInfo.pnFirstName = + owner["pn_first_name"].toString().isEmpty() ? + NULL : owner["pn_first_name"].toString(); + aData.ownerInfo.pnMiddleName = + owner["pn_middle_name"].toString().isEmpty() ? + NULL : owner["pn_middle_name"].toString(); + aData.ownerInfo.pnLastName = + owner["pn_last_name"].toString().isEmpty() ? + NULL : owner["pn_last_name"].toString(); + aData.ownerInfo.pnLastNameAtBirth = + owner["pn_last_name_at_birth"].toString().isEmpty() ? + NULL : owner["pn_last_name_at_birth"].toString(); + aData.ownerInfo.firmName = + owner["firm_name"].toString().isEmpty() ? + NULL : owner["firm_name"].toString(); + aData.ownerInfo.biDate = + owner["bi_date"].toString().isEmpty() ? + NULL : owner["bi_date"].toString(); + aData.ownerInfo.biCity = + owner["bi_city"].toString().isEmpty() ? + NULL : owner["bi_city"].toString(); + aData.ownerInfo.biCounty = + owner["bi_county"].toString().isEmpty() ? + NULL : owner["bi_county"].toString(); + aData.ownerInfo.biState = + owner["bi_state"].toString().isEmpty() ? + NULL : owner["bi_state"].toString(); + aData.ownerInfo.adCity = + owner["ad_city"].toString().isEmpty() ? + NULL : owner["ad_city"].toString(); + aData.ownerInfo.adStreet = + owner["ad_street"].toString().isEmpty() ? + NULL : owner["ad_street"].toString(); + aData.ownerInfo.adNumberInStreet = + owner["ad_number_in_street"].toString().isEmpty() ? + NULL : owner["ad_number_in_street"].toString(); + aData.ownerInfo.adNumberInMunicipality = + owner["ad_number_in_municipality"].toString().isEmpty() ? + NULL : owner["ad_number_in_municipality"].toString(); + aData.ownerInfo.adZipCode = + owner["ad_zip_code"].toString().isEmpty() ? + NULL : owner["ad_zip_code"].toString(); + aData.ownerInfo.adState = + owner["ad_state"].toString().isEmpty() ? + NULL : owner["ad_state"].toString(); + aData.ownerInfo.nationality = + owner["nationality"].toString().isEmpty() ? + NULL : owner["nationality"].toString(); + aData.ownerInfo.identifier = + owner["identifier"].toString().isEmpty() ? + NULL : owner["identifier"].toString(); + aData.ownerInfo.registryCode = + owner["registry_code"].toString().isEmpty() ? + NULL : owner["registry_code"].toString(); + aData.ownerInfo.dbState = owner["db_state"].toInt(); + aData.ownerInfo.dbEffectiveOVM = + owner["db_effective_ovm"].toBool(); + aData.ownerInfo.dbOpenAddressing = + owner["db_open_addressing"].toBool(); + + aData.userInfo.key = obj["user_id"].toString(); + aData.userInfo.pnFirstName = + user["pn_first_name"].toString().isEmpty() ? + NULL : user["pn_first_name"].toString(); + aData.userInfo.pnMiddleName = + user["pn_middle_name"].toString().isEmpty() ? + NULL : user["pn_middle_name"].toString(); + aData.userInfo.pnLastName = + user["pn_last_name"].toString().isEmpty() ? + NULL : user["pn_last_name"].toString(); + aData.userInfo.pnLastNameAtBirth = + user["pn_last_name_at_birth"].toString().isEmpty() ? + NULL : user["pn_last_name_at_birth"].toString(); + aData.userInfo.adCity = user["ad_city"].toString().isEmpty() ? + NULL : user["ad_city"].toString(); + aData.userInfo.adStreet = + user["ad_street"].toString().isEmpty() ? + NULL : user["ad_street"].toString(); + aData.userInfo.adNumberInStreet = + user["ad_number_in_street"].toString().isEmpty() ? + NULL : user["ad_number_in_street"].toString(); + aData.userInfo.adNumberInMunicipality = + user["ad_number_in_municipality"].toString().isEmpty() ? + NULL : user["ad_number_in_municipality"].toString(); + aData.userInfo.adZipCode = + user["ad_zip_code"].toString().isEmpty() ? + NULL : user["ad_zip_code"].toString(); + aData.userInfo.adState = + user["ad_state"].toString().isEmpty() ? + NULL : user["ad_state"].toString(); + aData.userInfo.biDate = user["bi_date"].toString().isEmpty() ? + NULL : user["bi_date"].toString(); + aData.userInfo.userType = + user["user_type"].toString().isEmpty() ? + NULL : user["user_type"].toString(); + aData.userInfo.userPrivils = user["user_privils"].toInt(); + aData.userInfo.ic = user["ic_db"].toInt(); + aData.userInfo.firmName = + user["firm_name"].toString().isEmpty() ? + NULL : user["firm_name"].toString(); + aData.userInfo.caStreet = + user["ca_street"].toString().isEmpty() ? + NULL : user["ca_street"].toString(); + aData.userInfo.caCity = user["ca_city"].toString().isEmpty() ? + NULL : user["ca_city"].toString(); + aData.userInfo.caZipCode = + user["ca_zip_code"].toString().isEmpty() ? + NULL : user["ca_zip_code"].toString(); + aData.userInfo.caState = + user["ca_state"].toString().isEmpty() ? + NULL : user["ca_state"].toString(); + + accountList.append(aData); + } + + return true; +} + + +bool JsonLayer::parseMessageList(const QByteArray &content, + QList &messageList, QString &errStr) +{ + QJsonDocument jsonResponse = QJsonDocument::fromJson(content); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + QJsonArray messageArray = jsonObject["messages"].toArray(); + + foreach (const QJsonValue &value, messageArray) { + QJsonObject obj = value.toObject(); + Envelope mEvnelope; + mEvnelope._tagList.clear(); + mEvnelope._read = obj["read"].toBool(); + + QJsonObject envel = obj["envelope"].toObject(); + mEvnelope.id = envel["id"].toInt(); + mEvnelope.dmID = envel["dm_id"].toString().toLongLong(); + mEvnelope.dbIDRecipient = envel["db_id_recipient"].toString(); + mEvnelope.dbIDSender = envel["db_id_sender"].toString(); + mEvnelope.dmAcceptanceTime = envel["dm_acceptance_time"].toString(); + mEvnelope.dmAllowSubstDelivery = envel["dm_allow_subst_delivery"].toBool(); + mEvnelope.dmAmbiguousRecipient = envel["dm_ambiguous_recipient"].toBool(); + mEvnelope.dmAnnotation = envel["dm_annotation"].toString(); + mEvnelope.dmAttachmentSize = envel["dm_attachment_size"].toInt(); + mEvnelope.dmDeliveryTime = envel["dm_delivery_time"].toString(); + mEvnelope.dmLegalTitleLaw = envel["dm_legal_title_law"].toString(); + mEvnelope.dmLegalTitlePar = envel["dm_legal_title_par"].toString(); + mEvnelope.dmLegalTitlePoint = envel["dm_legal_title_point"].toString(); + mEvnelope.dmLegalTitleSect = envel["dm_legal_title_sect"].toString(); + mEvnelope.dmLegalTitleYear = envel["dm_legal_title_year"].toString(); + mEvnelope.dmMessageStatus = envel["dm_message_status"].toInt(); + mEvnelope.dmPersonalDelivery = envel["dm_personal_delivery"].toBool(); + mEvnelope.dmRecipient = envel["dm_recipient"].toString(); + mEvnelope.dmRecipientAddress = envel["dm_recipient_address"].toString(); + mEvnelope.dmRecipientIdent = envel["dm_recipient_ident"].toString(); + mEvnelope.dmRecipientOrgUnit = envel["dm_recipient_org_unit"].toString(); + mEvnelope.dmRecipientOrgUnitNum = envel["dm_recipient_org_unit_num"].toString(); + mEvnelope.dmRecipientRefNumber = envel["dm_recipient_ref_number"].toString(); + mEvnelope.dmSender = envel["dm_sender"].toString(); + mEvnelope.dmSenderAddress = envel["dm_sender_address"].toString(); + mEvnelope.dmSenderIdent = envel["dm_sender_ident"].toString(); + mEvnelope.dmSenderOrgUnit = envel["dm_sender_org_unit"].toString(); + mEvnelope.dmSenderOrgUnitNum = envel["dm_sender_org_unit_num"].toString(); + mEvnelope.dmSenderRefNumber = envel["dm_sender_ref_number"].toString(); + mEvnelope.dmSenderType = envel["dm_sender_type"].toInt(); + mEvnelope.dmToHands = envel["dm_to_hands"].toString(); + mEvnelope.dmType = envel["dm_type"].toInt(); + + QJsonArray tagArray = obj["tags"].toArray(); + foreach (const QJsonValue &value, tagArray) { + mEvnelope._tagList.append(value.toInt()); + } + + messageList.append(mEvnelope); + } + + return true; +} + + +bool JsonLayer::parseTagList(const QByteArray &content, + QList &tagList, QString &errStr) +{ + QJsonDocument jsonResponse = QJsonDocument::fromJson(content); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + QJsonArray tagArray = jsonObject["tags"].toArray(); + + foreach (const QJsonValue &value, tagArray) { + QJsonObject obj = value.toObject(); + Tag tag; + tag.id = obj["id"].toInt(); + tag.name = obj["name"].toString(); + tag.color = obj["color"].toString(); + tagList.append(tag); + } + + return true; +} + + +bool JsonLayer::parseSearchRecipient(const QByteArray &content, + QList &resultList, bool &hasMore, + QString &errStr) +{ + QJsonDocument jsonResponse = QJsonDocument::fromJson(content); + QJsonObject jsonObject = jsonResponse.object(); + if (!jsonObject["success"].toBool()) { + errStr = jsonObject["errmsg"].toString(); + return false; + } + + hasMore = jsonObject["hasMore"].toBool(); + + QJsonArray recipientArray = jsonObject["results"].toArray(); + + foreach (const QJsonValue &value, recipientArray) { + QJsonObject obj = value.toObject(); + Recipient rec; + rec.recipientDbId = obj["id"].toString(); + rec.recipientName = obj["name"].toString(); + rec.recipientAddress = obj["address"].toString(); + rec.toHands = ""; + resultList.append(rec); + } + + return true; +} diff -Nru datovka-4.7.0/src/web/json.h datovka-4.7.1/src/web/json.h --- datovka-4.7.0/src/web/json.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/web/json.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,548 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _JSON_H_ +#define _JSON_H_ + +#include +#include +#include +#include + +#include "src/models/accounts_model.h" +#include "src/io/message_db.h" + +class JsonLayer : public QObject { + Q_OBJECT + +public: + + /*! + * @brief Holds information about owner and his databox. + */ + struct OwnerInfo { + public: + QString key; + QString dbID; + QString dbType; + QString ic; + QString pnFirstName; + QString pnMiddleName; + QString pnLastName; + QString pnLastNameAtBirth; + QString firmName; + QString biDate; + QString biCity; + QString biCounty; + QString biState; + QString adCity; + QString adStreet; + QString adNumberInStreet; + QString adNumberInMunicipality; + QString adZipCode; + QString adState; + QString nationality; + QString identifier; + QString registryCode; + int dbState; + bool dbEffectiveOVM; + bool dbOpenAddressing; + }; + + /*! + * @brief Holds information about an user. + */ + struct UserInfo { + public: + QString key; + QString pnFirstName; + QString pnMiddleName; + QString pnLastName; + QString pnLastNameAtBirth; + QString adCity; + QString adStreet; + QString adNumberInStreet; + QString adNumberInMunicipality; + QString adZipCode; + QString adState; + QString biDate; + QString userType; + int userPrivils; + int ic; + QString firmName; + QString caStreet; + QString caCity; + QString caZipCode; + QString caState; + }; + + /*! + * @brief Holds information about an tag properties. + */ + struct Tag { + public: + int id; + QString name; + QString color; + }; + + /*! + * @brief Holds data about recipient + */ + struct Recipient { + public: + QString recipientDbId; + QString recipientName; + QString recipientAddress; + QString toHands; + }; + + /*! + * @brief Holds file data + */ + struct File { + public: + QString fName; + QByteArray fContent; + }; + + /*! + * @brief Holds message envelope data from webdatovka. + */ + class Envelope { + public: + int id; + qint64 dmID; + QString dbIDSender; + QString dmSender; + QString dmSenderAddress; + int dmSenderType; + QString dmRecipient; + QString dmRecipientAddress; + QString dmAmbiguousRecipient; + QString dmSenderOrgUnit; + QString dmSenderOrgUnitNum; + QString dbIDRecipient; + QString dmRecipientOrgUnit; + QString dmRecipientOrgUnitNum; + QString dmToHands; + QString dmAnnotation; + QString dmRecipientRefNumber; + QString dmSenderRefNumber; + QString dmRecipientIdent; + QString dmSenderIdent; + QString dmLegalTitleLaw; + QString dmLegalTitleYear; + QString dmLegalTitleSect; + QString dmLegalTitlePar; + QString dmLegalTitlePoint; + bool dmPersonalDelivery; + bool dmAllowSubstDelivery; + QString dmQTimestamp; + QString dmDeliveryTime; + QString dmAcceptanceTime; + int dmMessageStatus; + int dmAttachmentSize; + QString dmType; + bool dmPublishOwnID; + bool dmOVM; + bool _read; + QList _tagList; + }; + + /*! + * @brief Holds account data and user info from webdatovka. + */ + struct AccountData { + public: + int userId; + int accountId; + QString name; + JsonLayer::OwnerInfo ownerInfo; + JsonLayer::UserInfo userInfo; + }; + + explicit JsonLayer(QObject *parent = 0); + ~JsonLayer(void); + + /*! + * @brief Fake login to Webdatovka - will be removed. + * + * @return sessionid from webdatovka. + */ + QNetworkCookie fakeLoginWebDatovka(void); + + /*! + * @brief First part of login to Webdatovka. + * Call webdatovka to obtain openconnect data. + * + * @param[out] lastUrl - last url of login sequence. + * @return true if first part was successed. + */ + bool startLoginToWebDatovka(QUrl &lastUrl); + + /*! + * @brief Middle part of login to Webdatovka. + * + * @param[in] method - selected login method. + * @param[in/out] lastUrl - last url of login sequence. + * @param[out] token - html security token. + * @return true if middle part was successed. + */ + bool loginMethodChanged(int method, QString &lastUrl, QString &token); + + /*! + * @brief Last part of login to Webdatovka. + * + * @param[in] lastUrl - last url of login sequence. + * @param[in] token - html security token. + * @param[in] username - mojeID username. + * @param[in] pwd - mojeID password. + * @param[in] otp - OTP password (optional). + * @param[in] certPath - path to certificate file. + * @param[out] errStr - contains an error string if unssucces. + * @param[out] sessionid - contains webdatovka sessionid. + * @return true if login success. + */ + bool loginToMojeID(const QString &lastUrl, + const QString &token, const QString &username, + const QString &pwd, const QString &otp, const QString &certPath, + QString &errStr, QNetworkCookie &sessionid); + + /*! + * @brief Ping to Webdatovka. + * + * @param[in] userName - account username. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool pingServer(const QString &userName, QString &errStr); + + /*! + * @brief Add account into Webdatovka. + * + * @param[in] userName - account username. + * @param[in] name - name of account. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool createAccount(const QString &userName, + const QString &name, QString &errStr); + + /*! + * @brief Update account name in Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[in] newName - new name of account. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool renameAccount(const QString &userName, + int accountID, const QString &newName, QString &errStr); + + /*! + * @brief Delete account from Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool deleteAccount(const QString &userName, + int accountID, QString &errStr); + + /*! + * @brief Download all accounts from Webdatovka for one mojeID identity. + * + * @param[in] sessionid - sessionid cookie of Webdatovka. + * @param[out] userId - mojeID user id. + * @param[out] accountList - list of accounts. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool getAccountList(const QNetworkCookie &sessionid, int &userId, + QList &accountList, + QString &errStr); + + /*! + * @brief Download current message list (envelopes) from Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[in] messageType - webadatovka message type (sent = -1, received = 1); + * @param[in] limit - how many records mat be returned. + * @param[in] offset - default is 0. + * @param[out] messageList - list of message envelopes. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool getMessageList(const QString &userName, + int accountID, int messageType, int limit, + int offset, QList &messageList, + QString &errStr); + + /*! + * @brief Synchronize one account with isds via Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool syncAccount(const QString &userName, + int accountID, QString &errStr); + + /*! + * @brief Download complete message from Webdatovka. + * + * @param[in] userName - account username. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return message zfo binary data or NULL. + */ + QByteArray downloadMessage(const QString &userName, + int msgId, QString &errStr); + + /*! + * @brief Download one file of message from Webdatovka. + * + * @param[in] userName - account username. + * @param[in] fileId - webdatovka file id. + * @param[out] errStr - contains an error string if unssucces. + * @return file binary data or NULL. + */ + QByteArray downloadFile(const QString &userName, + int fileId, QString &errStr); + + /*! + * @brief Download tag list from Webdatovka for username. + * + * @param[in] userName - account username. + * @param[out] tagList - list of tag attributes. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool getTagList(const QString &userName, + QList &tagList, QString &errStr); + + /*! + * @brief Create tag in Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] name - tag name. + * @param[in] color - tag color. + * @param[out] errStr - contains an error string if unssucces. + * @return true webdatovka id of new tag if success else -1. + */ + int createTag(const QString &userName, + const QString &name, const QString &color, QString &errStr); + + /*! + * @brief Update tag data into Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] tagId - webdatovka tag id. + * @param[in] name - tag name. + * @param[in] color - tag color. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool updateTag(const QString &userName, int tagId, + const QString &name, const QString &color, QString &errStr); + + /*! + * @brief Delete tag from Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] tagId - webdatovka tag id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool deleteTag(const QString &userName, + int tagId, QString &errStr); + + /*! + * @brief Assign tag to message in Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] tagId - webdatovka tag id. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool assignTag(const QString &userName, + int tagId, int msgId, QString &errStr); + + /*! + * @brief Remove tag assigment from message in Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] tagId - webdatovka tag id. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool removeTag(const QString &userName, + int tagId, int msgId, QString &errStr); + + /*! + * @brief Remove all tags from message in Webdatovka for username. + * + * @param[in] userName - account username. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool removeAllTags(const QString &userName, + int msgId, QString &errStr); + + /*! + * @brief Search recipients via Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[in] word - word for search. + * @param[in] position - result list part, firstly is 0. + * @param[out] resultList - list of recipients, where message was sent. + * @param[out] hasMore - another list part of recipents is available. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool searchRecipient(const QString &userName, + int accountID, const QString &word, int position, + QList &resultList, bool &hasMore, + QString &errStr); + + /*! + * @brief Send message to recipients via Webdatovka. + * + * @param[in] userName - account username. + * @param[in] accountID - webdatovka id of account. + * @param[in] recipientList - another recipents are available. + * @param[in] envelope - message envelope data. + * @param[in] fileList - list of files (attachments). + * @param[out] resultList - list of recipients, where message was sent. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool sendMessage(const QString &userName, int accountID, + const QList &recipientList, + const JsonLayer::Envelope &envelope, + const QList &fileList, + QStringList &resultList, QString &errStr); + + /*! + * @brief Delete message from Webdatovka. + * + * @param[in] userName - account username. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool deleteMessage(const QString &userName, int msgI, QString &errStr); + + /*! + * @brief Mark messages as read in Webdatovka. + * + * @param[in] userName - account username. + * @param[in] msgId - webdatovka message id. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool markMessageAsRead(const QString &userName, int msgId, + QString &errStr); + +private: + + /*! + * @brief Test if user is logged to Webdatovka. + * + * @param[in] userName - account username. + * @param[out] sessionid - sessionid cookie for GET/POST reguests. + * @return true if user is logged. + */ + bool isLoggedToWebDatovka(const QString &userName, + QNetworkCookie &sessionid); + + /*! + * @brief Update sessionid cookie. + * + * @param[in] userName - account username. + * @return true if success. + */ + bool updateSessionId(const QString &userName); + + /*! + * @brief Parse account list. + * + * @param[in] content - reply content. + * @param[out] userId - mojeID user id. + * @param[out] accountList - list of accounts. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool parseAccountList(const QByteArray &content, int &userId, + QList &accountList, + QString &errStr); + + /*! + * @brief Parse message list. + * + * @param[in] content - reply content. + * @param[out] messageList - list of message envelopes. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool parseMessageList(const QByteArray &content, + QList &messageList, QString &errStr); + + /*! + * @brief Parse tag list. + * + * @param[in] content - reply content. + * @param[out] tagList - list of tag attributes. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool parseTagList(const QByteArray &content, + QList &tagList, QString &errStr); + + /*! + * @brief Parse recipient records. + * + * @param[in] content - reply content. + * @param[out] resultList - list of recipients. + * @param[out] hasMore - another recipents are available. + * @param[out] errStr - contains an error string if unssucces. + * @return true if success. + */ + bool parseSearchRecipient(const QByteArray &content, + QList &resultList, bool &hasMore, + QString &errStr); +}; + +/* global jsonlazyer object */ +extern JsonLayer jsonlayer; + +#endif /* _JSON_H_ */ diff -Nru datovka-4.7.0/src/web/net_consts.h datovka-4.7.1/src/web/net_consts.h --- datovka-4.7.0/src/web/net_consts.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/web/net_consts.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef NET_CONST_H +#define NET_CONST_H + +#define APP_NAME "Datovka" + +/* HTTP request timeout, default 30s */ +#define NET_REQUEST_TIMEOUT 30000 + +/* Cookie names which we use */ +#define COOKIE_SESSION_ID "sessionid" +#define COOKIE_SESSION_MOJEID "mojeidsession" +#define COOKIE_CSRFTOKEN "csrftoken" + +/* URL of endpoints and services */ +#define WEBDATOVKA_SERVICE_URL "https://datovka.labs.nic.cz/development/" +#define MOJEID_URL_PASSWORD "https://mojeid.fred.nic.cz/endpoint/password/" +#define MOJEID_URL_CERTIFICATE "https://mojeid.fred.nic.cz/endpoint/certificate/" +#define MOJEID_URL_OTP "https://mojeid.fred.nic.cz/endpoint/otp/" +#define MOJEID_URL_CONFIRM "https://mojeid.fred.nic.cz/endpoint/confirmation/" +#define MOJEID_URL_SSLLOGIN "https://mojeid.fred.nic.cz/endpoint/ssllogin/" + +#endif // NET_CONST_H diff -Nru datovka-4.7.0/src/web/net.cpp datovka-4.7.1/src/web/net.cpp --- datovka-4.7.0/src/web/net.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/web/net.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,383 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "src/web/net.h" +#include "src/web/json.h" + +QList cookieList; +NetManager netmanager; + +static +void printRequest(QNetworkRequest request, QByteArray requestContent) +{ + qDebug() << ""; + qDebug() << "====================REQUEST========================="; + qDebug() << "URL:" << request.url().toString(); + qDebug() << "--------------------Headers-------------------------"; + QList reqHeaders = request.rawHeaderList(); + foreach (const QByteArray &reqName, reqHeaders) { + QByteArray reqValue = request.rawHeader(reqName); + qDebug() << reqName << ":" << reqValue; + } + qDebug() << "--------------------Content------------------------"; + qDebug() << requestContent; + qDebug() << "==================================================="; + qDebug() << ""; +} + + +NetManager::NetManager(QObject *parent) + : QObject(parent) +{ +} + +NetManager::~NetManager(void) +{ +} + +/* ========================================================================= */ +/* + * Func: Create POST request to WebDatovka. + */ +bool NetManager::createPostRequestWebDatovka(const QUrl &url, + const QNetworkCookie &sessionid, const QByteArray &data, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Accept", "application/json"); + request.setRawHeader("Connection", "keep-alive"); + request.setRawHeader("Content-Type", "application/json"); + request.setRawHeader("Content-Length", QByteArray::number(data.size())); + + if (!sessionid.name().isEmpty()) { + QVariant var; + var.setValue(sessionid); + request.setHeader(QNetworkRequest::CookieHeader, var); + } + + return sendRequest(request, data, outData, true); +} + + +/* ========================================================================= */ +/* + * Func: Create POST request for file sending to WebDatovka. + */ +bool NetManager::createPostRequestWebDatovkaSendFile(const QUrl &url, + const QNetworkCookie &sessionid, int &draftId, const QString &filename, + const QByteArray &filedata, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Accept", "application/json"); + request.setRawHeader("Draft-Id", QByteArray::number(draftId)); + QByteArray dispos; + dispos.append("form-data;"); + dispos.append("filename*=UTF-8''" + QUrl::toPercentEncoding(filename)); + request.setRawHeader("Content-Disposition", dispos); + request.setRawHeader("Connection", "keep-alive"); + request.setRawHeader("Content-type", "application/octet-stream"); + request.setRawHeader("Content-Length", QByteArray::number(filedata.size())); + + if (!sessionid.name().isEmpty()) { + QVariant var; + var.setValue(sessionid); + request.setHeader(QNetworkRequest::CookieHeader, var); + } + + return sendRequest(request, filedata, outData, true); +} + + +/* ========================================================================= */ +/* + * Func: Create GET request to WebDatovka. + */ +bool NetManager::createGetRequestWebDatovka(const QUrl &url, + const QNetworkCookie &sessionid, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Accept", + "text/html,application/xhtml+xml,application/xml"); + request.setRawHeader("Connection", "keep-alive"); + + if (!sessionid.name().isEmpty()) { + QVariant var; + var.setValue(sessionid); + request.setHeader(QNetworkRequest::CookieHeader, var); + } + + return sendRequest(request, QByteArray(), outData, false); +} + + +/* ========================================================================= */ +/* + * Func: Create POST request to MojeID. + */ +bool NetManager::createPostRequestMojeId(const QUrl &url, const QUrl &prevUrl, + const QByteArray &data, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Referer", prevUrl.toString().toUtf8()); + request.setRawHeader("Accept", + "text/html,application/xhtml+xml,application/xml"); + request.setRawHeader("Connection", "keep-alive"); + request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); + request.setRawHeader("Content-Length", QByteArray::number(data.size())); + + QVariant var; + var.setValue(cookieList); + request.setHeader(QNetworkRequest::CookieHeader, var); + + return sendRequest(request, data, outData, true); +} + + +/* ========================================================================= */ +/* + * Func: Create POST request to MojeID with client certificate. + */ +bool NetManager::createPostRequestMojeIdCert(const QUrl &url, const QUrl &prevUrl, + const QByteArray &data, const QSslCertificate &cert, + const QSslKey &key, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Referer", prevUrl.toString().toUtf8()); + request.setRawHeader("Accept", + "text/html,application/xhtml+xml,application/xml"); + request.setRawHeader("Connection", "keep-alive"); + request.setRawHeader("Content-Type", "application/x-www-form-urlencoded"); + request.setRawHeader("Content-Length", QByteArray::number(data.size())); + + QSslConfiguration sslConf = QSslConfiguration::defaultConfiguration(); + sslConf.setProtocol(QSsl::TlsV1_2); + sslConf.setLocalCertificate(cert); + sslConf.setPrivateKey(key); + request.setSslConfiguration(sslConf); + + QVariant var; + var.setValue(cookieList); + request.setHeader(QNetworkRequest::CookieHeader, var); + + return sendRequest(request, data, outData, true); +} + + +/* ========================================================================= */ +/* + * Func: Create GET request to MojeId. + */ +bool NetManager::createGetRequestMojeId(const QUrl &url, const QUrl &prevUrl, + QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + QByteArray appName(APP_NAME); + QNetworkRequest request(url); + request.setRawHeader("Host", url.host().toUtf8()); + request.setRawHeader("User-Agent", appName); + request.setRawHeader("Referer", prevUrl.toString().toUtf8()); + request.setRawHeader("Accept", + "text/html,application/xhtml+xml,application/xml"); + request.setRawHeader("Connection", "keep-alive"); + + QVariant var; + for (int i = 0; i < cookieList.size(); ++i) { + if (cookieList.at(i).name() == COOKIE_SESSION_MOJEID) { + var.setValue(cookieList.at(i)); + request.setHeader(QNetworkRequest::CookieHeader, var); + } + } + + return sendRequest(request, QByteArray(), outData, false); +} + + +/* ========================================================================= */ +/* + * Func: Send request. + */ +bool NetManager::sendRequest(QNetworkRequest &request, + const QByteArray &data, QByteArray &outData, bool postRqst) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + bool ret = true; + QNetworkReply *reply = NULL; + QNetworkAccessManager *nam = new QNetworkAccessManager; + +#if 1 + printRequest(request, data); +#endif + + if (postRqst) { + reply = nam->post(request, data); + } else { + reply = nam->get(request); + } + + /* TODO - add timer, set timeout from settings, run, + * abort request if timer = timeout + */ + + /* this eventloop makes synchronous soap requests */ + QEventLoop eventLoop; + QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); + eventLoop.exec(); + + ret = getResponse(reply, outData); + + reply->deleteLater(); + nam->deleteLater(); + + return ret; +} + + +/* ========================================================================= */ +/* + * Func: Response. + */ +bool NetManager::getResponse(QNetworkReply *reply, QByteArray &outData) +/* ========================================================================= */ +{ + qDebug("%s()", __func__); + + bool ret = true; + + int statusCode = reply->attribute( + QNetworkRequest::HttpStatusCodeAttribute).toInt(); + const QString url = reply->url().toString(); + const QString error = reply->errorString(); + const QString reason = reply->attribute( + QNetworkRequest::HttpReasonPhraseAttribute).toString(); + +#if 1 + qDebug() << ""; + qDebug() << "====================REPLY==========================="; + qDebug() << "URL:" << url; + qDebug() << "CODE:" << statusCode; + if (reply->error() != QNetworkReply::NoError) { + qDebug() << "ERROR:" << error; + } + qDebug() << "REASON:" << reason; + qDebug() << "--------------------Headers-------------------------"; + QList reqHeaders = reply->rawHeaderList(); + foreach (QByteArray reqName, reqHeaders) { + QByteArray reqValue = reply->rawHeader(reqName); + qDebug() << reqName << ":" << reqValue; + } + qDebug() << "----------------------------------------------------"; +#endif + + /* Process and store cookies */ + QVariant variantCookies = + reply->header(QNetworkRequest::SetCookieHeader); + QList list = + qvariant_cast >(variantCookies); + + bool up = false; + for (int i = 0; i < list.size(); ++i) { + up = false; + for (int j = 0; j < cookieList.count(); ++j) { + if (cookieList.at(j).name() == list.at(i).name()) { + cookieList.removeOne(cookieList.at(j)); + cookieList.append(list.at(i)); + up = true; + break; + } + } + if (!up) { + cookieList.append(list.at(i)); + } + } + + + switch (statusCode) { + case 200: /* HTTP status 200 OK */ + { + outData = reply->readAll(); + } + break; + + case 302: /* HTTP status 302 Found */ + { + outData = reply->readAll(); + QVariant possibleRedirectUrl = + reply->attribute(QNetworkRequest::RedirectionTargetAttribute); + newUrl = possibleRedirectUrl.toString(); + } + break; + + default: /* Any error occurred */ + outData = QByteArray(); + break; + } +#if 0 + qDebug() << outData; +#endif + return ret; +} diff -Nru datovka-4.7.0/src/web/net.h datovka-4.7.1/src/web/net.h --- datovka-4.7.0/src/web/net.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/web/net.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,155 @@ +/* + * Copyright (C) 2014-2016 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _NET_H_ +#define _NET_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "src/web/net_consts.h" + +class NetManager : public QObject { + Q_OBJECT + +public: + explicit NetManager(QObject *parent = 0); + ~NetManager(void); + +public: + + QString newUrl; + + /*! + * @brief Create POST request to WebDatovka. + * + * @param[in] url - url of request. + * @param[in] sessionid - cookie of request. + * @param[in] data - request content data. + * @param[out] outData - reply data. + * @return true if success. + */ + bool createPostRequestWebDatovka(const QUrl &url, + const QNetworkCookie &sessionid, const QByteArray &data, + QByteArray &outData); + + /*! + * @brief Create POST request for file sending to WebDatovka. + * + * @param[in] url - url of request. + * @param[in] sessionid - cookie of request. + * @param[in] draftId - draftId. + * @param[in] filename - file name. + * @param[in] filedata - file content data. + * @param[out] outData - reply data. + * @return true if success. + */ + bool createPostRequestWebDatovkaSendFile(const QUrl &url, + const QNetworkCookie &sessionid, int &draftId, + const QString &filename, const QByteArray &filedata, + QByteArray &outData); + + /*! + * @brief Create GET request to WebDatovka. + * + * @param[in] url - url of request. + * @param[in] sessionid - cookie of request. + * @param[out] outData -reply data. + * @return true if success. + */ + bool createGetRequestWebDatovka(const QUrl &url, + const QNetworkCookie &sessionid, QByteArray &outData); + + /*! + * @brief Create POST request to MojeID. + * + * @param[in] url - current url of request. + * @param[in] prevUrl - previous url. + * @param[in] data - request content data (cookie, credentials). + * @param[out] outData - reply data. + * @return true if success. + */ + bool createPostRequestMojeId(const QUrl &url, const QUrl &prevUrl, + const QByteArray &data, QByteArray &outData); + + /*! + * @brief Create POST request to MojeID with client certificate. + * + * @param[in] url - current url of request. + * @param[in] prevUrl - previous url. + * @param[in] data - request content data (cookie, credentials). + * @param[in] cert - certificate data. + * @param[in] key - private key data. + * @param[out] outData - reply data. + * @return true if success. + */ + bool createPostRequestMojeIdCert(const QUrl &url, const QUrl &prevUrl, + const QByteArray &data, const QSslCertificate &cert, + const QSslKey &key, QByteArray &outData); + + /*! + * @brief Create GET request to MojeID. + * + * @param[in] url - current url of request. + * @param[in] prevUrl - previous url. + * @param[out] outData - reply data. + * @return true if success. + */ + bool createGetRequestMojeId(const QUrl &url, const QUrl &prevUrl, + QByteArray &outData); + +private: + + /*! + * @brief Send request and run eventloop. + * + * @param[in] request - hold request data. + * @param[in] data - hold content data (may be NULL). + * @param[out] outData - reply data. + * @param[in] postRqst - it is POST request (POST = TRUE). + * @return true if success. + */ + bool sendRequest(QNetworkRequest &request, const QByteArray &data, + QByteArray &outData, bool postRqst); + + /*! + * @brief Parse response. + * + * @param[in] reply - pointer on the reply data. + * @param[out] outData - reply data. + * @return true if success. + */ + bool getResponse(QNetworkReply *reply, QByteArray &outData); +}; + +extern QList cookieList; +extern NetManager netmanager; + +#endif /* _NET_H_ */ diff -Nru datovka-4.7.0/src/worker/message_emitter.h datovka-4.7.1/src/worker/message_emitter.h --- datovka-4.7.0/src/worker/message_emitter.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/message_emitter.h 2017-01-19 09:29:26.000000000 +0000 @@ -49,6 +49,19 @@ bool listScheduled); /*! + * @brief Emitted when download message finishes - webdatovka. + * + * @param[in] usrName Account identifier (user login name). + * @param[in] msgId Message identifier. + * @param[in] result Operation outcome + * (enum TaskDownloadMessage::Result). + * @param[in] errDesc Error description string. + * @param[in] listScheduled True if ran from download message list. + */ + void downloadMessageFinishedMojeId(const QString &usrName, qint64 msgId, + int result, const QString &errDesc, bool listScheduled); + + /*! * @brief Emitted when download message finishes. * * @param[in] usrName Account identifier (user login name). @@ -86,7 +99,7 @@ */ void progressChange(const QString &label, int value); - /* + /*! * @brief Emitted when send message finishes. * * @param[in] userName Account identifier (user login name). @@ -103,6 +116,23 @@ const QString &transactId, int result, const QString &resultDesc, const QString &dbIDRecipient, const QString &recipientName, bool isPDZ, qint64 dmId); + + /*! + * @brief Emitted when mojeid send message finishes. + * + * @param[in] userName Account username. + * @param[in] resultList ResultList from webdatovka. + * @param[in] error Error message from netmanager. + */ + void sendMessageMojeIdFinished(const QString &userName, + const QStringList &resultList, const QString &errStr); + + /*! + * @brief This signal is emitted when account is changed. + * + * @param[in] account username. + */ + void refreshAccountList(const QString &userName); }; /*! diff -Nru datovka-4.7.0/src/worker/task.cpp datovka-4.7.1/src/worker/task.cpp --- datovka-4.7.0/src/worker/task.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -83,7 +83,8 @@ } qdatovka_error Task::storeEnvelope(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const struct isds_envelope *envel) + MessageDbSet &dbSet, const struct isds_envelope *envel, + QString msgId) { debugFuncCall(); @@ -106,10 +107,13 @@ MessageDb *messageDb = dbSet.accessMessageDb(deliveryTime, true); Q_ASSERT(0 != messageDb); + if (msgId.isEmpty()) { + msgId = "tRecord"; + } + /* insert message envelope in db */ if (messageDb->msgsInsertMessageEnvelope(dmId, - /* TODO - set correctly next two values */ - "tRecord", + msgId, envel->dbIDSender, envel->dmSender, envel->dmSenderAddress, @@ -168,7 +172,7 @@ qdatovka_error Task::storeMessage(bool signedMsg, enum MessageDirection msgDirect, MessageDbSet &dbSet, - const struct isds_message *msg, const QString &progressLabel) + const struct isds_message *msg, const QString &progressLabel, QString msgId) { debugFuncCall(); @@ -226,7 +230,7 @@ emit globMsgProcEmitter.progressChange(progressLabel, 30); - if (Q_SUCCESS == updateEnvelope(msgDirect, *messageDb, envel)) { + if (Q_SUCCESS == updateEnvelope(msgDirect, *messageDb, envel, msgId)) { logDebugLv0NL("Envelope of message '%" PRId64 "' updated.", dmID); } else { @@ -312,7 +316,7 @@ } qdatovka_error Task::updateEnvelope(enum MessageDirection msgDirect, - MessageDb &messageDb, const struct isds_envelope *envel) + MessageDb &messageDb, const struct isds_envelope *envel, QString msgId) { debugFuncCall(); @@ -330,10 +334,13 @@ } } + if (msgId.isEmpty()) { + msgId = "tReturnedMessage"; + } + /* Update message envelope in db. */ if (messageDb.msgsUpdateMessageEnvelope(dmId, - /* TODO - set correctly next two values */ - "tReturnedMessage", + msgId, envel->dbIDSender, envel->dmSender, envel->dmSenderAddress, @@ -390,3 +397,106 @@ return Q_GLOBAL_ERROR; } } + + +qdatovka_error Task::storeEnvelopeWebDatovka(enum MessageDirection msgDirect, + MessageDbSet &dbSet, const JsonLayer::Envelope &envel, bool isNew) +{ + debugFuncCall(); + + QDateTime dTime = fromIsoDatetimetoDateTime(envel.dmDeliveryTime); + + /* Allow invalid delivery time. */ + MessageDb *messageDb = dbSet.accessMessageDb(dTime, true); + Q_ASSERT(0 != messageDb); + + if (isNew) { + /* insert message envelope in db */ + if (messageDb->msgsInsertMessageEnvelope(envel.dmID, + QString::number(envel.id), + envel.dbIDSender, + envel.dmSender, + envel.dmSenderAddress, + envel.dmSenderType, + envel.dmRecipient, + envel.dmRecipientAddress, + envel.dmAmbiguousRecipient, + envel.dmSenderOrgUnit, + envel.dmSenderOrgUnitNum, + envel.dbIDRecipient, + envel.dmRecipientOrgUnit, + envel.dmRecipientOrgUnitNum, + envel.dmToHands, + envel.dmAnnotation, + envel.dmRecipientRefNumber, + envel.dmSenderRefNumber, + envel.dmRecipientIdent, + envel.dmSenderIdent, + envel.dmLegalTitleLaw, + envel.dmLegalTitleYear, + envel.dmLegalTitleSect, + envel.dmLegalTitlePar, + envel.dmLegalTitlePoint, + envel.dmPersonalDelivery, + envel.dmAllowSubstDelivery, + QByteArray(), + fromIsoDatetimetoDbformat(envel.dmDeliveryTime), + fromIsoDatetimetoDbformat(envel.dmAcceptanceTime), + envel.dmMessageStatus, + envel.dmAttachmentSize, + envel.dmType, + msgDirect)) { + logDebugLv0NL("Stored envelope of message '%" PRId64 "' into database.", + envel.dmID); + return Q_SUCCESS; + } else { + logErrorNL("Storing envelope of message '%" PRId64 "' failed.", + envel.dmID); + return Q_GLOBAL_ERROR; + } + } else { + /* Update message envelope in db. */ + if (messageDb->msgsUpdateMessageEnvelope(envel.dmID, + QString::number(envel.id), + envel.dbIDSender, + envel.dmSender, + envel.dmSenderAddress, + envel.dmSenderType, + envel.dmRecipient, + envel.dmRecipientAddress, + envel.dmAmbiguousRecipient, + envel.dmSenderOrgUnit, + envel.dmSenderOrgUnitNum, + envel.dbIDRecipient, + envel.dmRecipientOrgUnit, + envel.dmRecipientOrgUnitNum, + envel.dmToHands, + envel.dmAnnotation, + envel.dmRecipientRefNumber, + envel.dmSenderRefNumber, + envel.dmRecipientIdent, + envel.dmSenderIdent, + envel.dmLegalTitleLaw, + envel.dmLegalTitleYear, + envel.dmLegalTitleSect, + envel.dmLegalTitlePar, + envel.dmLegalTitlePoint, + envel.dmPersonalDelivery, + envel.dmAllowSubstDelivery, + QByteArray(), + fromIsoDatetimetoDbformat(envel.dmDeliveryTime), + fromIsoDatetimetoDbformat(envel.dmAcceptanceTime), + envel.dmMessageStatus, + envel.dmAttachmentSize, + envel.dmType, + msgDirect)) { + logDebugLv0NL("Stored envelope of message '%" PRId64 "' into database.", + envel.dmID); + return Q_SUCCESS; + } else { + logErrorNL("Storing envelope of message '%" PRId64 "' failed.", + envel.dmID); + return Q_GLOBAL_ERROR; + } + } +} diff -Nru datovka-4.7.0/src/worker/task_download_message.cpp datovka-4.7.1/src/worker/task_download_message.cpp --- datovka-4.7.0/src/worker/task_download_message.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -33,18 +33,18 @@ TaskDownloadMessage::TaskDownloadMessage(const QString &userName, MessageDbSet *dbSet, enum MessageDirection msgDirect, - qint64 dmId, const QDateTime &dTime, bool listScheduled) + const MessageDb::MsgId &msgId, bool listScheduled) : m_result(DM_ERR), m_isdsError(), m_isdsLongError(), - m_mId(dmId, dTime), + m_mId(msgId), m_userName(userName), m_dbSet(dbSet), m_msgDirect(msgDirect), m_listScheduled(listScheduled) { Q_ASSERT(0 != dbSet); - Q_ASSERT(0 <= dmId); + Q_ASSERT(0 <= msgId.dmId); } void TaskDownloadMessage::run(void) @@ -253,7 +253,7 @@ /* Store envelope in new location. */ Task::storeEnvelope(msgDirect, dbSet, - message->envelope); + message->envelope, NULL); } /* Update message delivery time. */ mId.deliveryTime = newDeliveryTime; @@ -261,7 +261,7 @@ /* Store the message. */ Task::storeMessage(signedMsg, msgDirect, dbSet, message, - progressLabel); + progressLabel, NULL); emit globMsgProcEmitter.progressChange(progressLabel, 90); diff -Nru datovka-4.7.0/src/worker/task_download_message.h datovka-4.7.1/src/worker/task_download_message.h --- datovka-4.7.0/src/worker/task_download_message.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message.h 2017-01-19 09:29:26.000000000 +0000 @@ -52,14 +52,13 @@ * @param[in] userName Account identifier (user login name). * @param[in,out] dbSet Non-null pointer to database container. * @param[in] msgDirect Received or sent list. - * @param[in] dmId Message identifier. - * @param[in] dTime Delivery time. + * @param[in] msgId Message identifier. * @param[in] listScheduled True if the task has been scheduled * from TaskDownloadMessageList. */ explicit TaskDownloadMessage(const QString &userName, MessageDbSet *dbSet, enum MessageDirection msgDirect, - qint64 dmId, const QDateTime &dTime, bool listScheduled); + const MessageDb::MsgId &msgId, bool listScheduled); /*! * @brief Performs actual message download. diff -Nru datovka-4.7.0/src/worker/task_download_message_list.cpp datovka-4.7.1/src/worker/task_download_message_list.cpp --- datovka-4.7.0/src/worker/task_download_message_list.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message_list.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -227,19 +227,20 @@ return DL_ISDS_ERROR; } - qint64 dmId = QString(item->envelope->dmID).toLongLong(); /* * Time may be invalid (e.g. messages which failed during * virus scan). */ - QDateTime deliveryTime = - timevalToDateTime(item->envelope->dmDeliveryTime); + MessageDb::MsgId msgId( + QString(item->envelope->dmID).toLongLong(), + timevalToDateTime(item->envelope->dmDeliveryTime)); + /* Delivery time may be invalid. */ - if ((0 != invalidDb) && deliveryTime.isValid()) { + if ((0 != invalidDb) && msgId.deliveryTime.isValid()) { /* Try deleting possible invalid entry. */ - invalidDb->msgsDeleteMessageData(dmId); + invalidDb->msgsDeleteMessageData(msgId.dmId); } - MessageDb *messageDb = dbSet.accessMessageDb(deliveryTime, + MessageDb *messageDb = dbSet.accessMessageDb(msgId.deliveryTime, true); Q_ASSERT(0 != messageDb); @@ -250,21 +251,21 @@ } #endif /* USE_TRANSACTIONS */ - const int dmDbMsgStatus = messageDb->msgsStatusIfExists(dmId); + const int dmDbMsgStatus = messageDb->msgsStatusIfExists( + msgId.dmId); /* Message is NOT in db (-1), -> insert */ if (-1 == dmDbMsgStatus) { - Task::storeEnvelope(msgDirect, dbSet, item->envelope); + Task::storeEnvelope(msgDirect, dbSet, item->envelope, NULL); if (downloadWhole) { TaskDownloadMessage *task; task = new (std::nothrow) TaskDownloadMessage( - userName, &dbSet, msgDirect, dmId, - deliveryTime, true); + userName, &dbSet, msgDirect, msgId, true); task->setAutoDelete(true); globWorkPool.assignLo(task, WorkerPool::PREPEND); } - newMsgIdList.append(dmId); + newMsgIdList.append(msgId.dmId); newcnt++; /* Message is in db (dmDbMsgStatus <> -1), -> update */ @@ -277,18 +278,19 @@ if (dmNewMsgStatus != dmDbMsgStatus) { /* Update envelope */ Task::updateEnvelope(msgDirect, *messageDb, - item->envelope); + item->envelope, NULL); /* * Download whole message again if exists in db * (and status has changed) or is required by * downloadWhole in the settings. */ - if (downloadWhole || messageDb->msgsStoredWhole(dmId)) { + if (downloadWhole || messageDb->msgsStoredWhole(msgId.dmId)) { + TaskDownloadMessage *task; task = new (std::nothrow) TaskDownloadMessage( - userName, &dbSet, msgDirect, dmId, - deliveryTime, true); + userName, &dbSet, msgDirect, msgId, + true); task->setAutoDelete(true); globWorkPool.assignLo(task, WorkerPool::PREPEND); @@ -297,7 +299,7 @@ /* Update delivery info of sent message */ if (MSG_SENT == msgDirect) { downloadMessageState(msgDirect, - userName, dmId, true, dbSet, + userName, msgId.dmId, true, dbSet, error, longError); } } @@ -429,7 +431,7 @@ * we get proper data from ISDS rather than storing potentially * guessed values. */ - Task::updateEnvelope(msgDirect, *messageDb, envel); + Task::updateEnvelope(msgDirect, *messageDb, envel, NULL); } else if (messageDb->msgsUpdateMessageState(dmID, dmDeliveryTime, dmAcceptanceTime, envel->dmMessageStatus ? diff -Nru datovka-4.7.0/src/worker/task_download_message_list_mojeid.cpp datovka-4.7.1/src/worker/task_download_message_list_mojeid.cpp --- datovka-4.7.0/src/worker/task_download_message_list_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message_list_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,305 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "src/io/dbs.h" +#include "src/log/log.h" +#include "src/worker/pool.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_download_message_list_mojeid.h" +#include "src/worker/task_download_message_mojeid.h" +#include "src/web/json.h" +#include "src/io/tag_db.h" +#include "src/io/tag_db_container.h" + +TaskDownloadMessageListMojeID::TaskDownloadMessageListMojeID( + const QString &userName, MessageDbSet *dbSet, + enum MessageDirection msgDirect, bool downloadWhole, + int dmLimit, int accountID, int dmOffset) + : m_result(DL_ERR), + m_userName(userName), + m_dbSet(dbSet), + m_msgDirect(msgDirect), + m_downloadWhole(downloadWhole), + m_dmLimit(dmLimit), + m_accountID(accountID), + m_dmOffset(dmOffset) +{ + Q_ASSERT(0 != m_dbSet); +} + +void TaskDownloadMessageListMojeID::run(void) +{ + if (m_userName.isEmpty()) { + Q_ASSERT(0); + return; + } + + if (0 == m_dbSet) { + Q_ASSERT(0); + return; + } + + if ((MSG_RECEIVED != m_msgDirect) && (MSG_SENT != m_msgDirect)) { + Q_ASSERT(0); + return; + } + + logDebugLv0NL("Starting download message list task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + int rt = 0; /*!< Received total. */ + int rn = 0; /*!< Received new. */ + int st = 0; /*!< Sent total. */ + int sn = 0; /*!< Sent new. */ + + logDebugLv1NL("%s", "-----------------------------------------------"); + logDebugLv1NL("Downloading %s message list for account '%s'.", + (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", + AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + logDebugLv1NL("%s", "-----------------------------------------------"); + + if (MSG_RECEIVED == m_msgDirect) { + m_result = downloadMessageList(m_userName, MSG_RECEIVED, + *m_dbSet, m_downloadWhole, m_error, + PL_DOWNLOAD_RECEIVED_LIST, rt, rn, m_dmLimit, + m_accountID, m_dmOffset); + } else { + m_result = downloadMessageList(m_userName, MSG_SENT, + *m_dbSet, m_downloadWhole, m_error, + PL_DOWNLOAD_SENT_LIST, st, sn, m_dmLimit, + m_accountID, m_dmOffset); + } + + if (DL_SUCCESS == m_result) { + logDebugLv1NL("Done downloading message list for account '%s'.", + AccountModel::globAccounts[m_userName]. + accountName().toUtf8().constData()); + } else { + logErrorNL("Downloading message list for account '%s' failed.", + AccountModel::globAccounts[m_userName]. + accountName().toUtf8().constData()); + } + + emit globMsgProcEmitter.downloadMessageListFinished(m_userName, + m_msgDirect, m_result, m_error, true, rt, rn , st, sn); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download message list task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +enum TaskDownloadMessageListMojeID::Result +TaskDownloadMessageListMojeID::downloadMessageList( + const QString &userName, enum MessageDirection msgDirect, + MessageDbSet &dbSet, bool downloadWhole, QString &error, + const QString &progressLabel, int &total, int &news, + int dmLimit, int accountID, int dmOffset) +{ + debugFuncCall(); + + #define USE_TRANSACTIONS 1 + + int newcnt = 0; + int allcnt = 0; + qint64 dmID = -1; + + if (userName.isEmpty()) { + Q_ASSERT(0); + return DL_ERR; + } + + emit globMsgProcEmitter.progressChange(progressLabel, 0); + + emit globMsgProcEmitter.progressChange(progressLabel, 10); + + QList messageList; + + /* webdatovka message types */ + int msgType = 1; + if (MSG_SENT == msgDirect) { + msgType = -1; + } + + if (!jsonlayer.getMessageList(userName, accountID, msgType, dmLimit, + dmOffset, messageList, error)) { + if (!error.isEmpty()) { + qDebug() << "ERROR:" << error; + } else { + qDebug() << "ERROR: get-mesasge-list fails"; + } + return DL_NET_ERROR; + } + + emit globMsgProcEmitter.progressChange(progressLabel, 20); + + float delta = 0.0; + float diff = 0.0; + allcnt = messageList.count(); + + if (allcnt == 0) { + emit globMsgProcEmitter.progressChange(progressLabel, 50); + } else { + delta = 80.0 / allcnt; + } + + /* Obtain invalid message database if has a separate file. */ + MessageDb *invalidDb = NULL; + { + QString invSecKey(dbSet.secondaryKey(QDateTime())); + QString valSecKey(dbSet.secondaryKey( + QDateTime::currentDateTime())); + if (invSecKey != valSecKey) { + /* Invalid database file may not exist. */ + invalidDb = dbSet.accessMessageDb(QDateTime(), false); + } + } + +#ifdef USE_TRANSACTIONS + QSet usedDbs; +#endif /* USE_TRANSACTIONS */ + + for (int i = 0; i < allcnt; ++i) { + + newcnt++; + diff += delta; + + emit globMsgProcEmitter.progressChange(progressLabel, + (int) (20 + diff)); + + dmID = messageList.at(i).dmID; + + /* + * Time may be invalid (e.g. messages which failed during + * virus scan). + */ + QDateTime deliveryTime = + fromIsoDatetimetoDateTime(messageList.at(i).dmDeliveryTime); + + /* Delivery time may be invalid. */ + if ((0 != invalidDb) && deliveryTime.isValid()) { + /* Try deleting possible invalid entry. */ + invalidDb->msgsDeleteMessageData(dmID); + } + MessageDb *messageDb = dbSet.accessMessageDb(deliveryTime, true); + Q_ASSERT(0 != messageDb); + + +#ifdef USE_TRANSACTIONS + if (!usedDbs.contains(messageDb)) { + usedDbs.insert(messageDb); + messageDb->beginTransaction(); + } +#endif /* USE_TRANSACTIONS */ + + const int dmDbMsgStatus = messageDb->msgsStatusIfExists(dmID); + + /* message is not in db (-1) */ + if (-1 == dmDbMsgStatus) { + + /* download and save complete message */ + if (downloadWhole) { + + TaskDownloadMessageMojeId *task; + task = new (std::nothrow) TaskDownloadMessageMojeId( + userName, &dbSet, msgDirect, + messageList.at(i).id, + messageList.at(i).dmID, + true); + task->setAutoDelete(true); + globWorkPool.assignLo(task, WorkerPool::PREPEND); + + /* store message envelope only */ + } else { + Task::storeEnvelopeWebDatovka(msgDirect, dbSet, + messageList.at(i), true); + } + + newcnt++; + + /* Message is in db (dmDbMsgStatus <> -1). */ + } else { + /* Update envelope if message status has changed. */ + if (messageList.at(i).dmMessageStatus != dmDbMsgStatus) { + Task::storeEnvelopeWebDatovka(msgDirect, + dbSet, messageList.at(i), false); + } + + /* download and save complete message */ + if (downloadWhole && !messageDb->msgsStoredWhole(dmID)) { + + TaskDownloadMessageMojeId *task; + task = new (std::nothrow) TaskDownloadMessageMojeId( + userName, &dbSet, msgDirect, + messageList.at(i).id, + messageList.at(i).dmID, + true); + task->setAutoDelete(true); + globWorkPool.assignLo(task, WorkerPool::PREPEND); + + } + } + + TagDb *tagDb = globWebDatovkaTagDbPtr-> + accessTagDb(getWebDatovkaTagDbPrefix(userName)); + Q_ASSERT(0 != tagDb); + + messageDb->smsgdtSetLocallyRead(dmID, messageList.at(i)._read); + tagDb->removeAllTagsFromMsg(userName, dmID); + + for (int t = 0; t < messageList.at(i)._tagList.count(); ++t) { + tagDb->assignTagToMsg(userName, + messageList.at(i)._tagList.at(t), dmID); + } + } + +#ifdef USE_TRANSACTIONS + /* Commit on all opened databases. */ + foreach (MessageDb *db, usedDbs) { + db->commitTransaction(); + } +#endif /* USE_TRANSACTIONS */ + + emit globMsgProcEmitter.progressChange(progressLabel, 100); + + if (MSG_RECEIVED == msgDirect) { + logDebugLv0NL("#Received total: %d #Received new: %d", + allcnt, newcnt); + } else { + logDebugLv0NL("#Sent total: %d #Sent new: %d", allcnt, newcnt); + } + + total = allcnt; + news = newcnt; + + return DL_SUCCESS; + +#undef USE_TRANSACTIONS +} diff -Nru datovka-4.7.0/src/worker/task_download_message_list_mojeid.h datovka-4.7.1/src/worker/task_download_message_list_mojeid.h --- datovka-4.7.0/src/worker/task_download_message_list_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message_list_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ +#define _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ + +#include +#include "src/io/message_db_set.h" +#include "src/worker/task.h" + +/*! + * @brief Task describing download message list. + */ +class TaskDownloadMessageListMojeID : public Task { +public: + /*! + * @brief Return state describing what happened. + */ + enum Result { + DL_SUCCESS, /*!< Operation was successful. */ + DL_NET_ERROR, /*!< Error communicating with webdatovka. */ + DL_DB_INS_ERR, /*!< Error inserting into database. */ + DL_ERR /*!< Other error. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] userName Account identifier (user login name). + * @param[in,out] dbSet Non-null pointer to database container. + * @param[in] msgDirect Received or sent list. + * @param[in] downloadWhole True to plan downloading whole messages. + * @param[in] dmLimit Message list length limit. + * @param[in] accountID Webdatovka account ID. + * @param[in] dmOffset ISDS message offset, default 0. + */ + explicit TaskDownloadMessageListMojeID(const QString &userName, + MessageDbSet *dbSet, enum MessageDirection msgDirect, + bool downloadWhole, int dmLimit, int accountID, int dmOffset); + + /*! + * @brief Performs actual message download. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + /*! + * @brief Download message list from ISDS for given account. + * + * TODO -- This method ought to be protected. + * + * @param[in] userName Account identifier (user login name). + * @param[in] msgDirect Received or sent message. + * @param[in,out] dbSet Database container. + * @param[in] downloadWhole True to plan downloading whole + * messages. + * @param[out] error Error description. + * @param[in] progressLabel Progress-bar label. + * @param[out] total Total number of messages. + * @param[out] news Number of new messages. + * @param[in] dmLimit Maximum number of message list; + * NULL if you don't care. + * @param[in] accountID Webdatovka account ID. + * @param[in] dmOffset ISDS message offset, default 0. + * @return Error state. + */ + static + enum Result downloadMessageList(const QString &userName, + enum MessageDirection msgDirect, MessageDbSet &dbSet, + bool downloadWhole, QString &error, + const QString &progressLabel, int &total, int &news, + int dmLimit, int accountID, int dmOffset); + + enum Result m_result; /*!< Return state. */ + QString m_error; + +private: + /*! + * Disable copy and assignment. + */ + TaskDownloadMessageListMojeID(const TaskDownloadMessageListMojeID &); + TaskDownloadMessageListMojeID &operator=(const TaskDownloadMessageListMojeID &); + + const QString m_userName; /*!< Account identifier (user login name). */ + MessageDbSet *m_dbSet; /*!< Pointer to database container. */ + enum MessageDirection m_msgDirect; /*!< Sent or received list. */ + const bool m_downloadWhole; /*!< Plan downloading whole messages. */ + int m_dmLimit; /*!< List length limit. */ + int m_accountID; /*!< Webdatovka account ID. */ + int m_dmOffset; /*!< ISDS message offset, default 0 */ +}; + +#endif /* _TASK_DOWNLOAD_MESSAGE_LIST_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_download_message_mojeid.cpp datovka-4.7.1/src/worker/task_download_message_mojeid.cpp --- datovka-4.7.0/src/worker/task_download_message_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include +#include + +#include "src/io/dbs.h" +#include "src/log/log.h" +#include "src/io/isds_sessions.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_download_message_mojeid.h" +#include "src/gui/dlg_import_zfo.h" /* TODO -- Remove this dependency. */ +#include "src/web/json.h" + +TaskDownloadMessageMojeId::TaskDownloadMessageMojeId(const QString &userName, + MessageDbSet *dbSet, enum MessageDirection msgDirect, int id, + qint64 dmId, bool listScheduled) + : m_result(DM_ERR), + m_error(), + m_id(id), + m_userName(userName), + m_dbSet(dbSet), + m_msgDirect(msgDirect), + m_dmId(dmId), + m_listScheduled(listScheduled) +{ + Q_ASSERT(0 != dbSet); +} + +void TaskDownloadMessageMojeId::run(void) +{ + if (m_userName.isEmpty()) { + Q_ASSERT(0); + return; + } + + if (0 == m_dbSet) { + Q_ASSERT(0); + return; + } + + if ((MSG_RECEIVED != m_msgDirect) && (MSG_SENT != m_msgDirect)) { + Q_ASSERT(0); + return; + } + + logDebugLv0NL("Starting download message task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + logDebugLv1NL("%s", "-----------------------------------------------"); + logDebugLv1NL("Downloading %s message '%" PRId64 "' for account '%s'.", + (MSG_RECEIVED == m_msgDirect) ? "received" : "sent", m_id, + AccountModel::globAccounts[m_userName].accountName().toUtf8().constData()); + logDebugLv1NL("%s", "-----------------------------------------------"); + + m_result = downloadMessage(m_id, m_msgDirect, *m_dbSet, + m_error, PL_DOWNLOAD_MESSAGE, m_userName); + + if (DM_SUCCESS == m_result) { + logDebugLv1NL( + "Done downloading message '%" PRId64 "' for account '%s'.", + m_id, AccountModel::globAccounts[m_userName]. + accountName().toUtf8().constData()); + } else { + logErrorNL("Downloading message '%" PRId64 "' for account '%s' failed.", + m_id, AccountModel::globAccounts[m_userName]. + accountName().toUtf8().constData()); + } + + emit globMsgProcEmitter.downloadMessageFinishedMojeId(m_userName, + m_dmId, m_result, m_error, m_listScheduled); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download message task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +enum TaskDownloadMessageMojeId::Result TaskDownloadMessageMojeId::downloadMessage( + int id, enum MessageDirection msgDirect, MessageDbSet &dbSet, QString &error, + const QString &progressLabel, const QString &userName) +{ + debugFuncCall(); + + logDebugLv0NL("Trying to download complete message '%" PRId64 "'", id); + + emit globMsgProcEmitter.progressChange(progressLabel, 0); + + QByteArray zfoData = jsonlayer.downloadMessage(userName, id, error); + + emit globMsgProcEmitter.progressChange(progressLabel, 30); + + if (zfoData.isEmpty()) { + return DM_ERR; + } + + struct isds_ctx *dummy_session = isds_ctx_create(); + if (NULL == dummy_session) { + logError("%s\n", "Cannot create dummy ISDS session."); + return DM_ERR; + } + + emit globMsgProcEmitter.progressChange(progressLabel, 40); + + struct isds_message *message; + message = loadZfoData(dummy_session, zfoData, + ImportZFODialog::IMPORT_MESSAGE_ZFO); + if (NULL == message) { + logError("%s\n", "Cannot parse message data."); + return DM_ERR; + } + + emit globMsgProcEmitter.progressChange(progressLabel, 60); + + Task::storeEnvelope(msgDirect, dbSet, message->envelope, + QString::number(id)); + emit globMsgProcEmitter.progressChange(progressLabel, 80); + + Task::storeMessage(true, msgDirect, dbSet, message, + progressLabel, QString::number(id)); + + jsonlayer.markMessageAsRead(userName, id, error); + + emit globMsgProcEmitter.progressChange(progressLabel, 100); + + logDebugLv0NL("Done with %s().", __func__); + + return DM_SUCCESS; +} diff -Nru datovka-4.7.0/src/worker/task_download_message_mojeid.h datovka-4.7.1/src/worker/task_download_message_mojeid.h --- datovka-4.7.0/src/worker/task_download_message_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_message_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ +#define _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ + +#include +#include + +#include "src/io/message_db.h" +#include "src/io/message_db_set.h" +#include "src/worker/task.h" + +/*! + * @brief Task describing download message. + */ +class TaskDownloadMessageMojeId : public Task { +public: + /*! + * @brief Return state describing what happened. + */ + enum Result { + DM_SUCCESS, /*!< Operation was successful. */ + DM_NET_ERROR, /*!< Error communicating with webdatovka. */ + DM_DB_INS_ERR, /*!< Error inserting into database. */ + DM_ERR /*!< Other error. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] userName Account identifier (user login name). + * @param[in,out] dbSet Non-null pointer to database container. + * @param[in] msgDirect Received or sent list. + * @param[in] id Message webdatovka identifier. + * @param[in] dmId Message isds identifier. + * @param[in] listScheduled True if the task has been scheduled + * from TaskDownloadMessageList. + */ + explicit TaskDownloadMessageMojeId(const QString &userName, + MessageDbSet *dbSet, enum MessageDirection msgDirect, int id, + qint64 dmId, bool listScheduled); + + /*! + * @brief Performs actual message download. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + /*! + * @brief Download whole message (envelope, attachments, raw). + * + * TODO -- This method ought to be protected. + * + * @param[in] id Message identifier. + * @param[in] msgDirect Received or sent message. + * @param[in,out] dbSet Database container. + * @param[out] error Error description. + * @param[in] progressLabel Progress-bar label. + * @param[in] userName Account identifier (user login name) + * @return Error state. + */ + static + enum Result downloadMessage(int id, + enum MessageDirection msgDirect, MessageDbSet &dbSet, + QString &error, const QString &progressLabel, const QString &userName); + + enum Result m_result; /*!< Return state. */ + QString m_error; /*!< Error description. */ + int m_id; /*!< Message webdatovka identifier. */ + + +private: + /*! + * Disable copy and assignment. + */ + TaskDownloadMessageMojeId(const TaskDownloadMessageMojeId &); + TaskDownloadMessageMojeId &operator=(const TaskDownloadMessageMojeId &); + + const QString m_userName; /*!< Account identifier (user login name). */ + MessageDbSet *m_dbSet; /*!< Pointer to database container. */ + enum MessageDirection m_msgDirect; /*!< Sent or received message. */ + qint64 m_dmId; /*!< Message isds ID. */ + bool m_listScheduled; /*< + * Whether the task has been scheduled from + * download message list task. + */ +}; + +#endif /* _TASK_DOWNLOAD_MESSAGE_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_download_owner_info_mojeid.cpp datovka-4.7.1/src/worker/task_download_owner_info_mojeid.cpp --- datovka-4.7.0/src/worker/task_download_owner_info_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_owner_info_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/io/account_db.h" +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_download_owner_info_mojeid.h" +#include "src/web/json.h" + +TaskDownloadOwnerInfoMojeId::TaskDownloadOwnerInfoMojeId(int id) + : m_success(false), + m_isdsError(), + m_id(id) +{ +} + +void TaskDownloadOwnerInfoMojeId::run(void) +{ + + logDebugLv0NL("Starting download owner info task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_success = downloadOwnerInfo(m_id, m_isdsError); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download owner info task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +bool TaskDownloadOwnerInfoMojeId::downloadOwnerInfo(int id, QString &error) +{ + JsonLayer::AccountInfo aInfo; + + emit globMsgProcEmitter.progressChange(PL_IDLE, -1); + + if (jsonlayer.getAccountInfo(id, aInfo, error)) { + return globAccountDbPtr->insertAccountIntoDb( + aInfo.key + "___True", + aInfo.dbID, + aInfo.dbType, + aInfo.ic.toInt(), + aInfo.pnFirstName, + aInfo.pnMiddleName, + aInfo.pnLastName, + aInfo.pnLastNameAtBirth, + aInfo.firmName, + aInfo.biDate, + aInfo.biCity, + aInfo.biCounty, + aInfo.biState, + aInfo.adCity, + aInfo.adStreet, + aInfo.adNumberInStreet, + aInfo.adNumberInMunicipality, + aInfo.adZipCode, + aInfo.adState, + aInfo.nationality, + aInfo.identifier, + aInfo.registryCode, + aInfo.dbState, + aInfo.dbEffectiveOVM, + aInfo.dbOpenAddressing + ); + } else { + return false; + } +} diff -Nru datovka-4.7.0/src/worker/task_download_owner_info_mojeid.h datovka-4.7.1/src/worker/task_download_owner_info_mojeid.h --- datovka-4.7.0/src/worker/task_download_owner_info_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_owner_info_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ +#define _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ + +#include + +#include "src/worker/task.h" + +/*! + * @brief Task describing download owner information. + */ +class TaskDownloadOwnerInfoMojeId : public Task { +public: + /*! + * @brief Constructor. + * + * @param[in] id Account identifier (account id). + */ + explicit TaskDownloadOwnerInfoMojeId(int id); + + /*! + * @brief Performs action. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + bool m_success; /*!< True on success. */ + QString m_isdsError; /*!< Error description. */ + +private: + /*! + * Disable copy and assignment. + */ + TaskDownloadOwnerInfoMojeId(const TaskDownloadOwnerInfoMojeId &); + TaskDownloadOwnerInfoMojeId &operator=(const TaskDownloadOwnerInfoMojeId &); + + /*! + * @brief Download owner information. + * + * @param[in] id Account identifier (account id). + * @param[out] error Error description. + * @return True on success. + */ + static + bool downloadOwnerInfo(int id, QString &error); + + int m_id; /*!< Account identifier (account id). */ +}; + +#endif /* _TASK_DOWNLOAD_OWNER_INFO_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_download_user_info_mojeid.cpp datovka-4.7.1/src/worker/task_download_user_info_mojeid.cpp --- datovka-4.7.0/src/worker/task_download_user_info_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_user_info_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/io/account_db.h" +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_download_user_info_mojeid.h" +#include "src/web/json.h" + +TaskDownloadUserInfoMojeId::TaskDownloadUserInfoMojeId(int id) + : m_success(false), + m_isdsError(), + m_id(id) +{ +} + +void TaskDownloadUserInfoMojeId::run(void) +{ + logDebugLv0NL("Starting download user info task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_success = downloadUserInfo(m_id, m_isdsError); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download user info task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +bool TaskDownloadUserInfoMojeId::downloadUserInfo(int id, QString &error) +{ + JsonLayer::UserInfo uInfo; + + emit globMsgProcEmitter.progressChange(PL_IDLE, -1); + + if (jsonlayer.getUserInfo(id, uInfo, error)) { + return globAccountDbPtr->insertUserIntoDb( + uInfo.key + "___True", + uInfo.userType, + uInfo.userPrivils, + uInfo.pnFirstName, + uInfo.pnMiddleName, + uInfo.pnLastName, + uInfo.pnLastNameAtBirth, + uInfo.adCity, + uInfo.adStreet, + uInfo.adNumberInStreet, + uInfo.adNumberInMunicipality, + uInfo.adZipCode, + uInfo.adState, + uInfo.biDate, + uInfo.ic, + uInfo.firmName, + uInfo.caStreet, + uInfo.caCity, + uInfo.caZipCode, + uInfo.caState + ); + } else { + return false; + } +} diff -Nru datovka-4.7.0/src/worker/task_download_user_info_mojeid.h datovka-4.7.1/src/worker/task_download_user_info_mojeid.h --- datovka-4.7.0/src/worker/task_download_user_info_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_download_user_info_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ +#define _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ + +#include + +#include "src/worker/task.h" + +/*! + * @brief Task describing download user information. + */ +class TaskDownloadUserInfoMojeId : public Task { +public: + /*! + * @brief Constructor. + * + * @param[in] id Account identifier (account id). + */ + explicit TaskDownloadUserInfoMojeId(int id); + + /*! + * @brief Performs action. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + bool m_success; /*!< True on success. */ + QString m_isdsError; /*!< Error description. */ + +private: + /*! + * Disable copy and assignment. + */ + TaskDownloadUserInfoMojeId(const TaskDownloadUserInfoMojeId &); + TaskDownloadUserInfoMojeId &operator=(const TaskDownloadUserInfoMojeId &); + + /*! + * @brief Download user information. + * + * @param[in] id Account identifier (account id). + * @param[out] error Error description. + * @return True on success. + */ + static + bool downloadUserInfo(int id, QString &error); + + int m_id; /*!< Account identifier (account id). */ +}; + + +#endif /* _TASK_DOWNLOAD_USER_INFO_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_erase_message.cpp datovka-4.7.1/src/worker/task_erase_message.cpp --- datovka-4.7.0/src/worker/task_erase_message.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_erase_message.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -31,20 +31,20 @@ #include "src/worker/task_erase_message.h" TaskEraseMessage::TaskEraseMessage(const QString &userName, MessageDbSet *dbSet, - qint64 dmId, const QDateTime &deliveryTime, bool incoming, bool delFromIsds) + const MessageDb::MsgId &msgId, enum MessageDirection msgDirect, + bool delFromIsds) : m_result(NOT_DELETED), m_isdsError(), m_isdsLongError(), m_userName(userName), m_dbSet(dbSet), - m_dmId(dmId), - m_deliveryTime(deliveryTime), - m_incoming(incoming), + m_msgId(msgId), + m_msgDirect(msgDirect), m_delFromIsds(delFromIsds) { Q_ASSERT(!m_userName.isEmpty()); Q_ASSERT(0 != m_dbSet); - Q_ASSERT(m_dmId >= 0); + Q_ASSERT(m_msgId.dmId >= 0); } void TaskEraseMessage::run(void) @@ -59,7 +59,7 @@ return; } - if (0 > m_dmId) { + if (0 > m_msgId.dmId) { Q_ASSERT(0); return; } @@ -69,8 +69,8 @@ /* ### Worker task begin. ### */ - m_result = eraseMessage(m_userName, m_dbSet, m_dmId, m_deliveryTime, - m_incoming, m_delFromIsds, m_isdsError, m_isdsLongError); + m_result = eraseMessage(m_userName, m_dbSet, m_msgId, m_msgDirect, + m_delFromIsds, m_isdsError, m_isdsLongError); emit globMsgProcEmitter.progressChange(PL_IDLE, 0); @@ -81,17 +81,18 @@ } enum TaskEraseMessage::Result TaskEraseMessage::eraseMessage( - const QString &userName, MessageDbSet *dbSet, qint64 dmId, - const QDateTime &deliveryTime, bool incoming, bool delFromIsds, - QString &error, QString &longError) + const QString &userName, MessageDbSet *dbSet, const MessageDb::MsgId &msgId, + enum MessageDirection msgDirect, bool delFromIsds, QString &error, + QString &longError) { Q_ASSERT(!userName.isEmpty()); Q_ASSERT(0 != dbSet); - Q_ASSERT(dmId >= 0); + Q_ASSERT(msgId.dmId >= 0); isds_error status = IE_SUCCESS; - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return NOT_DELETED; @@ -106,19 +107,20 @@ } status = isds_delete_message_from_storage(session, - QString::number(dmId).toUtf8().constData(), incoming); + QString::number(msgId.dmId).toUtf8().constData(), + msgDirect == MSG_RECEIVED); if (IE_SUCCESS == status) { logDebugLv1NL( "Message '%" PRId64 "' was deleted from ISDS.", - dmId); + msgId.dmId); } else { error = isdsStrError(status); longError = isdsLongMessage(session); logErrorNL( "Erasing message '%" PRId64 "'from ISDS returned status '%d': '%s'", - dmId, status, error.toUtf8().constData()); + msgId.dmId, status, error.toUtf8().constData()); } } @@ -126,15 +128,15 @@ return NOT_DELETED; } - if (messageDb->msgsDeleteMessageData(dmId)) { + if (messageDb->msgsDeleteMessageData(msgId.dmId)) { logDebugLv1NL( "Message '%" PRId64 "' was deleted from local database.", - dmId); + msgId.dmId); return (delFromIsds && (IE_SUCCESS == status)) ? DELETED_ISDS_LOCAL : DELETED_LOCAL; } else { logErrorNL( "Could not delete message '%" PRId64 "' from local database.", - dmId); + msgId.dmId); return (delFromIsds && (IE_SUCCESS == status)) ? DELETED_ISDS : NOT_DELETED; } } diff -Nru datovka-4.7.0/src/worker/task_erase_message.h datovka-4.7.1/src/worker/task_erase_message.h --- datovka-4.7.0/src/worker/task_erase_message.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_erase_message.h 2017-01-19 09:29:26.000000000 +0000 @@ -27,6 +27,7 @@ #include #include +#include "src/io/message_db.h" #include "src/io/message_db_set.h" #include "src/worker/task.h" @@ -47,13 +48,12 @@ * * @param[in] userName Account identifier (user login name). * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] dmId Message identifier. - * @param[in] deliveryTime Message delivery time. - * @param[in] incoming True if message is received. + * @param[in] msgId Message identifier. + * @param[in] msgDirect Received or sent. * @param[in] delFromIsds True if also delete from ISDS. */ explicit TaskEraseMessage(const QString &userName, MessageDbSet *dbSet, - qint64 dmId, const QDateTime &deliveryTime, bool incoming, + const MessageDb::MsgId &msgId, enum MessageDirection msgDirect, bool delFromIsds); /*! @@ -78,9 +78,8 @@ * * @param[in] userName Account identifier (user login name). * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] dmId Message identifier. - * @param[in] deliveryTime Message delivery time. - * @param[in] incoming True if message is received. + * @param[in] msgId Message identifier. + * @param[in] msgDirect Received or sent. * @param[in] delFromIsds True if also delete from ISDS. * @param[out] error Error description. * @param[out] longError Long error description. @@ -88,14 +87,13 @@ */ static enum Result eraseMessage(const QString &userName, MessageDbSet *dbSet, - qint64 dmId, const QDateTime &deliveryTime, bool incoming, + const MessageDb::MsgId &msgId, enum MessageDirection msgDirect, bool delFromIsds, QString &error, QString &longError); const QString m_userName; /*!< Account identifier (user login name). */ MessageDbSet *m_dbSet; /*!< Pointer to database container. */ - const qint64 m_dmId; /*!< Message identifier. */ - const QDateTime m_deliveryTime; /*!< Message delivery time. */ - const bool m_incoming; /*!< True if message is received. */ + const MessageDb::MsgId m_msgId; /*!< Message identifier. */ + enum MessageDirection m_msgDirect; /*!< Received or sent. */ const bool m_delFromIsds; /*!< True is also delete from ISDS. */ }; diff -Nru datovka-4.7.0/src/worker/task_get_account_list_mojeid.cpp datovka-4.7.1/src/worker/task_get_account_list_mojeid.cpp --- datovka-4.7.0/src/worker/task_get_account_list_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_get_account_list_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/io/account_db.h" +#include "src/models/accounts_model.h" +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_get_account_list_mojeid.h" +#include "src/web/json.h" +#include "src/io/wd_sessions.h" + +TaskGetAccountListMojeId::TaskGetAccountListMojeId(const QString &userName, + const QNetworkCookie &sessionid, bool syncWithAll, + AccountModel *accountModel, QStringList &deletedAccounts) + : m_return(ACNTLIST_SUCCESS), + m_error(), + m_userName(userName), + m_sessionid(sessionid), + m_syncWithAll(syncWithAll), + m_accountModel(accountModel), + m_deletedAccounts(deletedAccounts) +{ +} + +void TaskGetAccountListMojeId::run(void) +{ + + logDebugLv0NL("Starting download account list task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_return = getAccountList(m_userName, m_sessionid, m_syncWithAll, + m_accountModel, m_error, m_deletedAccounts); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Download account list task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +enum TaskGetAccountListMojeId::Result TaskGetAccountListMojeId::getAccountList( + const QString &userName, const QNetworkCookie &sessionid, + bool syncWithAll, AccountModel *accountModel, QString &error, + QStringList &deletedAccounts) +{ + int newUserId = 0; + int userId = 0; + QString localUserName = userName; + QList accountList; + QModelIndex index; + + emit globMsgProcEmitter.progressChange(PL_GET_ACCOUNT_LIST, -1); + + if (!jsonlayer.getAccountList(sessionid, newUserId, accountList, error)) { + return ACNTLIST_WEBDAT_ERR; + } + + /* test, if we are logged for relevant userId (account) */ + if (!localUserName.isEmpty()) { + userId = getWebDatovkaUserId(localUserName); + if (userId != newUserId) { + if (accountList.isEmpty()) { + return ACNTLIST_WRONGUSER; + } else { + return ACNTLIST_WU_HAS_ACNT; + } + } + deletedAccounts.clear(); + + /* how many accounts are relevant to given userId */ + AccountsMap::iterator i; + for (i = accountModel->globAccounts.begin(); + i != accountModel->globAccounts.end(); ++i) { + if (isWebDatovkaAccount(i->userName())) { + if (newUserId == getWebDatovkaUserId(i->userName())) { + deletedAccounts.append(i->userName()); + } + } + } + } + + /* if account list is empty, do nothing */ + if (accountList.isEmpty()) { + return ACNTLIST_NONEXIST; + } + + /* do action with account list (add/update account) */ + for (int i = 0; i < accountList.count(); ++i) { + localUserName = getWebDatovkaUsername( + QString::number(accountList.at(i).userId), + QString::number(accountList.at(i).accountId)); + if (!accountModel->globAccounts.contains(localUserName)) { + AcntSettings aSet; + aSet.setUserName(localUserName); + aSet.setAccountName(accountList.at(i).name); + aSet.setLoginMethod(AcntSettings::LIM_MOJE_ID); + aSet.setSyncWithAll(syncWithAll); + accountModel->addAccount(aSet, &index); + } else { + deletedAccounts.removeOne(localUserName); + accountModel->globAccounts[localUserName].setAccountName( + accountList.at(i).name); + } + + updateMojeIdAccountData(localUserName, accountList.at(i)); + + wdSessions.createCleanSession(localUserName); + wdSessions.setSessionCookie(localUserName, sessionid); + emit globMsgProcEmitter.refreshAccountList(localUserName); + } + + /* if relevantAccounts are not empty + * so any account(s) was/were removed from Webdatovka. + */ + if (!deletedAccounts.isEmpty()) { + return ACNTLIST_DELETE_ACNT; + } + + return ACNTLIST_SUCCESS; +} + +bool TaskGetAccountListMojeId::updateMojeIdAccountData(const QString &userName, + const JsonLayer::AccountData &aData) +{ + bool ret = globAccountDbPtr->insertAccountIntoDb( + userName + "___True", + aData.ownerInfo.dbID, + aData.ownerInfo.dbType, + aData.ownerInfo.ic.toInt(), + aData.ownerInfo.pnFirstName, + aData.ownerInfo.pnMiddleName, + aData.ownerInfo.pnLastName, + aData.ownerInfo.pnLastNameAtBirth, + aData.ownerInfo.firmName, + aData.ownerInfo.biDate, + aData.ownerInfo.biCity, + aData.ownerInfo.biCounty, + aData.ownerInfo.biState, + aData.ownerInfo.adCity, + aData.ownerInfo.adStreet, + aData.ownerInfo.adNumberInStreet, + aData.ownerInfo.adNumberInMunicipality, + aData.ownerInfo.adZipCode, + aData.ownerInfo.adState, + aData.ownerInfo.nationality, + aData.ownerInfo.identifier, + aData.ownerInfo.registryCode, + aData.ownerInfo.dbState, + aData.ownerInfo.dbEffectiveOVM, + aData.ownerInfo.dbOpenAddressing + ); + + ret = globAccountDbPtr->insertUserIntoDb( + userName + "___True", + aData.userInfo.userType, + aData.userInfo.userPrivils, + aData.userInfo.pnFirstName, + aData.userInfo.pnMiddleName, + aData.userInfo.pnLastName, + aData.userInfo.pnLastNameAtBirth, + aData.userInfo.adCity, + aData.userInfo.adStreet, + aData.userInfo.adNumberInStreet, + aData.userInfo.adNumberInMunicipality, + aData.userInfo.adZipCode, + aData.userInfo.adState, + aData.userInfo.biDate, + aData.userInfo.ic, + aData.userInfo.firmName, + aData.userInfo.caStreet, + aData.userInfo.caCity, + aData.userInfo.caZipCode, + aData.userInfo.caState + ); + + return ret; +} diff -Nru datovka-4.7.0/src/worker/task_get_account_list_mojeid.h datovka-4.7.1/src/worker/task_get_account_list_mojeid.h --- datovka-4.7.0/src/worker/task_get_account_list_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_get_account_list_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_GET_ACCOUNT_LIST_H_ +#define _TASK_GET_ACCOUNT_LIST_H_ + +#include + +#include "src/worker/task.h" + +/*! + * @brief Task describing download account list and its information data. + */ +class TaskGetAccountListMojeId : public Task { +public: + + /*! + * @Brief Return state describing what happened. + */ + enum Result { + ACNTLIST_SUCCESS, /*!< Action was successful. */ + ACNTLIST_NONEXIST, /*!< There aren't any accounts for mojeID. */ + ACNTLIST_WRONGUSER, /*!< UserID is not match with exists account userId. */ + ACNTLIST_WU_HAS_ACNT, /*!< UserID is not match with exists userId but new userId has any account */ + ACNTLIST_WEBDAT_ERR, /*!< Other webdatovka error. */ + ACNTLIST_DELETE_ACNT /*!< Any account was deleted in webdatovka. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] userName Username of account. + * @param[in] sessionid Session cookie from mojeid. + * @param[in] syncWithAll If will be synchronized with all accounts. + * @param[in] accountModel Pointer to account model. + * @param[out] deletedAccounts Deleted account usernames. + */ + explicit TaskGetAccountListMojeId(const QString &userName, + const QNetworkCookie &sessionid, bool syncWithAll, + AccountModel *accountModel, QStringList &deletedAccounts); + + /*! + * @brief Performs action. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + enum Result m_return; /*!< Retrun error code. */ + QString m_error; /*!< Error description. */ + QString m_userName; /*!< Account username or NULL. */ + const QNetworkCookie m_sessionid;/*!< Session cookie from mojeid. */ + bool m_syncWithAll; /*!< If will be synchronized with all accounts. */ + AccountModel *m_accountModel; /*!< Pointer to account model. */ + QStringList m_deletedAccounts; /*!< List of deleted accounts */ + +private: + /*! + * Disable copy and assignment. + */ + TaskGetAccountListMojeId(const TaskGetAccountListMojeId &); + TaskGetAccountListMojeId &operator=(const TaskGetAccountListMojeId &); + + /*! + * @brief Download account list, + * + * @param[in] userName Username of account. + * @param[in] sessionid Session cookie from mojeid. + * @param[in] syncWithAll If will be synchronized with all accounts. + * @param[in] accountModel Pointer to account model. + * @param[out] error Error description. + * @param[out] deletedAccounts Deleted account usernames. + * @return Action result. + */ + static + enum Result getAccountList(const QString &userName, + const QNetworkCookie &sessionid, bool syncWithAll, + AccountModel *accountModel, QString &error, + QStringList &deletedAccounts); + + /*! + * @brief Insert/update owner and user information. + * + * @param[in] userName Account username. + * @param[in] aData Account data. + * @return True on success. + */ + static + bool updateMojeIdAccountData(const QString &userName, + const JsonLayer::AccountData &aData); +}; + +#endif /* _TASK_GET_ACCOUNT_LIST_H_ */ diff -Nru datovka-4.7.0/src/worker/task.h datovka-4.7.1/src/worker/task.h --- datovka-4.7.0/src/worker/task.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task.h 2017-01-19 09:29:26.000000000 +0000 @@ -30,6 +30,8 @@ #include "src/common.h" // qdatovka_error, enum MessageDirection #include "src/io/message_db.h" // MessageDb::MsgId #include "src/io/message_db_set.h" +#include "src/web/json.h" + /*! * @brief Maximum length of message list to be downloaded. @@ -46,6 +48,8 @@ #define PL_IMPORT_ZFO_DINFO "ImportZfoDeliveryInfo" #define PL_IMPORT_ZFO_MSG "ImportZfoMessage" #define PL_SEND_MESSAGE "SendMessage" +#define PL_SYNC_ACCOUNT "SyncAccount" +#define PL_GET_ACCOUNT_LIST "GetAccounts" /*! * @brief This class contains generic functions that can be used in derived @@ -89,6 +93,7 @@ void run(void) = 0; protected: + /*! * @brief Store message delivery information into database. * @@ -108,11 +113,13 @@ * @param[in] msgDirect Received or sent message. * @param[in,out] dbSet Database container. * @param[in] envel Message envelope. + * @param[in] msgId Message webdatovka id or NULL. * @return Error state. */ static qdatovka_error storeEnvelope(enum MessageDirection msgDirect, - MessageDbSet &dbSet, const struct isds_envelope *envel); + MessageDbSet &dbSet, const struct isds_envelope *envel, + QString msgId); /*! * @brief Store message into database. @@ -129,7 +136,7 @@ qdatovka_error storeMessage(bool signedMsg, enum MessageDirection msgDirect, MessageDbSet &dbSet, const struct isds_message *msg, - const QString &progressLabel); + const QString &progressLabel, QString msgId); /*! * @brief Store attachments into database. @@ -149,11 +156,26 @@ * @param[in] msgDirect Received or sent message. * @param[in,out] messageDb Database. * @param[in] envel Message envelope. + * @param[in] msgId Message webdatovka id or NULL. * @return True on success. */ static qdatovka_error updateEnvelope(enum MessageDirection msgDirect, - MessageDb &messageDb, const struct isds_envelope *envel); + MessageDb &messageDb, const struct isds_envelope *envel, + QString msgId); + + /*! + * @brief Store envelope into database. + * + * @param[in] msgDirect Received or sent message. + * @param[in,out] dbSet Database container. + * @param[in] envel Message envelope. + * @param[in] isNew true = insert into db, false = update in db. + * @return Error state. + */ + static + qdatovka_error storeEnvelopeWebDatovka(enum MessageDirection msgDirect, + MessageDbSet &dbSet, const JsonLayer::Envelope &envel, bool isNew); private: // /*! diff -Nru datovka-4.7.0/src/worker/task_import_zfo.cpp datovka-4.7.1/src/worker/task_import_zfo.cpp --- datovka-4.7.0/src/worker/task_import_zfo.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_import_zfo.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -256,9 +256,9 @@ /* Store envelope and message. */ if ((Q_SUCCESS != Task::storeEnvelope(direct, *(acnt.messageDbSet), - message->envelope)) || + message->envelope, NULL)) || (Q_SUCCESS != Task::storeMessage(true, direct, *(acnt.messageDbSet), - message, ""))) { + message, "", NULL))) { resultDesc = QObject::tr("File has not been imported because " "an error was detected during insertion process."); return TaskImportZfo::IMP_DB_INS_ERR; diff -Nru datovka-4.7.0/src/worker/task_send_message_mojeid.cpp datovka-4.7.1/src/worker/task_send_message_mojeid.cpp --- datovka-4.7.0/src/worker/task_send_message_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_send_message_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_send_message_mojeid.h" + + +TaskSendMessageMojeId::TaskSendMessageMojeId(const QString &userName, + int accountID, const QList &recipientList, + const JsonLayer::Envelope &envelope, const QList &fileList) + : + m_userName(userName), + m_accountID(accountID), + m_recipientList(recipientList), + m_envelope(envelope), + m_fileList(fileList), + m_resultList(QStringList()), + m_error(QString()) +{ +} + + +void TaskSendMessageMojeId::run(void) +{ + logDebugLv0NL("Starting send message task in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + sendMessage(m_userName, m_accountID, m_recipientList, m_envelope, + m_fileList, PL_SEND_MESSAGE, m_resultList, m_error); + + emit globMsgProcEmitter.sendMessageMojeIdFinished(m_userName, + m_resultList, m_error); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Send message task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +enum TaskSendMessageMojeId::Result TaskSendMessageMojeId::sendMessage( + const QString &userName, + int accountID, const QList &recipientList, + const JsonLayer::Envelope &envelope, const QList &fileList, + const QString &progressLabel, QStringList &resultList, + QString &errStr) +{ + emit globMsgProcEmitter.progressChange(progressLabel, -1); + + jsonlayer.sendMessage(userName, accountID, recipientList, envelope, + fileList, resultList, errStr); + + emit globMsgProcEmitter.progressChange(progressLabel, 100); + + return SM_SUCCESS; +} diff -Nru datovka-4.7.0/src/worker/task_send_message_mojeid.h datovka-4.7.1/src/worker/task_send_message_mojeid.h --- datovka-4.7.0/src/worker/task_send_message_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_send_message_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_SEND_MESSAGE_MOJEID_H_ +#define _TASK_SEND_MESSAGE_MOJEID_H_ + +#include +#include + +#include "src/worker/task.h" +#include "src/web/json.h" + +/*! + * @brief Task describing sending message. + */ +class TaskSendMessageMojeId : public Task { +public: + /*! + * @brief Return state describing what happened. + */ + enum Result { + SM_SUCCESS, /*!< Operation was successful. */ + SM_NET_ERROR, /*!< Error communicating with webdatovka. */ + SM_ERR /*!< Other error. */ + }; + + /*! + * @brief Constructor. + * + * @param[in] userName Account identifier (user login name). + * @param[in] accountID Account ID of webdatovka. + * @param[in] recipientList List of recipients. + * @param[in] envelope Envelope data. + * @param[in] fileList List of attachments. + */ + explicit TaskSendMessageMojeId(const QString &userName, + int accountID, const QList &recipientList, + const JsonLayer::Envelope &envelope, + const QList &fileList); + + /*! + * @brief Performs actual message sending. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + +private: + /*! + * Disable copy and assignment. + */ + TaskSendMessageMojeId(const TaskSendMessageMojeId &); + TaskSendMessageMojeId &operator=(const TaskSendMessageMojeId &); + + /*! + * @brief Sends a single message to ISDS fro given account. + * + * @param[in] userName Account identifier (user login name). + * @param[in] accountID Account ID of webdatovka. + * @param[in] recipientList List of recipients. + * @param[in] envelope Envelope data. + * @param[in] fileList List of attachments. + * @param[in] progressLabel Progress-bar label. + * @param[out] resultList ResultList. + * @param[out] error Error message. + * @return Error state. + */ + static + enum Result sendMessage(const QString &userName, + int accountID, const QList &recipientList, + const JsonLayer::Envelope &envelope, + const QList &fileList, + const QString &progressLabel, + QStringList &resultList, + QString &error); + + const QString m_userName; /*!< Account identifier (user login name). */ + const int m_accountID; /*!< Account id of webdatovka. */ + const QList m_recipientList; /*!< List of recipients. */ + const JsonLayer::Envelope m_envelope; /*!< Envelope data. */ + const QList m_fileList; /*!< List of attachments. */ + QStringList m_resultList; /*!< ResultList. */ + QString m_error; +}; + +#endif /* _TASK_SEND_MESSAGE_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_sync_mojeid.cpp datovka-4.7.1/src/worker/task_sync_mojeid.cpp --- datovka-4.7.0/src/worker/task_sync_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_sync_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/io/account_db.h" +#include "src/io/dbs.h" +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_sync_mojeid.h" +#include "src/web/json.h" + +TaskSyncAccount::TaskSyncAccount(const QString &userName, int id) + : m_success(false), + m_isdsError(), + m_userName(userName), + m_id(id) +{ +} + +void TaskSyncAccount::run(void) +{ + logDebugLv0NL("Starting account sync in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_success = syncAccount(m_userName, m_id, m_isdsError); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Account sync task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +bool TaskSyncAccount::syncAccount(const QString &userName, int id, + QString &error) +{ + emit globMsgProcEmitter.progressChange(PL_SYNC_ACCOUNT, -1); + + return jsonlayer.syncAccount(userName, id, error); +} diff -Nru datovka-4.7.0/src/worker/task_sync_mojeid.h datovka-4.7.1/src/worker/task_sync_mojeid.h --- datovka-4.7.0/src/worker/task_sync_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_sync_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_SYNC_MOJEID_H_ +#define _TASK_SYNC_MOJEID_H_ + +#include + +#include "src/worker/task.h" + +/*! + * @brief Task describing sync account information. + */ +class TaskSyncAccount : public Task { +public: + /*! + * @brief Constructor. + * + * @param[in] userName Account identifier (user login name) + * @param[in] id Account identifier. + */ + explicit TaskSyncAccount(const QString &userName, int id); + + /*! + * @brief Performs action. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + bool m_success; /*!< True on success. */ + QString m_isdsError; /*!< Error description. */ + +private: + /*! + * Disable copy and assignment. + */ + TaskSyncAccount(const TaskSyncAccount &); + TaskSyncAccount &operator=(const TaskSyncAccount &); + + /*! + * @brief Sync account. + * + * @param[in] userName Account identifier (user login name) + * @param[in] id Account identifier. + * @param[out] error Error description. + * @return True on success. + */ + static + bool syncAccount(const QString &userName, int id, QString &error); + + const QString m_userName; /*!< Account identifier (user login name). */ + int m_id; /*!< Account identifier. */ +}; + +#endif /* _TASK_SYNC_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_tag_sync_mojeid.cpp datovka-4.7.1/src/worker/task_tag_sync_mojeid.cpp --- datovka-4.7.0/src/worker/task_tag_sync_mojeid.cpp 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_tag_sync_mojeid.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#include + +#include "src/log/log.h" +#include "src/worker/message_emitter.h" +#include "src/worker/task_tag_sync_mojeid.h" +#include "src/io/tag_db_container.h" +#include "src/web/json.h" + +TaskTagSyncAccount::TaskTagSyncAccount(const QString &userName) + : m_success(false), + m_error(), + m_userName(userName) +{ +} + +void TaskTagSyncAccount::run(void) +{ + logDebugLv0NL("Starting tag sync in thread '%p'", + (void *) QThread::currentThreadId()); + + /* ### Worker task begin. ### */ + + m_success = syncTagList(m_userName, m_error); + + emit globMsgProcEmitter.progressChange(PL_IDLE, 0); + + /* ### Worker task end. ### */ + + logDebugLv0NL("Tag sync task finished in thread '%p'", + (void *) QThread::currentThreadId()); +} + +bool TaskTagSyncAccount::syncTagList(const QString &userName, QString &error) +{ + emit globMsgProcEmitter.progressChange(PL_SYNC_ACCOUNT, -1); + + QList tagList; + + if (jsonlayer.getTagList(userName, tagList, error)) { + globWebDatovkaTagDbPtr->accessTagDb( + getWebDatovkaTagDbPrefix(userName))->deleteAllTags(); + foreach (const JsonLayer::Tag &tag, tagList) { + globWebDatovkaTagDbPtr->accessTagDb( + getWebDatovkaTagDbPrefix(userName))-> + insertUpdateWebDatovkaTag(tag.id, tag.name, + tag.color); + } + } + + return true; +} diff -Nru datovka-4.7.0/src/worker/task_tag_sync_mojeid.h datovka-4.7.1/src/worker/task_tag_sync_mojeid.h --- datovka-4.7.0/src/worker/task_tag_sync_mojeid.h 1970-01-01 00:00:00.000000000 +0000 +++ datovka-4.7.1/src/worker/task_tag_sync_mojeid.h 2017-01-19 09:29:26.000000000 +0000 @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2014-2015 CZ.NIC + * + * 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 . + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations including + * the two. + */ + +#ifndef _TASK_TAG_SYNC_MOJEID_H_ +#define _TASK_TAG_SYNC_MOJEID_H_ + +#include + +#include "src/worker/task.h" + +/*! + * @brief Task describing sync account information. + */ +class TaskTagSyncAccount : public Task { +public: + /*! + * @brief Constructor. + * + * @param[in] userName Account identifier (user login name) + */ + explicit TaskTagSyncAccount(const QString &userName); + + /*! + * @brief Performs action. + */ + virtual + void run(void) Q_DECL_OVERRIDE; + + bool m_success; /*!< True on success. */ + QString m_error; /*!< Error description. */ + +private: + /*! + * Disable copy and assignment. + */ + TaskTagSyncAccount(const TaskTagSyncAccount &); + TaskTagSyncAccount &operator=(const TaskTagSyncAccount &); + + /*! + * @brief Sync account. + * + * @param[in] userName Account identifier (user login name) + * @param[out] error Error description. + * @return True on success. + */ + static + bool syncTagList(const QString &userName, QString &error); + + const QString m_userName; /*!< Account identifier (user login name). */ +}; + +#endif /* _TASK_TAG_SYNC_MOJEID_H_ */ diff -Nru datovka-4.7.0/src/worker/task_vacuum_db_set.cpp datovka-4.7.1/src/worker/task_vacuum_db_set.cpp --- datovka-4.7.0/src/worker/task_vacuum_db_set.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_vacuum_db_set.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -26,7 +26,7 @@ #if (QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)) #include #else /* < Qt-5.4 */ -#warning "Compiling against version < Qt-5.4." /* Doesn't have QStorageInfo. */ +#warning "Compiling against version < Qt-5.4 which does not have QStorageInfo." #include #endif /* >= Qt-5.4 */ #include diff -Nru datovka-4.7.0/src/worker/task_verify_message.cpp datovka-4.7.1/src/worker/task_verify_message.cpp --- datovka-4.7.0/src/worker/task_verify_message.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_verify_message.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -33,19 +33,18 @@ #include "src/worker/task_verify_message.h" TaskVerifyMessage::TaskVerifyMessage(const QString &userName, - MessageDbSet *dbSet, qint64 dmId, const QDateTime &deliveryTime) + MessageDbSet *dbSet, const MessageDb::MsgId &msgId) : m_result(VERIFY_ERR), m_isdsError(), m_isdsLongError(), m_userName(userName), m_dbSet(dbSet), - m_dmId(dmId), - m_deliveryTime(deliveryTime) + m_msgId(msgId) { Q_ASSERT(!m_userName.isEmpty()); Q_ASSERT(0 != m_dbSet); - Q_ASSERT(m_dmId >= 0); - Q_ASSERT(m_deliveryTime.isValid()); + Q_ASSERT(m_msgId.dmId >= 0); + Q_ASSERT(m_msgId.deliveryTime.isValid()); } void TaskVerifyMessage::run(void) @@ -60,12 +59,12 @@ return; } - if (0 > m_dmId) { + if (0 > m_msgId.dmId) { Q_ASSERT(0); return; } - if (!m_deliveryTime.isValid()) { + if (!m_msgId.deliveryTime.isValid()) { Q_ASSERT(0); return; } @@ -75,8 +74,8 @@ /* ### Worker task begin. ### */ - m_result = verifyMessage(m_userName, m_dbSet, m_dmId, m_deliveryTime, - m_isdsError, m_isdsLongError); + m_result = verifyMessage(m_userName, m_dbSet, m_msgId, m_isdsError, + m_isdsLongError); emit globMsgProcEmitter.progressChange(PL_IDLE, 0); @@ -128,15 +127,16 @@ } enum TaskVerifyMessage::Result TaskVerifyMessage::verifyMessage( - const QString &userName, MessageDbSet *dbSet, qint64 dmId, - const QDateTime &deliveryTime, QString &error, QString &longError) + const QString &userName, MessageDbSet *dbSet, const MessageDb::MsgId &msgId, + QString &error, QString &longError) { Q_ASSERT(!userName.isEmpty()); Q_ASSERT(0 != dbSet); - Q_ASSERT(dmId >= 0); - Q_ASSERT(deliveryTime.isValid()); + Q_ASSERT(msgId.dmId >= 0); + Q_ASSERT(msgId.deliveryTime.isValid()); - MessageDb *messageDb = dbSet->accessMessageDb(deliveryTime, false); + MessageDb *messageDb = dbSet->accessMessageDb(msgId.deliveryTime, + false); if (0 == messageDb) { Q_ASSERT(0); return VERIFY_ERR; @@ -150,10 +150,10 @@ struct isds_hash *hashIsds = NULL; isds_error status = isds_download_message_hash(session, - QString::number(dmId).toUtf8().constData(), &hashIsds); + QString::number(msgId.dmId).toUtf8().constData(), &hashIsds); if (IE_SUCCESS != status) { logErrorNL("Error downloading hash of message '%" PRId64 "'.", - dmId); + msgId.dmId); error = isds_error(status); longError = isdsLongMessage(session); isds_hash_free(&hashIsds); @@ -162,11 +162,11 @@ Q_ASSERT(NULL != hashIsds); - struct isds_hash *hashLocal = localMessageHash(messageDb, dmId); + struct isds_hash *hashLocal = localMessageHash(messageDb, msgId.dmId); if (NULL == hashLocal) { logErrorNL( "Error obtaining hash of message '%" PRId64 "' from local database.", - dmId); + msgId.dmId); isds_hash_free(&hashIsds); return VERIFY_SQL_ERR; } diff -Nru datovka-4.7.0/src/worker/task_verify_message.h datovka-4.7.1/src/worker/task_verify_message.h --- datovka-4.7.0/src/worker/task_verify_message.h 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/src/worker/task_verify_message.h 2017-01-19 09:29:26.000000000 +0000 @@ -27,6 +27,7 @@ #include #include +#include "src/io/message_db.h" #include "src/io/message_db_set.h" #include "src/worker/task.h" @@ -51,11 +52,10 @@ * * @param[in] userName Account identifier (user login name). * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] dmId Message identifier. - * @param[in] deliveryTime Message delivery time. + * @param[in] msgId Message identifier. */ explicit TaskVerifyMessage(const QString &userName, MessageDbSet *dbSet, - qint64 dmId, const QDateTime &deliveryTime); + const MessageDb::MsgId &msgId); /*! * @brief Performs action. @@ -79,21 +79,18 @@ * * @param[in] userName Account identifier (user login name). * @param[in,out] dbSet Non-null pointer to database container. - * @param[in] dmId Message identifier. - * @param[in] deliveryTime Message delivery time. + * @param[in] msgId Message identifier. * @param[out] error Error description. * @param[out] longError Long error description. * @return Verification result. */ static enum Result verifyMessage(const QString &userName, MessageDbSet *dbSet, - qint64 dmId, const QDateTime &deliveryTime, QString &error, - QString &longError); + const MessageDb::MsgId &msgId, QString &error, QString &longError); const QString m_userName; /*!< Account identifier (user login name). */ MessageDbSet *m_dbSet; /*!< Pointer to database container. */ - const qint64 m_dmId; /*!< Message identifier. */ - const QDateTime m_deliveryTime; /*!< Message delivery time. */ + const MessageDb::MsgId m_msgId; /*!< Message identifier. */ }; #endif /* _TASK_VERIFY_MESSAGE_H_ */ diff -Nru datovka-4.7.0/tests/test_db_container.pri datovka-4.7.1/tests/test_db_container.pri --- datovka-4.7.0/tests/test_db_container.pri 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/tests/test_db_container.pri 2017-01-19 09:29:26.000000000 +0000 @@ -15,6 +15,7 @@ $${top_srcdir}src/common.cpp \ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ + $${top_srcdir}src/dimensions/dimensions.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ $${top_srcdir}src/io/filesystem.cpp \ @@ -35,6 +36,7 @@ $${top_srcdir}src/crypto/crypto.h \ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ + $${top_srcdir}src/dimensions/dimensions.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ $${top_srcdir}src/io/filesystem.h \ diff -Nru datovka-4.7.0/tests/test_message_db_set.pri datovka-4.7.1/tests/test_message_db_set.pri --- datovka-4.7.0/tests/test_message_db_set.pri 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/tests/test_message_db_set.pri 2017-01-19 09:29:26.000000000 +0000 @@ -15,6 +15,7 @@ $${top_srcdir}src/common.cpp \ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ + $${top_srcdir}src/dimensions/dimensions.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ $${top_srcdir}src/io/filesystem.cpp \ @@ -34,6 +35,7 @@ $${top_srcdir}src/crypto/crypto.h \ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ + $${top_srcdir}src/dimensions/dimensions.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ $${top_srcdir}src/io/filesystem.h \ diff -Nru datovka-4.7.0/tests/test_task_downloads.cpp datovka-4.7.1/tests/test_task_downloads.cpp --- datovka-4.7.0/tests/test_task_downloads.cpp 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/tests/test_task_downloads.cpp 2017-01-19 09:29:26.000000000 +0000 @@ -27,6 +27,7 @@ #include "src/io/account_db.h" #include "src/io/isds_sessions.h" +#include "src/io/message_db.h" #include "src/settings/preferences.h" #include "src/worker/task_download_message.h" #include "src/worker/task_download_message_list.h" @@ -251,8 +252,8 @@ /* Should fail, is a received message. */ task = new (::std::nothrow) TaskDownloadMessage(m_recipient.userName, - m_recipientDbSet, MSG_SENT, m_receivedMsgId, m_deliveryTime, - false); + m_recipientDbSet, MSG_SENT, + MessageDb::MsgId(m_receivedMsgId, m_deliveryTime), false); QVERIFY(task != NULL); task->setAutoDelete(false); @@ -265,8 +266,8 @@ /* Must succeed. */ task = new (::std::nothrow) TaskDownloadMessage(m_recipient.userName, - m_recipientDbSet, MSG_RECEIVED, m_receivedMsgId, m_deliveryTime, - false); + m_recipientDbSet, MSG_RECEIVED, + MessageDb::MsgId(m_receivedMsgId, m_deliveryTime), false); QVERIFY(task != NULL); task->setAutoDelete(false); diff -Nru datovka-4.7.0/tests/test_task_downloads.pri datovka-4.7.1/tests/test_task_downloads.pri --- datovka-4.7.0/tests/test_task_downloads.pri 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/tests/test_task_downloads.pri 2017-01-19 09:29:26.000000000 +0000 @@ -16,6 +16,7 @@ $${top_srcdir}src/common.cpp \ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ + $${top_srcdir}src/dimensions/dimensions.cpp \ $${top_srcdir}src/io/account_db.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ @@ -45,6 +46,7 @@ $${top_srcdir}src/crypto/crypto.h \ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ + $${top_srcdir}src/dimensions/dimensions.h \ $${top_srcdir}src/io/account_db.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \ diff -Nru datovka-4.7.0/tests/test_task_send_message.pri datovka-4.7.1/tests/test_task_send_message.pri --- datovka-4.7.0/tests/test_task_send_message.pri 2016-10-19 07:53:33.000000000 +0000 +++ datovka-4.7.1/tests/test_task_send_message.pri 2017-01-19 09:29:26.000000000 +0000 @@ -16,6 +16,7 @@ $${top_srcdir}src/common.cpp \ $${top_srcdir}src/crypto/crypto.c \ $${top_srcdir}src/delegates/tag_item.cpp \ + $${top_srcdir}src/dimensions/dimensions.cpp \ $${top_srcdir}src/io/account_db.cpp \ $${top_srcdir}src/io/db_tables.cpp \ $${top_srcdir}src/io/dbs.cpp \ @@ -42,6 +43,7 @@ $${top_srcdir}src/crypto/crypto.h \ $${top_srcdir}src/crypto/crypto_funcs.h \ $${top_srcdir}src/delegates/tag_item.h \ + $${top_srcdir}src/dimensions/dimensions.h \ $${top_srcdir}src/io/account_db.h \ $${top_srcdir}src/io/db_tables.h \ $${top_srcdir}src/io/dbs.h \