2010-06-22 17:39:49 +04:00
/*
2017-03-07 16:10:42 +03:00
* Bittorrent Client using Qt and libtorrent .
* Copyright ( C ) 2017 Vladimir Golovnev < glassez @ yandex . ru >
* Copyright ( C ) 2010 Christophe Dumez < chris @ qbittorrent . org >
2010-06-22 17:39:49 +04:00
*
* This program is free software ; you can redistribute it and / or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation ; either version 2
* of the License , or ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 , USA .
*
* In addition , as a special exception , the copyright holders give permission to
* link this program with the OpenSSL project ' s " OpenSSL " library ( or with
* modified versions of it that use the same license as the " OpenSSL " library ) ,
* and distribute the linked executables . You must obey the GNU General Public
* License in all respects for all of the code used other than " OpenSSL " . If you
* modify file ( s ) , you may extend this exception to your version of the file ( s ) ,
* but you are not obligated to do so . If you do not wish to do so , delete this
* exception statement from your version .
*/
2017-03-07 16:10:42 +03:00
# include "automatedrssdownloader.h"
2017-01-29 01:24:41 +03:00
# include <QCursor>
# include <QFileDialog>
2010-11-13 18:51:36 +03:00
# include <QMenu>
2017-03-07 16:10:42 +03:00
# include <QMessageBox>
2017-02-11 08:33:18 +03:00
# include <QRegularExpression>
2017-03-07 16:10:42 +03:00
# include <QShortcut>
# include <QSignalBlocker>
# include <QString>
2010-11-13 13:49:22 +03:00
2016-02-09 11:56:48 +03:00
# include "base/bittorrent/session.h"
2018-11-18 21:40:37 +03:00
# include "base/global.h"
2022-02-08 06:03:48 +03:00
# include "base/path.h"
2017-01-29 01:24:41 +03:00
# include "base/preferences.h"
2017-03-07 16:10:42 +03:00
# include "base/rss/rss_article.h"
# include "base/rss/rss_autodownloader.h"
# include "base/rss/rss_feed.h"
# include "base/rss/rss_folder.h"
# include "base/rss/rss_session.h"
2021-04-05 08:02:28 +03:00
# include "base/utils/compare.h"
2021-09-05 07:29:32 +03:00
# include "base/utils/io.h"
2015-09-25 11:10:05 +03:00
# include "base/utils/string.h"
2020-04-30 10:53:43 +03:00
# include "gui/autoexpandabledialog.h"
2021-02-06 16:13:57 +03:00
# include "gui/torrentcategorydialog.h"
2020-04-30 10:53:43 +03:00
# include "gui/uithememanager.h"
# include "gui/utils.h"
2016-02-09 11:56:48 +03:00
# include "ui_automatedrssdownloader.h"
2010-06-22 17:39:49 +04:00
2022-03-29 05:41:17 +03:00
const QString EXT_JSON = u " .json " _qs ;
const QString EXT_LEGACY = u " .rssrules " _qs ;
2017-11-23 10:25:43 +03:00
2017-03-07 16:10:42 +03:00
AutomatedRssDownloader : : AutomatedRssDownloader ( QWidget * parent )
2017-01-29 01:24:41 +03:00
: QDialog ( parent )
2022-03-29 05:41:17 +03:00
, m_formatFilterJSON ( u " %1 (*%2) " _qs . arg ( tr ( " Rules " ) , EXT_JSON ) )
, m_formatFilterLegacy ( u " %1 (*%2) " _qs . arg ( tr ( " Rules (legacy) " ) , EXT_LEGACY ) )
2017-03-07 16:10:42 +03:00
, m_ui ( new Ui : : AutomatedRssDownloader )
, m_currentRuleItem ( nullptr )
2010-06-22 17:39:49 +04:00
{
2017-03-07 16:10:42 +03:00
m_ui - > setupUi ( this ) ;
2017-01-08 03:46:01 +03:00
// Icons
2022-03-12 17:00:58 +03:00
m_ui - > removeRuleBtn - > setIcon ( UIThemeManager : : instance ( ) - > getIcon ( u " list-remove " _qs ) ) ;
m_ui - > addRuleBtn - > setIcon ( UIThemeManager : : instance ( ) - > getIcon ( u " list-add " _qs ) ) ;
m_ui - > addCategoryBtn - > setIcon ( UIThemeManager : : instance ( ) - > getIcon ( u " list-add " _qs ) ) ;
2017-01-08 03:46:01 +03:00
// Ui Settings
2017-03-07 16:10:42 +03:00
m_ui - > listRules - > setSortingEnabled ( true ) ;
m_ui - > listRules - > setSelectionMode ( QAbstractItemView : : ExtendedSelection ) ;
m_ui - > treeMatchingArticles - > setSortingEnabled ( true ) ;
m_ui - > treeMatchingArticles - > sortByColumn ( 0 , Qt : : AscendingOrder ) ;
m_ui - > hsplitter - > setCollapsible ( 0 , false ) ;
m_ui - > hsplitter - > setCollapsible ( 1 , false ) ;
m_ui - > hsplitter - > setCollapsible ( 2 , true ) ; // Only the preview list is collapsible
2019-08-20 15:34:40 +03:00
m_ui - > lineSavePath - > setDialogCaption ( tr ( " Destination directory " ) ) ;
m_ui - > lineSavePath - > setMode ( FileSystemPathEdit : : Mode : : DirectorySave ) ;
2017-03-07 16:10:42 +03:00
connect ( m_ui - > checkRegex , & QAbstractButton : : toggled , this , & AutomatedRssDownloader : : updateFieldsToolTips ) ;
connect ( m_ui - > listRules , & QWidget : : customContextMenuRequested , this , & AutomatedRssDownloader : : displayRulesListMenu ) ;
2022-03-12 17:00:58 +03:00
m_episodeRegex = new QRegularExpression ( u " ^(^ \\ d{1,4}x( \\ d{1,4}(-( \\ d{1,4})?)?;){1,}){1,1} " _qs
2017-03-07 16:10:42 +03:00
, QRegularExpression : : CaseInsensitiveOption ) ;
2022-03-12 17:00:58 +03:00
const QString tip = u " <p> " + tr ( " Matches articles based on episode filter. " ) + u " </p><p><b> " + tr ( " Example: " )
+ u " 1x2;8-15;5;30-;</b> " + tr ( " will match 2, 5, 8 through 15, 30 and onward episodes of season one " , " example X will match " ) + u " </p> "
+ u " <p> " + tr ( " Episode filter rules: " ) + u " </p><ul><li> " + tr ( " Season number is a mandatory non-zero value " ) + u " </li> "
+ u " <li> " + tr ( " Episode number is a mandatory positive value " ) + u " </li> "
+ u " <li> " + tr ( " Filter must end with semicolon " ) + u " </li> "
+ u " <li> " + tr ( " Three range types for episodes are supported: " ) + u " </li> " + u " <li><ul> "
+ u " <li> " + tr ( " Single number: <b>1x25;</b> matches episode 25 of season one " ) + u " </li> "
+ u " <li> " + tr ( " Normal range: <b>1x25-40;</b> matches episodes 25 through 40 of season one " ) + u " </li> "
+ u " <li> " + tr ( " Infinite range: <b>1x25-;</b> matches episodes 25 and upward of season one, and all episodes of later seasons " ) + u " </li> " + u " </ul></li></ul> " ;
2017-03-07 16:10:42 +03:00
m_ui - > lineEFilter - > setToolTip ( tip ) ;
2017-01-08 03:46:01 +03:00
initCategoryCombobox ( ) ;
loadSettings ( ) ;
2017-03-07 16:10:42 +03:00
connect ( RSS : : AutoDownloader : : instance ( ) , & RSS : : AutoDownloader : : ruleAdded , this , & AutomatedRssDownloader : : handleRuleAdded ) ;
connect ( RSS : : AutoDownloader : : instance ( ) , & RSS : : AutoDownloader : : ruleRenamed , this , & AutomatedRssDownloader : : handleRuleRenamed ) ;
connect ( RSS : : AutoDownloader : : instance ( ) , & RSS : : AutoDownloader : : ruleChanged , this , & AutomatedRssDownloader : : handleRuleChanged ) ;
connect ( RSS : : AutoDownloader : : instance ( ) , & RSS : : AutoDownloader : : ruleAboutToBeRemoved , this , & AutomatedRssDownloader : : handleRuleAboutToBeRemoved ) ;
2017-01-08 03:46:01 +03:00
// Update matching articles when necessary
2017-03-07 16:10:42 +03:00
connect ( m_ui - > lineContains , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
connect ( m_ui - > lineContains , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : updateMustLineValidity ) ;
connect ( m_ui - > lineNotContains , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
connect ( m_ui - > lineNotContains , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : updateMustNotLineValidity ) ;
connect ( m_ui - > lineEFilter , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
connect ( m_ui - > lineEFilter , & QLineEdit : : textEdited , this , & AutomatedRssDownloader : : updateEpisodeFilterValidity ) ;
connect ( m_ui - > checkRegex , & QCheckBox : : stateChanged , this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
connect ( m_ui - > checkRegex , & QCheckBox : : stateChanged , this , & AutomatedRssDownloader : : updateMustLineValidity ) ;
connect ( m_ui - > checkRegex , & QCheckBox : : stateChanged , this , & AutomatedRssDownloader : : updateMustNotLineValidity ) ;
2016-05-22 16:59:31 +03:00
connect ( m_ui - > checkSmart , & QCheckBox : : stateChanged , this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
2019-07-24 20:41:09 +03:00
connect ( m_ui - > spinIgnorePeriod , qOverload < int > ( & QSpinBox : : valueChanged )
2018-05-18 14:41:52 +03:00
, this , & AutomatedRssDownloader : : handleRuleDefinitionChanged ) ;
2017-03-07 16:10:42 +03:00
connect ( m_ui - > listFeeds , & QListWidget : : itemChanged , this , & AutomatedRssDownloader : : handleFeedCheckStateChange ) ;
connect ( m_ui - > listRules , & QListWidget : : itemSelectionChanged , this , & AutomatedRssDownloader : : updateRuleDefinitionBox ) ;
connect ( m_ui - > listRules , & QListWidget : : itemChanged , this , & AutomatedRssDownloader : : handleRuleCheckStateChange ) ;
2019-07-13 07:55:21 +03:00
const auto * editHotkey = new QShortcut ( Qt : : Key_F2 , m_ui - > listRules , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( editHotkey , & QShortcut : : activated , this , & AutomatedRssDownloader : : renameSelectedRule ) ;
const auto * deleteHotkey = new QShortcut ( QKeySequence : : Delete , m_ui - > listRules , nullptr , nullptr , Qt : : WidgetShortcut ) ;
connect ( deleteHotkey , & QShortcut : : activated , this , & AutomatedRssDownloader : : on_removeRuleBtn_clicked ) ;
2017-03-07 16:10:42 +03:00
2019-07-13 07:55:21 +03:00
connect ( m_ui - > listRules , & QAbstractItemView : : doubleClicked , this , & AutomatedRssDownloader : : renameSelectedRule ) ;
2017-03-07 16:10:42 +03:00
loadFeedList ( ) ;
m_ui - > listRules - > blockSignals ( true ) ;
2018-11-27 23:15:04 +03:00
for ( const RSS : : AutoDownloadRule & rule : asConst ( RSS : : AutoDownloader : : instance ( ) - > rules ( ) ) )
2017-03-07 16:10:42 +03:00
createRuleItem ( rule ) ;
m_ui - > listRules - > blockSignals ( false ) ;
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
updateRuleDefinitionBox ( ) ;
2010-06-22 17:39:49 +04:00
2017-03-07 16:10:42 +03:00
if ( RSS : : AutoDownloader : : instance ( ) - > isProcessingEnabled ( ) )
m_ui - > labelWarn - > hide ( ) ;
connect ( RSS : : AutoDownloader : : instance ( ) , & RSS : : AutoDownloader : : processingStateChanged
, this , & AutomatedRssDownloader : : handleProcessingStateChanged ) ;
2010-06-22 17:39:49 +04:00
}
2017-03-07 16:10:42 +03:00
AutomatedRssDownloader : : ~ AutomatedRssDownloader ( )
2017-01-22 07:36:27 +03:00
{
2017-03-07 16:10:42 +03:00
// Save current item on exit
saveEditedRule ( ) ;
saveSettings ( ) ;
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
delete m_ui ;
delete m_episodeRegex ;
2017-01-22 07:36:27 +03:00
}
2010-10-31 15:35:07 +03:00
void AutomatedRssDownloader : : loadSettings ( )
{
2022-03-11 08:40:58 +03:00
const auto * pref = Preferences : : instance ( ) ;
resize ( pref - > getRssGeometrySize ( ) ) ;
2017-03-07 16:10:42 +03:00
m_ui - > hsplitter - > restoreState ( pref - > getRssHSplitterSizes ( ) ) ;
2010-10-31 15:35:07 +03:00
}
void AutomatedRssDownloader : : saveSettings ( )
{
2017-01-08 03:46:01 +03:00
Preferences * const pref = Preferences : : instance ( ) ;
2017-12-03 10:32:58 +03:00
pref - > setRssGeometrySize ( size ( ) ) ;
2017-03-07 16:10:42 +03:00
pref - > setRssHSplitterSizes ( m_ui - > hsplitter - > saveState ( ) ) ;
2010-11-13 13:49:22 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : createRuleItem ( const RSS : : AutoDownloadRule & rule )
2010-11-13 13:49:22 +03:00
{
2017-03-07 16:10:42 +03:00
QListWidgetItem * item = new QListWidgetItem ( rule . name ( ) , m_ui - > listRules ) ;
m_itemsByRuleName . insert ( rule . name ( ) , item ) ;
item - > setFlags ( item - > flags ( ) | Qt : : ItemIsUserCheckable ) ;
item - > setCheckState ( rule . isEnabled ( ) ? Qt : : Checked : Qt : : Unchecked ) ;
2010-11-13 13:49:22 +03:00
}
void AutomatedRssDownloader : : loadFeedList ( )
{
2017-03-07 16:10:42 +03:00
const QSignalBlocker feedListSignalBlocker ( m_ui - > listFeeds ) ;
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
for ( const auto feed : asConst ( RSS : : Session : : instance ( ) - > feeds ( ) ) )
{
2017-03-07 16:10:42 +03:00
QListWidgetItem * item = new QListWidgetItem ( feed - > name ( ) , m_ui - > listFeeds ) ;
item - > setData ( Qt : : UserRole , feed - > url ( ) ) ;
2021-02-19 17:51:53 +03:00
item - > setFlags ( item - > flags ( ) | Qt : : ItemIsUserCheckable | Qt : : ItemIsAutoTristate ) ;
2017-01-08 03:46:01 +03:00
}
2017-01-22 07:36:27 +03:00
updateFeedList ( ) ;
2010-11-13 13:49:22 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : updateFeedList ( )
2010-11-13 13:49:22 +03:00
{
2017-03-07 16:10:42 +03:00
const QSignalBlocker feedListSignalBlocker ( m_ui - > listFeeds ) ;
2017-01-22 07:36:27 +03:00
QList < QListWidgetItem * > selection ;
2017-03-07 16:10:42 +03:00
if ( m_currentRuleItem )
selection < < m_currentRuleItem ;
2017-01-22 07:36:27 +03:00
else
2017-03-07 16:10:42 +03:00
selection = m_ui - > listRules - > selectedItems ( ) ;
2017-01-22 07:36:27 +03:00
bool enable = ! selection . isEmpty ( ) ;
2020-11-16 10:02:11 +03:00
for ( int i = 0 ; i < m_ui - > listFeeds - > count ( ) ; + + i )
{
2017-03-07 16:10:42 +03:00
QListWidgetItem * item = m_ui - > listFeeds - > item ( i ) ;
const QString feedURL = item - > data ( Qt : : UserRole ) . toString ( ) ;
2017-01-22 07:36:27 +03:00
item - > setHidden ( ! enable ) ;
bool allEnabled = true ;
bool anyEnabled = false ;
2020-11-16 10:02:11 +03:00
for ( const QListWidgetItem * ruleItem : asConst ( selection ) )
{
2019-02-22 00:31:43 +03:00
const auto rule = RSS : : AutoDownloader : : instance ( ) - > ruleByName ( ruleItem - > text ( ) ) ;
2017-03-07 16:10:42 +03:00
if ( rule . feedURLs ( ) . contains ( feedURL ) )
2017-01-22 07:36:27 +03:00
anyEnabled = true ;
2017-03-07 16:10:42 +03:00
else
2017-01-22 07:36:27 +03:00
allEnabled = false ;
2017-01-08 03:46:01 +03:00
}
2017-01-22 07:36:27 +03:00
if ( anyEnabled & & allEnabled )
2017-01-08 03:46:01 +03:00
item - > setCheckState ( Qt : : Checked ) ;
2017-01-22 07:36:27 +03:00
else if ( anyEnabled )
item - > setCheckState ( Qt : : PartiallyChecked ) ;
2017-01-08 03:46:01 +03:00
else
item - > setCheckState ( Qt : : Unchecked ) ;
2010-11-13 20:12:13 +03:00
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
m_ui - > listFeeds - > sortItems ( ) ;
m_ui - > lblListFeeds - > setEnabled ( enable ) ;
m_ui - > listFeeds - > setEnabled ( enable ) ;
2010-11-13 13:49:22 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : updateRuleDefinitionBox ( )
2010-11-13 13:49:22 +03:00
{
2017-03-07 16:10:42 +03:00
const QList < QListWidgetItem * > selection = m_ui - > listRules - > selectedItems ( ) ;
QListWidgetItem * currentRuleItem = ( ( selection . count ( ) = = 1 ) ? selection . first ( ) : nullptr ) ;
2020-11-16 10:02:11 +03:00
if ( m_currentRuleItem ! = currentRuleItem )
{
2017-03-07 16:10:42 +03:00
saveEditedRule ( ) ; // Save previous rule first
m_currentRuleItem = currentRuleItem ;
//m_ui->listRules->setCurrentItem(m_currentRuleItem);
}
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
// Update rule definition box
2020-11-16 10:02:11 +03:00
if ( m_currentRuleItem )
{
2017-03-07 16:10:42 +03:00
m_currentRule = RSS : : AutoDownloader : : instance ( ) - > ruleByName ( m_currentRuleItem - > text ( ) ) ;
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
m_ui - > lineContains - > setText ( m_currentRule . mustContain ( ) ) ;
m_ui - > lineNotContains - > setText ( m_currentRule . mustNotContain ( ) ) ;
if ( ! m_currentRule . episodeFilter ( ) . isEmpty ( ) )
m_ui - > lineEFilter - > setText ( m_currentRule . episodeFilter ( ) ) ;
else
m_ui - > lineEFilter - > clear ( ) ;
2018-06-14 12:38:18 +03:00
m_ui - > checkBoxSaveDiffDir - > setChecked ( ! m_currentRule . savePath ( ) . isEmpty ( ) ) ;
2022-02-08 06:03:48 +03:00
m_ui - > lineSavePath - > setSelectedPath ( m_currentRule . savePath ( ) ) ;
2017-03-07 16:10:42 +03:00
m_ui - > checkRegex - > blockSignals ( true ) ;
m_ui - > checkRegex - > setChecked ( m_currentRule . useRegex ( ) ) ;
m_ui - > checkRegex - > blockSignals ( false ) ;
2016-05-22 16:59:31 +03:00
m_ui - > checkSmart - > blockSignals ( true ) ;
m_ui - > checkSmart - > setChecked ( m_currentRule . useSmartFilter ( ) ) ;
m_ui - > checkSmart - > blockSignals ( false ) ;
2017-03-07 16:10:42 +03:00
m_ui - > comboCategory - > setCurrentIndex ( m_ui - > comboCategory - > findText ( m_currentRule . assignedCategory ( ) ) ) ;
if ( m_currentRule . assignedCategory ( ) . isEmpty ( ) )
m_ui - > comboCategory - > clearEditText ( ) ;
int index = 0 ;
2021-01-02 16:55:17 +03:00
if ( m_currentRule . addPaused ( ) . has_value ( ) )
index = ( * m_currentRule . addPaused ( ) ? 1 : 2 ) ;
2017-03-07 16:10:42 +03:00
m_ui - > comboAddPaused - > setCurrentIndex ( index ) ;
2019-11-09 18:05:52 +03:00
index = 0 ;
2020-12-10 09:54:27 +03:00
if ( m_currentRule . torrentContentLayout ( ) )
index = static_cast < int > ( * m_currentRule . torrentContentLayout ( ) ) + 1 ;
m_ui - > comboContentLayout - > setCurrentIndex ( index ) ;
2017-03-07 16:10:42 +03:00
m_ui - > spinIgnorePeriod - > setValue ( m_currentRule . ignoreDays ( ) ) ;
QDateTime dateTime = m_currentRule . lastMatch ( ) ;
QString lMatch ;
if ( dateTime . isValid ( ) )
lMatch = tr ( " Last Match: %1 days ago " ) . arg ( dateTime . daysTo ( QDateTime : : currentDateTime ( ) ) ) ;
else
lMatch = tr ( " Last Match: Unknown " ) ;
m_ui - > lblLastMatch - > setText ( lMatch ) ;
updateMustLineValidity ( ) ;
updateMustNotLineValidity ( ) ;
updateEpisodeFilterValidity ( ) ;
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
updateFieldsToolTips ( m_ui - > checkRegex - > isChecked ( ) ) ;
m_ui - > ruleDefBox - > setEnabled ( true ) ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2017-03-07 16:10:42 +03:00
m_currentRule = RSS : : AutoDownloadRule ( ) ;
2017-01-08 03:46:01 +03:00
clearRuleDefinitionBox ( ) ;
2017-03-07 16:10:42 +03:00
m_ui - > ruleDefBox - > setEnabled ( false ) ;
2010-11-13 13:49:22 +03:00
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
updateFeedList ( ) ;
updateMatchingArticles ( ) ;
2010-11-13 13:49:22 +03:00
}
2010-11-13 20:12:13 +03:00
void AutomatedRssDownloader : : clearRuleDefinitionBox ( )
{
2017-03-07 16:10:42 +03:00
m_ui - > lineContains - > clear ( ) ;
m_ui - > lineNotContains - > clear ( ) ;
m_ui - > lineEFilter - > clear ( ) ;
2018-06-14 12:38:18 +03:00
m_ui - > checkBoxSaveDiffDir - > setChecked ( false ) ;
2017-03-07 16:10:42 +03:00
m_ui - > lineSavePath - > clear ( ) ;
m_ui - > comboCategory - > clearEditText ( ) ;
m_ui - > comboCategory - > setCurrentIndex ( - 1 ) ;
m_ui - > checkRegex - > setChecked ( false ) ;
2016-05-22 16:59:31 +03:00
m_ui - > checkSmart - > setChecked ( false ) ;
2017-03-07 16:10:42 +03:00
m_ui - > spinIgnorePeriod - > setValue ( 0 ) ;
m_ui - > comboAddPaused - > clearEditText ( ) ;
m_ui - > comboAddPaused - > setCurrentIndex ( - 1 ) ;
2020-12-10 09:54:27 +03:00
m_ui - > comboContentLayout - > clearEditText ( ) ;
m_ui - > comboContentLayout - > setCurrentIndex ( - 1 ) ;
2017-03-07 16:10:42 +03:00
updateFieldsToolTips ( m_ui - > checkRegex - > isChecked ( ) ) ;
2017-01-08 03:46:01 +03:00
updateMustLineValidity ( ) ;
updateMustNotLineValidity ( ) ;
2017-01-22 07:36:27 +03:00
updateEpisodeFilterValidity ( ) ;
2010-11-13 20:12:13 +03:00
}
2016-02-09 11:56:48 +03:00
void AutomatedRssDownloader : : initCategoryCombobox ( )
2010-11-13 13:49:22 +03:00
{
2017-01-08 03:46:01 +03:00
// Load torrent categories
2021-05-20 10:36:44 +03:00
QStringList categories = BitTorrent : : Session : : instance ( ) - > categories ( ) ;
2021-04-05 08:02:28 +03:00
std : : sort ( categories . begin ( ) , categories . end ( ) , Utils : : Compare : : NaturalLessThan < Qt : : CaseInsensitive > ( ) ) ;
2022-03-12 17:00:58 +03:00
m_ui - > comboCategory - > addItem ( u " " _qs ) ;
2017-03-07 16:10:42 +03:00
m_ui - > comboCategory - > addItems ( categories ) ;
2010-11-13 13:49:22 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : updateEditedRule ( )
2010-11-13 20:12:13 +03:00
{
2017-03-07 16:10:42 +03:00
if ( ! m_currentRuleItem | | ! m_ui - > ruleDefBox - > isEnabled ( ) ) return ;
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
m_currentRule . setEnabled ( m_currentRuleItem - > checkState ( ) ! = Qt : : Unchecked ) ;
m_currentRule . setUseRegex ( m_ui - > checkRegex - > isChecked ( ) ) ;
2016-05-22 16:59:31 +03:00
m_currentRule . setUseSmartFilter ( m_ui - > checkSmart - > isChecked ( ) ) ;
2017-03-07 16:10:42 +03:00
m_currentRule . setMustContain ( m_ui - > lineContains - > text ( ) ) ;
m_currentRule . setMustNotContain ( m_ui - > lineNotContains - > text ( ) ) ;
m_currentRule . setEpisodeFilter ( m_ui - > lineEFilter - > text ( ) ) ;
2022-02-08 06:03:48 +03:00
m_currentRule . setSavePath ( m_ui - > checkBoxSaveDiffDir - > isChecked ( ) ? m_ui - > lineSavePath - > selectedPath ( ) : Path ( ) ) ;
2017-03-07 16:10:42 +03:00
m_currentRule . setCategory ( m_ui - > comboCategory - > currentText ( ) ) ;
2021-01-02 16:55:17 +03:00
std : : optional < bool > addPaused ;
2017-03-07 16:10:42 +03:00
if ( m_ui - > comboAddPaused - > currentIndex ( ) = = 1 )
2021-01-02 16:55:17 +03:00
addPaused = true ;
2017-03-07 16:10:42 +03:00
else if ( m_ui - > comboAddPaused - > currentIndex ( ) = = 2 )
2021-01-02 16:55:17 +03:00
addPaused = false ;
2017-03-07 16:10:42 +03:00
m_currentRule . setAddPaused ( addPaused ) ;
2020-12-10 09:54:27 +03:00
2021-01-02 15:45:36 +03:00
std : : optional < BitTorrent : : TorrentContentLayout > contentLayout ;
2020-12-10 09:54:27 +03:00
if ( m_ui - > comboContentLayout - > currentIndex ( ) > 0 )
contentLayout = static_cast < BitTorrent : : TorrentContentLayout > ( m_ui - > comboContentLayout - > currentIndex ( ) - 1 ) ;
m_currentRule . setTorrentContentLayout ( contentLayout ) ;
2017-03-07 16:10:42 +03:00
m_currentRule . setIgnoreDays ( m_ui - > spinIgnorePeriod - > value ( ) ) ;
}
2017-01-08 03:46:01 +03:00
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : saveEditedRule ( )
{
if ( ! m_currentRuleItem | | ! m_ui - > ruleDefBox - > isEnabled ( ) ) return ;
updateEditedRule ( ) ;
RSS : : AutoDownloader : : instance ( ) - > insertRule ( m_currentRule ) ;
2010-11-13 13:49:22 +03:00
}
void AutomatedRssDownloader : : on_addRuleBtn_clicked ( )
{
2017-03-07 16:10:42 +03:00
// saveEditedRule();
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
// Ask for a rule name
2017-03-07 16:10:42 +03:00
const QString ruleName = AutoExpandableDialog : : getText (
this , tr ( " New rule name " ) , tr ( " Please type the name of the new download rule. " ) ) ;
if ( ruleName . isEmpty ( ) ) return ;
2017-01-08 03:46:01 +03:00
// Check if this rule name already exists
2020-11-16 10:02:11 +03:00
if ( RSS : : AutoDownloader : : instance ( ) - > hasRule ( ruleName ) )
{
2017-03-07 16:10:42 +03:00
QMessageBox : : warning ( this , tr ( " Rule name conflict " )
, tr ( " A rule with this name already exists, please choose another name. " ) ) ;
2017-01-08 03:46:01 +03:00
return ;
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
RSS : : AutoDownloader : : instance ( ) - > insertRule ( RSS : : AutoDownloadRule ( ruleName ) ) ;
2010-11-13 13:49:22 +03:00
}
void AutomatedRssDownloader : : on_removeRuleBtn_clicked ( )
{
2017-03-07 16:10:42 +03:00
const QList < QListWidgetItem * > selection = m_ui - > listRules - > selectedItems ( ) ;
2017-01-08 03:46:01 +03:00
if ( selection . isEmpty ( ) ) return ;
2017-03-07 16:10:42 +03:00
2017-01-08 03:46:01 +03:00
// Ask for confirmation
2017-03-07 16:10:42 +03:00
const QString confirmText = ( ( selection . count ( ) = = 1 )
? tr ( " Are you sure you want to remove the download rule named '%1'? " )
. arg ( selection . first ( ) - > text ( ) )
: tr ( " Are you sure you want to remove the selected download rules? " ) ) ;
if ( QMessageBox : : question ( this , tr ( " Rule deletion confirmation " ) , confirmText , QMessageBox : : Yes , QMessageBox : : No ) ! = QMessageBox : : Yes )
2017-01-08 03:46:01 +03:00
return ;
2017-01-22 07:36:27 +03:00
2018-11-18 21:40:37 +03:00
for ( const QListWidgetItem * item : selection )
2017-03-07 16:10:42 +03:00
RSS : : AutoDownloader : : instance ( ) - > removeRule ( item - > text ( ) ) ;
2010-11-13 13:49:22 +03:00
}
2021-02-06 16:13:57 +03:00
void AutomatedRssDownloader : : on_addCategoryBtn_clicked ( )
{
const QString newCategoryName = TorrentCategoryDialog : : createCategory ( this ) ;
if ( ! newCategoryName . isEmpty ( ) )
{
m_ui - > comboCategory - > addItem ( newCategoryName ) ;
m_ui - > comboCategory - > setCurrentText ( newCategoryName ) ;
}
}
2010-11-13 15:08:29 +03:00
void AutomatedRssDownloader : : on_exportBtn_clicked ( )
{
2020-11-16 10:02:11 +03:00
if ( RSS : : AutoDownloader : : instance ( ) - > rules ( ) . isEmpty ( ) )
{
2017-11-22 20:25:12 +03:00
QMessageBox : : warning ( this , tr ( " Invalid action " )
, tr ( " The list is empty, there is nothing to export. " ) ) ;
return ;
}
2017-11-23 10:25:43 +03:00
QString selectedFilter { m_formatFilterJSON } ;
2022-02-08 06:03:48 +03:00
Path path { QFileDialog : : getSaveFileName (
2017-11-23 10:25:43 +03:00
this , tr ( " Export RSS rules " ) , QDir : : homePath ( )
2022-03-29 05:41:17 +03:00
, u " %1;;%2 " _qs . arg ( m_formatFilterJSON , m_formatFilterLegacy ) , & selectedFilter ) } ;
2022-02-08 06:03:48 +03:00
2017-11-22 20:25:12 +03:00
if ( path . isEmpty ( ) ) return ;
2020-11-16 10:02:11 +03:00
const RSS : : AutoDownloader : : RulesFileFormat format
{
2017-11-23 10:25:43 +03:00
( selectedFilter = = m_formatFilterJSON )
? RSS : : AutoDownloader : : RulesFileFormat : : JSON
: RSS : : AutoDownloader : : RulesFileFormat : : Legacy
} ;
2017-11-22 20:25:12 +03:00
2020-11-16 10:02:11 +03:00
if ( format = = RSS : : AutoDownloader : : RulesFileFormat : : JSON )
{
2022-02-08 06:03:48 +03:00
if ( ! path . hasExtension ( EXT_JSON ) )
2017-11-23 10:25:43 +03:00
path + = EXT_JSON ;
}
2020-11-16 10:02:11 +03:00
else
{
2022-02-08 06:03:48 +03:00
if ( ! path . hasExtension ( EXT_LEGACY ) )
2017-11-23 10:25:43 +03:00
path + = EXT_LEGACY ;
}
2021-09-05 07:29:32 +03:00
const QByteArray rules = RSS : : AutoDownloader : : instance ( ) - > exportRules ( format ) ;
const nonstd : : expected < void , QString > result = Utils : : IO : : saveToFile ( path , rules ) ;
if ( ! result )
2021-09-03 17:56:19 +03:00
{
QMessageBox : : critical ( this , tr ( " I/O Error " )
2021-09-05 07:29:32 +03:00
, tr ( " Failed to create the destination file. Reason: %1 " ) . arg ( result . error ( ) ) ) ;
2017-11-22 20:25:12 +03:00
}
2010-11-13 15:08:29 +03:00
}
void AutomatedRssDownloader : : on_importBtn_clicked ( )
{
2017-11-23 10:25:43 +03:00
QString selectedFilter { m_formatFilterJSON } ;
2022-02-08 06:03:48 +03:00
const Path path { QFileDialog : : getOpenFileName (
this , tr ( " Import RSS rules " ) , QDir : : homePath ( )
2022-03-29 05:41:17 +03:00
, u " %1;;%2 " _qs . arg ( m_formatFilterJSON , m_formatFilterLegacy ) , & selectedFilter ) } ;
2022-02-08 06:03:48 +03:00
if ( ! path . exists ( ) )
2017-11-22 20:25:12 +03:00
return ;
2022-02-08 06:03:48 +03:00
QFile file { path . data ( ) } ;
2020-11-16 10:02:11 +03:00
if ( ! file . open ( QIODevice : : ReadOnly ) )
{
2017-11-22 20:25:12 +03:00
QMessageBox : : critical (
this , tr ( " I/O Error " )
, tr ( " Failed to open the file. Reason: %1 " ) . arg ( file . errorString ( ) ) ) ;
return ;
}
2020-11-16 10:02:11 +03:00
const RSS : : AutoDownloader : : RulesFileFormat format
{
2017-11-23 10:25:43 +03:00
( selectedFilter = = m_formatFilterJSON )
? RSS : : AutoDownloader : : RulesFileFormat : : JSON
: RSS : : AutoDownloader : : RulesFileFormat : : Legacy
} ;
2020-11-16 10:02:11 +03:00
try
{
2017-11-23 10:25:43 +03:00
RSS : : AutoDownloader : : instance ( ) - > importRules ( file . readAll ( ) , format ) ;
}
2020-11-16 10:02:11 +03:00
catch ( const RSS : : ParsingError & error )
{
2017-11-22 20:25:12 +03:00
QMessageBox : : critical (
this , tr ( " Import Error " )
2017-11-23 10:25:43 +03:00
, tr ( " Failed to import the selected rules file. Reason: %1 " ) . arg ( error . message ( ) ) ) ;
2017-11-22 20:25:12 +03:00
}
2010-11-13 15:08:29 +03:00
}
2010-11-13 18:51:36 +03:00
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : displayRulesListMenu ( )
2010-11-13 18:51:36 +03:00
{
2019-06-03 10:10:19 +03:00
QMenu * menu = new QMenu ( this ) ;
menu - > setAttribute ( Qt : : WA_DeleteOnClose ) ;
2022-03-12 17:00:58 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( u " list-add " _qs ) , tr ( " Add new rule... " )
2021-01-17 09:56:56 +03:00
, this , & AutomatedRssDownloader : : on_addRuleBtn_clicked ) ;
2019-06-03 10:10:19 +03:00
2017-03-07 16:10:42 +03:00
const QList < QListWidgetItem * > selection = m_ui - > listRules - > selectedItems ( ) ;
2016-05-22 16:59:31 +03:00
2020-11-16 10:02:11 +03:00
if ( ! selection . isEmpty ( ) )
{
if ( selection . count ( ) = = 1 )
{
2022-03-12 17:00:58 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( u " list-remove " _qs ) , tr ( " Delete rule " )
2021-01-17 09:56:56 +03:00
, this , & AutomatedRssDownloader : : on_removeRuleBtn_clicked ) ;
2019-06-03 10:10:19 +03:00
menu - > addSeparator ( ) ;
2022-03-12 17:00:58 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( u " edit-rename " _qs ) , tr ( " Rename rule... " )
2021-01-17 09:56:56 +03:00
, this , & AutomatedRssDownloader : : renameSelectedRule ) ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2022-03-12 17:00:58 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( u " list-remove " _qs ) , tr ( " Delete selected rules " )
2021-01-17 09:56:56 +03:00
, this , & AutomatedRssDownloader : : on_removeRuleBtn_clicked ) ;
2017-01-08 03:46:01 +03:00
}
2019-06-03 10:10:19 +03:00
menu - > addSeparator ( ) ;
2022-03-12 17:00:58 +03:00
menu - > addAction ( UIThemeManager : : instance ( ) - > getIcon ( u " edit-clear " _qs ) , tr ( " Clear downloaded episodes... " )
2021-01-17 09:56:56 +03:00
, this , & AutomatedRssDownloader : : clearSelectedRuleDownloadedEpisodeList ) ;
2017-01-08 03:46:01 +03:00
}
2017-03-07 16:10:42 +03:00
2019-06-03 10:10:19 +03:00
menu - > popup ( QCursor : : pos ( ) ) ;
2010-11-13 18:51:36 +03:00
}
void AutomatedRssDownloader : : renameSelectedRule ( )
{
2017-03-07 16:10:42 +03:00
const QList < QListWidgetItem * > selection = m_ui - > listRules - > selectedItems ( ) ;
if ( selection . isEmpty ( ) ) return ;
2017-01-08 03:46:01 +03:00
QListWidgetItem * item = selection . first ( ) ;
2020-11-16 10:02:11 +03:00
forever
{
2017-03-07 16:10:42 +03:00
QString newName = AutoExpandableDialog : : getText (
this , tr ( " Rule renaming " ) , tr ( " Please type the new rule name " )
, QLineEdit : : Normal , item - > text ( ) ) ;
newName = newName . trimmed ( ) ;
if ( newName . isEmpty ( ) ) return ;
2020-11-16 10:02:11 +03:00
if ( RSS : : AutoDownloader : : instance ( ) - > hasRule ( newName ) )
{
2017-03-07 16:10:42 +03:00
QMessageBox : : warning ( this , tr ( " Rule name conflict " )
, tr ( " A rule with this name already exists, please choose another name. " ) ) ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2017-01-08 03:46:01 +03:00
// Rename the rule
2017-03-07 16:10:42 +03:00
RSS : : AutoDownloader : : instance ( ) - > renameRule ( item - > text ( ) , newName ) ;
2017-01-08 03:46:01 +03:00
return ;
}
2010-11-13 18:51:36 +03:00
}
}
2010-11-13 20:12:13 +03:00
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleCheckStateChange ( QListWidgetItem * ruleItem )
2016-11-06 05:52:12 +03:00
{
2017-03-07 16:10:42 +03:00
m_ui - > listRules - > setCurrentItem ( ruleItem ) ;
2016-11-06 05:52:12 +03:00
}
2016-05-22 16:59:31 +03:00
void AutomatedRssDownloader : : clearSelectedRuleDownloadedEpisodeList ( )
{
2018-01-27 16:40:00 +03:00
const QMessageBox : : StandardButton reply = QMessageBox : : question (
2016-05-22 16:59:31 +03:00
this ,
tr ( " Clear downloaded episodes " ) ,
tr ( " Are you sure you want to clear the list of downloaded episodes for the selected rule? " ) ,
QMessageBox : : Yes | QMessageBox : : No ) ;
2020-11-16 10:02:11 +03:00
if ( reply = = QMessageBox : : Yes )
{
2016-05-22 16:59:31 +03:00
m_currentRule . setPreviouslyMatchedEpisodes ( QStringList ( ) ) ;
handleRuleDefinitionChanged ( ) ;
}
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleFeedCheckStateChange ( QListWidgetItem * feedItem )
2010-11-13 20:12:13 +03:00
{
2017-03-07 16:10:42 +03:00
const QString feedURL = feedItem - > data ( Qt : : UserRole ) . toString ( ) ;
2020-11-16 10:02:11 +03:00
for ( QListWidgetItem * ruleItem : asConst ( m_ui - > listRules - > selectedItems ( ) ) )
{
2017-03-07 16:10:42 +03:00
RSS : : AutoDownloadRule rule = ( ruleItem = = m_currentRuleItem
? m_currentRule
: RSS : : AutoDownloader : : instance ( ) - > ruleByName ( ruleItem - > text ( ) ) ) ;
QStringList affectedFeeds = rule . feedURLs ( ) ;
if ( ( feedItem - > checkState ( ) = = Qt : : Checked ) & & ! affectedFeeds . contains ( feedURL ) )
affectedFeeds < < feedURL ;
else if ( ( feedItem - > checkState ( ) = = Qt : : Unchecked ) & & affectedFeeds . contains ( feedURL ) )
affectedFeeds . removeOne ( feedURL ) ;
rule . setFeedURLs ( affectedFeeds ) ;
if ( ruleItem ! = m_currentRuleItem )
RSS : : AutoDownloader : : instance ( ) - > insertRule ( rule ) ;
else
m_currentRule = rule ;
2010-11-13 21:08:09 +03:00
}
2017-03-07 16:10:42 +03:00
handleRuleDefinitionChanged ( ) ;
2010-11-13 22:36:46 +03:00
}
void AutomatedRssDownloader : : updateMatchingArticles ( )
{
2017-03-07 16:10:42 +03:00
m_ui - > treeMatchingArticles - > clear ( ) ;
2020-11-16 10:02:11 +03:00
for ( const QListWidgetItem * ruleItem : asConst ( m_ui - > listRules - > selectedItems ( ) ) )
{
2017-03-07 16:10:42 +03:00
RSS : : AutoDownloadRule rule = ( ruleItem = = m_currentRuleItem
? m_currentRule
: RSS : : AutoDownloader : : instance ( ) - > ruleByName ( ruleItem - > text ( ) ) ) ;
2020-11-16 10:02:11 +03:00
for ( const QString & feedURL : asConst ( rule . feedURLs ( ) ) )
{
2017-03-07 16:10:42 +03:00
auto feed = RSS : : Session : : instance ( ) - > feedByURL ( feedURL ) ;
2018-05-31 12:19:07 +03:00
if ( ! feed ) continue ; // feed doesn't exist
2017-03-07 16:10:42 +03:00
QStringList matchingArticles ;
2018-11-27 23:15:04 +03:00
for ( const auto article : asConst ( feed - > articles ( ) ) )
2018-05-18 14:41:52 +03:00
if ( rule . matches ( article - > data ( ) ) )
2017-03-07 16:10:42 +03:00
matchingArticles < < article - > title ( ) ;
if ( ! matchingArticles . isEmpty ( ) )
addFeedArticlesToTree ( feed , matchingArticles ) ;
2017-01-08 03:46:01 +03:00
}
2010-11-13 22:36:46 +03:00
}
2017-01-22 07:36:27 +03:00
m_treeListEntries . clear ( ) ;
2010-11-13 22:36:46 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : addFeedArticlesToTree ( RSS : : Feed * feed , const QStringList & articles )
2010-11-13 22:36:46 +03:00
{
2017-01-22 07:36:27 +03:00
// Turn off sorting while inserting
2017-03-07 16:10:42 +03:00
m_ui - > treeMatchingArticles - > setSortingEnabled ( false ) ;
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
// Check if this feed is already in the tree
2017-03-07 16:10:42 +03:00
QTreeWidgetItem * treeFeedItem = nullptr ;
2020-11-16 10:02:11 +03:00
for ( int i = 0 ; i < m_ui - > treeMatchingArticles - > topLevelItemCount ( ) ; + + i )
{
2017-03-07 16:10:42 +03:00
QTreeWidgetItem * item = m_ui - > treeMatchingArticles - > topLevelItem ( i ) ;
2020-11-16 10:02:11 +03:00
if ( item - > data ( 0 , Qt : : UserRole ) . toString ( ) = = feed - > url ( ) )
{
2017-01-08 03:46:01 +03:00
treeFeedItem = item ;
break ;
}
}
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
// If there is none, create it
2020-11-16 10:02:11 +03:00
if ( ! treeFeedItem )
{
2017-03-07 16:10:42 +03:00
treeFeedItem = new QTreeWidgetItem ( QStringList ( ) < < feed - > name ( ) ) ;
treeFeedItem - > setToolTip ( 0 , feed - > name ( ) ) ;
2017-01-08 03:46:01 +03:00
QFont f = treeFeedItem - > font ( 0 ) ;
f . setBold ( true ) ;
treeFeedItem - > setFont ( 0 , f ) ;
2022-03-12 17:00:58 +03:00
treeFeedItem - > setData ( 0 , Qt : : DecorationRole , UIThemeManager : : instance ( ) - > getIcon ( u " inode-directory " _qs ) ) ;
2017-01-08 03:46:01 +03:00
treeFeedItem - > setData ( 0 , Qt : : UserRole , feed - > url ( ) ) ;
2017-03-07 16:10:42 +03:00
m_ui - > treeMatchingArticles - > addTopLevelItem ( treeFeedItem ) ;
2017-01-08 03:46:01 +03:00
}
2017-01-22 07:36:27 +03:00
2017-01-08 03:46:01 +03:00
// Insert the articles
2020-11-16 10:02:11 +03:00
for ( const QString & article : articles )
{
2021-12-27 12:20:26 +03:00
const std : : pair < QString , QString > key ( feed - > name ( ) , article ) ;
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( ! m_treeListEntries . contains ( key ) )
{
2017-01-22 07:36:27 +03:00
m_treeListEntries < < key ;
2017-03-07 16:10:42 +03:00
QTreeWidgetItem * item = new QTreeWidgetItem ( QStringList ( ) < < article ) ;
item - > setToolTip ( 0 , article ) ;
2017-01-22 07:36:27 +03:00
treeFeedItem - > addChild ( item ) ;
}
2010-11-13 22:36:46 +03:00
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
m_ui - > treeMatchingArticles - > expandItem ( treeFeedItem ) ;
m_ui - > treeMatchingArticles - > sortItems ( 0 , Qt : : AscendingOrder ) ;
m_ui - > treeMatchingArticles - > setSortingEnabled ( true ) ;
2010-11-13 20:12:13 +03:00
}
2011-04-18 14:49:06 +04:00
void AutomatedRssDownloader : : updateFieldsToolTips ( bool regex )
{
2017-01-08 03:46:01 +03:00
QString tip ;
2020-11-16 10:02:11 +03:00
if ( regex )
{
2022-03-12 17:00:58 +03:00
tip = u " <p> " + tr ( " Regex mode: use Perl-compatible regular expressions " ) + u " </p> " ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2022-03-12 17:00:58 +03:00
tip = u " <p> " + tr ( " Wildcard mode: you can use " ) + u " <ul> "
+ u " <li> " + tr ( " ? to match any single character " ) + u " </li> "
+ u " <li> " + tr ( " * to match zero or more of any characters " ) + u " </li> "
+ u " <li> " + tr ( " Whitespaces count as AND operators (all words, any order) " ) + u " </li> "
+ u " <li> " + tr ( " | is used as OR operator " ) + u " </li></ul></p> "
+ u " <p> " + tr ( " If word order is important use * instead of whitespace. " ) + u " </p> " ;
2017-01-08 03:46:01 +03:00
}
2017-02-05 00:53:33 +03:00
// Whether regex or wildcard, warn about a potential gotcha for users.
// Explanatory string broken over multiple lines for readability (and multiple
// statements to prevent uncrustify indenting excessively.
2022-03-12 17:00:58 +03:00
tip + = u " <p> " ;
2017-02-05 00:53:33 +03:00
tip + = tr ( " An expression with an empty %1 clause (e.g. %2) " ,
" We talk about regex/wildcards in the RSS filters section here. "
" So a valid sentence would be: An expression with an empty | clause (e.g. expr|) "
2022-03-12 17:00:58 +03:00
) . arg ( u " <tt>|</tt> " _qs , u " <tt>expr|</tt> " _qs ) ;
m_ui - > lineContains - > setToolTip ( tip + tr ( " will match all articles. " ) + u " </p> " ) ;
m_ui - > lineNotContains - > setToolTip ( tip + tr ( " will exclude all articles. " ) + u " </p> " ) ;
2011-04-18 19:56:22 +04:00
}
void AutomatedRssDownloader : : updateMustLineValidity ( )
{
2017-03-07 16:10:42 +03:00
const QString text = m_ui - > lineContains - > text ( ) ;
bool isRegex = m_ui - > checkRegex - > isChecked ( ) ;
2017-01-08 03:46:01 +03:00
bool valid = true ;
2017-02-11 08:33:18 +03:00
QString error ;
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( ! text . isEmpty ( ) )
{
2017-01-22 07:36:27 +03:00
QStringList tokens ;
2017-02-11 08:33:18 +03:00
if ( isRegex )
2021-03-14 18:11:23 +03:00
{
2017-01-22 07:36:27 +03:00
tokens < < text ;
2021-03-14 18:11:23 +03:00
}
2017-01-22 07:36:27 +03:00
else
2021-03-14 18:11:23 +03:00
{
2022-03-12 17:00:58 +03:00
for ( const QString & token : asConst ( text . split ( u ' | ' ) ) )
2021-03-14 18:11:23 +03:00
tokens < < Utils : : String : : wildcardToRegexPattern ( token ) ;
}
2017-02-11 08:33:18 +03:00
2020-11-16 10:02:11 +03:00
for ( const QString & token : asConst ( tokens ) )
{
2017-02-11 08:33:18 +03:00
QRegularExpression reg ( token , QRegularExpression : : CaseInsensitiveOption ) ;
2020-11-16 10:02:11 +03:00
if ( ! reg . isValid ( ) )
{
2017-02-11 08:33:18 +03:00
if ( isRegex )
error = tr ( " Position %1: %2 " ) . arg ( reg . patternErrorOffset ( ) ) . arg ( reg . errorString ( ) ) ;
2017-01-22 07:36:27 +03:00
valid = false ;
break ;
}
2017-01-08 03:46:01 +03:00
}
}
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( valid )
{
2022-03-12 17:00:58 +03:00
m_ui - > lineContains - > setStyleSheet ( { } ) ;
2018-06-14 12:38:18 +03:00
m_ui - > labelMustStat - > setPixmap ( QPixmap ( ) ) ;
2022-03-12 17:00:58 +03:00
m_ui - > labelMustStat - > setToolTip ( { } ) ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2022-03-12 17:00:58 +03:00
m_ui - > lineContains - > setStyleSheet ( u " QLineEdit { color: #ff0000; } " _qs ) ;
m_ui - > labelMustStat - > setPixmap ( UIThemeManager : : instance ( ) - > getIcon ( u " task-attention " _qs ) . pixmap ( 16 , 16 ) ) ;
2018-06-14 12:38:18 +03:00
m_ui - > labelMustStat - > setToolTip ( error ) ;
2011-04-18 19:56:22 +04:00
}
}
void AutomatedRssDownloader : : updateMustNotLineValidity ( )
{
2017-03-07 16:10:42 +03:00
const QString text = m_ui - > lineNotContains - > text ( ) ;
bool isRegex = m_ui - > checkRegex - > isChecked ( ) ;
2017-01-08 03:46:01 +03:00
bool valid = true ;
2017-02-11 08:33:18 +03:00
QString error ;
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( ! text . isEmpty ( ) )
{
2017-01-22 07:36:27 +03:00
QStringList tokens ;
2017-02-11 08:33:18 +03:00
if ( isRegex )
2021-03-14 18:11:23 +03:00
{
2017-01-22 07:36:27 +03:00
tokens < < text ;
2021-03-14 18:11:23 +03:00
}
2017-01-22 07:36:27 +03:00
else
2021-03-14 18:11:23 +03:00
{
2022-03-12 17:00:58 +03:00
for ( const QString & token : asConst ( text . split ( u ' | ' ) ) )
2021-03-14 18:11:23 +03:00
tokens < < Utils : : String : : wildcardToRegexPattern ( token ) ;
}
2017-02-11 08:33:18 +03:00
2020-11-16 10:02:11 +03:00
for ( const QString & token : asConst ( tokens ) )
{
2017-02-11 08:33:18 +03:00
QRegularExpression reg ( token , QRegularExpression : : CaseInsensitiveOption ) ;
2020-11-16 10:02:11 +03:00
if ( ! reg . isValid ( ) )
{
2017-02-11 08:33:18 +03:00
if ( isRegex )
error = tr ( " Position %1: %2 " ) . arg ( reg . patternErrorOffset ( ) ) . arg ( reg . errorString ( ) ) ;
2017-01-22 07:36:27 +03:00
valid = false ;
break ;
}
2017-01-08 03:46:01 +03:00
}
}
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( valid )
{
2022-03-12 17:00:58 +03:00
m_ui - > lineNotContains - > setStyleSheet ( { } ) ;
2018-06-14 12:38:18 +03:00
m_ui - > labelMustNotStat - > setPixmap ( QPixmap ( ) ) ;
2022-03-12 17:00:58 +03:00
m_ui - > labelMustNotStat - > setToolTip ( { } ) ;
2017-01-08 03:46:01 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2022-03-12 17:00:58 +03:00
m_ui - > lineNotContains - > setStyleSheet ( u " QLineEdit { color: #ff0000; } " _qs ) ;
m_ui - > labelMustNotStat - > setPixmap ( UIThemeManager : : instance ( ) - > getIcon ( u " task-attention " _qs ) . pixmap ( 16 , 16 ) ) ;
2018-06-14 12:38:18 +03:00
m_ui - > labelMustNotStat - > setToolTip ( error ) ;
2011-04-18 19:56:22 +04:00
}
2011-04-18 14:49:06 +04:00
}
2016-11-06 08:53:06 +03:00
void AutomatedRssDownloader : : updateEpisodeFilterValidity ( )
{
2017-03-07 16:10:42 +03:00
const QString text = m_ui - > lineEFilter - > text ( ) ;
2017-02-11 08:33:18 +03:00
bool valid = text . isEmpty ( ) | | m_episodeRegex - > match ( text ) . hasMatch ( ) ;
2017-01-22 07:36:27 +03:00
2020-11-16 10:02:11 +03:00
if ( valid )
{
2022-03-12 17:00:58 +03:00
m_ui - > lineEFilter - > setStyleSheet ( { } ) ;
m_ui - > labelEpFilterStat - > setPixmap ( { } ) ;
2016-11-06 08:53:06 +03:00
}
2020-11-16 10:02:11 +03:00
else
{
2022-03-12 17:00:58 +03:00
m_ui - > lineEFilter - > setStyleSheet ( u " QLineEdit { color: #ff0000; } " _qs ) ;
m_ui - > labelEpFilterStat - > setPixmap ( UIThemeManager : : instance ( ) - > getIcon ( u " task-attention " _qs ) . pixmap ( 16 , 16 ) ) ;
2016-11-06 08:53:06 +03:00
}
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleDefinitionChanged ( )
2017-01-22 07:36:27 +03:00
{
2017-03-07 16:10:42 +03:00
updateEditedRule ( ) ;
updateMatchingArticles ( ) ;
2017-01-22 07:36:27 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleAdded ( const QString & ruleName )
2017-01-22 07:36:27 +03:00
{
2017-03-07 16:10:42 +03:00
createRuleItem ( RSS : : AutoDownloadRule ( ruleName ) ) ;
2017-01-22 07:36:27 +03:00
}
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleRenamed ( const QString & ruleName , const QString & oldRuleName )
2017-01-08 03:46:01 +03:00
{
2017-08-23 16:45:14 +03:00
auto item = m_itemsByRuleName . take ( oldRuleName ) ;
2017-03-07 16:10:42 +03:00
m_itemsByRuleName . insert ( ruleName , item ) ;
2017-08-23 16:45:14 +03:00
if ( m_currentRule . name ( ) = = oldRuleName )
m_currentRule . setName ( ruleName ) ;
2017-03-07 16:10:42 +03:00
item - > setText ( ruleName ) ;
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleChanged ( const QString & ruleName )
{
auto item = m_itemsByRuleName . value ( ruleName ) ;
2016-05-22 16:59:31 +03:00
if ( item & & ( item ! = m_currentRuleItem ) )
2017-03-07 16:10:42 +03:00
item - > setCheckState ( RSS : : AutoDownloader : : instance ( ) - > ruleByName ( ruleName ) . isEnabled ( ) ? Qt : : Checked : Qt : : Unchecked ) ;
}
2017-01-22 07:36:27 +03:00
2017-03-07 16:10:42 +03:00
void AutomatedRssDownloader : : handleRuleAboutToBeRemoved ( const QString & ruleName )
{
2017-12-23 16:25:09 +03:00
m_currentRuleItem = nullptr ;
2017-03-07 16:10:42 +03:00
delete m_itemsByRuleName . take ( ruleName ) ;
}
void AutomatedRssDownloader : : handleProcessingStateChanged ( bool enabled )
{
m_ui - > labelWarn - > setVisible ( ! enabled ) ;
2013-07-01 12:52:23 +04:00
}