mirror of
https://github.com/martinrotter/rssguard.git
synced 2025-01-29 00:30:12 +01:00
Save, currently broken
This commit is contained in:
parent
9cbb44bfdb
commit
6e51dd34b0
@ -135,7 +135,7 @@ Erro: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New articles fetched</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Novos artigos buscados</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -216,27 +216,27 @@ Erro: %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Removing read articles...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Removendo artigos lidos...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Read articles purged...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Artigos lidos removidos...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Removing old articles...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Removendo artigos antigos...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Old articles purged...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Artigos antigos removidos...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Removing starred articles...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Removendo artigos com estrela...</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starred articles purged...</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Artigos com estrela removidos...</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -449,25 +449,25 @@ Status: %3</translation>
|
||||
<message>
|
||||
<source>does not use auto-fetching of articles</source>
|
||||
<extracomment>Describes feed auto-update status.</extracomment>
|
||||
<translation type="unfinished"/>
|
||||
<translation>não usa a busca automática de artigos</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>uses global settings (%n minute(s) to next auto-fetch of articles)</source>
|
||||
<extracomment>Describes feed auto-update status.</extracomment>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>usa configurações globais (%n minuto(s) para próxima busca automática de artigos)</numerusform><numerusform>usa configurações globais (%n minuto(s) para próxima busca automática de artigos)</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>uses global settings (global auto-fetching of articles is disabled)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>usa configurações globais (busca automática de artigos global desativada)</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>uses specific settings (%n minute(s) to next auto-fetching of new articles)</source>
|
||||
<extracomment>Describes feed auto-update status.</extracomment>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>usa configurações específicas (%n minuto(s) para próxima busca automática de artigos)</numerusform><numerusform>usa configurações específicas (%n minuto(s) para próxima busca automática de artigos)</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>has new articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>possui novos artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -478,26 +478,26 @@ Status: %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Toolbar for articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Barra de ferramentas para artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>FeedReader</name>
|
||||
<message>
|
||||
<source>Cannot fetch articles for all items</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Não foi possível buscar artigos para todos os itens</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>You cannot fetch new articles for your items because another critical operation is ongoing.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Você não pode buscar novos artigos para seus itens pois outra operação crítica está em andamento.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Starting auto-download of some feeds' articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Iniciando download automático de alguns artigos de feeds</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>I will auto-download new articles for %n feed(s).</source>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>Farei o download automático de novos artigos para%n feed(s).</numerusform><numerusform>Farei o download automático de novos artigos para%n feed(s).</numerusform></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -600,7 +600,7 @@ Status: %3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Beware of downloading too many articles, because Feedly permanently caches ALL articles of the feed forever so you might end up with thousands of articles which you will never read anyway.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Cuidado para não baixar muitos artigos, porque o Feedly armazena em cache permanentemente TODOS os artigos do feed para sempre, então você pode acabar com milhares de artigos que nunca irá ler de qualquer maneira.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -757,7 +757,7 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Context menu for important articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Menu de contexto para artigos importantes</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1119,7 +1119,7 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Edit "%1"</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Editar "%1"</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1134,7 +1134,7 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source> day(s)</source>
|
||||
<translation><numerusform>dia(s)</numerusform><numerusform>dia(s)</numerusform></translation>
|
||||
<translation><numerusform> dia(s)</numerusform><numerusform> dia(s)</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Shrink database file</source>
|
||||
@ -1270,19 +1270,19 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Edit "%1"</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Editar "%1"</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fetch articles using global interval</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Buscar artigos usando intervalo global</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fetch articles every</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Buscar artigos a cada</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Disable auto-fetching of articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Desativar busca automática de artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1726,19 +1726,19 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>F&eeds</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>F&eeds</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Art&icles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Art&igos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Web browser && tabs</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Navegador &web && abas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Ta&bs</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>A&bas</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -1885,22 +1885,25 @@ ou esta função ainda não foi implementada.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Filter articles like this</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Filtrar artigos como este</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New article filter</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Novo filtro de artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>EXISTING articles filtering error: '%1'.
|
||||
</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Erro ao filtrar artigos EXISTENTES: "%1".
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Article will be %1.
|
||||
|
||||
</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo será %1.
|
||||
|
||||
</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Output (modified) article is:
|
||||
@ -1911,12 +1914,20 @@ ou esta função ainda não foi implementada.</translation>
|
||||
Created on = '%6'
|
||||
Contents = '%7'
|
||||
RAW contents = '%8'</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo de saída (modificado) é:
|
||||
Título = '%1'
|
||||
URL = '%2'
|
||||
Autor = '%3'
|
||||
Foi lido/é importante = '%4/%5'
|
||||
Criado em = '%6'
|
||||
Conteúdo = '%7'
|
||||
Conteúdo RAW = '%8'</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>SAMPLE article filtering error: '%1'.
|
||||
</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Erro ao filtrar artigos de AMOSTRA: "%1".
|
||||
</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2543,7 +2554,7 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Yeah.</source>
|
||||
<translation>Legal</translation>
|
||||
<translation>Legal.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Username cannot be empty.</source>
|
||||
@ -2579,7 +2590,7 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Limiting the number of fetched articles per feed makes fetching of articles faster, but if your feed contains more articles than specified limit, then some older articles might not be fetched at all.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Limitar o número de artigos buscados por feed forna a busca de artigos mais rápida, mas se seu feed contém mais artigos que o limite especificado, então alguns artigos mais antigos podem não ser buscados.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -2864,26 +2875,26 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>article</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>artigo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>MessagePreviewer</name>
|
||||
<message>
|
||||
<source>Mark article read</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Marcar artigo como lido</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Mark article unread</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Marcar artigo como não lido</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Switch article importance</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Alterar importância do artigo</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3008,79 +3019,79 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Loading of articles from item '%1' failed.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Falha ao carregar artigos do item '%1'.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Loading of articles failed, maybe messages could not be downloaded.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Falha ao carregar artigos, talvez as mensagens não puderam ser baixadas.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ID of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ID do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Is article read?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo foi lido?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Is article important?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo é importante?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Is article deleted?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo foi excluído?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Is article permanently deleted from recycle bin?</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>O artigo foi permanentemente excluído da Lixeira?</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>ID of feed which this article belongs to.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ID do feed ao qual este artigo pertence.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Title of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Título do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Url of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>URL do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Author of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Autor do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Creation date of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Data de criação do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Contents of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Conteúdo do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Score of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nota do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Account ID of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ID da conta do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Custom ID of the article</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ID personalizado do artigo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Custom hash of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Hash personalizado do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Custom ID of feed of the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>ID personalizado do feed do artigo.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Indication of enclosures presence within the article.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Indicação da presença de anexos dentro do artigo.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3095,31 +3106,31 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Search articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Pesquisar artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Article search box</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Caixa de pesquisa de artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Menu for highlighting articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Menu para destacar artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Highlight unread articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Destacar artigos não lidos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Highlight important articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Destacar artigos importantes</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Display all articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Exibir todos os artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Article highlighter</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Destacador de artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3150,7 +3161,7 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Context menu for articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Menu de contexto para artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3306,15 +3317,15 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>Show more articles (%n remaining)</source>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>Exibir mais artigos (%n restante(s))</numerusform><numerusform>Exibir mais artigos (%n restante(s))</numerusform></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot show more articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Não é possível mostrar mais artigos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot show more articles because parent feed was removed.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Não é possível mostrar mais artigos pois o feed principal foi removido.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3464,7 +3475,7 @@ Expiração dos tokens de login: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3565,31 +3576,31 @@ O Feedly é um espaço seguro onde você pode organizar e pesquisar com privacid
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot insert article filter, because current database cannot return last inserted row ID.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Não é possível inserir o filtro do artigo, pois o banco de dados atual não pode retornar o último ID de linha inserido.</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New articles fetched</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Novos artigos buscados</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Fetching articles right now</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Buscando artigos agora mesmo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Login data refreshed</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Dados de login atualizados</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>New %1 version is available</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Nova versão %1 disponível</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Miscellaneous events</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Eventos diversos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Unknown event</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Evento desconhecido</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3608,11 +3619,11 @@ O Feedly é um espaço seguro onde você pode organizar e pesquisar com privacid
|
||||
</message>
|
||||
<message>
|
||||
<source>Recycle bin contains all deleted articles from all feeds.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>A Lixeira contém todos os artigos excluídos de todos os feeds.</translation>
|
||||
</message>
|
||||
<message numerus="yes">
|
||||
<source>%n deleted article(s).</source>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>%n artigo(s) excluído(s).</numerusform><numerusform>%n artigo(s) excluído(s).</numerusform></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3620,7 +3631,7 @@ O Feedly é um espaço seguro onde você pode organizar e pesquisar com privacid
|
||||
<message numerus="yes">
|
||||
<source>%n unread article(s).</source>
|
||||
<extracomment>Tooltip for "unread" column of feed list.</extracomment>
|
||||
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
|
||||
<translation><numerusform>%n artigo(s) não lido(s).</numerusform><numerusform>%n artigo(s) não lido(s).</numerusform></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -3673,7 +3684,7 @@ O Feedly é um espaço seguro onde você pode organizar e pesquisar com privacid
|
||||
</message>
|
||||
<message>
|
||||
<source>Synchronize article cache</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Sincronizar cache dos artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4275,11 +4286,11 @@ Os autores deste aplicativo NÃO são responsáveis pela perda de dados.</transl
|
||||
</message>
|
||||
<message>
|
||||
<source>Tray area</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Área de notificação</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Toolbar for articles list</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Barra de ferramentas para lista de artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4317,7 +4328,7 @@ Os autores deste aplicativo NÃO são responsáveis pela perda de dados.</transl
|
||||
</message>
|
||||
<message>
|
||||
<source>You must have "tray icon" activated to have balloon notifications working.</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Você precisa ter o "ícone da área de notificação" ativado para que as janelas de notificação funcionem.</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4346,15 +4357,15 @@ Os autores deste aplicativo NÃO são responsáveis pela perda de dados.</transl
|
||||
<name>SingleNotificationEditor</name>
|
||||
<message>
|
||||
<source>Sound</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Som</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Full path to your WAV sound file</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Caminho completo para arquivo de som WAV</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Clear</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>&Limpar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>&Browse</source>
|
||||
@ -4362,19 +4373,19 @@ Os autores deste aplicativo NÃO são responsáveis pela perda de dados.</transl
|
||||
</message>
|
||||
<message>
|
||||
<source>&Play</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>&Tocar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Balloon notification</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Balão de notificação</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Select sound file</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Selecionar arquivo de som</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>WAV files (*.wav)</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Arquivos WAV (*.wav)</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
@ -4832,7 +4843,7 @@ Notícias não lidas: %2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Browse your feeds and articles</source>
|
||||
<translation type="unfinished"/>
|
||||
<translation>Procurar seus feeds e artigos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -30,7 +30,7 @@
|
||||
<url type="donation">https://martinrotter.github.io/donate/</url>
|
||||
<content_rating type="oars-1.1" />
|
||||
<releases>
|
||||
<release version="3.9.2" date="2021-06-24"/>
|
||||
<release version="3.9.2" date="2021-06-25"/>
|
||||
</releases>
|
||||
<content_rating type="oars-1.0">
|
||||
<content_attribute id="violence-cartoon">none</content_attribute>
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "core/feedsmodel.h"
|
||||
#include "core/messagefilter.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "exceptions/filteringexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "services/abstract/cacheforserviceroot.h"
|
||||
@ -117,192 +118,209 @@ void FeedDownloader::updateOneFeed(Feed* feed) {
|
||||
<< feed->customId() << "' URL: '" << feed->source() << "' title: '" << feed->title() << "' in thread: '"
|
||||
<< QThread::currentThreadId() << "'.";
|
||||
|
||||
bool error_during_obtaining = false;
|
||||
int acc_id = feed->getParentServiceRoot()->accountId();
|
||||
QElapsedTimer tmr; tmr.start();
|
||||
QList<Message> msgs = feed->getParentServiceRoot()->obtainNewMessages({ feed }, &error_during_obtaining);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Downloaded " << msgs.size() << " messages for feed ID '"
|
||||
<< feed->customId() << "' URL: '" << feed->source() << "' title: '" << feed->title() << "' in thread: '"
|
||||
<< QThread::currentThreadId() << "'. Operation took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
try {
|
||||
QList<Message> msgs = feed->getParentServiceRoot()->obtainNewMessages({ feed });
|
||||
|
||||
// Now, sanitize messages (tweak encoding etc.).
|
||||
for (auto& msg : msgs) {
|
||||
msg.m_accountId = acc_id;
|
||||
msg.sanitize();
|
||||
}
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Downloaded " << msgs.size() << " messages for feed ID '"
|
||||
<< feed->customId() << "' URL: '" << feed->source() << "' title: '" << feed->title() << "' in thread: '"
|
||||
<< QThread::currentThreadId() << "'. Operation took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
if (!feed->messageFilters().isEmpty()) {
|
||||
tmr.restart();
|
||||
// Now, sanitize messages (tweak encoding etc.).
|
||||
for (auto& msg : msgs) {
|
||||
msg.m_accountId = acc_id;
|
||||
msg.sanitize();
|
||||
}
|
||||
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
// Perform per-message filtering.
|
||||
QJSEngine filter_engine;
|
||||
|
||||
// Create JavaScript communication wrapper for the message.
|
||||
MessageObject msg_obj(&database,
|
||||
feed->customId(),
|
||||
feed->getParentServiceRoot()->accountId(),
|
||||
feed->getParentServiceRoot()->labelsNode()->labels());
|
||||
|
||||
MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Setting up JS evaluation took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
QList<Message> read_msgs, important_msgs;
|
||||
|
||||
for (int i = 0; i < msgs.size(); i++) {
|
||||
Message msg_backup(msgs[i]);
|
||||
Message* msg_orig = &msgs[i];
|
||||
|
||||
// Attach live message object to wrapper.
|
||||
if (!feed->messageFilters().isEmpty()) {
|
||||
tmr.restart();
|
||||
msg_obj.setMessage(msg_orig);
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Hooking message took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
auto feed_filters = feed->messageFilters();
|
||||
bool remove_msg = false;
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
for (int j = 0; j < feed_filters.size(); j++) {
|
||||
QPointer<MessageFilter> filter = feed_filters.at(j);
|
||||
// Perform per-message filtering.
|
||||
QJSEngine filter_engine;
|
||||
|
||||
if (filter.isNull()) {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Message filter was probably deleted, removing its pointer from list of filters.";
|
||||
feed_filters.removeAt(j--);
|
||||
continue;
|
||||
// Create JavaScript communication wrapper for the message.
|
||||
MessageObject msg_obj(&database,
|
||||
feed->customId(),
|
||||
feed->getParentServiceRoot()->accountId(),
|
||||
feed->getParentServiceRoot()->labelsNode()->labels());
|
||||
|
||||
MessageFilter::initializeFilteringEngine(filter_engine, &msg_obj);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Setting up JS evaluation took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
QList<Message> read_msgs, important_msgs;
|
||||
|
||||
for (int i = 0; i < msgs.size(); i++) {
|
||||
Message msg_backup(msgs[i]);
|
||||
Message* msg_orig = &msgs[i];
|
||||
|
||||
// Attach live message object to wrapper.
|
||||
tmr.restart();
|
||||
msg_obj.setMessage(msg_orig);
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Hooking message took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
auto feed_filters = feed->messageFilters();
|
||||
bool remove_msg = false;
|
||||
|
||||
for (int j = 0; j < feed_filters.size(); j++) {
|
||||
QPointer<MessageFilter> filter = feed_filters.at(j);
|
||||
|
||||
if (filter.isNull()) {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Message filter was probably deleted, removing its pointer from list of filters.";
|
||||
feed_filters.removeAt(j--);
|
||||
continue;
|
||||
}
|
||||
|
||||
MessageFilter* msg_filter = filter.data();
|
||||
|
||||
tmr.restart();
|
||||
|
||||
try {
|
||||
MessageObject::FilteringAction decision = msg_filter->filterMessage(&filter_engine);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Running filter script, it took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
|
||||
switch (decision) {
|
||||
case MessageObject::FilteringAction::Accept:
|
||||
// Message is normally accepted, it could be tweaked by the filter.
|
||||
continue;
|
||||
|
||||
case MessageObject::FilteringAction::Ignore:
|
||||
case MessageObject::FilteringAction::Purge:
|
||||
default:
|
||||
// Remove the message, we do not want it.
|
||||
remove_msg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (const FilteringException& ex) {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Error when evaluating filtering JS function: "
|
||||
<< QUOTE_W_SPACE_DOT(ex.message())
|
||||
<< " Accepting message.";
|
||||
continue;
|
||||
}
|
||||
|
||||
// If we reach this point. Then we ignore the message which is by now
|
||||
// already removed, go to next message.
|
||||
break;
|
||||
}
|
||||
|
||||
MessageFilter* msg_filter = filter.data();
|
||||
if (!msg_backup.m_isRead && msg_orig->m_isRead) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as read by message scripts.";
|
||||
|
||||
tmr.restart();
|
||||
read_msgs << *msg_orig;
|
||||
}
|
||||
|
||||
try {
|
||||
MessageObject::FilteringAction decision = msg_filter->filterMessage(&filter_engine);
|
||||
if (!msg_backup.m_isImportant && msg_orig->m_isImportant) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as important by message scripts.";
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Running filter script, it took " << tmr.nsecsElapsed() / 1000 << " microseconds.";
|
||||
important_msgs << *msg_orig;
|
||||
}
|
||||
|
||||
switch (decision) {
|
||||
case MessageObject::FilteringAction::Accept:
|
||||
// Message is normally accepted, it could be tweaked by the filter.
|
||||
continue;
|
||||
// Process changed labels.
|
||||
for (Label* lbl : qAsConst(msg_backup.m_assignedLabels)) {
|
||||
if (!msg_orig->m_assignedLabels.contains(lbl)) {
|
||||
// Label is not there anymore, it was deassigned.
|
||||
lbl->deassignFromMessage(*msg_orig);
|
||||
|
||||
case MessageObject::FilteringAction::Ignore:
|
||||
case MessageObject::FilteringAction::Purge:
|
||||
default:
|
||||
// Remove the message, we do not want it.
|
||||
remove_msg = true;
|
||||
break;
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "It was detected that label" << QUOTE_W_SPACE(lbl->customId())
|
||||
<< "was DEASSIGNED from message" << QUOTE_W_SPACE(msg_orig->m_customId)
|
||||
<< "by message filter(s).";
|
||||
}
|
||||
}
|
||||
catch (const FilteringException& ex) {
|
||||
|
||||
for (Label* lbl : qAsConst(msg_orig->m_assignedLabels)) {
|
||||
if (!msg_backup.m_assignedLabels.contains(lbl)) {
|
||||
// Label is in new message, but is not in old message, it
|
||||
// was newly assigned.
|
||||
lbl->assignToMessage(*msg_orig);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "It was detected that label" << QUOTE_W_SPACE(lbl->customId())
|
||||
<< "was ASSIGNED to message" << QUOTE_W_SPACE(msg_orig->m_customId)
|
||||
<< "by message filter(s).";
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_msg) {
|
||||
msgs.removeAt(i--);
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_msgs.isEmpty()) {
|
||||
// Now we push new read states to the service.
|
||||
if (feed->getParentServiceRoot()->onBeforeSetMessagesRead(feed, read_msgs, RootItem::ReadStatus::Read)) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notified services about messages marked as read by message filters.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Error when evaluating filtering JS function: "
|
||||
<< QUOTE_W_SPACE_DOT(ex.message())
|
||||
<< " Accepting message.";
|
||||
continue;
|
||||
<< "Notification of services about messages marked as read by message filters FAILED.";
|
||||
}
|
||||
|
||||
// If we reach this point. Then we ignore the message which is by now
|
||||
// already removed, go to next message.
|
||||
break;
|
||||
}
|
||||
|
||||
if (!msg_backup.m_isRead && msg_orig->m_isRead) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as read by message scripts.";
|
||||
|
||||
read_msgs << *msg_orig;
|
||||
}
|
||||
|
||||
if (!msg_backup.m_isImportant && msg_orig->m_isImportant) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Message with custom ID: '" << msg_backup.m_customId << "' was marked as important by message scripts.";
|
||||
|
||||
important_msgs << *msg_orig;
|
||||
}
|
||||
|
||||
// Process changed labels.
|
||||
for (Label* lbl : qAsConst(msg_backup.m_assignedLabels)) {
|
||||
if (!msg_orig->m_assignedLabels.contains(lbl)) {
|
||||
// Label is not there anymore, it was deassigned.
|
||||
lbl->deassignFromMessage(*msg_orig);
|
||||
if (!important_msgs.isEmpty()) {
|
||||
// Now we push new read states to the service.
|
||||
auto list = boolinq::from(important_msgs).select([](const Message& msg) {
|
||||
return ImportanceChange(msg, RootItem::Importance::Important);
|
||||
}).toStdList();
|
||||
QList<ImportanceChange> chngs = FROM_STD_LIST(QList<ImportanceChange>, list);
|
||||
|
||||
if (feed->getParentServiceRoot()->onBeforeSwitchMessageImportance(feed, chngs)) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "It was detected that label" << QUOTE_W_SPACE(lbl->customId())
|
||||
<< "was DEASSIGNED from message" << QUOTE_W_SPACE(msg_orig->m_customId)
|
||||
<< "by message filter(s).";
|
||||
<< "Notified services about messages marked as important by message filters.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notification of services about messages marked as important by message filters FAILED.";
|
||||
}
|
||||
}
|
||||
|
||||
for (Label* lbl : qAsConst(msg_orig->m_assignedLabels)) {
|
||||
if (!msg_backup.m_assignedLabels.contains(lbl)) {
|
||||
// Label is in new message, but is not in old message, it
|
||||
// was newly assigned.
|
||||
lbl->assignToMessage(*msg_orig);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "It was detected that label" << QUOTE_W_SPACE(lbl->customId())
|
||||
<< "was ASSIGNED to message" << QUOTE_W_SPACE(msg_orig->m_customId)
|
||||
<< "by message filter(s).";
|
||||
}
|
||||
}
|
||||
|
||||
if (remove_msg) {
|
||||
msgs.removeAt(i--);
|
||||
}
|
||||
}
|
||||
|
||||
if (!read_msgs.isEmpty()) {
|
||||
// Now we push new read states to the service.
|
||||
if (feed->getParentServiceRoot()->onBeforeSetMessagesRead(feed, read_msgs, RootItem::ReadStatus::Read)) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notified services about messages marked as read by message filters.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notification of services about messages marked as read by message filters FAILED.";
|
||||
}
|
||||
}
|
||||
// Now make sure, that messages are actually stored to SQL in a locked state.
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Saving messages of feed ID '"
|
||||
<< feed->customId() << "' URL: '" << feed->source() << "' title: '" << feed->title() << "' in thread: '"
|
||||
<< QThread::currentThreadId() << "'.";
|
||||
|
||||
if (!important_msgs.isEmpty()) {
|
||||
// Now we push new read states to the service.
|
||||
auto list = boolinq::from(important_msgs).select([](const Message& msg) {
|
||||
return ImportanceChange(msg, RootItem::Importance::Important);
|
||||
}).toStdList();
|
||||
QList<ImportanceChange> chngs = FROM_STD_LIST(QList<ImportanceChange>, list);
|
||||
auto updated_messages = feed->updateMessages(msgs, false);
|
||||
|
||||
if (feed->getParentServiceRoot()->onBeforeSwitchMessageImportance(feed, chngs)) {
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notified services about messages marked as important by message filters.";
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Notification of services about messages marked as important by message filters FAILED.";
|
||||
}
|
||||
feed->setStatus(updated_messages.first > 0 || updated_messages.second > 0
|
||||
? Feed::Status::NewMessages
|
||||
: Feed::Status::Normal);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< updated_messages << " messages for feed "
|
||||
<< feed->customId() << " stored in DB.";
|
||||
|
||||
if (updated_messages.first > 0) {
|
||||
m_results.appendUpdatedFeed(QPair<QString, int>(feed->title(), updated_messages.first));
|
||||
}
|
||||
}
|
||||
catch (const FeedFetchException& feed_ex) {
|
||||
// TODO: logovat chybu, todo datachanged feed
|
||||
|
||||
feed->setStatus(feed_ex.feedStatus());
|
||||
}
|
||||
|
||||
catch (const ApplicationException& app_ex) {
|
||||
// TODO: logovat chybu, todo datachanged feed
|
||||
|
||||
feed->setStatus(Feed::Status::OtherError);
|
||||
}
|
||||
|
||||
m_feedsUpdated++;
|
||||
|
||||
// Now make sure, that messages are actually stored to SQL in a locked state.
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER << "Saving messages of feed ID '"
|
||||
<< feed->customId() << "' URL: '" << feed->source() << "' title: '" << feed->title() << "' in thread: '"
|
||||
<< QThread::currentThreadId() << "'.";
|
||||
|
||||
int updated_messages = feed->updateMessages(msgs, error_during_obtaining);
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< updated_messages << " messages for feed "
|
||||
<< feed->customId() << " stored in DB.";
|
||||
|
||||
if (updated_messages > 0) {
|
||||
m_results.appendUpdatedFeed(QPair<QString, int>(feed->title(), updated_messages));
|
||||
}
|
||||
|
||||
qDebugNN << LOGSEC_FEEDDOWNLOADER
|
||||
<< "Made progress in feed updates, total feeds count "
|
||||
<< m_feedsUpdated << "/" << m_feedsOriginalCount << " (id of feed is "
|
||||
|
@ -958,20 +958,20 @@ QList<Message> DatabaseQueries::getUndeletedMessagesForAccount(const QSqlDatabas
|
||||
return messages;
|
||||
}
|
||||
|
||||
int DatabaseQueries::updateMessages(QSqlDatabase db,
|
||||
const QList<Message>& messages,
|
||||
const QString& feed_custom_id,
|
||||
int account_id,
|
||||
const QString& url,
|
||||
bool force_update,
|
||||
bool* ok) {
|
||||
QPair<int, int> DatabaseQueries::updateMessages(QSqlDatabase db,
|
||||
const QList<Message>& messages,
|
||||
const QString& feed_custom_id,
|
||||
int account_id,
|
||||
const QString& url,
|
||||
bool force_update,
|
||||
bool* ok) {
|
||||
if (messages.isEmpty()) {
|
||||
*ok = true;
|
||||
return 0;
|
||||
return { 0, 0 };
|
||||
}
|
||||
|
||||
bool use_transactions = qApp->settings()->value(GROUP(Database), SETTING(Database::UseTransactions)).toBool();
|
||||
int updated_messages = 0;
|
||||
QPair<int, int> updated_messages = { 0, 0 };
|
||||
|
||||
// Prepare queries.
|
||||
QSqlQuery query_select_with_url(db);
|
||||
@ -1198,7 +1198,12 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
||||
<< "URL"
|
||||
<< QUOTE_W_SPACE(message.m_url)
|
||||
<< "in DB.";
|
||||
updated_messages++;
|
||||
|
||||
if (!message.m_isRead) {
|
||||
updated_messages.first++;
|
||||
}
|
||||
|
||||
updated_messages.second++;
|
||||
}
|
||||
else if (query_update.lastError().isValid()) {
|
||||
qWarningNN << LOGSEC_DB
|
||||
@ -1226,7 +1231,11 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
||||
query_insert.bindValue(QSL(":account_id"), account_id);
|
||||
|
||||
if (query_insert.exec() && query_insert.numRowsAffected() == 1) {
|
||||
updated_messages++;
|
||||
if (!message.m_isRead) {
|
||||
updated_messages.first++;
|
||||
}
|
||||
|
||||
updated_messages.second++;
|
||||
|
||||
if (query_insert.lastInsertId().isValid()) {
|
||||
id_existing_message = query_insert.lastInsertId().toInt();
|
||||
@ -1289,7 +1298,7 @@ int DatabaseQueries::updateMessages(QSqlDatabase db,
|
||||
|
||||
if (ok != nullptr) {
|
||||
*ok = false;
|
||||
updated_messages = 0;
|
||||
updated_messages = { 0, 0 };
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -109,8 +109,10 @@ class DatabaseQueries {
|
||||
static void loadFromDatabase(ServiceRoot* root);
|
||||
static bool storeNewOauthTokens(const QSqlDatabase& db, const QString& refresh_token, int account_id);
|
||||
static void createOverwriteAccount(const QSqlDatabase& db, ServiceRoot* account);
|
||||
static int updateMessages(QSqlDatabase db, const QList<Message>& messages, const QString& feed_custom_id,
|
||||
int account_id, const QString& url, bool force_update, bool* ok = nullptr);
|
||||
|
||||
// Returns counts of updated messages <unread, all>.
|
||||
static QPair<int, int> updateMessages(QSqlDatabase db, const QList<Message>& messages, const QString& feed_custom_id,
|
||||
int account_id, const QString& url, bool force_update, bool* ok = nullptr);
|
||||
static bool deleteAccount(const QSqlDatabase& db, int account_id);
|
||||
static bool deleteAccountData(const QSqlDatabase& db, int account_id, bool delete_messages_too);
|
||||
static bool cleanLabelledMessages(const QSqlDatabase& db, bool clean_read_only, Label* label);
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
class ApplicationException {
|
||||
public:
|
||||
explicit ApplicationException(QString message = QString());
|
||||
explicit ApplicationException(QString message = {});
|
||||
|
||||
QString message() const;
|
||||
|
||||
|
10
src/librssguard/exceptions/feedfetchexception.cpp
Executable file
10
src/librssguard/exceptions/feedfetchexception.cpp
Executable file
@ -0,0 +1,10 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
|
||||
FeedFetchException::FeedFetchException(Feed::Status feed_status, QString message)
|
||||
: ApplicationException(message), m_feedStatus(feed_status) {}
|
||||
|
||||
Feed::Status FeedFetchException::feedStatus() const {
|
||||
return m_feedStatus;
|
||||
}
|
19
src/librssguard/exceptions/feedfetchexception.h
Executable file
19
src/librssguard/exceptions/feedfetchexception.h
Executable file
@ -0,0 +1,19 @@
|
||||
// For license of this file, see <project-root-folder>/LICENSE.md.
|
||||
|
||||
#ifndef FEEDFETCHEXCEPTION_H
|
||||
#define FEEDFETCHEXCEPTION_H
|
||||
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "services/abstract/feed.h"
|
||||
|
||||
class FeedFetchException : public ApplicationException {
|
||||
public:
|
||||
explicit FeedFetchException(Feed::Status feed_status, QString message = {});
|
||||
|
||||
Feed::Status feedStatus() const;
|
||||
|
||||
private:
|
||||
Feed::Status m_feedStatus;
|
||||
};
|
||||
|
||||
#endif // FEEDFETCHEXCEPTION_H
|
@ -422,7 +422,10 @@ void FormMessageFiltersManager::processCheckedFeeds() {
|
||||
}
|
||||
|
||||
// Update messages in DB and reload selection.
|
||||
it->toFeed()->updateMessages(msgs, false, true);
|
||||
it->toFeed()->updateMessages(msgs, true);
|
||||
|
||||
// TODO: ted hazi vyjimku, ošetřit
|
||||
|
||||
displayMessagesOfFeed();
|
||||
}
|
||||
}
|
||||
|
@ -56,6 +56,7 @@ HEADERS += core/feeddownloader.h \
|
||||
dynamic-shortcuts/dynamicshortcutswidget.h \
|
||||
dynamic-shortcuts/shortcutcatcher.h \
|
||||
exceptions/applicationexception.h \
|
||||
exceptions/feedfetchexception.h \
|
||||
exceptions/filteringexception.h \
|
||||
exceptions/ioexception.h \
|
||||
exceptions/networkexception.h \
|
||||
@ -240,6 +241,7 @@ SOURCES += core/feeddownloader.cpp \
|
||||
dynamic-shortcuts/dynamicshortcutswidget.cpp \
|
||||
dynamic-shortcuts/shortcutcatcher.cpp \
|
||||
exceptions/applicationexception.cpp \
|
||||
exceptions/feedfetchexception.cpp \
|
||||
exceptions/filteringexception.cpp \
|
||||
exceptions/ioexception.cpp \
|
||||
exceptions/networkexception.cpp \
|
||||
|
@ -95,6 +95,8 @@ Application::Application(const QString& id, int& argc, char** argv)
|
||||
|
||||
if (isFirstRun()) {
|
||||
m_notifications->save({
|
||||
Notification(Notification::Event::GeneralEvent,
|
||||
true),
|
||||
Notification(Notification::Event::NewArticlesFetched,
|
||||
true,
|
||||
QSL("%1/rooster.wav").arg(SOUNDS_BUILTIN_DIRECTORY)),
|
||||
|
@ -188,65 +188,56 @@ bool Feed::markAsReadUnread(RootItem::ReadStatus status) {
|
||||
return service->markFeedsReadUnread(QList<Feed*>() << this, status);
|
||||
}
|
||||
|
||||
int Feed::updateMessages(const QList<Message>& messages, bool error_during_obtaining, bool force_update) {
|
||||
QList<RootItem*> items_to_update;
|
||||
int updated_messages = 0;
|
||||
QPair<int, int> Feed::updateMessages(const QList<Message>& messages, bool force_update) {
|
||||
QPair<int, int> updated_messages = { 0, 0 };
|
||||
|
||||
if (!error_during_obtaining) {
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
|
||||
qDebugNN << LOGSEC_CORE
|
||||
<< "Updating messages in DB. Main thread:"
|
||||
<< QUOTE_W_SPACE_DOT(is_main_thread ? "true" : "false");
|
||||
|
||||
bool ok = true;
|
||||
|
||||
if (!messages.isEmpty()) {
|
||||
qDebugNN << LOGSEC_CORE
|
||||
<< "There are some messages to be updated/added to DB.";
|
||||
|
||||
QString custom_id = customId();
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
updated_messages = DatabaseQueries::updateMessages(database, messages, custom_id, account_id,
|
||||
source(), force_update, &ok);
|
||||
}
|
||||
else {
|
||||
qDebugNN << LOGSEC_CORE
|
||||
<< "There are no messages for update.";
|
||||
}
|
||||
|
||||
if (ok) {
|
||||
setStatus(updated_messages > 0 ? Status::NewMessages : Status::Normal);
|
||||
updateCounts(true);
|
||||
|
||||
if (getParentServiceRoot()->recycleBin() != nullptr && updated_messages > 0) {
|
||||
getParentServiceRoot()->recycleBin()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->recycleBin());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->importantNode() != nullptr && updated_messages > 0) {
|
||||
getParentServiceRoot()->importantNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->importantNode());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->unreadNode() != nullptr && updated_messages > 0) {
|
||||
getParentServiceRoot()->unreadNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->unreadNode());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->labelsNode() != nullptr) {
|
||||
getParentServiceRoot()->labelsNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->labelsNode());
|
||||
}
|
||||
}
|
||||
if (messages.isEmpty()) {
|
||||
return updated_messages;
|
||||
}
|
||||
else {
|
||||
qCriticalNN << LOGSEC_CORE
|
||||
<< "There is indication that there was error during messages obtaining.";
|
||||
|
||||
QList<RootItem*> items_to_update;
|
||||
bool is_main_thread = QThread::currentThread() == qApp->thread();
|
||||
|
||||
qDebugNN << LOGSEC_CORE
|
||||
<< "Updating messages in DB. Main thread:"
|
||||
<< QUOTE_W_SPACE_DOT(is_main_thread);
|
||||
|
||||
bool ok = false;
|
||||
|
||||
qDebugNN << LOGSEC_CORE
|
||||
<< "There are some messages to be updated/added to DB.";
|
||||
|
||||
QString custom_id = customId();
|
||||
int account_id = getParentServiceRoot()->accountId();
|
||||
QSqlDatabase database = is_main_thread ?
|
||||
qApp->database()->driver()->connection(metaObject()->className()) :
|
||||
qApp->database()->driver()->connection(QSL("feed_upd"));
|
||||
|
||||
updated_messages = DatabaseQueries::updateMessages(database, messages, custom_id, account_id,
|
||||
source(), force_update, &ok);
|
||||
|
||||
if (ok && (updated_messages.first > 0 || updated_messages.second > 0)) {
|
||||
updateCounts(true);
|
||||
|
||||
if (getParentServiceRoot()->recycleBin() != nullptr) {
|
||||
getParentServiceRoot()->recycleBin()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->recycleBin());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->importantNode() != nullptr) {
|
||||
getParentServiceRoot()->importantNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->importantNode());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->unreadNode() != nullptr) {
|
||||
getParentServiceRoot()->unreadNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->unreadNode());
|
||||
}
|
||||
|
||||
if (getParentServiceRoot()->labelsNode() != nullptr) {
|
||||
getParentServiceRoot()->labelsNode()->updateCounts(true);
|
||||
items_to_update.append(getParentServiceRoot()->labelsNode());
|
||||
}
|
||||
}
|
||||
|
||||
// Some messages were really added to DB, reload feed in model.
|
||||
|
@ -75,7 +75,8 @@ class Feed : public RootItem {
|
||||
void setMessageFilters(const QList<QPointer<MessageFilter>>& messageFilters);
|
||||
void removeMessageFilter(MessageFilter* filter);
|
||||
|
||||
int updateMessages(const QList<Message>& messages, bool error_during_obtaining, bool force_update = false);
|
||||
// Returns counts of updated messages <unread, all>.
|
||||
QPair<int, int> updateMessages(const QList<Message>& messages, bool force_update);
|
||||
|
||||
public slots:
|
||||
virtual void updateCounts(bool including_total_count);
|
||||
|
@ -92,7 +92,9 @@ class ServiceRoot : public RootItem {
|
||||
virtual void stop();
|
||||
|
||||
// Obtains list of messages.
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) = 0;
|
||||
// Throws exception subclassed from ApplicationException, preferably FeedFetchException
|
||||
// if any problems arise.
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds) = 0;
|
||||
|
||||
// This method should prepare messages for given "item" (download them maybe?)
|
||||
// into predefined "Messages" table
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "exceptions/networkexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
@ -71,25 +72,15 @@ void FeedlyServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool());
|
||||
}
|
||||
|
||||
QList<Message> FeedlyServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> FeedlyServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> messages;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
try {
|
||||
messages << m_network->streamContents(feed->customId());
|
||||
|
||||
feed->setStatus(Feed::Status::Normal);
|
||||
*error_during_obtaining = false;
|
||||
}
|
||||
catch (const ApplicationException& ex) {
|
||||
feed->setStatus(Feed::Status::NetworkError);
|
||||
*error_during_obtaining = true;
|
||||
|
||||
qCriticalNN << LOGSEC_FEEDLY
|
||||
<< "Problem"
|
||||
<< QUOTE_W_SPACE(ex.message())
|
||||
<< "when obtaining messages for feed"
|
||||
<< QUOTE_W_SPACE_DOT(customId());
|
||||
throw FeedFetchException(Feed::Status::NetworkError, ex.message());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ class FeedlyServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual LabelOperation supportedLabelOperations() const;
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
FeedlyNetwork* network() const;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "services/gmail/gmailserviceroot.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
@ -73,7 +74,7 @@ void GmailServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->oauth()->setRedirectUrl(data["redirect_uri"].toString());
|
||||
}
|
||||
|
||||
QList<Message> GmailServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> GmailServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> messages;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
@ -83,7 +84,7 @@ QList<Message> GmailServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bo
|
||||
feed->setStatus(error);
|
||||
|
||||
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError || error == Feed::Status::ParsingError) {
|
||||
*error_during_obtaining = true;
|
||||
throw FeedFetchException(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class GmailServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
protected:
|
||||
virtual RootItem* obtainNewTreeForSyncIn() const;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
@ -56,7 +57,7 @@ void GreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool());
|
||||
}
|
||||
|
||||
QList<Message> GreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> GreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> messages;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
@ -66,7 +67,7 @@ QList<Message> GreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds,
|
||||
feed->setStatus(error);
|
||||
|
||||
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
|
||||
*error_during_obtaining = true;
|
||||
throw FeedFetchException(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -31,7 +31,7 @@ class GreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual LabelOperation supportedLabelOperations() const;
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
GreaderNetwork* network() const;
|
||||
|
||||
|
@ -57,11 +57,13 @@ InoreaderAccountDetails::InoreaderAccountDetails(QWidget* parent)
|
||||
void InoreaderAccountDetails::testSetup(const QNetworkProxy& custom_proxy) {
|
||||
m_lastProxy = custom_proxy;
|
||||
|
||||
m_oauth->logout();
|
||||
m_oauth->setClientId(m_ui.m_txtAppId->lineEdit()->text());
|
||||
m_oauth->setClientSecret(m_ui.m_txtAppKey->lineEdit()->text());
|
||||
m_oauth->setRedirectUrl(m_ui.m_txtRedirectUrl->lineEdit()->text());
|
||||
m_oauth->login();
|
||||
if (m_oauth != nullptr) {
|
||||
m_oauth->logout();
|
||||
m_oauth->setClientId(m_ui.m_txtAppId->lineEdit()->text());
|
||||
m_oauth->setClientSecret(m_ui.m_txtAppKey->lineEdit()->text());
|
||||
m_oauth->setRedirectUrl(m_ui.m_txtRedirectUrl->lineEdit()->text());
|
||||
m_oauth->login();
|
||||
}
|
||||
}
|
||||
|
||||
void InoreaderAccountDetails::checkUsername(const QString& username) {
|
||||
@ -96,7 +98,6 @@ void InoreaderAccountDetails::onAuthGranted() {
|
||||
InoreaderNetworkFactory fac;
|
||||
|
||||
fac.setOauth(m_oauth);
|
||||
|
||||
auto resp = fac.userInfo(m_lastProxy);
|
||||
|
||||
m_ui.m_txtUsername->lineEdit()->setText(resp["userEmail"].toString());
|
||||
@ -109,9 +110,11 @@ void InoreaderAccountDetails::onAuthGranted() {
|
||||
}
|
||||
|
||||
void InoreaderAccountDetails::hookNetwork() {
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieved, this, &InoreaderAccountDetails::onAuthGranted);
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &InoreaderAccountDetails::onAuthError);
|
||||
connect(m_oauth, &OAuth2Service::authFailed, this, &InoreaderAccountDetails::onAuthFailed);
|
||||
if (m_oauth != nullptr) {
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieved, this, &InoreaderAccountDetails::onAuthGranted);
|
||||
connect(m_oauth, &OAuth2Service::tokensRetrieveError, this, &InoreaderAccountDetails::onAuthError);
|
||||
connect(m_oauth, &OAuth2Service::authFailed, this, &InoreaderAccountDetails::onAuthFailed);
|
||||
}
|
||||
}
|
||||
|
||||
void InoreaderAccountDetails::registerApi() {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "services/inoreader/inoreaderserviceroot.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "network-web/oauth2service.h"
|
||||
@ -55,7 +56,7 @@ void InoreaderServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->oauth()->setRedirectUrl(data["redirect_uri"].toString());
|
||||
}
|
||||
|
||||
QList<Message> InoreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> InoreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> messages;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
@ -65,7 +66,7 @@ QList<Message> InoreaderServiceRoot::obtainNewMessages(const QList<Feed*>& feeds
|
||||
feed->setStatus(error);
|
||||
|
||||
if (error == Feed::Status::NetworkError || error == Feed::Status::AuthError) {
|
||||
*error_during_obtaining = true;
|
||||
throw FeedFetchException(error);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ class InoreaderServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
protected:
|
||||
virtual RootItem* obtainNewTreeForSyncIn() const;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
@ -149,18 +150,16 @@ void OwnCloudServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool());
|
||||
}
|
||||
|
||||
QList<Message> OwnCloudServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> OwnCloudServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> msgs;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
OwnCloudGetMessagesResponse messages = network()->getMessages(feed->customNumericId(), networkProxy());
|
||||
|
||||
if (messages.networkError() != QNetworkReply::NetworkError::NoError) {
|
||||
feed->setStatus(Feed::Status::NetworkError);
|
||||
*error_during_obtaining = true;
|
||||
throw FeedFetchException(Feed::Status::NetworkError);
|
||||
}
|
||||
else {
|
||||
*error_during_obtaining = false;
|
||||
msgs << messages.messages();
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class OwnCloudServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
OwnCloudNetworkFactory* network() const;
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "database/databasequeries.h"
|
||||
#include "definitions/definitions.h"
|
||||
#include "exceptions/applicationexception.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "exceptions/scriptexception.h"
|
||||
#include "gui/messagebox.h"
|
||||
#include "miscellaneous/application.h"
|
||||
@ -143,7 +144,7 @@ Qt::ItemFlags StandardServiceRoot::additionalFlags() const {
|
||||
return Qt::ItemFlag::ItemIsDropEnabled;
|
||||
}
|
||||
|
||||
QList<Message> StandardServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> StandardServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> msgs;
|
||||
|
||||
for (Feed* f : feeds) {
|
||||
@ -178,12 +179,7 @@ QList<Message> StandardServiceRoot::obtainNewMessages(const QList<Feed*>& feeds,
|
||||
<< QUOTE_W_SPACE(feed->networkError())
|
||||
<< "during fetching of new messages for feed"
|
||||
<< QUOTE_W_SPACE_DOT(feed->source());
|
||||
feed->setStatus(StandardFeed::Status::NetworkError);
|
||||
*error_during_obtaining = true;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
*error_during_obtaining = false;
|
||||
throw FeedFetchException(Feed::Status::NetworkError);
|
||||
}
|
||||
|
||||
// Encode downloaded data for further parsing.
|
||||
@ -213,9 +209,7 @@ QList<Message> StandardServiceRoot::obtainNewMessages(const QList<Feed*>& feeds,
|
||||
<< "Custom script for generating feed file failed:"
|
||||
<< QUOTE_W_SPACE_DOT(ex.message());
|
||||
|
||||
feed->setStatus(Feed::Status::OtherError);
|
||||
*error_during_obtaining = true;
|
||||
continue;
|
||||
throw FeedFetchException(Feed::Status::OtherError, ex.message());
|
||||
}
|
||||
}
|
||||
|
||||
@ -234,9 +228,7 @@ QList<Message> StandardServiceRoot::obtainNewMessages(const QList<Feed*>& feeds,
|
||||
<< "Post-processing script for feed file failed:"
|
||||
<< QUOTE_W_SPACE_DOT(ex.message());
|
||||
|
||||
feed->setStatus(Feed::Status::OtherError);
|
||||
*error_during_obtaining = true;
|
||||
continue;
|
||||
throw FeedFetchException(Feed::Status::OtherError, ex.message());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ class StandardServiceRoot : public ServiceRoot {
|
||||
virtual bool supportsFeedAdding() const;
|
||||
virtual bool supportsCategoryAdding() const;
|
||||
virtual Qt::ItemFlags additionalFlags() const;
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
QList<QAction*> serviceMenu();
|
||||
QList<QAction*> getContextMenuForFeed(StandardFeed* feed);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "services/tt-rss/ttrssserviceroot.h"
|
||||
|
||||
#include "database/databasequeries.h"
|
||||
#include "exceptions/feedfetchexception.h"
|
||||
#include "miscellaneous/application.h"
|
||||
#include "miscellaneous/iconfactory.h"
|
||||
#include "miscellaneous/mutex.h"
|
||||
@ -213,7 +214,7 @@ void TtRssServiceRoot::setCustomDatabaseData(const QVariantHash& data) {
|
||||
m_network->setDownloadOnlyUnreadMessages(data["download_only_unread"].toBool());
|
||||
}
|
||||
|
||||
QList<Message> TtRssServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining) {
|
||||
QList<Message> TtRssServiceRoot::obtainNewMessages(const QList<Feed*>& feeds) {
|
||||
QList<Message> messages;
|
||||
|
||||
for (Feed* feed : feeds) {
|
||||
@ -228,10 +229,7 @@ QList<Message> TtRssServiceRoot::obtainNewMessages(const QList<Feed*>& feeds, bo
|
||||
networkProxy());
|
||||
|
||||
if (network()->lastError() != QNetworkReply::NetworkError::NoError) {
|
||||
feed->setStatus(Feed::Status::NetworkError);
|
||||
*error_during_obtaining = true;
|
||||
itemChanged(QList<RootItem*>() << this);
|
||||
continue;
|
||||
throw FeedFetchException(Feed::Status::NetworkError);
|
||||
}
|
||||
else {
|
||||
QList<Message> new_messages = headlines.messages(this);
|
||||
|
@ -33,7 +33,7 @@ class TtRssServiceRoot : public ServiceRoot, public CacheForServiceRoot {
|
||||
virtual void saveAllCachedData(bool ignore_errors);
|
||||
virtual QVariantHash customDatabaseData() const;
|
||||
virtual void setCustomDatabaseData(const QVariantHash& data);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds, bool* error_during_obtaining);
|
||||
virtual QList<Message> obtainNewMessages(const QList<Feed*>& feeds);
|
||||
|
||||
// Access to network.
|
||||
TtRssNetworkFactory* network() const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user