diff --git a/Changelog.md b/Changelog.md index 61500c1..f150012 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,19 @@ +# 2022.7.7.0 + +- Added + - **Scheduler** (creating multiple automation tasks) + - Automation startup delay + - Download ```webp``` in ```jpg``` format + - Development: the ability to create a label control, that provides some information +- Removed + - Instagram auto-fill hash from cookies +- Updated + - Plugins +- Fixed + - ```Stop``` option not working properly + - In some cases, Twitter image is not downloading + - Minor bugs + # 2022.6.10.0 **Attention! From now on, Instagram requires Cookies, Hash and authorization headers!** diff --git a/ProgramScreenshots/SettingsAutoDownloader.png b/ProgramScreenshots/SettingsAutoDownloader.png index b38f96f..0ad48e7 100644 Binary files a/ProgramScreenshots/SettingsAutoDownloader.png and b/ProgramScreenshots/SettingsAutoDownloader.png differ diff --git a/ProgramScreenshots/SettingsGlobalDefaults.png b/ProgramScreenshots/SettingsGlobalDefaults.png index 2390592..7d3848e 100644 Binary files a/ProgramScreenshots/SettingsGlobalDefaults.png and b/ProgramScreenshots/SettingsGlobalDefaults.png differ diff --git a/ProgramScreenshots/SettingsScheduler.png b/ProgramScreenshots/SettingsScheduler.png new file mode 100644 index 0000000..9684b9f Binary files /dev/null and b/ProgramScreenshots/SettingsScheduler.png differ diff --git a/ProgramScreenshots/SettingsSiteInstagram.png b/ProgramScreenshots/SettingsSiteInstagram.png index 00fd911..c04ae6b 100644 Binary files a/ProgramScreenshots/SettingsSiteInstagram.png and b/ProgramScreenshots/SettingsSiteInstagram.png differ diff --git a/README.md b/README.md index 70803bc..5d5a42d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,4 @@ -# :rainbow_flag: Happy LGBT Pride Month :tada: - -# Social networks crawler +# :rainbow_flag: Social networks crawler :rainbow_flag: [![GitHub release (latest by date)](https://img.shields.io/github/v/release/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/releases/latest) [![GitHub license](https://img.shields.io/github/license/AAndyProgram/SCrawler)](https://github.com/AAndyProgram/SCrawler/blob/main/LICENSE) diff --git a/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb b/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb index aff7654..74db492 100644 --- a/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb +++ b/SCrawler.Plugin.LPSG/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb b/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb index 75cb7a4..905d15a 100644 --- a/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb +++ b/SCrawler.Plugin.XVIDEOS/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb b/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb index cbbfb97..fc5a4b3 100644 --- a/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.Designer.vb @@ -25,14 +25,9 @@ Partial Public Class SettingsForm : Inherits System.Windows.Forms.Form Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(SettingsForm)) Me.LIST_DOMAINS = New System.Windows.Forms.ListBox() - Me.ToolbarTOP = New System.Windows.Forms.ToolStrip() - Me.BTT_ADD = New System.Windows.Forms.ToolStripButton() - Me.BTT_DELETE = New System.Windows.Forms.ToolStripButton() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() CONTAINER_MAIN.ContentPanel.SuspendLayout() - CONTAINER_MAIN.TopToolStripPanel.SuspendLayout() CONTAINER_MAIN.SuspendLayout() - Me.ToolbarTOP.SuspendLayout() Me.SuspendLayout() ' 'CONTAINER_MAIN @@ -41,7 +36,7 @@ Partial Public Class SettingsForm : Inherits System.Windows.Forms.Form 'CONTAINER_MAIN.ContentPanel ' CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_DOMAINS) - CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 266) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(384, 291) CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill CONTAINER_MAIN.LeftToolStripPanelVisible = False CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) @@ -50,52 +45,15 @@ Partial Public Class SettingsForm : Inherits System.Windows.Forms.Form CONTAINER_MAIN.Size = New System.Drawing.Size(384, 291) CONTAINER_MAIN.TabIndex = 0 ' - 'CONTAINER_MAIN.TopToolStripPanel - ' - CONTAINER_MAIN.TopToolStripPanel.Controls.Add(Me.ToolbarTOP) - ' 'LIST_DOMAINS ' Me.LIST_DOMAINS.Dock = System.Windows.Forms.DockStyle.Fill Me.LIST_DOMAINS.FormattingEnabled = True Me.LIST_DOMAINS.Location = New System.Drawing.Point(0, 0) Me.LIST_DOMAINS.Name = "LIST_DOMAINS" - Me.LIST_DOMAINS.Size = New System.Drawing.Size(384, 266) + Me.LIST_DOMAINS.Size = New System.Drawing.Size(384, 291) Me.LIST_DOMAINS.TabIndex = 0 ' - 'ToolbarTOP - ' - Me.ToolbarTOP.Dock = System.Windows.Forms.DockStyle.None - Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden - Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_ADD, Me.BTT_DELETE}) - Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0) - Me.ToolbarTOP.Name = "ToolbarTOP" - Me.ToolbarTOP.Size = New System.Drawing.Size(384, 25) - Me.ToolbarTOP.Stretch = True - Me.ToolbarTOP.TabIndex = 0 - ' - 'BTT_ADD - ' - Me.BTT_ADD.AutoToolTip = False - Me.BTT_ADD.BackColor = System.Drawing.Color.FromArgb(CType(CType(192, Byte), Integer), CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer)) - Me.BTT_ADD.ForeColor = System.Drawing.Color.DarkGreen - Me.BTT_ADD.Image = CType(resources.GetObject("BTT_ADD.Image"), System.Drawing.Image) - Me.BTT_ADD.ImageTransparentColor = System.Drawing.Color.Magenta - Me.BTT_ADD.Name = "BTT_ADD" - Me.BTT_ADD.Size = New System.Drawing.Size(49, 22) - Me.BTT_ADD.Text = "Add" - ' - 'BTT_DELETE - ' - Me.BTT_DELETE.AutoToolTip = False - Me.BTT_DELETE.BackColor = System.Drawing.Color.FromArgb(CType(CType(255, Byte), Integer), CType(CType(192, Byte), Integer), CType(CType(192, Byte), Integer)) - Me.BTT_DELETE.ForeColor = System.Drawing.Color.Maroon - Me.BTT_DELETE.Image = CType(resources.GetObject("BTT_DELETE.Image"), System.Drawing.Image) - Me.BTT_DELETE.ImageTransparentColor = System.Drawing.Color.Magenta - Me.BTT_DELETE.Name = "BTT_DELETE" - Me.BTT_DELETE.Size = New System.Drawing.Size(60, 22) - Me.BTT_DELETE.Text = "Delete" - ' 'SettingsForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) @@ -112,18 +70,11 @@ Partial Public Class SettingsForm : Inherits System.Windows.Forms.Form Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.Text = "Settings" CONTAINER_MAIN.ContentPanel.ResumeLayout(False) - CONTAINER_MAIN.TopToolStripPanel.ResumeLayout(False) - CONTAINER_MAIN.TopToolStripPanel.PerformLayout() CONTAINER_MAIN.ResumeLayout(False) CONTAINER_MAIN.PerformLayout() - Me.ToolbarTOP.ResumeLayout(False) - Me.ToolbarTOP.PerformLayout() Me.ResumeLayout(False) End Sub Private WithEvents LIST_DOMAINS As Windows.Forms.ListBox - Private WithEvents ToolbarTOP As Windows.Forms.ToolStrip - Private WithEvents BTT_ADD As Windows.Forms.ToolStripButton - Private WithEvents BTT_DELETE As Windows.Forms.ToolStripButton End Class \ No newline at end of file diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.resx b/SCrawler.Plugin.XVIDEOS/SettingsForm.resx index 7083d71..ee5b946 100644 --- a/SCrawler.Plugin.XVIDEOS/SettingsForm.resx +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.resx @@ -120,60 +120,7 @@ False - - 17, 17 - - - - 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 - FHW1qQAAAABJRU5ErkJggg== - - AAABAAUAEBAAAAEAIABoBAAAVgAAABgYAAABACAAiAkAAL4EAAAgIAAAAQAIAKgIAABGDgAAMDAAAAEA diff --git a/SCrawler.Plugin.XVIDEOS/SettingsForm.vb b/SCrawler.Plugin.XVIDEOS/SettingsForm.vb index 3f47857..824f346 100644 --- a/SCrawler.Plugin.XVIDEOS/SettingsForm.vb +++ b/SCrawler.Plugin.XVIDEOS/SettingsForm.vb @@ -8,18 +8,19 @@ ' but WITHOUT ANY WARRANTY Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Forms -Public Class SettingsForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps +Public Class SettingsForm + Private WithEvents MyDefs As DefaultFormOptions Private ReadOnly Property Settings As SiteSettings - Friend Sub New(ByRef s As SiteSettings) + Friend Sub New(ByRef s As SiteSettings, ByRef Design As XML.XmlFile) InitializeComponent() - MyDefs = New DefaultFormProps Settings = s + MyDefs = New DefaultFormOptions(Me, Design) End Sub Private Sub SettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load Try With MyDefs - .MyViewInitialize(Me, Settings.Design, True) + .MyViewInitialize(True) + .AddEditToolbar({EditToolbar.ControlItem.Add, EditToolbar.ControlItem.Delete}) .AddOkCancelToolbar() If Settings.Domains.Count > 0 Then Settings.Domains.ForEach(Sub(d) LIST_DOMAINS.Items.Add(d)) .EndLoaderOperations() @@ -28,7 +29,7 @@ Public Class SettingsForm : Implements IOkCancelToolbar MyDefs.InvokeLoaderError(ex) End Try End Sub - Private Sub OK() Implements IOkCancelToolbar.OK + Private Sub MyDefs_ButtonOkClick() Handles MyDefs.ButtonOkClick Settings.Domains.Clear() With LIST_DOMAINS If .Items.Count > 0 Then @@ -38,10 +39,7 @@ Public Class SettingsForm : Implements IOkCancelToolbar Settings.UpdateDomains() MyDefs.CloseForm() End Sub - Private Sub Cancel() Implements IOkCancelToolbar.Cancel - MyDefs.CloseForm(Windows.Forms.DialogResult.Cancel) - End Sub - Private Sub BTT_ADD_Click(sender As Object, e As EventArgs) Handles BTT_ADD.Click + Private Sub MyDefs_ButtonAddClick() Handles MyDefs.ButtonAddClick Dim nd$ = InputBoxE("Enter a new domain using the pattern [xvideos.com]:", "New domain") If Not nd.IsEmptyString Then If Not LIST_DOMAINS.Items.Contains(nd) Then @@ -51,7 +49,7 @@ Public Class SettingsForm : Implements IOkCancelToolbar End If End If End Sub - Private Sub BTT_DELETE_Click(sender As Object, e As EventArgs) Handles BTT_DELETE.Click + Private Sub MyDefs_ButtonDeleteClick() Handles MyDefs.ButtonDeleteClickE If _LatestSelected.ValueBetween(0, LIST_DOMAINS.Items.Count - 1) Then Dim n$ = LIST_DOMAINS.Items(_LatestSelected) If MsgBoxE({$"Are you sure you want to delete the [{n}] domain?", diff --git a/SCrawler.Plugin.XVIDEOS/SiteSettings.vb b/SCrawler.Plugin.XVIDEOS/SiteSettings.vb index 6adce0a..3714131 100644 --- a/SCrawler.Plugin.XVIDEOS/SiteSettings.vb +++ b/SCrawler.Plugin.XVIDEOS/SiteSettings.vb @@ -41,7 +41,6 @@ Public Class SiteSettings : Implements ISiteSettings Public ReadOnly Property Responser As Response Private Const DomainsDefault As String = "xvideos.com|xnxx.com" Private _Initialized As Boolean = False - Friend Design As XmlFile Public Sub New() Responser = New Response($"Settings\Responser_{Site}.xml") With Responser @@ -109,10 +108,8 @@ Public Class SiteSettings : Implements ISiteSettings Public Sub Reset() Implements ISiteSettings.Reset End Sub Public Sub OpenSettingsForm() Implements ISiteSettings.OpenSettingsForm - Using f As New SettingsForm(Me) - Design = New XmlFile("Settings\Design_XVIDEOS.xml") - f.ShowDialog() - Design.Dispose() + Using Design As New XmlFile("Settings\Design_XVIDEOS.xml") + Using f As New SettingsForm(Me, Design) : f.ShowDialog() : End Using End Using End Sub Public Sub UserOptions(ByRef Options As Object, ByVal OpenForm As Boolean) Implements ISiteSettings.UserOptions diff --git a/SCrawler.PluginProvider/Attributes/Attributes.vb b/SCrawler.PluginProvider/Attributes/Attributes.vb index f1a2174..daa2628 100644 --- a/SCrawler.PluginProvider/Attributes/Attributes.vb +++ b/SCrawler.PluginProvider/Attributes/Attributes.vb @@ -32,6 +32,10 @@ Namespace Plugin.Attributes Public Property AllowNull As Boolean = True ''' Offset the control from the left border of the form.
Default: 100
Public Property LeftOffset As Integer = 100 + ''' This control is an information label.
Default:
+ Public Property IsInformationLabel As Boolean = False + ''' Label text alignment.
Default:
+ Public Property LabelTextAlign As Drawing.ContentAlignment = Drawing.ContentAlignment.TopCenter ''' This is an authorization property Public Property IsAuth As Boolean = False ''' Initialize a new property option attribute diff --git a/SCrawler.PluginProvider/My Project/AssemblyInfo.vb b/SCrawler.PluginProvider/My Project/AssemblyInfo.vb index 5d309d8..237504a 100644 --- a/SCrawler.PluginProvider/My Project/AssemblyInfo.vb +++ b/SCrawler.PluginProvider/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler/API/Base/DownDetector.vb b/SCrawler/API/Base/DownDetector.vb index 9079dfd..d8bb2e7 100644 --- a/SCrawler/API/Base/DownDetector.vb +++ b/SCrawler/API/Base/DownDetector.vb @@ -16,7 +16,7 @@ Namespace API.Base Friend Structure Data : Implements IRegExCreator, IComparable(Of Data) Friend [Date] As Date Friend Value As Integer - Friend Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray + Private Function CreateFromArray(ByVal ParamsArray() As String) As Object Implements IRegExCreator.CreateFromArray If ParamsArray.ListExists Then Try : [Date] = Date.Parse(ParamsArray(0)) : Catch : End Try If ParamsArray.Length > 1 Then Value = AConvert(Of Integer)(ParamsArray(1), 0) @@ -26,7 +26,7 @@ Namespace API.Base Public Overrides Function ToString() As String Return $"{AConvert(Of String)([Date], ADateTime.Formats.BaseDateTime, String.Empty)} [{Value}]" End Function - Friend Function CompareTo(ByVal Other As Data) As Integer Implements IComparable(Of Data).CompareTo + Private Function CompareTo(ByVal Other As Data) As Integer Implements IComparable(Of Data).CompareTo Return [Date].CompareTo(Other.Date) * -1 End Function End Structure diff --git a/SCrawler/API/Base/ProfileSaved.vb b/SCrawler/API/Base/ProfileSaved.vb index 525cb8d..5929fd0 100644 --- a/SCrawler/API/Base/ProfileSaved.vb +++ b/SCrawler/API/Base/ProfileSaved.vb @@ -40,7 +40,7 @@ Namespace API.Base End With HOST.BeforeStartDownload(user, PDownload.SavedPosts) user.DownloadData(Token) - Progress.InformationTemporary = $"Images: {user.DownloadedPictures(False)}; Videos: {user.DownloadedVideos(False)}" + Progress.InformationTemporary = $"{HOST.Name} Images: {user.DownloadedPictures(False)}; Videos: {user.DownloadedVideos(False)}" HOST.AfterDownload(user, PDownload.SavedPosts) End If End Using diff --git a/SCrawler/API/Base/SiteSettingsBase.vb b/SCrawler/API/Base/SiteSettingsBase.vb index 6dcb635..4263934 100644 --- a/SCrawler/API/Base/SiteSettingsBase.vb +++ b/SCrawler/API/Base/SiteSettingsBase.vb @@ -6,15 +6,15 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY -Imports SCrawler.Plugin Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Tools.WEB +Imports SCrawler.Plugin Imports Download = SCrawler.Plugin.ISiteSettings.Download Namespace API.Base Friend MustInherit Class SiteSettingsBase : Implements ISiteSettings Friend ReadOnly Property Site As String Implements ISiteSettings.Site - Friend Overridable ReadOnly Property Icon As Icon = Nothing Implements ISiteSettings.Icon - Friend Overridable ReadOnly Property Image As Image = Nothing Implements ISiteSettings.Image + Friend Overridable ReadOnly Property Icon As Icon Implements ISiteSettings.Icon + Friend Overridable ReadOnly Property Image As Image Implements ISiteSettings.Image Private Property Logger As ILogProvider = LogConnector Implements ISiteSettings.Logger Friend Overridable ReadOnly Property Responser As Response Friend MustOverride Function GetInstance(ByVal What As Download) As IPluginContentProvider Implements ISiteSettings.GetInstance diff --git a/SCrawler/API/Base/Structures.vb b/SCrawler/API/Base/Structures.vb index eb1d131..3c425ae 100644 --- a/SCrawler/API/Base/Structures.vb +++ b/SCrawler/API/Base/Structures.vb @@ -106,12 +106,12 @@ Namespace API.Base Friend Function CompareTo(ByVal Other As UserPost) As Integer Implements IComparable(Of UserPost).CompareTo Return GetCompareValue(Me).CompareTo(GetCompareValue(Other)) End Function -#End Region Private Function GetCompareValue(ByVal Post As UserPost) As Long Dim v& = 0 If Post.Date.HasValue Then v = Post.Date.Value.Ticks * -1 Return v End Function +#End Region End Structure Friend Structure Sizes : Implements IComparable(Of Sizes) Friend Value As Integer diff --git a/SCrawler/API/Base/UserDataBase.vb b/SCrawler/API/Base/UserDataBase.vb index ac67729..243a9e0 100644 --- a/SCrawler/API/Base/UserDataBase.vb +++ b/SCrawler/API/Base/UserDataBase.vb @@ -9,8 +9,8 @@ Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Forms.Toolbars -Imports PersonalUtilities.Tools.WEB Imports PersonalUtilities.Tools +Imports PersonalUtilities.Tools.WEB Imports System.IO Imports System.Net Imports System.Threading @@ -21,28 +21,33 @@ Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Base Friend MustInherit Class UserDataBase : Implements IUserData, IPluginContentProvider, IThrower Friend Const UserFileAppender As String = "User" - Private ReadOnly _OnUserUpdatedHandlers As List(Of IUserData.OnUserUpdatedEventHandler) - Friend Custom Event OnUserUpdated As IUserData.OnUserUpdatedEventHandler Implements IUserData.OnUserUpdated - AddHandler(ByVal e As IUserData.OnUserUpdatedEventHandler) - If Not _OnUserUpdatedHandlers.Contains(e) Then _OnUserUpdatedHandlers.Add(e) +#Region "Events" + Private ReadOnly UserUpdatedEventHandlers As List(Of IUserData.UserUpdatedEventHandler) + Friend Custom Event UserUpdated As IUserData.UserUpdatedEventHandler Implements IUserData.UserUpdated + AddHandler(ByVal e As IUserData.UserUpdatedEventHandler) + If Not UserUpdatedEventHandlers.Contains(e) Then UserUpdatedEventHandlers.Add(e) End AddHandler - RemoveHandler(ByVal e As IUserData.OnUserUpdatedEventHandler) - If _OnUserUpdatedHandlers.Contains(e) Then _OnUserUpdatedHandlers.Remove(e) + RemoveHandler(ByVal e As IUserData.UserUpdatedEventHandler) + If UserUpdatedEventHandlers.Contains(e) Then UserUpdatedEventHandlers.Remove(e) End RemoveHandler RaiseEvent(ByVal User As IUserData) - If _OnUserUpdatedHandlers.Count > 0 Then - For Each e As IUserData.OnUserUpdatedEventHandler In _OnUserUpdatedHandlers - Try : e.Invoke(User) : Catch : End Try - Next - End If + Try + If UserUpdatedEventHandlers.Count > 0 Then + For i% = 0 To UserUpdatedEventHandlers.Count - 1 + Try : UserUpdatedEventHandlers(i).Invoke(User) : Catch : End Try + Next + End If + Catch + End Try End RaiseEvent End Event - Protected Sub RaiseEvent_OnUserUpdated() - RaiseEvent OnUserUpdated(Me) + Protected Sub OnUserUpdated() + RaiseEvent UserUpdated(Me) End Sub Friend Sub RemoveUpdateHandlers() - _OnUserUpdatedHandlers.Clear() + UserUpdatedEventHandlers.Clear() End Sub +#End Region #Region "Collection buttons" Private _CollectionButtonsExists As Boolean = False Private _CollectionButtonsColorsSet As Boolean = False @@ -130,12 +135,21 @@ Namespace API.Base #End Region #End Region #Region "Declarations" +#Region "Host, Site, Progress, Self" + Friend Property HOST As SettingsHost Implements IUserData.HOST Friend ReadOnly Property Site As String Implements IContentProvider.Site Get Return HOST.Name End Get End Property Friend Property Progress As MyProgress + Friend ReadOnly Property Self As IUserData Implements IUserData.Self + Get + Return Me + End Get + End Property +#End Region +#Region "User name, ID, exist, suspend" Friend User As UserInfo Friend Property IsSavedPosts As Boolean Implements IPluginContentProvider.IsSavedPosts Friend Overridable Property UserExists As Boolean = True Implements IUserData.Exists, IPluginContentProvider.UserExists @@ -152,7 +166,8 @@ Namespace API.Base End Property Friend Overridable Property ID As String = String.Empty Implements IContentProvider.ID, IPluginContentProvider.ID Friend Overridable Property FriendlyName As String = String.Empty Implements IContentProvider.FriendlyName -#Region "UserDescription" +#End Region +#Region "Description" Friend Property UserDescription As String = String.Empty Implements IContentProvider.Description, IPluginContentProvider.UserDescription Protected _DescriptionEveryTime As Boolean = False Protected _DescriptionChecked As Boolean = False @@ -174,7 +189,7 @@ Namespace API.Base _DescriptionEveryTime = Settings.UpdateUserDescriptionEveryTime End Sub #End Region - Friend Property ParseUserMediaOnly As Boolean = False Implements IUserData.ParseUserMediaOnly, IPluginContentProvider.ParseUserMediaOnly +#Region "Favorite, Temporary" Protected _Favorite As Boolean = False Friend Overridable Property Favorite As Boolean Implements IContentProvider.Favorite Get @@ -195,17 +210,15 @@ Namespace API.Base If _Temporary Then _Favorite = False End Set End Property +#End Region +#Region "Channel" Friend Overridable ReadOnly Property IsChannel As Boolean Implements IUserData.IsChannel Get Return User.IsChannel End Get End Property Friend Property CreatedByChannel As Boolean = False - Friend ReadOnly Property Self As IUserData Implements IUserData.Self - Get - Return Me - End Get - End Property +#End Region #Region "Images" Friend Overridable Function GetUserPicture() As Image Implements IUserData.GetPicture If Settings.ViewModeIsPicture Then @@ -303,7 +316,7 @@ BlockNullPicture: End Get End Property #End Region -#Region "Collections support" +#Region "Collections" Protected _IsCollection As Boolean = False Protected Friend ReadOnly Property IsCollection As Boolean Implements IUserData.IsCollection Get @@ -332,9 +345,10 @@ BlockNullPicture: End Sub Friend Overridable ReadOnly Property Labels As List(Of String) Implements IUserData.Labels #End Region -#Region "Downloading params" +#Region "Downloading" Protected _DataLoaded As Boolean = False Protected _DataParsed As Boolean = False + Friend Property ParseUserMediaOnly As Boolean = False Implements IUserData.ParseUserMediaOnly, IPluginContentProvider.ParseUserMediaOnly Friend Overridable Property ReadyForDownload As Boolean = True Implements IUserData.ReadyForDownload Friend Property DownloadImages As Boolean = True Implements IUserData.DownloadImages Friend Property DownloadVideos As Boolean = True Implements IUserData.DownloadVideos @@ -378,7 +392,7 @@ BlockNullPicture: End Set End Property #End Region -#Region "Information" +#Region "Information, counters, error, update date" Friend Overridable Property LastUpdated As Date? Friend Overridable Property HasError As Boolean = False Implements IUserData.HasError Private _DownloadedPicturesTotal As Integer = 0 @@ -422,6 +436,25 @@ BlockNullPicture: $" (P - {DownloadedPictures(True)}; V - {DownloadedVideos(True)})" End Get End Property + Friend Overridable Function GetUserInformation() As String + Dim OutStr$ = $"User: {Name}" + OutStr.StringAppendLine($"Path: {MyFile.CutPath.Path}") + OutStr.StringAppendLine($"Total downloaded ({DownloadedTotal(True).NumToString(ANumbers.Formats.Number, 3)}):") + OutStr.StringAppendLine($"Pictures: {DownloadedPictures(True).NumToString(ANumbers.Formats.Number, 3)}") + OutStr.StringAppendLine($"Videos: {DownloadedVideos(True).NumToString(ANumbers.Formats.Number, 3)}") + If Not UserDescription.IsEmptyString Then + OutStr.StringAppendLine(String.Empty) + OutStr.StringAppendLine(UserDescription) + End If + OutStr.StringAppendLine(String.Empty) + OutStr.StringAppendLine($"Last updated at: {AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, "not yet")}") + If _DataParsed Then + OutStr.StringAppendLine("Downloaded now:") + OutStr.StringAppendLine($"Pictures: {DownloadedTotal(False).NumToString(ANumbers.Formats.Number, 3)}") + OutStr.StringAppendLine($"Videos: {DownloadedVideos(False).NumToString(ANumbers.Formats.Number, 3)}") + End If + Return OutStr + End Function #End Region #Region "Script" Friend Overridable Property ScriptUse As Boolean = False Implements IUserData.ScriptUse @@ -431,7 +464,6 @@ BlockNullPicture: #Region "Plugins Support" Protected Event ProgressChanged As IPluginContentProvider.ProgressChangedEventHandler Implements IPluginContentProvider.ProgressChanged Protected Event TotalCountChanged As IPluginContentProvider.TotalCountChangedEventHandler Implements IPluginContentProvider.TotalCountChanged - Friend Property HOST As SettingsHost Implements IUserData.HOST Private Property IPluginContentProvider_Settings As ISiteSettings Implements IPluginContentProvider.Settings Get Return HOST.Source @@ -524,37 +556,16 @@ BlockNullPicture: Return Destination.Groups.Item(LabelsKeeper.NoLabeledName) End Try End Function - Friend Overridable Function GetUserInformation() As String - Dim OutStr$ = $"User: {Name}" - OutStr.StringAppendLine($"Path: {MyFile.CutPath.Path}") - OutStr.StringAppendLine($"Total downloaded ({DownloadedTotal(True).NumToString(ANumbers.Formats.Number, 3)}):") - OutStr.StringAppendLine($"Pictures: {DownloadedPictures(True).NumToString(ANumbers.Formats.Number, 3)}") - OutStr.StringAppendLine($"Videos: {DownloadedVideos(True).NumToString(ANumbers.Formats.Number, 3)}") - If Not UserDescription.IsEmptyString Then - OutStr.StringAppendLine(String.Empty) - OutStr.StringAppendLine(UserDescription) - End If - OutStr.StringAppendLine(String.Empty) - OutStr.StringAppendLine($"Last updated at: {AConvert(Of String)(LastUpdated, ADateTime.Formats.BaseDateTime, "not yet")}") - If _DataParsed Then - OutStr.StringAppendLine("Downloaded now:") - OutStr.StringAppendLine($"Pictures: {DownloadedTotal(False).NumToString(ANumbers.Formats.Number, 3)}") - OutStr.StringAppendLine($"Videos: {DownloadedVideos(False).NumToString(ANumbers.Formats.Number, 3)}") - End If - Return OutStr - End Function #End Region #Region "Initializer" - Private ReadOnly _InvokeImageHandler As Boolean ''' By using this constructor you must set UserName and MyFile manually Friend Sub New(Optional ByVal InvokeImageHandler As Boolean = True) - _InvokeImageHandler = InvokeImageHandler _ContentList = New List(Of UserMedia) _ContentNew = New List(Of UserMedia) _TempMediaList = New List(Of UserMedia) _TempPostsList = New List(Of String) Labels = New List(Of String) - _OnUserUpdatedHandlers = New List(Of IUserData.OnUserUpdatedEventHandler) + UserUpdatedEventHandlers = New List(Of IUserData.UserUpdatedEventHandler) If InvokeImageHandler Then ImageHandler(Me) End Sub Friend Sub SetEnvironment(ByRef h As SettingsHost, ByVal u As UserInfo, ByVal _LoadUserInformation As Boolean, @@ -680,15 +691,16 @@ BlockNullPicture: End Function For Each v As EContainer In x _ContentList.Add(New UserMedia With { - .Type = AConvert(Of Integer)(v.Attribute(Name_MediaType).Value, 0), - .URL = v.Attribute(Name_MediaURL).Value, - .URL_BASE = v.Value, - .MD5 = v.Attribute(Name_MediaHash).Value, - .File = fs & gfn.Invoke(v.Attribute(Name_MediaFile).Value), - .Post = New UserPost With { - .ID = v.Attribute(Name_MediaPostID).Value, - .[Date] = AConvert(Of Date)(v.Attribute(Name_MediaPostDate).Value, ParsersDataDateProvider, Nothing)} - }) + .Type = AConvert(Of Integer)(v.Attribute(Name_MediaType).Value, 0), + .URL = v.Attribute(Name_MediaURL).Value, + .URL_BASE = v.Value, + .MD5 = v.Attribute(Name_MediaHash).Value, + .File = fs & gfn.Invoke(v.Attribute(Name_MediaFile).Value), + .Post = New UserPost With { + .ID = v.Attribute(Name_MediaPostID).Value, + .[Date] = AConvert(Of Date)(v.Attribute(Name_MediaPostDate).Value, ParsersDataDateProvider, Nothing) + } + }) Next End If _DataLoaded = True @@ -705,14 +717,15 @@ BlockNullPicture: Using x As New XmlFile With {.AllowSameNames = True, .Name = "Data"} If _ContentList.Count > 0 Then For Each i As UserMedia In _ContentList - x.Add(New EContainer("MediaData", i.URL_BASE, - {New EAttribute(Name_MediaType, CInt(i.Type)), - New EAttribute(Name_MediaURL, i.URL), - New EAttribute(Name_MediaHash, i.MD5), - New EAttribute(Name_MediaFile, i.File.File), - New EAttribute(Name_MediaPostID, i.Post.ID), - New EAttribute(Name_MediaPostDate, AConvert(Of String)(i.Post.Date, ParsersDataDateProvider, String.Empty)) - })) + x.Add(New EContainer("MediaData", i.URL_BASE, {New EAttribute(Name_MediaType, CInt(i.Type)), + New EAttribute(Name_MediaURL, i.URL), + New EAttribute(Name_MediaHash, i.MD5), + New EAttribute(Name_MediaFile, i.File.File), + New EAttribute(Name_MediaPostID, i.Post.ID), + New EAttribute(Name_MediaPostDate, AConvert(Of String)(i.Post.Date, ParsersDataDateProvider, String.Empty)) + } + ) + ) Next End If x.Save(MyFileData) @@ -730,7 +743,7 @@ BlockNullPicture: If Not URL.IsEmptyString Then Process.Start(URL) Catch ex As Exception If Not e.Exists Then e = New ErrorsDescriber(EDP.ShowAllMsg) - MsgBoxE($"Error on trying to open [{Site}] page of user [{Name}]", MsgBoxStyle.Critical, e) + MsgBoxE({$"Error on trying to open [{Site}] page of user [{Name}]", $"User [{ToString()}]"}, MsgBoxStyle.Critical, e, ex) End Try End Sub Friend Overridable Sub OpenFolder() Implements IUserData.OpenFolder @@ -803,7 +816,7 @@ BlockNullPicture: If _CollectionButtonsExists AndAlso EnvirChanged.Invoke Then UpdateButtonsColor() End If ThrowIfDisposed() - If UpPic Or EnvirChanged.Invoke Then RaiseEvent_OnUserUpdated() + If UpPic Or EnvirChanged.Invoke Then OnUserUpdated() Catch oex As OperationCanceledException When Token.IsCancellationRequested MyMainLOG = $"{Site} - {Name}: downloading canceled" Canceled = True @@ -814,7 +827,7 @@ BlockNullPicture: HasError = True Finally If Not Responser Is Nothing Then Responser.Dispose() : Responser = Nothing - If Not Canceled Then _DataParsed = True ': LastUpdated = Now + If Not Canceled Then _DataParsed = True _ContentNew.Clear() DownloadTopCount = Nothing DownloadToDate = Nothing @@ -886,6 +899,8 @@ BlockNullPicture: Case UTypes.Video : f.Extension = "mp4" Case UTypes.GIF : f.Extension = "gif" End Select + ElseIf f.Extension = "webp" And Settings.DownloadNativeImageFormat Then + f.Extension = "jpg" End If If Not v.SpecialFolder.IsEmptyString Then @@ -1201,7 +1216,7 @@ BlockNullPicture: If Not BTT_CONTEXT_DELETE Is Nothing Then BTT_CONTEXT_DELETE.Dispose() If Not BTT_CONTEXT_OPEN_PATH Is Nothing Then BTT_CONTEXT_OPEN_PATH.Dispose() If Not BTT_CONTEXT_OPEN_SITE Is Nothing Then BTT_CONTEXT_OPEN_SITE.Dispose() - _OnUserUpdatedHandlers.Clear() + UserUpdatedEventHandlers.Clear() End If disposedValue = True End If @@ -1228,7 +1243,7 @@ BlockNullPicture: Sub DownloadData(ByVal Token As CancellationToken) End Interface Friend Interface IUserData : Inherits IContentProvider, IComparable(Of UserDataBase), IComparable, IEquatable(Of UserDataBase), IIndexable, IDisposable - Event OnUserUpdated(ByVal User As IUserData) + Event UserUpdated(ByVal User As IUserData) Property ParseUserMediaOnly As Boolean #Region "Images" Function GetPicture() As Image diff --git a/SCrawler/API/Imgur/Envir.vb b/SCrawler/API/Imgur/Envir.vb index 36f25bc..b9b99e7 100644 --- a/SCrawler/API/Imgur/Envir.vb +++ b/SCrawler/API/Imgur/Envir.vb @@ -10,8 +10,8 @@ Imports PersonalUtilities.Functions.XML Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Tools.WebDocuments.JSON Imports System.Net -Imports SCrawler.API.Imgur.Declarations Imports SCrawler.API.Base +Imports SCrawler.API.Imgur.Declarations Namespace API.Imgur Namespace Declarations Friend Module Imgur_Declarations diff --git a/SCrawler/API/Instagram/AuthNullException.vb b/SCrawler/API/Instagram/AuthNullException.vb deleted file mode 100644 index cc1e6f4..0000000 --- a/SCrawler/API/Instagram/AuthNullException.vb +++ /dev/null @@ -1,36 +0,0 @@ -' Copyright (C) 2022 Andy -' This program is free software: you can redistribute it and/or modify -' it under the terms of the GNU General Public License as published by -' the Free Software Foundation, either version 3 of the License, or -' (at your option) any later version. -' -' This program is distributed in the hope that it will be useful, -' but WITHOUT ANY WARRANTY -Imports Sections = SCrawler.API.Instagram.UserData.Sections -Namespace API.Instagram - Friend Class AuthNullException : Inherits ArgumentNullException - Public Overrides ReadOnly Property ParamName As String - Public Overrides ReadOnly Property Message As String - Friend Sub New(ByVal s As Sections, ByVal IsSavedPosts As Boolean) - If IsSavedPosts Then - ParamName = "HashSavedPosts" - ElseIf s = Sections.Timeline Then - ParamName = "Hash" - Else - ParamName = "IG_APP_ID, IG_WWW_CLAIM" - End If - Message = $"Instagram auth for [{s}] is not set" - End Sub - Friend Shared Sub ThrowIfNull(ByVal s As Sections, ByVal IsSavedPosts As Boolean, ByVal Host As SiteSettings) - Dim b As Boolean = False - If IsSavedPosts Then - If Not ACheck(Host.HashSavedPosts.Value) Then b = True - ElseIf s = Sections.Timeline Then - If Not ACheck(Host.Hash.Value) Then Host.HashUpdateRequired.Value = True : b = True - Else - If Not Host.StoriesAndTaggedReady Then b = True - End If - If b Then Throw New AuthNullException(s, IsSavedPosts) - End Sub - End Class -End Namespace \ No newline at end of file diff --git a/SCrawler/API/Instagram/Declarations.vb b/SCrawler/API/Instagram/Declarations.vb index e2c0974..62285aa 100644 --- a/SCrawler/API/Instagram/Declarations.vb +++ b/SCrawler/API/Instagram/Declarations.vb @@ -13,8 +13,8 @@ Namespace API.Instagram Friend ReadOnly FilesPattern As RParams = RParams.DMS(".+?([^/\?]+?\.[\w\d]{3,4})(?=(\?|\Z))", 1, EDP.ReturnValue) Friend ReadOnly Property DateProvider As New JsonDate Friend Class JsonDate : Implements ICustomProvider - Friend Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, - Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert + Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, + Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert Return ADateTime.ParseUnicode(Value) End Function Private Function GetFormat(ByVal FormatType As Type) As Object Implements IFormatProvider.GetFormat diff --git a/SCrawler/API/Instagram/EditorExchangeOptions.vb b/SCrawler/API/Instagram/EditorExchangeOptions.vb index 9ed3b3b..bc42809 100644 --- a/SCrawler/API/Instagram/EditorExchangeOptions.vb +++ b/SCrawler/API/Instagram/EditorExchangeOptions.vb @@ -11,10 +11,8 @@ Namespace API.Instagram Friend Class EditorExchangeOptions Friend Property GetStories As Boolean Friend Property GetTagged As Boolean - Private ReadOnly Property MySiteSettings As SiteSettings Friend Sub New(ByVal h As ISiteSettings) - MySiteSettings = DirectCast(h, SiteSettings) - With MySiteSettings + With DirectCast(h, SiteSettings) GetStories = CBool(.GetStories.Value) GetTagged = CBool(.GetTagged.Value) End With diff --git a/SCrawler/API/Instagram/ExitException.vb b/SCrawler/API/Instagram/ExitException.vb deleted file mode 100644 index 32033df..0000000 --- a/SCrawler/API/Instagram/ExitException.vb +++ /dev/null @@ -1,15 +0,0 @@ -' Copyright (C) 2022 Andy -' This program is free software: you can redistribute it and/or modify -' it under the terms of the GNU General Public License as published by -' the Free Software Foundation, either version 3 of the License, or -' (at your option) any later version. -' -' This program is distributed in the hope that it will be useful, -' but WITHOUT ANY WARRANTY -Namespace API.Instagram - Friend Class ExitException : Inherits Exception - Friend Sub New(ByRef CompleteArg As Boolean) - CompleteArg = True - End Sub - End Class -End Namespace \ No newline at end of file diff --git a/SCrawler/API/Instagram/OptionsForm.vb b/SCrawler/API/Instagram/OptionsForm.vb index 3b96b4e..d6b3058 100644 --- a/SCrawler/API/Instagram/OptionsForm.vb +++ b/SCrawler/API/Instagram/OptionsForm.vb @@ -10,12 +10,12 @@ Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Toolbars Namespace API.Instagram Friend Class OptionsForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Private ReadOnly Property MyExchangeOptions As EditorExchangeOptions Friend Sub New(ByRef ExchangeOptions As EditorExchangeOptions) InitializeComponent() MyExchangeOptions = ExchangeOptions - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub Private Sub OptionsForm_Load(sender As Object, e As EventArgs) Handles Me.Load With MyDefs diff --git a/SCrawler/API/Instagram/SiteSettings.vb b/SCrawler/API/Instagram/SiteSettings.vb index bd03f70..cbb67a2 100644 --- a/SCrawler/API/Instagram/SiteSettings.vb +++ b/SCrawler/API/Instagram/SiteSettings.vb @@ -18,7 +18,8 @@ Imports Download = SCrawler.Plugin.ISiteSettings.Download Namespace API.Instagram Friend Class SiteSettings : Inherits SiteSettingsBase -#Region "Interface Declarations" +#Region "Declarations" +#Region "Images" Friend Overrides ReadOnly Property Icon As Icon Get Return My.Resources.InstagramIcon @@ -89,14 +90,31 @@ Namespace API.Instagram Friend Property IG_WWW_CLAIM As PropertyValue Friend ReadOnly Property SavedPostsUserName As PropertyValue - Friend ReadOnly Property StoriesAndTaggedReady As Boolean + Friend ReadOnly Property BaseAuthExists As Boolean Get - Return ACheck(IG_APP_ID.Value) And ACheck(IG_WWW_CLAIM.Value) And ACheck(CSRF_TOKEN.Value) + Return Responser.Cookies.Count > 0 And ACheck(IG_APP_ID.Value) And ACheck(IG_WWW_CLAIM.Value) And ACheck(CSRF_TOKEN.Value) End Get End Property + Private Const Header_IG_APP_ID As String = "x-ig-app-id" + Private Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim" + Private Const Header_CSRF_TOKEN As String = "x-csrftoken" + Private Sub ChangeResponserFields(ByVal PropName As String, ByVal Value As Object) + If Not PropName.IsEmptyString Then + Dim f$ = String.Empty + Select Case PropName + Case NameOf(IG_APP_ID) : f = Header_IG_APP_ID + Case NameOf(IG_WWW_CLAIM) : f = Header_IG_WWW_CLAIM + Case NameOf(CSRF_TOKEN) : f = Header_CSRF_TOKEN + End Select + If Not f.IsEmptyString Then + If Responser.Headers.Count > 0 AndAlso Responser.Headers.ContainsKey(f) Then Responser.Headers.Remove(f) + If Not CStr(Value).IsEmptyString Then Responser.Headers.Add(f, CStr(Value)) + Responser.SaveSettings() + End If + End If + End Sub #End Region #Region "Download properties" - Friend ReadOnly Property HashUpdateRequired As XMLValue(Of Boolean) Friend ReadOnly Property RequestsWaitTimer As PropertyValue @@ -121,7 +139,7 @@ Namespace API.Instagram Private ReadOnly Property TaggedNotifyLimitProvider As IFormatProvider #End Region #Region "429 bypass" - Friend ReadOnly Property DownloadingErrorDate As XMLValue(Of Date) + Private ReadOnly Property DownloadingErrorDate As XMLValue(Of Date) Friend Property LastApplyingValue As Integer? = Nothing Friend ReadOnly Property ReadyForDownload As Boolean Get @@ -134,8 +152,11 @@ Namespace API.Instagram End With End Get End Property - Friend ReadOnly Property LastDownloadDate As XMLValue(Of Date) - Friend ReadOnly Property LastRequestsCount As XMLValue(Of Integer) + Private ReadOnly Property LastDownloadDate As XMLValue(Of Date) + Private ReadOnly Property LastRequestsCount As XMLValue(Of Integer) + + Private Property LastRequestsCountLabel As PropertyValue + Private ReadOnly LastRequestsCountLabelStr As Func(Of Integer, String) = Function(r) $"Number of spent requests: {r.NumToGroupIntegral}" Private TooManyRequestsReadyForCatch As Boolean = True Friend Function GetWaitDate() As Date With DownloadingErrorDate @@ -155,7 +176,7 @@ Namespace API.Instagram LastApplyingValue = If(LastApplyingValue, 0) + 10 TooManyRequestsReadyForCatch = False MyMainLOG = $"Instagram downloading error: too many requests. Try again after {If(LastApplyingValue, 10)} minutes..." - End If + End If End If Else .ValueF = Nothing @@ -166,6 +187,9 @@ Namespace API.Instagram End Sub #End Region Friend Overrides ReadOnly Property Responser As WEB.Response + Private Initialized As Boolean = False +#End Region +#Region "Initializer" Friend Sub New(ByRef _XML As XmlFile, ByVal GlobalPath As SFile) MyBase.New(InstagramSite) Responser = New WEB.Response($"{SettingsFolderName}\Responser_{Site}.xml") @@ -192,7 +216,6 @@ Namespace API.Instagram SavedPostsUserName = New PropertyValue(String.Empty, GetType(String)) - HashUpdateRequired = New XMLValue(Of Boolean)("InstaHashUpdateRequired", True, _XML, n) Hash = New PropertyValue(String.Empty, GetType(String)) HashSavedPosts = New PropertyValue(String.Empty, GetType(String)) CSRF_TOKEN = New PropertyValue(token, GetType(String), Sub(v) ChangeResponserFields(NameOf(CSRF_TOKEN), v)) @@ -216,39 +239,20 @@ Namespace API.Instagram DownloadingErrorDate.SetExtended("InstagramDownloadingErrorDate", Now.AddYears(-10), _XML, n) LastDownloadDate = New XMLValue(Of Date)("LastDownloadDate", Now.AddDays(-1), _XML, n) LastRequestsCount = New XMLValue(Of Integer)("LastRequestsCount", 0, _XML, n) + LastRequestsCountLabel = New PropertyValue(LastRequestsCountLabelStr.Invoke(LastRequestsCount.Value)) + AddHandler LastRequestsCount.OnValueChanged, Sub(sender, __name, __value) LastRequestsCountLabel.Value = LastRequestsCountLabelStr.Invoke(__value) UrlPatternUser = "https://www.instagram.com/{0}/" UserRegex = RParams.DMS("[htps:/]{7,8}.*?instagram.com/([^/]+)", 1) ImageVideoContains = "instagram.com" End Sub - Friend Overrides Function GetInstance(ByVal What As Download) As IPluginContentProvider - Select Case What - Case Download.Main : Return New UserData - Case Download.SavedPosts - Dim u As New UserData - DirectCast(u, UserDataBase).User = New UserInfo With {.Name = CStr(AConvert(Of String)(SavedPostsUserName.Value, String.Empty))} - Return u - End Select - Return Nothing - End Function - Private Const Header_IG_APP_ID As String = "x-ig-app-id" - Private Const Header_IG_WWW_CLAIM As String = "x-ig-www-claim" - Private Const Header_CSRF_TOKEN As String = "x-csrftoken" - Private Sub ChangeResponserFields(ByVal PropName As String, ByVal Value As Object) - If Not PropName.IsEmptyString Then - Dim f$ = String.Empty - Select Case PropName - Case NameOf(IG_APP_ID) : f = Header_IG_APP_ID - Case NameOf(IG_WWW_CLAIM) : f = Header_IG_WWW_CLAIM - Case NameOf(CSRF_TOKEN) : f = Header_CSRF_TOKEN - End Select - If Not f.IsEmptyString Then - If Responser.Headers.Count > 0 AndAlso Responser.Headers.ContainsKey(f) Then Responser.Headers.Remove(f) - If Not CStr(Value).IsEmptyString Then Responser.Headers.Add(f, CStr(Value)) - Responser.SaveSettings() - End If - End If + Friend Overrides Sub BeginInit() End Sub + Friend Overrides Sub EndInit() + Initialized = True + End Sub +#End Region +#Region "PropertiesDataChecker" Private Function CheckHashControls(ByVal p As IEnumerable(Of PropertyData)) As Boolean If p.ListExists(2) Then @@ -292,20 +296,32 @@ Namespace API.Instagram End If Return False End Function - Friend Overrides Sub BeginInit() - End Sub - Friend Overrides Sub EndInit() - If (CStr(Hash.Value).IsEmptyString Or HashUpdateRequired) AndAlso Responser.Cookies.ListExists Then GatherInstaHash() - End Sub - Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean - Return ActiveJobs < 2 AndAlso ReadyForDownload +#End Region +#Region "Plugin functions" + Friend Overrides Function GetInstance(ByVal What As Download) As IPluginContentProvider + Select Case What + Case Download.Main : Return New UserData + Case Download.SavedPosts + Dim u As New UserData + DirectCast(u, UserDataBase).User = New UserInfo With {.Name = CStr(AConvert(Of String)(SavedPostsUserName.Value, String.Empty))} + Return u + End Select + Return Nothing End Function #Region "Downloading" + Friend Overrides Function ReadyToDownload(ByVal What As Download) As Boolean + If ActiveJobs < 2 AndAlso ReadyForDownload AndAlso BaseAuthExists Then + Select Case What + Case Download.Main : Return ACheck(Hash.Value) + Case Download.SavedPosts : Return ACheck(HashSavedPosts.Value) + End Select + End If + Return False + End Function Private ActiveJobs As Integer = 0 Private _NextWNM As UserData.WNM = UserData.WNM.Notify Private _NextTagged As Boolean = True Friend Overrides Sub DownloadStarted(ByVal What As Download) - If CStr(Hash.Value).IsEmptyString Or HashUpdateRequired Then GatherInstaHash() ActiveJobs += 1 End Sub Friend Overrides Sub BeforeStartDownload(ByVal User As Object, ByVal What As Download) @@ -336,40 +352,8 @@ Namespace API.Instagram _NextTagged = True LastDownloadDate.Value = Now ActiveJobs -= 1 - If HashUpdateRequired Then MyMainLOG = "Check your Instagram credentials" End Sub #End Region - - Friend Function GatherInstaHash() As Boolean - Try - If Not Responser.Cookies.ListExists Then Throw New Exception("Instagram cookies does not set") - Dim rs As New RParams("preload"" href=""(https://static.cdninstagram.com/rsrc.php/[^""]+?.js[^""]*)""", Nothing, 1, RegexReturn.List) With {.MatchTimeOut = 10} - Dim h$ - Dim r$ = Responser.GetResponse("https://www.instagram.com",, EDP.ThrowException) - If Not r.IsEmptyString Then - Dim JsUrls As List(Of String) = RegexReplace(r, rs) - If JsUrls.ListExists Then - rs = New RParams("\{.+?var h=""([\w\d\S]+?)"".+?\)\.generatePaginationActionCreators", Nothing, 1) With {.MatchTimeOut = 10} - For Each url$ In JsUrls - r = Responser.GetResponse(url,, EDP.ReturnValue) - If Not r.IsEmptyString Then - h = RegexReplace(r, rs) - If Not h.IsEmptyString AndAlso h.Length > 30 Then - Hash.Value = h - HashUpdateRequired.Value = False - Return True - End If - End If - Next - End If - End If - Return False - Catch ex As Exception - HashUpdateRequired.Value = True - Hash.Value = String.Empty - Return ErrorsDescriber.Execute(EDP.SendInLog + EDP.ReturnValue, ex, "[SiteSettings.GaterInstaHash]", False) - End Try - End Function Friend Overrides Function GetSpecialDataF(ByVal URL As String) As IEnumerable(Of UserMedia) Return UserData.GetVideoInfo(URL, Responser, Me) End Function @@ -379,5 +363,6 @@ Namespace API.Instagram Using f As New OptionsForm(Options) : f.ShowDialog() : End Using End If End Sub +#End Region End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Instagram/UserData.vb b/SCrawler/API/Instagram/UserData.vb index 598bb60..52e632d 100644 --- a/SCrawler/API/Instagram/UserData.vb +++ b/SCrawler/API/Instagram/UserData.vb @@ -12,18 +12,20 @@ Imports PersonalUtilities.Functions.RegularExpressions Imports PersonalUtilities.Tools.WEB Imports PersonalUtilities.Tools.WebDocuments.JSON Imports SCrawler.API.Base -Imports System.Threading Imports System.Net +Imports System.Threading Imports System.Reflection Imports UTypes = SCrawler.API.Base.UserMedia.Types Namespace API.Instagram Friend Class UserData : Inherits UserDataBase - Private Const MaxPostsCount As Integer = 200 +#Region "XML Names" Private Const Name_LastCursor As String = "LastCursor" Private Const Name_FirstLoadingDone As String = "FirstLoadingDone" Private Const Name_GetStories As String = "GetStories" Private Const Name_GetTagged As String = "GetTaggedData" Private Const Name_TaggedChecked As String = "TaggedChecked" +#End Region +#Region "Declarations" Private ReadOnly Property MySiteSettings As SiteSettings Get Return DirectCast(HOST.Source, SiteSettings) @@ -34,6 +36,8 @@ Namespace API.Instagram Private FirstLoadingDone As Boolean = False Friend Property GetStories As Boolean Friend Property GetTaggedData As Boolean +#End Region +#Region "Exchange options" Friend Overrides Function ExchangeOptionsGet() As Object Return New EditorExchangeOptions(HOST.Source) With {.GetStories = GetStories, .GetTagged = GetTaggedData} End Function @@ -45,6 +49,8 @@ Namespace API.Instagram End With End If End Sub +#End Region +#Region "Initializer, loader" Friend Sub New() End Sub Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) @@ -62,7 +68,13 @@ Namespace API.Instagram Container.Add(Name_TaggedChecked, TaggedChecked.BoolToInteger) End If End Sub +#End Region #Region "Download data" + Private Class ExitException : Inherits Exception + Friend Sub New(ByRef CompleteArg As Boolean) + CompleteArg = True + End Sub + End Class Protected Overrides Sub DownloadDataF(ByVal Token As CancellationToken) Try _InstaHash = String.Empty @@ -80,7 +92,7 @@ Namespace API.Instagram If FirstLoadingDone Then LastCursor = String.Empty If IsSavedPosts Then DownloadPosts(Token) - ElseIf MySiteSettings.StoriesAndTaggedReady Then + ElseIf MySiteSettings.BaseAuthExists Then DownloadedTags = 0 If GetStories Then DownloadData(String.Empty, Sections.Stories, Token) If GetTaggedData Then DownloadData(String.Empty, Sections.Tagged, Token) @@ -100,6 +112,7 @@ Namespace API.Instagram Private Const StoriesFolder As String = "Stories" Private Const TaggedFolder As String = "Tagged" #Region "429 bypass" + Private Const MaxPostsCount As Integer = 200 Friend Property RequestsCount As Integer = 0 Friend Enum WNM As Integer Notify = 0 @@ -247,7 +260,6 @@ Namespace API.Instagram 'Check environment If Cursor.IsEmptyString And _InstaHash.IsEmptyString Then _ _InstaHash = CStr(If(IsSavedPosts, MySiteSettings.HashSavedPosts, MySiteSettings.Hash).Value) - AuthNullException.ThrowIfNull(Section, IsSavedPosts, MySiteSettings) If ID.IsEmptyString Then GetUserId() If ID.IsEmptyString Then Throw New ArgumentException("User ID is not detected", "ID") @@ -351,9 +363,6 @@ Namespace API.Instagram End If _DownloadComplete = True If HasNextPage And Not EndCursor.IsEmptyString Then DownloadData(EndCursor, Section, Token) - Catch iane As AuthNullException - ErrorsDescriber.Execute(EDP.SendInLog, iane) - Throw New ExitException(_DownloadComplete) Catch eex As ExitException Throw eex Catch oex As OperationCanceledException When Token.IsCancellationRequested @@ -433,6 +442,9 @@ Namespace API.Instagram ProcessException(DoEx, Token, $"downloading saved posts error [{URL}]") End Try End Sub + Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) + End Sub + #End Region #Region "Obtain Media" Private Sub ObtainMedia(ByVal node As EContainer, ByVal PostID As String, ByVal PostDate As String, ByVal SpecFolder As String) @@ -630,11 +642,12 @@ Namespace API.Instagram End Try End Function #End Region - Protected Overrides Sub ReparseVideo(ByVal Token As CancellationToken) - End Sub +#Region "Download content" Protected Overrides Sub DownloadContent(ByVal Token As CancellationToken) DownloadContentDefault(Token) End Sub +#End Region +#Region "Exceptions" ''' '''
''' 1 - continue @@ -647,8 +660,7 @@ Namespace API.Instagram UserExists = False ElseIf Responser.StatusCode = HttpStatusCode.BadRequest Then HasError = True - MyMainLOG = $"Instagram credentials have expired: {ToString()} [{s}]" - MySiteSettings.HashUpdateRequired.Value = True + MyMainLOG = $"Instagram credentials have expired [{CInt(Responser.StatusCode)}]: {ToString()} [{s}]" ElseIf Responser.StatusCode = HttpStatusCode.Forbidden And s = Sections.Tagged Then Return 3 ElseIf Responser.StatusCode = 429 Then @@ -661,13 +673,14 @@ Namespace API.Instagram MyMainLOG = $"Number of requests before error 429: {RequestsCount}" Return 1 Else - MySiteSettings.HashUpdateRequired.Value = True - MyMainLOG = $"Instagram hash requested: {ToString()} [{s}]" + MyMainLOG = $"Instagram hash requested [{CInt(Responser.StatusCode)}]: {ToString()} [{s}]" If Not FromPE Then LogError(ex, Message) : HasError = True Return 0 End If Return 2 End Function +#End Region +#Region "Create media" Private Shared Function MediaFromData(ByVal t As UTypes, ByVal _URL As String, ByVal PostID As String, ByVal PostDate As String, Optional ByVal SpecialFolder As String = Nothing) As UserMedia _URL = LinkFormatterSecure(RegexReplace(_URL.Replace("\", String.Empty), LinkPattern)) @@ -677,6 +690,8 @@ Namespace API.Instagram m.SpecialFolder = SpecialFolder Return m End Function +#End Region +#Region "Standalone downloader" Friend Shared Function GetVideoInfo(ByVal URL As String, ByVal r As Response, ByVal _Settings As SiteSettings) As IEnumerable(Of UserMedia) Try If Not URL.IsEmptyString AndAlso URL.Contains("instagram.com") Then @@ -697,9 +712,12 @@ Namespace API.Instagram Return ErrorsDescriber.Execute(EDP.ShowMainMsg + EDP.SendInLog, ex, "Instagram standalone downloader: fetch media error") End Try End Function +#End Region +#Region "IDisposable Support" Protected Overrides Sub Dispose(ByVal disposing As Boolean) If Not disposedValue And disposing Then _SavedPostsIDs.Clear() MyBase.Dispose(disposing) End Sub +#End Region End Class End Namespace \ No newline at end of file diff --git a/SCrawler/API/Reddit/Channel.vb b/SCrawler/API/Reddit/Channel.vb index 3741b27..968e111 100644 --- a/SCrawler/API/Reddit/Channel.vb +++ b/SCrawler/API/Reddit/Channel.vb @@ -44,10 +44,12 @@ Namespace API.Reddit Return ListAddList(Nothing, Posts).ListAddList(PostsLatest).ListSort End Get End Property - Private ReadOnly Property Source As IEnumerable(Of UserPost) Implements IRangeSwitcherContainer(Of UserPost).Source + Private Property Source As IEnumerable(Of UserPost) Implements IRangeSwitcherContainer(Of UserPost).Source Get Return Posts End Get + Set(ByVal s As IEnumerable(Of UserPost)) + End Set End Property Friend Property LatestParsedDate As Date? = Nothing Private _Downloading As Boolean = False diff --git a/SCrawler/API/Reddit/RedditViewSettingsForm.vb b/SCrawler/API/Reddit/RedditViewSettingsForm.vb index ee1c689..48c7cb6 100644 --- a/SCrawler/API/Reddit/RedditViewSettingsForm.vb +++ b/SCrawler/API/Reddit/RedditViewSettingsForm.vb @@ -12,12 +12,12 @@ Imports CView = SCrawler.API.Reddit.IRedditView.View Imports CPeriod = SCrawler.API.Reddit.IRedditView.Period Namespace API.Reddit Friend Class RedditViewSettingsForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Private ReadOnly Property MyOptions As IRedditView Friend Sub New(ByRef opt As IRedditView) InitializeComponent() MyOptions = opt - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub Private Sub ChannelSettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load Try diff --git a/SCrawler/API/Reddit/UserData.vb b/SCrawler/API/Reddit/UserData.vb index 43a30bd..4ef07ba 100644 --- a/SCrawler/API/Reddit/UserData.vb +++ b/SCrawler/API/Reddit/UserData.vb @@ -664,6 +664,7 @@ Namespace API.Reddit f = SFile.Indexed_IndexFile(f,,, EDP.ReturnValue) End If End If + If f.Extension = "webp" And Settings.DownloadNativeImageFormat Then f.Extension = "jpg" f.Path = MyDir Try If (v.Type = UTypes.Video Or v.Type = UTypes.m3u8 Or (ImgurUrls.Count > 0 AndAlso f.Extension = "mp4")) And @@ -728,9 +729,10 @@ Namespace API.Reddit ElseIf Responser.StatusCode = HttpStatusCode.Forbidden Then UserSuspended = True ElseIf Responser.StatusCode = HttpStatusCode.BadGateway Or - Responser.StatusCode = HttpStatusCode.ServiceUnavailable Or - Responser.StatusCode = HttpStatusCode.GatewayTimeout Then + Responser.StatusCode = HttpStatusCode.ServiceUnavailable Then MyMainLOG = $"[{CInt(Responser.StatusCode)}] Reddit is currently unavailable ({ToString()})" + ElseIf Responser.StatusCode = HttpStatusCode.GatewayTimeout Then + Return 1 Else If Not FromPE Then LogError(ex, Message) : HasError = True Return 0 diff --git a/SCrawler/API/Twitter/SiteSettings.vb b/SCrawler/API/Twitter/SiteSettings.vb index c89bdbb..427ea16 100644 --- a/SCrawler/API/Twitter/SiteSettings.vb +++ b/SCrawler/API/Twitter/SiteSettings.vb @@ -6,11 +6,11 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY +Imports SCrawler.API.Base Imports SCrawler.Plugin Imports SCrawler.Plugin.Attributes Imports PersonalUtilities.Tools Imports PersonalUtilities.Functions.RegularExpressions -Imports SCrawler.API.Base Namespace API.Twitter Friend Class SiteSettings : Inherits SiteSettingsBase diff --git a/SCrawler/API/Twitter/UserData.vb b/SCrawler/API/Twitter/UserData.vb index f3a0c09..8bc984d 100644 --- a/SCrawler/API/Twitter/UserData.vb +++ b/SCrawler/API/Twitter/UserData.vb @@ -176,7 +176,8 @@ Namespace API.Twitter If Orig.HasValue AndAlso l(0).Value < Orig.Value.Value Then Return P4K ElseIf l(0).Data.IsEmptyString Then - If LargeContained Then Return "large" Else Return P4K + Return P4K + 'If LargeContained Then Return "large" Else Return P4K Else Return l(0).Data End If diff --git a/SCrawler/API/UserDataBind.vb b/SCrawler/API/UserDataBind.vb index a0b2a7e..7acfed4 100644 --- a/SCrawler/API/UserDataBind.vb +++ b/SCrawler/API/UserDataBind.vb @@ -267,6 +267,7 @@ Namespace API End Property #End Region #End Region +#Region "Initializers" Friend Sub New() _IsCollection = True Collections = New List(Of IUserData) @@ -276,6 +277,8 @@ Namespace API Me.New CollectionName = _Name End Sub +#End Region +#Region "Load, Update" Friend Overrides Sub LoadUserInformation() If Count > 0 Then Collections.ForEach(Sub(c) c.LoadUserInformation()) End Sub @@ -287,6 +290,8 @@ Namespace API End Sub Protected Overrides Sub LoadUserInformation_OptionalFields(ByRef Container As XmlFile, ByVal Loading As Boolean) End Sub +#End Region +#Region "Download" Friend Overrides Property DownloadTopCount As Integer? Get If Count > 0 Then @@ -312,8 +317,10 @@ Namespace API Return 0 End Function Private Sub User_OnUserUpdated(ByVal User As IUserData) - RaiseEvent_OnUserUpdated() + OnUserUpdated() End Sub +#End Region +#Region "Open site, folder" Friend Overrides Sub OpenSite(Optional ByVal e As ErrorsDescriber = Nothing) If Not e.Exists Then e = New ErrorsDescriber(EDP.SendInLog) If Count > 0 Then Collections.ForEach(Sub(c) c.OpenSite(e)) @@ -324,6 +331,7 @@ Namespace API Catch ex As Exception End Try End Sub +#End Region #Region "ICollection Support" Default Friend ReadOnly Property Item(ByVal Index As Integer) As IUserData Implements IMyEnumerator(Of IUserData).MyEnumeratorObject Get @@ -353,7 +361,7 @@ Namespace API End If ImageHandler(_Item, False) AddRemoveBttDeleteHandler(.Self, True) - AddHandler .Self.OnUserUpdated, AddressOf User_OnUserUpdated + AddHandler .Self.UserUpdated, AddressOf User_OnUserUpdated End With Else Throw New InvalidOperationException("User data was not moved to the collection folder") @@ -367,7 +375,7 @@ Namespace API With Collections.Last If _CollectionName.IsEmptyString Then _CollectionName = .CollectionName AddRemoveBttDeleteHandler(.Self, True) - AddHandler .OnUserUpdated, AddressOf User_OnUserUpdated + AddHandler .UserUpdated, AddressOf User_OnUserUpdated End With Else Collections.RemoveAt(Count - 1) diff --git a/SCrawler/Channels/ChannelViewForm.Designer.vb b/SCrawler/Channels/ChannelViewForm.Designer.vb index f2a31ba..bbf55c6 100644 --- a/SCrawler/Channels/ChannelViewForm.Designer.vb +++ b/SCrawler/Channels/ChannelViewForm.Designer.vb @@ -15,8 +15,6 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form Private Sub InitializeComponent() Me.components = New System.ComponentModel.Container() Dim SEP_1 As System.Windows.Forms.ToolStripSeparator - Dim SEP_2 As System.Windows.Forms.ToolStripSeparator - Dim SEP_3 As System.Windows.Forms.ToolStripSeparator Dim CONTEXT_SEP_1 As System.Windows.Forms.ToolStripSeparator Dim CONTEXT_SEP_2 As System.Windows.Forms.ToolStripSeparator Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(ChannelViewForm)) @@ -34,11 +32,9 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form Me.BTT_C_OPEN_POST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_C_OPEN_PICTURE = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_C_OPEN_FOLDER = New System.Windows.Forms.ToolStripMenuItem() - Me.BTT_C_ADD_TO_BLACKLIST = New System.Windows.Forms.ToolStripMenuItem() Me.BTT_C_REMOVE_FROM_SELECTED = New System.Windows.Forms.ToolStripMenuItem() + Me.BTT_C_ADD_TO_BLACKLIST = New System.Windows.Forms.ToolStripMenuItem() SEP_1 = New System.Windows.Forms.ToolStripSeparator() - SEP_2 = New System.Windows.Forms.ToolStripSeparator() - SEP_3 = New System.Windows.Forms.ToolStripSeparator() CONTEXT_SEP_1 = New System.Windows.Forms.ToolStripSeparator() CONTEXT_SEP_2 = New System.Windows.Forms.ToolStripSeparator() Me.ToolbarTOP.SuspendLayout() @@ -51,25 +47,20 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form SEP_1.Name = "SEP_1" SEP_1.Size = New System.Drawing.Size(6, 25) ' - 'SEP_2 - ' - SEP_2.Name = "SEP_2" - SEP_2.Size = New System.Drawing.Size(6, 25) - ' - 'SEP_3 - ' - SEP_3.Name = "SEP_3" - SEP_3.Size = New System.Drawing.Size(6, 25) - ' 'CONTEXT_SEP_1 ' CONTEXT_SEP_1.Name = "CONTEXT_SEP_1" CONTEXT_SEP_1.Size = New System.Drawing.Size(302, 6) ' + 'CONTEXT_SEP_2 + ' + CONTEXT_SEP_2.Name = "CONTEXT_SEP_2" + CONTEXT_SEP_2.Size = New System.Drawing.Size(302, 6) + ' 'ToolbarTOP ' Me.ToolbarTOP.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden - Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWNLOAD, Me.BTT_STOP, SEP_1, Me.BTT_ADD_USERS, SEP_2, SEP_3}) + Me.ToolbarTOP.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_DOWNLOAD, Me.BTT_STOP, SEP_1, Me.BTT_ADD_USERS}) Me.ToolbarTOP.Location = New System.Drawing.Point(0, 0) Me.ToolbarTOP.Name = "ToolbarTOP" Me.ToolbarTOP.Size = New System.Drawing.Size(744, 25) @@ -138,7 +129,7 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form ' Me.LCONTEXT.Items.AddRange(New System.Windows.Forms.ToolStripItem() {Me.BTT_C_OPEN_USER, Me.BTT_C_OPEN_POST, Me.BTT_C_OPEN_PICTURE, Me.BTT_C_OPEN_FOLDER, CONTEXT_SEP_1, Me.BTT_C_REMOVE_FROM_SELECTED, CONTEXT_SEP_2, Me.BTT_C_ADD_TO_BLACKLIST}) Me.LCONTEXT.Name = "LCONTEXT" - Me.LCONTEXT.Size = New System.Drawing.Size(306, 170) + Me.LCONTEXT.Size = New System.Drawing.Size(306, 148) ' 'BTT_C_OPEN_USER ' @@ -164,17 +155,6 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form Me.BTT_C_OPEN_FOLDER.Size = New System.Drawing.Size(305, 22) Me.BTT_C_OPEN_FOLDER.Text = "Open folder" ' - 'BTT_C_ADD_TO_BLACKLIST - ' - Me.BTT_C_ADD_TO_BLACKLIST.Name = "BTT_C_ADD_TO_BLACKLIST" - Me.BTT_C_ADD_TO_BLACKLIST.Size = New System.Drawing.Size(305, 22) - Me.BTT_C_ADD_TO_BLACKLIST.Text = "Add/Remove this user to/from the BlackList" - ' - 'CONTEXT_SEP_2 - ' - CONTEXT_SEP_2.Name = "CONTEXT_SEP_2" - CONTEXT_SEP_2.Size = New System.Drawing.Size(302, 6) - ' 'BTT_C_REMOVE_FROM_SELECTED ' Me.BTT_C_REMOVE_FROM_SELECTED.AutoToolTip = True @@ -183,6 +163,12 @@ Partial Friend Class ChannelViewForm : Inherits System.Windows.Forms.Form Me.BTT_C_REMOVE_FROM_SELECTED.Text = "Remove user from selected" Me.BTT_C_REMOVE_FROM_SELECTED.ToolTipText = "Remove this user from selected users if user was added to" ' + 'BTT_C_ADD_TO_BLACKLIST + ' + Me.BTT_C_ADD_TO_BLACKLIST.Name = "BTT_C_ADD_TO_BLACKLIST" + Me.BTT_C_ADD_TO_BLACKLIST.Size = New System.Drawing.Size(305, 22) + Me.BTT_C_ADD_TO_BLACKLIST.Text = "Add/Remove this user to/from the BlackList" + ' 'ChannelViewForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) diff --git a/SCrawler/Channels/ChannelViewForm.resx b/SCrawler/Channels/ChannelViewForm.resx index 0eaaeec..814e7af 100644 --- a/SCrawler/Channels/ChannelViewForm.resx +++ b/SCrawler/Channels/ChannelViewForm.resx @@ -120,15 +120,12 @@ False - - False - - - False - False + + False + 241, 17 @@ -141,9 +138,6 @@ 342, 17 - - False - diff --git a/SCrawler/Channels/ChannelViewForm.vb b/SCrawler/Channels/ChannelViewForm.vb index e3b568f..a59155e 100644 --- a/SCrawler/Channels/ChannelViewForm.vb +++ b/SCrawler/Channels/ChannelViewForm.vb @@ -16,8 +16,8 @@ Imports System.Threading Imports SCrawler.API.Base Imports SCrawler.API.Reddit Imports SCrawler.Plugin.Hosts -Imports CmbDefaultButtons = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons -Imports RButton = PersonalUtilities.Tools.RangeSwitcherButton.Types +Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons +Imports RButton = PersonalUtilities.Forms.Toolbars.RangeSwitcherToolbar.ControlItem Friend Class ChannelViewForm : Implements IChannelLimits Friend Event OnUsersAdded(ByVal StartIndex As Integer) Friend Event OnDownloadDone As NotificationEventHandler @@ -49,7 +49,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits End Structure #End Region #Region "Declarations" - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions #Region "Controls" Private WithEvents CMB_CHANNELS As ComboBoxExtended Private WithEvents CH_HIDE_EXISTS_USERS As CheckBox @@ -125,7 +125,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits Private ReadOnly HOST As SettingsHost Private ReadOnly PendingUsers As List(Of PendingUser) Private ReadOnly LNC As New ListAddParams(LAP.NotContainsOnly) - Private WithEvents MyRange As RangeSwitcher(Of UserPost) + Private WithEvents MyRange As RangeSwitcherToolbar(Of UserPost) Private ReadOnly SelectorExpression As Predicate(Of UserPost) = Function(ByVal Post As UserPost) As Boolean If Post.UserID.ToLower = "[deleted]" Or Settings.BlackList.Contains(Post.UserID) Then Return False @@ -141,7 +141,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits #Region "Initializer and form methods" Friend Sub New() InitializeComponent() - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions CProgress = New MyProgress(ToolbarBOTTOM, PR_CN, LBL_STATUS, "Downloading data") With {.PerformMod = 10, .DropCurrentProgressOnTotalChange = False} CProvider = New ANumbers With {.FormatOptions = ANumbers.Options.GroupIntegral} LimitProvider = New ADateTime("dd.MM.yyyy HH:mm") @@ -157,10 +157,10 @@ Friend Class ChannelViewForm : Implements IChannelLimits .ListMaxDropDownItems = 15, .CaptionPadding = New Padding(0, 3, 0, 0) } - CMB_CHANNELS.Buttons.AddRange({CmbDefaultButtons.Refresh, CmbDefaultButtons.Add, CmbDefaultButtons.Delete, - New ActionButton(CmbDefaultButtons.Up) With {.ToolTipText = "Previous item (F1)"}, - New ActionButton(CmbDefaultButtons.Down) With {.ToolTipText = "Next item (F4)"}, - CmbDefaultButtons.Edit, CmbDefaultButtons.Info}) + CMB_CHANNELS.Buttons.AddRange({ADB.Refresh, ADB.Add, ADB.Delete, + New ActionButton(ADB.Up) With {.ToolTipText = "Previous item (F1)"}, + New ActionButton(ADB.Down) With {.ToolTipText = "Next item (F4)"}, + ADB.Edit, ADB.Info}) TXT_LIMIT = New TextBoxExtended With { .CaptionText = "Limit", .Margin = New Padding(2), @@ -186,6 +186,16 @@ Friend Class ChannelViewForm : Implements IChannelLimits TT_MAIN.SetToolTip(CH_HIDE_EXISTS_USERS, "Hide users which already exists in collection") TT_MAIN.SetToolTip(OPT_LIMITS_COUNT, "Total posts count limit") TT_MAIN.SetToolTip(OPT_LIMITS_POST, "Looking limit till post(-s) (comma separated)") + MyRange = New RangeSwitcherToolbar(Of UserPost)(ToolbarTOP) + With MyRange + .Switcher = New RangeSwitcher(Of UserPost) With {.Selector = SelectorExpression} + .Buttons = {RButton.First, RButton.Previous, RButton.Label, RButton.Next, RButton.Last, RButton.Separator} + .AutoToolTip = True + .ButtonKey(RButton.Previous) = Keys.F2 + .ButtonKey(RButton.Next) = Keys.F3 + .LabelNumbersProvider = CProvider + .AddThisToolbar() + End With ToolbarTOP.Items.AddRange({CMB_CHANNELS.GetControlHost, New ToolStripSeparator, LBL_LIMITS, @@ -198,17 +208,6 @@ Friend Class ChannelViewForm : Implements IChannelLimits New ToolStripSeparator, New ToolStripControlHost(CH_HIDE_EXISTS_USERS), BTT_SHOW_STATS}) - MyRange = New RangeSwitcher(Of UserPost) With {.Selector = SelectorExpression} - With MyRange - .Limit = ImagesInRow * ImagesRows - .InsertButtons(ToolbarTOP,, 5) - .SetButtonKey(RButton.Previous, Keys.F2) - .SetButtonKey(RButton.Next, Keys.F3) - .BindForm(Me) - .LabelNumbersProvider = CProvider - .LabelShowAbsolutIndexes = False - .UpdateControls() - End With AddHandler Settings.ChannelsImagesColumns.OnValueChanged, AddressOf ImagesCountChanged AddHandler Settings.ChannelsImagesRows.OnValueChanged, AddressOf ImagesCountChanged End Sub @@ -344,8 +343,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits CH_HIDE_EXISTS_USERS.Enabled = False CMB_CHANNELS.Enabled(True) = False BTT_SHOW_STATS.Enabled = False - MyRange.EnableButton(RButton.Previous, False) - MyRange.EnableButton(RButton.Next, False) + MyRange.Enabled = False End If End Sub Dim c As Channel @@ -374,7 +372,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits End If If Not c Is Nothing Then SetLimitsByChannel(c) - MyRange.ChangeSource(c) + MyRange.Source = c End If Else MsgBoxE("No one channels detected", MsgBoxStyle.Exclamation) @@ -403,10 +401,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits CMB_CHANNELS.Enabled(True) = True BTT_SHOW_STATS.Enabled = True CMB_CHANNELS_ActionOnCheckedChange(CMB_CHANNELS.Checked) - With MyRange - .EnableButton(RButton.Previous, .Count > 0 AndAlso .CurrentIndex > 0) - .EnableButton(RButton.Next, .Count > 0 AndAlso .CurrentIndex < .Max) - End With + MyRange.Enabled = True + MyRange.UpdateControls() End If End Try End Sub @@ -573,14 +569,14 @@ Friend Class ChannelViewForm : Implements IChannelLimits Private Sub CMB_CHANNELS_ActionSelectedItemChanged(ByVal _Item As ListViewItem) Handles CMB_CHANNELS.ActionSelectedItemChanged SetLimitsByChannel() Dim c As Channel = GetCurrentChannel() - If Not c Is Nothing Then MyRange.ChangeSource(c, EDP.SendInLog) + If Not c Is Nothing Then MyRange.Source = c End Sub Private Sub CMB_CHANNELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles CMB_CHANNELS.ActionOnButtonClick Dim c As Channel Select Case Sender.DefaultButton - Case CmbDefaultButtons.Refresh : RefillChannels() - Case CmbDefaultButtons.Add : AddNewChannel() - Case CmbDefaultButtons.Delete + Case ADB.Refresh : RefillChannels() + Case ADB.Add : AddNewChannel() + Case ADB.Delete Try c = GetCurrentChannel() If Not c Is Nothing AndAlso MsgBoxE($"Do you really want to delete channel [{c}]?", MsgBoxStyle.Exclamation + MsgBoxStyle.YesNo) = 0 Then @@ -590,9 +586,9 @@ Friend Class ChannelViewForm : Implements IChannelLimits Catch ex As Exception ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to delete channel") End Try - Case CmbDefaultButtons.Up : ChangeComboIndex(-1) - Case CmbDefaultButtons.Down : ChangeComboIndex(1) - Case CmbDefaultButtons.Edit + Case ADB.Up : ChangeComboIndex(-1) + Case ADB.Down : ChangeComboIndex(1) + Case ADB.Edit Try c = GetCurrentChannel() If Not c Is Nothing Then @@ -604,7 +600,7 @@ Friend Class ChannelViewForm : Implements IChannelLimits Catch ex As Exception ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on trying to edit channel") End Try - Case CmbDefaultButtons.Info + Case ADB.Info Try c = GetCurrentChannel() If Not c Is Nothing Then MsgBoxE({c.GetChannelStats(True), "Channel statistics"}) @@ -621,8 +617,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits LBL_LIMIT_TEXT.Text = String.Empty ChangeComboIndex(0) Else - CMB_CHANNELS.Button(ActionButton.BTT_UP_NAME).Enabled = False - CMB_CHANNELS.Button(ActionButton.BTT_DOWN_NAME).Enabled = False + CMB_CHANNELS.Button(ADB.Up).Enabled = False + CMB_CHANNELS.Button(ADB.Down).Enabled = False SetLimitsByChannel() End If End Sub @@ -661,8 +657,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits _ComboUpEnabled = i > 0 And c > 0 _ComboDownEnabled = i < c And c > 0 End If - CMB_CHANNELS.Button(ActionButton.BTT_UP_NAME).Enabled = _ComboUpEnabled - CMB_CHANNELS.Button(ActionButton.BTT_DOWN_NAME).Enabled = _ComboDownEnabled + CMB_CHANNELS.Button(ADB.Up).Enabled = _ComboUpEnabled + CMB_CHANNELS.Button(ADB.Down).Enabled = _ComboDownEnabled Catch ex As Exception ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "ComboBox index changing") End Try @@ -799,10 +795,10 @@ Friend Class ChannelViewForm : Implements IChannelLimits #Region "MyRange" Private Sub ImagesCountChanged(ByVal Sender As Object, ByVal _Name As String, ByVal _Value As Object) AppendPendingUsers() - MyRange.Update(ImagesInRow * ImagesRows) - MyRange.GoTo(0, EDP.SendInLog) + MyRange.Limit = ImagesInRow * ImagesRows + MyRange.GoTo(0) End Sub - Private Sub MyRange_IndexChanged(ByVal Index As Integer) Handles MyRange.IndexChanged + Private Sub MyRange_IndexChanged(ByVal Sender As IRangeSwitcherProvider, ByVal Index As Integer) Handles MyRange.IndexChanged Try If MyDefs.Initializing Then Exit Sub AppendPendingUsers() @@ -832,8 +828,8 @@ Friend Class ChannelViewForm : Implements IChannelLimits ErrorsDescriber.Execute(EDP.LogMessageValue, ex) End Try End Sub - Private Sub MyRange_RangesChanged(ByVal Sender As RangeSwitcher(Of UserPost)) Handles MyRange.RangesChanged - If Sender.Count > 0 Then MyRange_IndexChanged(0) + Private Sub MyRange_RangesChanged(ByVal Sender As IRangeSwitcherProvider, ByVal Index As Integer) Handles MyRange.RangesChanged + If Sender.Count > 0 Then MyRange_IndexChanged(Nothing, 0) End Sub #End Region End Class \ No newline at end of file diff --git a/SCrawler/Channels/ChannelsStatsForm.Designer.vb b/SCrawler/Channels/ChannelsStatsForm.Designer.vb index 22fa9a2..5293d85 100644 --- a/SCrawler/Channels/ChannelsStatsForm.Designer.vb +++ b/SCrawler/Channels/ChannelsStatsForm.Designer.vb @@ -55,15 +55,12 @@ Partial Friend Class ChannelsStatsForm : Inherits System.Windows.Forms.Form 'CMB_CHANNELS ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_COMBOBOX_ARROW" - ActionButton1.Visible = False + ActionButton1.Name = "Clear" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_CLEAR" + ActionButton2.Name = "Delete" ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 2 - ActionButton3.Name = "BTT_DELETE" + ActionButton3.Name = "ArrowDown" + ActionButton3.Visible = False Me.CMB_CHANNELS.Buttons.Add(ActionButton1) Me.CMB_CHANNELS.Buttons.Add(ActionButton2) Me.CMB_CHANNELS.Buttons.Add(ActionButton3) diff --git a/SCrawler/Channels/ChannelsStatsForm.resx b/SCrawler/Channels/ChannelsStatsForm.resx index 1e95d2e..f45e744 100644 --- a/SCrawler/Channels/ChannelsStatsForm.resx +++ b/SCrawler/Channels/ChannelsStatsForm.resx @@ -122,6 +122,43 @@ + + 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 @@ -209,43 +246,6 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A AAAASUVORK5CYII= - - - - - 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 diff --git a/SCrawler/Channels/ChannelsStatsForm.vb b/SCrawler/Channels/ChannelsStatsForm.vb index a5db274..7126fb0 100644 --- a/SCrawler/Channels/ChannelsStatsForm.vb +++ b/SCrawler/Channels/ChannelsStatsForm.vb @@ -11,11 +11,11 @@ Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Toolbars Friend Class ChannelsStatsForm : Implements IOkCancelDeleteToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Friend Property DeletedChannels As Integer = 0 Friend Sub New() InitializeComponent() - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub Private Sub ChannelsStatsForm_Load(sender As Object, e As EventArgs) Handles Me.Load Try diff --git a/SCrawler/Download/ActiveDownloadingProgress.Designer.vb b/SCrawler/Download/ActiveDownloadingProgress.Designer.vb index f4482f5..c82c577 100644 --- a/SCrawler/Download/ActiveDownloadingProgress.Designer.vb +++ b/SCrawler/Download/ActiveDownloadingProgress.Designer.vb @@ -36,8 +36,8 @@ Namespace DownloadObjects Me.TP_MAIN.Location = New System.Drawing.Point(0, 0) Me.TP_MAIN.Name = "TP_MAIN" Me.TP_MAIN.RowCount = 1 - Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 62.0!)) - Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 62.0!)) + Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!)) + Me.TP_MAIN.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 64.0!)) Me.TP_MAIN.Size = New System.Drawing.Size(434, 61) Me.TP_MAIN.TabIndex = 0 ' diff --git a/SCrawler/Download/AutoDownloader.vb b/SCrawler/Download/AutoDownloader.vb index a3c0480..a21875b 100644 --- a/SCrawler/Download/AutoDownloader.vb +++ b/SCrawler/Download/AutoDownloader.vb @@ -8,12 +8,13 @@ ' but WITHOUT ANY WARRANTY Imports System.Threading Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Functions.XML.Base Imports PersonalUtilities.Tools.Notifications Imports SCrawler.DownloadObjects.Groups Imports SCrawler.API Imports SCrawler.API.Base Namespace DownloadObjects - Friend Class AutoDownloader : Inherits GroupParameters + Friend Class AutoDownloader : Inherits GroupParameters : Implements IEContainerProvider Friend Event UserFind(ByVal Key As String, ByVal Activate As Boolean) Friend Enum Modes As Integer None = 0 @@ -31,6 +32,7 @@ Namespace DownloadObjects Private ReadOnly UserKeys As List(Of NotifiedUser) Private Class NotifiedUser : Implements IDisposable Private ReadOnly Property User As IUserData + Friend ReadOnly Property IUserDataKey As String Private ReadOnly Property Key As String Private ReadOnly Property KeyFolder As String Private ReadOnly Property KeySite As String @@ -49,6 +51,7 @@ Namespace DownloadObjects Friend Sub New(ByVal _Key As String, ByRef _User As IUserData) Me.New(_Key) User = _User + IUserDataKey = _User.Key End Sub Public Shared Widening Operator CType(ByVal Key As String) As NotifiedUser Return New NotifiedUser(Key) @@ -138,10 +141,12 @@ Namespace DownloadObjects Private Const Name_Groups As String = "Groups" Private Const Name_Labels As String = "Labels" Private Const Name_Timer As String = "Timer" + Private Const Name_StartupDelay As String = "StartupDelay" Private Const Name_LastDownloadDate As String = "LastDownloadDate" Private Const Name_ShowNotifications As String = "Notify" #End Region #Region "Declarations" + Friend Property Source As Scheduler Private _Mode As Modes = Modes.None Friend Property Mode As Modes Get @@ -154,36 +159,99 @@ Namespace DownloadObjects End Property Friend ReadOnly Property Groups As List(Of String) Friend Property Timer As Integer = DefaultTimer + Friend Property StartupDelay As Integer = 0 Friend Property ShowNotifications As Boolean = True - Friend Property LastDownloadDate As Date = Now.AddYears(-1) +#Region "Date" + Private ReadOnly LastDownloadDateXML As Date? = Nothing + Private _LastDownloadDate As Date = Now.AddYears(-1) + Private _LastDownloadDateChanged As Boolean = False + Friend Property LastDownloadDate As Date + Get + Return _LastDownloadDate + End Get + Set(ByVal d As Date) + _LastDownloadDate = d + If Not Initialization Then _LastDownloadDateChanged = True + End Set + End Property Private ReadOnly DateProvider As New ADateTime(ADateTime.Formats.BaseDateTime) + Private Function GetLastDateString() As String + If LastDownloadDateXML.HasValue Or _LastDownloadDateChanged Then + Return LastDownloadDate.ToStringDate(ADateTime.Formats.BaseDateTime) + Else + Return "never" + End If + End Function + Private Function GetNextDateString() As String + If _LastDownloadDateChanged Then + Return LastDownloadDate.AddMinutes(Timer).ToStringDate(ADateTime.Formats.BaseDateTime) + Else + Return _StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime) + End If + End Function +#End Region Friend ReadOnly Property Information As String Get - Return $"Last download date: {LastDownloadDate.ToStringDate(ADateTime.Formats.BaseDateTime)} " & - $"({IIf(Working, "working", "stopped")}{IIf(Working And Pause, ", paused", String.Empty)})" + Return $"Last download date: {GetLastDateString()} ({GetWorkingState()})" End Get End Property + Private Function GetWorkingState() As String + Dim OutStr$ + If Working Then + If StartupDelay > 0 And _StartTime.AddMinutes(StartupDelay) > Now Then + OutStr = $"delayed until {_StartTime.AddMinutes(StartupDelay).ToStringDate(ADateTime.Formats.BaseDateTime)}" + ElseIf _StopRequested Then + OutStr = "stopping" + Else + OutStr = "working" + End If + If Pause Then OutStr &= ", paused" + Else + OutStr = "stopped" + End If + Return OutStr + End Function + Public Overrides Function ToString() As String + Return $"{Name} ({GetWorkingState()}): last download date: {GetLastDateString()}; next run: {GetNextDateString()}" + End Function Private File As SFile = $"Settings\AutoDownload.xml" Private AThread As Thread #End Region #Region "Initializer" - Friend Sub New() + Private ReadOnly Initialization As Boolean = True + Private _IsNewPlan As Boolean = False + Friend ReadOnly Property IsNewPlan As Boolean + Get + Return _IsNewPlan + End Get + End Property + Friend Sub New(Optional ByVal IsNewPlan As Boolean = False) Groups = New List(Of String) UserKeys = New List(Of NotifiedUser) - If File.Exists Then - Using x As New XmlFile(File) - Mode = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None) - Groups.ListAddList(x.Value(Name_Groups).StringToList(Of String)("|"), LAP.NotContainsOnly) - Labels.ListAddList(x.Value(Name_Labels).StringToList(Of String)("|"), LAP.NotContainsOnly) - Temporary = x.Value(Name_Temporary).FromXML(Of Integer)(CheckState.Indeterminate) - Favorite = x.Value(Name_Favorite).FromXML(Of Integer)(CheckState.Indeterminate) - ReadyForDownload = x.Value(Name_ReadyForDownload).FromXML(Of Boolean)(True) - ReadyForDownloadIgnore = x.Value(Name_ReadyForDownloadIgnore).FromXML(Of Boolean)(False) - Timer = x.Value(Name_Timer).FromXML(Of Integer)(DefaultTimer) - ShowNotifications = x.Value(Name_ShowNotifications).FromXML(Of Boolean)(True) - LastDownloadDate = AConvert(Of Date)(x.Value(Name_LastDownloadDate), DateProvider, Now.AddYears(-1)) - End Using + _IsNewPlan = IsNewPlan + End Sub + Friend Sub New(ByVal x As EContainer) + Me.New + Name = x.Value(Name_Name).FromXML(Of String)("Default") + Mode = x.Value(Name_Mode).FromXML(Of Integer)(Modes.None) + Groups.ListAddList(x.Value(Name_Groups).StringToList(Of String)("|"), LAP.NotContainsOnly) + Labels.ListAddList(x.Value(Name_Labels).StringToList(Of String)("|"), LAP.NotContainsOnly) + Temporary = x.Value(Name_Temporary).FromXML(Of Integer)(CheckState.Indeterminate) + Favorite = x.Value(Name_Favorite).FromXML(Of Integer)(CheckState.Indeterminate) + ReadyForDownload = x.Value(Name_ReadyForDownload).FromXML(Of Boolean)(True) + ReadyForDownloadIgnore = x.Value(Name_ReadyForDownloadIgnore).FromXML(Of Boolean)(False) + Timer = x.Value(Name_Timer).FromXML(Of Integer)(DefaultTimer) + If Timer <= 0 Then Timer = DefaultTimer + StartupDelay = x.Value(Name_StartupDelay).FromXML(Of Integer)(0) + If StartupDelay < 0 Then StartupDelay = 0 + ShowNotifications = x.Value(Name_ShowNotifications).FromXML(Of Boolean)(True) + LastDownloadDateXML = AConvert(Of Date)(x.Value(Name_LastDownloadDate), DateProvider, Nothing) + If LastDownloadDateXML.HasValue Then + LastDownloadDate = LastDownloadDateXML.Value + Else + LastDownloadDate = Now.AddYears(-1) End If + Initialization = False End Sub #End Region #Region "Groups Support" @@ -202,33 +270,37 @@ Namespace DownloadObjects #End Region #Region "Update" Friend Sub Update() - Try - Using x As New XmlFile With {.Name = "Settings"} - x.Add(Name_Mode, CInt(Mode)) - x.Add(Name_Groups, Groups.ListToString("|")) - x.Add(Name_Labels, Labels.ListToString("|")) - x.Add(Name_Temporary, CInt(Temporary)) - x.Add(Name_Favorite, CInt(Favorite)) - x.Add(Name_ReadyForDownload, ReadyForDownload.BoolToInteger) - x.Add(Name_ReadyForDownloadIgnore, ReadyForDownloadIgnore.BoolToInteger) - x.Add(Name_Timer, Timer) - x.Add(Name_ShowNotifications, ShowNotifications.BoolToInteger) - x.Add(Name_LastDownloadDate, CStr(AConvert(Of String)(LastDownloadDate, DateProvider, String.Empty))) - x.Save(File) - End Using - Catch ex As Exception - ErrorsDescriber.Execute(EDP.SendInLog, ex, "[AutoDownloader.Update]") - End Try + If Not Source Is Nothing Then Source.Update() End Sub + Private Function ToEContainer(Optional ByVal e As ErrorsDescriber = Nothing) As EContainer Implements IEContainerProvider.ToEContainer + Return New EContainer(Scheduler.Name_Plan, String.Empty) From { + New EContainer(Name_Name, Name), + New EContainer(Name_Mode, CInt(Mode)), + New EContainer(Name_Groups, Groups.ListToString("|")), + New EContainer(Name_Labels, Labels.ListToString("|")), + New EContainer(Name_Temporary, CInt(Temporary)), + New EContainer(Name_Favorite, CInt(Favorite)), + New EContainer(Name_ReadyForDownload, ReadyForDownload.BoolToInteger), + New EContainer(Name_ReadyForDownloadIgnore, ReadyForDownloadIgnore.BoolToInteger), + New EContainer(Name_Timer, Timer), + New EContainer(Name_StartupDelay, StartupDelay), + New EContainer(Name_ShowNotifications, ShowNotifications.BoolToInteger), + New EContainer(Name_LastDownloadDate, CStr(AConvert(Of String)(If(LastDownloadDateXML.HasValue Or _LastDownloadDateChanged, + CObj(LastDownloadDate), Nothing), DateProvider, String.Empty))) + } + End Function #End Region #Region "Execution" - Private ReadOnly Property Working As Boolean + Friend ReadOnly Property Working As Boolean Get Return If(AThread?.IsAlive, False) End Get End Property - Friend Sub Start() - If Not If(AThread?.IsAlive, False) And Not Mode = Modes.None Then + Private _StartTime As Date = Now + Friend Sub Start(ByVal Init As Boolean) + If Init Then _StartTime = Now + _IsNewPlan = False + If Not Working And Not Mode = Modes.None Then AThread = New Thread(New ThreadStart(AddressOf Checker)) AThread.SetApartmentState(ApartmentState.MTA) AThread.Start() @@ -239,10 +311,18 @@ Namespace DownloadObjects Friend Sub [Stop]() If Working Then _StopRequested = True End Sub + Friend Sub Skip() + If LastDownloadDate.AddMinutes(Timer) <= Now Then + LastDownloadDate = Now.AddMinutes(Timer) + Else + LastDownloadDate = LastDownloadDate.AddMinutes(Timer) + End If + End Sub Private Sub Checker() Try - While Not _StopRequested Or Downloader.Working - If LastDownloadDate.AddMinutes(Timer) < Now And Not Downloader.Working And Not Pause And Not _StopRequested Then Download() + While (Not _StopRequested Or Downloader.Working) And Not Mode = Modes.None + If LastDownloadDate.AddMinutes(Timer) < Now And _StartTime.AddMinutes(StartupDelay) < Now And + Not Downloader.Working And Not Pause And Not _StopRequested And Not Mode = Modes.None Then Download() Thread.Sleep(500) End While Catch ex As Exception @@ -251,7 +331,14 @@ Namespace DownloadObjects _StopRequested = False End Try End Sub + Private _Downloading As Boolean = False + Friend ReadOnly Property Downloading As Boolean + Get + Return _Downloading + End Get + End Property Private Sub Download() + _Downloading = True Dim Keys As New List(Of String) Try Dim users As New List(Of IUserData) @@ -299,7 +386,6 @@ Namespace DownloadObjects .AutoDownloaderWorking = True If .Downloaded.Count > 0 Then .Downloaded.RemoveAll(Function(u) Keys.Contains(u.Key)) : .InvokeDownloadsChangeEvent() .AddRange(users) - .DisableOpenForms = False While .Working Or .Count > 0 : notify.Invoke() : Thread.Sleep(200) : End While .AutoDownloaderWorking = False notify.Invoke @@ -311,21 +397,23 @@ Namespace DownloadObjects Keys.Clear() LastDownloadDate = Now Update() + _Downloading = False End Try End Sub Private Sub ShowNotification(ByVal u As IUserData) - Dim i% = UserKeys.IndexOf(u.Key) + Dim k$ = $"{Name}_{u.Key}" + Dim i% = UserKeys.IndexOf(k) If i >= 0 Then UserKeys(i).ShowNotification() Else - UserKeys.Add(New NotifiedUser(u.Key, TDownloader.GetUserFromMainCollection(u))) + UserKeys.Add(New NotifiedUser(k, TDownloader.GetUserFromMainCollection(u))) UserKeys.Last.ShowNotification() End If End Sub Friend Function NotificationClicked(ByVal Key As String) As Boolean Dim i% = UserKeys.IndexOf(Key) If i >= 0 Then - RaiseEvent UserFind(Key, UserKeys(i).Open(Key)) + RaiseEvent UserFind(UserKeys(i).IUserDataKey, UserKeys(i).Open(Key)) Return True Else Return False diff --git a/SCrawler/Download/AutoDownloaderEditorForm.Designer.vb b/SCrawler/Download/AutoDownloaderEditorForm.Designer.vb index de7e4c7..27fa31f 100644 --- a/SCrawler/Download/AutoDownloaderEditorForm.Designer.vb +++ b/SCrawler/Download/AutoDownloaderEditorForm.Designer.vb @@ -29,6 +29,7 @@ Namespace DownloadObjects Dim ActionButton2 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_MODE As System.Windows.Forms.TableLayoutPanel Dim ActionButton3 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton4 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TT_MAIN As System.Windows.Forms.ToolTip Me.DEF_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults() Me.TXT_GROUPS = New PersonalUtilities.Forms.Controls.TextBoxExtended() @@ -40,6 +41,7 @@ Namespace DownloadObjects Me.CH_NOTIFY = New System.Windows.Forms.CheckBox() Me.TXT_TIMER = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.LBL_LAST_TIME_UP = New System.Windows.Forms.Label() + Me.NUM_DELAY = New PersonalUtilities.Forms.Controls.TextBoxExtended() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() TP_MODE = New System.Windows.Forms.TableLayoutPanel() TT_MAIN = New System.Windows.Forms.ToolTip(Me.components) @@ -49,6 +51,7 @@ Namespace DownloadObjects CType(Me.TXT_GROUPS, System.ComponentModel.ISupportInitialize).BeginInit() TP_MODE.SuspendLayout() CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).BeginInit() + CType(Me.NUM_DELAY, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' 'CONTAINER_MAIN @@ -57,13 +60,13 @@ Namespace DownloadObjects 'CONTAINER_MAIN.ContentPanel ' CONTAINER_MAIN.ContentPanel.Controls.Add(Me.DEF_GROUP) - CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 242) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 301) CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill CONTAINER_MAIN.LeftToolStripPanelVisible = False CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) CONTAINER_MAIN.Name = "CONTAINER_MAIN" CONTAINER_MAIN.RightToolStripPanelVisible = False - CONTAINER_MAIN.Size = New System.Drawing.Size(476, 242) + CONTAINER_MAIN.Size = New System.Drawing.Size(476, 301) CONTAINER_MAIN.TabIndex = 0 CONTAINER_MAIN.TopToolStripPanelVisible = False ' @@ -72,44 +75,45 @@ Namespace DownloadObjects Me.DEF_GROUP.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] Me.DEF_GROUP.ColumnCount = 1 Me.DEF_GROUP.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - Me.DEF_GROUP.Controls.Add(Me.TXT_GROUPS, 0, 4) + Me.DEF_GROUP.Controls.Add(Me.TXT_GROUPS, 0, 5) Me.DEF_GROUP.Controls.Add(TP_MODE, 0, 0) - Me.DEF_GROUP.Controls.Add(Me.CH_NOTIFY, 0, 5) - Me.DEF_GROUP.Controls.Add(Me.TXT_TIMER, 0, 6) - Me.DEF_GROUP.Controls.Add(Me.LBL_LAST_TIME_UP, 0, 7) + Me.DEF_GROUP.Controls.Add(Me.CH_NOTIFY, 0, 6) + Me.DEF_GROUP.Controls.Add(Me.TXT_TIMER, 0, 7) + Me.DEF_GROUP.Controls.Add(Me.LBL_LAST_TIME_UP, 0, 9) + Me.DEF_GROUP.Controls.Add(Me.NUM_DELAY, 0, 8) Me.DEF_GROUP.Dock = System.Windows.Forms.DockStyle.Fill Me.DEF_GROUP.Location = New System.Drawing.Point(0, 0) Me.DEF_GROUP.Name = "DEF_GROUP" - Me.DEF_GROUP.RowCount = 9 + Me.DEF_GROUP.RowCount = 11 Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) + Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEF_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - Me.DEF_GROUP.Size = New System.Drawing.Size(476, 242) + Me.DEF_GROUP.Size = New System.Drawing.Size(476, 301) Me.DEF_GROUP.TabIndex = 0 ' 'TXT_GROUPS ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_EDIT" + ActionButton1.Name = "Edit" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_CLEAR" + ActionButton2.Name = "Clear" Me.TXT_GROUPS.Buttons.Add(ActionButton1) Me.TXT_GROUPS.Buttons.Add(ActionButton2) Me.TXT_GROUPS.CaptionText = "Groups" Me.TXT_GROUPS.CaptionWidth = 50.0R Me.TXT_GROUPS.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_GROUPS.Location = New System.Drawing.Point(4, 111) + Me.TXT_GROUPS.Location = New System.Drawing.Point(4, 140) Me.TXT_GROUPS.Name = "TXT_GROUPS" Me.TXT_GROUPS.Size = New System.Drawing.Size(468, 22) - Me.TXT_GROUPS.TabIndex = 4 + Me.TXT_GROUPS.TabIndex = 2 ' 'TP_MODE ' @@ -132,7 +136,7 @@ Namespace DownloadObjects TP_MODE.RowCount = 1 TP_MODE.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) TP_MODE.Size = New System.Drawing.Size(474, 25) - TP_MODE.TabIndex = 8 + TP_MODE.TabIndex = 1 ' 'OPT_ALL ' @@ -203,52 +207,71 @@ Namespace DownloadObjects ' Me.CH_NOTIFY.AutoSize = True Me.CH_NOTIFY.Dock = System.Windows.Forms.DockStyle.Fill - Me.CH_NOTIFY.Location = New System.Drawing.Point(4, 140) + Me.CH_NOTIFY.Location = New System.Drawing.Point(4, 169) Me.CH_NOTIFY.Name = "CH_NOTIFY" Me.CH_NOTIFY.Size = New System.Drawing.Size(468, 19) - Me.CH_NOTIFY.TabIndex = 12 + Me.CH_NOTIFY.TabIndex = 3 Me.CH_NOTIFY.Text = "Show notifications" Me.CH_NOTIFY.UseVisualStyleBackColor = True ' 'TXT_TIMER ' ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 0 - ActionButton3.Name = "BTT_REFRESH" + ActionButton3.Name = "Refresh" Me.TXT_TIMER.Buttons.Add(ActionButton3) Me.TXT_TIMER.CaptionText = "Timer" Me.TXT_TIMER.CaptionWidth = 50.0R Me.TXT_TIMER.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_TIMER.Location = New System.Drawing.Point(4, 166) + Me.TXT_TIMER.Location = New System.Drawing.Point(4, 195) Me.TXT_TIMER.Name = "TXT_TIMER" Me.TXT_TIMER.Size = New System.Drawing.Size(468, 22) - Me.TXT_TIMER.TabIndex = 16 + Me.TXT_TIMER.TabIndex = 4 ' 'LBL_LAST_TIME_UP ' Me.LBL_LAST_TIME_UP.AutoSize = True Me.LBL_LAST_TIME_UP.Dock = System.Windows.Forms.DockStyle.Fill Me.LBL_LAST_TIME_UP.Font = New System.Drawing.Font("Microsoft Sans Serif", 8.25!, System.Drawing.FontStyle.Italic, System.Drawing.GraphicsUnit.Point, CType(204, Byte)) - Me.LBL_LAST_TIME_UP.Location = New System.Drawing.Point(4, 192) + Me.LBL_LAST_TIME_UP.Location = New System.Drawing.Point(4, 250) Me.LBL_LAST_TIME_UP.Name = "LBL_LAST_TIME_UP" Me.LBL_LAST_TIME_UP.Size = New System.Drawing.Size(468, 25) - Me.LBL_LAST_TIME_UP.TabIndex = 20 + Me.LBL_LAST_TIME_UP.TabIndex = 6 Me.LBL_LAST_TIME_UP.Text = "Last download date: " Me.LBL_LAST_TIME_UP.TextAlign = System.Drawing.ContentAlignment.TopCenter ' + 'NUM_DELAY + ' + ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) + ActionButton4.Name = "Refresh" + Me.NUM_DELAY.Buttons.Add(ActionButton4) + Me.NUM_DELAY.CaptionText = "Delay" + Me.NUM_DELAY.CaptionToolTipEnabled = True + Me.NUM_DELAY.CaptionToolTipText = "Startup delay" + Me.NUM_DELAY.CaptionWidth = 50.0R + Me.NUM_DELAY.ClearTextByButtonClear = False + Me.NUM_DELAY.ControlMode = PersonalUtilities.Forms.Controls.TextBoxExtended.ControlModes.NumericUpDown + Me.NUM_DELAY.Dock = System.Windows.Forms.DockStyle.Fill + Me.NUM_DELAY.Location = New System.Drawing.Point(4, 224) + Me.NUM_DELAY.Name = "NUM_DELAY" + Me.NUM_DELAY.NumberMaximum = New Decimal(New Integer() {1440, 0, 0, 0}) + Me.NUM_DELAY.NumberUpDownAlign = System.Windows.Forms.LeftRightAlignment.Left + Me.NUM_DELAY.Size = New System.Drawing.Size(468, 22) + Me.NUM_DELAY.TabIndex = 5 + Me.NUM_DELAY.Text = "0" + ' 'AutoDownloaderEditorForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font - Me.ClientSize = New System.Drawing.Size(476, 242) + Me.ClientSize = New System.Drawing.Size(476, 301) Me.Controls.Add(CONTAINER_MAIN) Me.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) Me.KeyPreview = True Me.MaximizeBox = False - Me.MaximumSize = New System.Drawing.Size(492, 281) + Me.MaximumSize = New System.Drawing.Size(492, 340) Me.MinimizeBox = False - Me.MinimumSize = New System.Drawing.Size(492, 281) + Me.MinimumSize = New System.Drawing.Size(492, 340) Me.Name = "AutoDownloaderEditorForm" Me.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide Me.Text = "AutoDownloader settings" @@ -261,6 +284,7 @@ Namespace DownloadObjects TP_MODE.ResumeLayout(False) TP_MODE.PerformLayout() CType(Me.TXT_TIMER, System.ComponentModel.ISupportInitialize).EndInit() + CType(Me.NUM_DELAY, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) End Sub @@ -274,5 +298,6 @@ Namespace DownloadObjects Friend WithEvents TXT_TIMER As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents OPT_GROUP As RadioButton Private WithEvents LBL_LAST_TIME_UP As Label + Private WithEvents NUM_DELAY As PersonalUtilities.Forms.Controls.TextBoxExtended End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Download/AutoDownloaderEditorForm.resx b/SCrawler/Download/AutoDownloaderEditorForm.resx index 2a0eae1..2bd6ddd 100644 --- a/SCrawler/Download/AutoDownloaderEditorForm.resx +++ b/SCrawler/Download/AutoDownloaderEditorForm.resx @@ -210,6 +210,22 @@ HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74 qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 + JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAACOElE + QVQ4T2P4//8/QczOJyyqHpzfiE0OQwAZC8iqszAzs7CJ69o4BR768V/W2jcGXQ0KB4aFNS3dDQtnrbCb + ePCK48wTN1wXXXzge/jXf/clV55zC4hIIatF0cjIyMikElzc57z0wX+XHd/+2+//99/ywP//xlu//tdb + +eK/4Zp3/1WTOhYzARViNUAluKjTdf37/0ZTTn9TbdhwXblhwwW1/qOP1Ja9+K8w+95/6cm3/6v2Xvkv + qKjniGGAoIqRpW3/4e8S9uGdzFz82gwMDFxAzCxm4ZegtuLDf+VJ1/8rZM25IqLvnM/CximCYYCic1QN + v7x2JIwPwyrJ3XNUylddE9G2TWNmZOBDl4czmJiZMSRBmFdSyYyJgUEQmxwIYxWEYXZBCUls4sgYq6CA + prWNbtG8nXKeaVPR5XiVjSxEzf0yYXy4BBMLO6eQjoOXZvrkbbazrv53Xf/2v4CSbjBMXkhBl1/CMyNZ + qWnvGy5pNQ+YONwAfjXzAOupl/47LLr333L50/96q9/8l23YdES6cO5KuYqVW+R7Tj6SnfP0v4hryjyY + HhQDmFjYeHVKFp7WX/Xuv9Kq9/+Vd/z7r7rv/3+l7f//y676DEwDN/9L+BVvYkKLCTgDhNkkVUyVlr74 + qbbz73/VOTc/qsy89kWx+9h7qbQpJwS1bbOAscGGrB6EUTggLOqf16C55ft/HlnNAFZOXgVWdi4FRgYG + VnR1MIwhwMTCyqEQ37qEmZVDFF0OE/9nAACtFF4Ey6OP+wAAAABJRU5ErkJggg== diff --git a/SCrawler/Download/AutoDownloaderEditorForm.vb b/SCrawler/Download/AutoDownloaderEditorForm.vb index 4ee05fa..2ab4c45 100644 --- a/SCrawler/Download/AutoDownloaderEditorForm.vb +++ b/SCrawler/Download/AutoDownloaderEditorForm.vb @@ -12,15 +12,16 @@ Imports PersonalUtilities.Forms.Toolbars Imports DModes = SCrawler.DownloadObjects.AutoDownloader.Modes Namespace DownloadObjects Friend Class AutoDownloaderEditorForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Private ReadOnly MyGroups As List(Of String) - Friend Property IsControlForm As Boolean = False - Friend Sub New() + Private ReadOnly Property Plan As AutoDownloader + Friend Sub New(ByRef _Plan As AutoDownloader) InitializeComponent() - MyDefs = New DefaultFormProps - MyGroups.ListAddList(Settings.Automation.Groups, LAP.NotContainsOnly) + Plan = _Plan + MyDefs = New DefaultFormOptions + MyGroups.ListAddList(Plan.Groups, LAP.NotContainsOnly) End Sub - Friend Class AutomationTimerChecker : Implements IFieldsCheckerProvider + Private Class AutomationTimerChecker : Implements IFieldsCheckerProvider Private Property ErrorMessage As String = "The timer value must be greater than 0" Implements IFieldsCheckerProvider.ErrorMessage Private Property Name As String Implements IFieldsCheckerProvider.Name Private Property TypeError As Boolean Implements IFieldsCheckerProvider.TypeError @@ -36,18 +37,11 @@ Namespace DownloadObjects Throw New NotImplementedException() End Function End Class - Private _Loaded As Boolean = False - Friend Shadows Sub Show() - MyBase.Show() - If Not _Loaded And IsControlForm Then AutoDownloaderEditorForm_Load(Nothing, EventArgs.Empty) - End Sub Private Sub AutoDownloaderEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load With MyDefs - If Not IsControlForm Then - .MyViewInitialize(Me, Settings.Design, True) - .AddOkCancelToolbar() - End If - With Settings.Automation + .MyViewInitialize(Me, Settings.Design, True) + .AddOkCancelToolbar() + With Plan Select Case .Mode Case DModes.None : OPT_DISABLED.Checked = True Case DModes.All : OPT_ALL.Checked = True @@ -56,30 +50,30 @@ Namespace DownloadObjects Case DModes.Groups : OPT_GROUP.Checked = True End Select ChangeEnabled() - DEF_GROUP.Set(Settings.Automation) + DEF_GROUP.Set(Plan) If MyGroups.Count > 0 Then TXT_GROUPS.Text = MyGroups.ListToString If Settings.Groups.Count = 0 Then TXT_GROUPS.Clear() : TXT_GROUPS.Enabled = False CH_NOTIFY.Checked = .ShowNotifications TXT_TIMER.Text = .Timer + NUM_DELAY.Value = .StartupDelay LBL_LAST_TIME_UP.Text = .Information End With - If Not IsControlForm Then - .MyFieldsChecker = New FieldsChecker - With DirectCast(.MyFieldsChecker, FieldsChecker) - .AddControl(Of Integer)(TXT_TIMER, TXT_TIMER.CaptionText,, New AutomationTimerChecker) - .EndLoaderOperations() - End With + .MyFieldsChecker = New FieldsChecker + With .MyFieldsCheckerE + .AddControl(Of String)(DEF_GROUP.TXT_NAME, DEF_GROUP.TXT_NAME.CaptionText,, + New Groups.GroupEditorForm.NameChecker(Plan.Name, Settings.Automation, "Plan")) + .AddControl(Of Integer)(TXT_TIMER, TXT_TIMER.CaptionText,, New AutomationTimerChecker) .EndLoaderOperations() - End If + End With + .EndLoaderOperations() End With - _Loaded = True End Sub Private Sub AutoDownloaderEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed MyGroups.Clear() End Sub - Friend Sub SaveSettings() Implements IOkCancelToolbar.OK + Private Sub OK() Implements IOkCancelToolbar.OK If If(MyDefs.MyFieldsChecker?.AllParamsOK, True) Then - With Settings.Automation + With Plan Select Case True Case OPT_DISABLED.Checked : .Mode = DModes.None Case OPT_ALL.Checked : .Mode = DModes.All @@ -87,13 +81,14 @@ Namespace DownloadObjects Case OPT_SPEC.Checked : .Mode = DModes.Specified Case OPT_GROUP.Checked : .Mode = DModes.Groups End Select - DEF_GROUP.Get(Settings.Automation) + DEF_GROUP.Get(Plan) .Groups.Clear() .Groups.ListAddList(MyGroups) .Timer = AConvert(Of Integer)(TXT_TIMER.Text, AutoDownloader.DefaultTimer) + .StartupDelay = NUM_DELAY.Value .Update() End With - If Not IsControlForm Then MyDefs.CloseForm() + MyDefs.CloseForm() End If End Sub Private Sub Cancel() Implements IOkCancelToolbar.Cancel @@ -128,7 +123,11 @@ Namespace DownloadObjects DEF_GROUP.Enabled = OPT_SPEC.Checked TXT_GROUPS.Enabled = OPT_GROUP.Checked TXT_TIMER.Enabled = Not OPT_DISABLED.Checked + NUM_DELAY.Enabled = Not OPT_DISABLED.Checked CH_NOTIFY.Enabled = Not OPT_DISABLED.Checked End Sub + Private Sub NUM_DELAY_ActionOnButtonClick(ByVal Sender As ActionButton) Handles NUM_DELAY.ActionOnButtonClick + If Sender.DefaultButton = ActionButton.DefaultButtons.Clear Then NUM_DELAY.Value = 0 + End Sub End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Download/DownloadedInfoForm.Designer.vb b/SCrawler/Download/DownloadedInfoForm.Designer.vb index 793cf83..056af62 100644 --- a/SCrawler/Download/DownloadedInfoForm.Designer.vb +++ b/SCrawler/Download/DownloadedInfoForm.Designer.vb @@ -152,10 +152,10 @@ Me.Controls.Add(Me.LIST_DOWN) Me.Controls.Add(Me.ToolbarBOTTOM) Me.Controls.Add(Me.ToolbarTOP) + Me.Icon = CType(resources.GetObject("$this.Icon"), System.Drawing.Icon) Me.KeyPreview = True Me.MinimumSize = New System.Drawing.Size(570, 450) Me.Name = "DownloadedInfoForm" - Me.ShowIcon = False Me.Text = "Downloaded items" Me.ToolbarTOP.ResumeLayout(False) Me.ToolbarTOP.PerformLayout() diff --git a/SCrawler/Download/DownloadedInfoForm.resx b/SCrawler/Download/DownloadedInfoForm.resx index 9e3ed28..50397e1 100644 --- a/SCrawler/Download/DownloadedInfoForm.resx +++ b/SCrawler/Download/DownloadedInfoForm.resx @@ -198,4 +198,507 @@ 133, 17 + + + AAABAAwAMDAQAAEABABoBgAAxgAAACAgEAABAAQA6AIAAC4HAAAYGBAAAQAEAOgBAAAWCgAAEBAQAAEA + BAAoAQAA/gsAADAwAAABAAgAqA4AACYNAAAgIAAAAQAIAKgIAADOGwAAGBgAAAEACADIBgAAdiQAABAQ + AAABAAgAaAUAAD4rAAAwMAAAAQAgAKglAACmMAAAICAAAAEAIACoEAAATlYAABgYAAABACAAiAkAAPZm + AAAQEAAAAQAgAGgEAAB+cAAAKAAAADAAAABgAAAAAQAEAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP// + /wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjsjgAAAAAAAAAAAA + AAAAAAAAAAAAAAAIbOh4AAAAAAAAAAAAAAAAAAAAAAAAAAAH5mfsgAAAAAAAAAAAAAAAAAAAAAAAAAB+ + xs54YAAAAAAAAAAAAAAAAAAAAAAAAAfsbmxo5wAAAAAAAAAAAAAAAAAAAAAAAIbObObOeMAAAAAAAAAA + AAAAAAAAAAAACG5+zmzsaOgAAAAAAAAAAAAAAAAAAAAABn7ObOZmbneAAAAAAAAAAAAAAAAAAAAAfs5s + 5+zs7I7AAAAAAAAAAAAAAAAAAAAH7Ofm7G7GbGiOAAAAAAAAAAAAAAAAAAB+fs7Ofs5+zmzngAAAAAAA + AAAAAAAAAAhn7Ojs5uzm7OZ4yAAAAAAAAAAAAAAAAAaOfm7Obsfsbs7OjnAAAAAAAAAAAAAAAH7Ojs7n + 7O7ObOZs54AAAAAAAAAAAAAABn6Ozuduzn5uznzmyOcAAAAAAAAAAAAAfn7I6M7s5+zn7Obs5oyAAAAA + AAAAAAAIZ+jujuzo7Obs5uxubOjnAAAAAAAAAAAG586M5+js7n7OfOfs5s54cAAAAAAAAABnzo7o5+zu + fs5+5uzmzmzowAAAAAAAAAdujn5+fu7Ozuzs7Ofs5+bI6AAAAAAAAHzn7OjOjI5+5+jufs5uzs5ueOAA + AAAAAG6M6O6O7n7Ofs7Ozo7Ofmzs53gAAAAAB+zo7IznyOzuzufufs6Ofo6Ofn4AAAAACEdsZ2Z87o5+ + js7O7O5cjHx8jIgAAAAAAAAAAAAAfOfs7Ojs6OfgAAAAAAAAAAAAAAAAAAAAbo7O6O7O7OfAAAAAAAAA + AAAAAAAAAAAAfsjm7Obo7s6AAAAAAAAAAAAAAAAAAAAAaO5+zo7OyO5wAAAAAAAAAAAAAAAAAAAAzn7O + js7n7sjAAAAAAAAAAAAAAAAAAAAAaM6Ozuzuzu5wAAAAAAAAAAAAAAAAAAAAbn7Obn5+jshgAAAAAAAA + AAAAAAAAAAAAbOjn7Ozs7O5wAAAAAAAAAAAAAAAAAAAAfnzn5+bn7n7AAAAAAAAAAAAAAAAAAAAAbOjs + 7OzuzshgAAAAAAAAAAAAAAAAAAAAaOyOfn7I5+5wAAAAAAAAAAAAAAAAAAAAbOfs7Ozm7OfAAAAAAAAA + AAAAAAAAAAAAbnzn5+bs5u5wAAAAAAAAAAAAAAAAAAAAfOfsjOx+zn7AAAAAAAAAAAAAAAAAAAAAbnzn + 5o7OfshgAAAAAAAAAAAAAAAAAAAAx+Z+zs5uzm5gAAAAAAAAAAAAAAAAAAAAbs7H5+fObsjAAAAAAAAA + AAAAAAAAAAAAZ2js585s7O5wAAAAAAAAAAAAAAAAAAAAjOyH5+jn53aAAAAAAAAAAAAAAAAAAAAACGZs + bHxsfGgAAAAAAAAAAAD///////8AAP///////wAA////////AAD///j///8AAP//8H///wAA///gP/// + AAD//+Af//8AAP//wB///wAA//+AD///AAD//wAH//8AAP/+AAP//wAA//4AAf//AAD//AAB//8AAP/4 + AAD//wAA//AAAH//AAD/4AAAP/8AAP/gAAAf/wAA/8AAAB//AAD/gAAAD/8AAP8AAAAH/wAA/gAAAAP/ + AAD+AAAAAf8AAPwAAAAB/wAA+AAAAAD/AADwAAAAAH8AAPAAAAAAPwAA4AAAAAA/AADgAAAAAD8AAP/8 + AAH//wAA//wAAf//AAD//AAB//8AAP/8AAH//wAA//wAAf//AAD//AAB//8AAP/8AAH//wAA//wAAf// + AAD//AAB//8AAP/8AAH//wAA//wAAf//AAD//AAB//8AAP/8AAH//wAA//wAAf//AAD//AAB//8AAP/8 + AAH//wAA//wAAf//AAD//AAB//8AAP/8AAH//wAA//4AA///AAAoAAAAIAAAAEAAAAABAAQAAAAAAAAC + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/ + AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA5+AAAAAAAAAAAAAAAAAA + BoyHAAAAAAAAAAAAAAAAAOfn7AAAAAAAAAAAAAAAAAjIzn6AAAAAAAAAAAAAAAAO5uxo7AAAAAAAAAAA + AAAAaM7ObI6AAAAAAAAAAAAADn5ubOboyAAAAAAAAAAAAH7Ozs5sbo4AAAAAAAAAAAjI5+fn7saM4AAA + AAAAAAAO7n7Ozsbs6OcAAAAAAAAAaH7O5+bn5s6MgAAAAAAABo7o5+zs7Ozm6OAAAAAAAH7I7Ozufn5u + zsfsAAAAAAjOjn6Ofs7s5+bsjnAAAAAG6Ozo7O7n5+zs5ujnAAAAaOyOjo587Ozo6I7IjIAAAGxmxsZ+ + 7o7uzsbG7O4AAAAAAAAM587OyOhgAAAAAAAAAAAABo7n5+7OYAAAAAAAAAAAAAzozuzujsAAAAAAAAAA + AAAGjufuzs5wAAAAAAAAAAAADOfOyOfowAAAAAAAAAAAAAaOfm7O7mAAAAAAAAAAAAAM7Ofs5sjAAAAA + AAAAAAAABn585+7oYAAAAAAAAAAAAAyM6Oxs58AAAAAAAAAAAAAG5+zm5+5gAAAAAAAAAAAABOx+fs7I + wAAAAAAAAAAAAAZ+Z8hs7kAAAAAAAAAAAAAMjOjm52fAAAAAAAAAAAAAAGbExsbOAAAAAAAA///////8 + f///+D////A////gH///4A///8AH//+AA///AAP//gAB//4AAP/8AAB/+AAAf/AAAD/gAAAf4AAAD8AA + AAfAAAAP/4AH//+AB///gAf//4AH//+AB///gAf//4AH//+AB///gAf//4AH//+AB///gAf//4AH///A + D/8oAAAAGAAAADAAAAABAAQAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA + AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAA + AAAABgAAAAAAAAAAAAAAeOAAAAAAAAAAAAAG7IcAAAAAAAAAAAB+fujgAAAAAAAAAAbs7OyHAAAAAAAA + AGjufm7oYAAAAAAABo7OzsfOhwAAAAAAaO5+5+7s6GAAAAAG5+zs7Ozn7PYAAABo6Ojo7n6IjojgAAAM + bGzs7OyOx+wAAAAAAAfo7o7nAAAAAAAAAAaM7OyGAAAAAAAAAAbufu6MAAAAAAAAAAd+zn6GAAAAAAAA + AAzn7OznAAAAAAAAAAaOzuiGAAAAAAAAAAbn587sAAAAAAAAAAZ87m6GAAAAAAAAAAzozs6MAAAAAAAA + AAaOh+eGAAAAAAAAAABsbGxgAAAAAAAAAAAAAAAAAAAAAP///wD/7/8A/8f/AP+D/wD/Af8A/gD/APwA + fwD4AD8A8AAfAOAADwDAAAcA4AAPAP4A/wD+AP8A/gD/AP4A/wD+AP8A/gD/AP4A/wD+AP8A/gD/AP4A + /wD/Af8A////ACgAAAAQAAAAIAAAAAEABAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACA + AAAAgIAAgAAAAIAAgACAgAAAgICAAMDAwAAAAP8AAP8AAAD//wD/AAAA/wD/AP//AAD///8AAAAABgAA + AAAAAABoYAAAAAAABo6MAAAAAABozshgAAAABo5uboYAAABo7OfOeGAABo5+fn6OhgB2xs7O6MfHgAAA + aOfIYAAAAABuzujgAAAAAGjn6MAAAAAAzs5+cAAAAABo5+jAAAAAAG7OyOAAAAAAaI6OcAAAAAAMbGYA + AAD+/wAA/H8AAPg/AADwHwAA4A8AAMAHAACAAwAAAAEAAPAfAADwHwAA8B8AAPAfAADwHwAA8B8AAPAf + AAD4PwAAKAAAADAAAABgAAAAAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAEAAAAAAACjaB0ApmsgAKlt + IwCrcCYArXMqALF1LACzeC4ArHYwALR6MQC4fTQAt385AMh1AADJdwQAy3gAAM17AADOfQEAy3oHAM5/ + CQDMfA0A0H4BAMt/GQC7gDcAvoI6ALmBPADRgAIA0oIEANSDBADVhQUA1ogGANaMBwDZiQYA3I0GANKE + CgDWhwkA0YIMANaMCwDZiggA2o0JANyOCQDbkgsA3pAKAN6UCwDekg0A3ZQNAM+EGgDRhhUA1YkSANiN + EgDajhcA2pISANqSHgDalh4A3ZgaAOGUCgDgkg0A4ZUOAOSWDgDhmA4A5ZgPAOicDgDklxAA45cVAOGY + EADlmRAA5ZwRAOSdFwDonRIA550YAOmfGwDpoBIA6qEUAO2iFADrpBQA7qUWAO6mGADvqBgA8KUXAPCm + GADxqRgA9KsZAPKsGgD0rBoA9a0cAPiuGgD1sBsA+bEbAPixHADOhycAzo0lAMqKKwDRjCIA0Y8lANSP + JgDTji0A05ImANiRIwDdnScA1JQpANmVKwDXmCoA25stAMGJNQDAhj0A0I84AM2VPwDTmTYA3JwyANKR + OQDSlDgA2Js6AOGeIADknS8A3qAxANyiPwDopCAA7qogAOKiLQDtqykA8asjAPOxJwD6syAA+LMkAPq1 + JwD2tSoA+rYsAPq4LgDiozEA6qUzAOepNQDpqTEA66wyAOmrNwDtqjUA6qw2AO2vNQDjpjoA6aw4AOir + PwDwrDgA67A3AO2xOQDssT8A8rIwAPazMwD2tzEA8bE2APq7NgDytDoA+Lc6APW5PAD5uToA+bw7APi7 + PQD5vD0A/L49APzAPgCxgEMAv4VAALaFSAC5h0sAvJZmALyacgC5mnYAxYlBAMOLRgDHi0QAyY1GAMaO + SgDJj0oAyZBEAMyQSgDPlEkAypFNAM6TTADNlE4A0pVHANebQwDUnUUA0JRNANaaSgDDkVUAzpZWAM2X + WwDOmVsAzZpdANGZVgDUmlcA0ppaANOcWwDQnF4A16BHANqiSADapUkA3adLAN2lTQDbo1QA1KFeANql + WwDgpkMA4KtOAO6sSwDxrUYA8rdAAPGxRQD1uUAA+r1AAPSySADirl0Ax5ljAMOYZgDFmWUAz51gAM+f + ZADBnG4AxJ1uANGeYgDQnmUA0aBjANalYwDVoWQA2KRgAN+sYwDbqWYA3aplAN2sZwDRo2sA1KdrANWl + bADZqmoA3q5qAMWhcgDNpHMAzKV1AMmmeQDUqXAA1Kp5ANuwcADhrWAA569jAOCvaQDismgA5LRoAOGy + bADitGwA+8BDALGchQCxnokAxa2OAMqwkQDPs5MA1LiXAN3AngDjwJYAAAAAAP///wAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + 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 + AAC/YQAAvGgNALllFwC5Zx8AtWUpAMJkAADFaAAAyGsAAMxuAgDOcQYA0nYJANR5DQDFdREAz34aANd8 + EADafxMA0IAGANSDBQDThAYA1YUFANiJBwDThg8A2YoIANqNCQDcjQoA25AKAN2QCgDekQ0A35UNAN2A + FgDXjxAA2Y4UAN6DGQDWjBsA3ZEQAN6UFgDdmBgA4JMKAOCSDQDhlQ4A5ZcPAOSZDgDghhsA44geAOSW + EADjmxEA5ZoQAOScEQDnnxQA6Z0SAOWcGgDpoBIA6aEUAO2iFADtpBYA5qAZAO+oGgDwphcA8acYAPGp + GAD0qxkA86waAPSsGgD1rhwA9rAbAPawHAD4sBoA+LEcAMyAIADXhSMA0IUnAN+NKgDRkScA2pYhAN2b + IwDcmyUA05MoANWWKQDali8A2ZksANucLQDcnS4A3Z0xAN2TOwDblT8A1po7ANKYPADVmj0A154+AOaO + JADjkCoA5ZIuAOqTKgDtkysA7ZQrAOiTLQDulSwA4pIxAOmWMQDrlzUA6J02AOOaOQDgnTwA6pw5APCa + NADynj0A36AvAN6hMADdoDgA2aE/AOSgIQDioSYA7KchAO2oJgDgoCkA6agrAPewIAD5tCIA+bQnAPOx + KAD5tigA+bcvAOOmMgDjpjQA5KU0AOepNQDnrD8A6Ko4AOyvOADprj8A86A/AO+zOgDysjAA8LE3APe4 + NgD7ujEA8rY7APCzPQDytj4A9Lg6APW6PQD7vDoA+b0+AMWARADPkEUA3ZlEANmbTQDPnF8A0phUAOqe + QgDdoEEA2aJGAN2kRADep0kA3aVOANuiUADdplQA4ahGAO2qRwDooEgA4alKAOOtTQDzoUAA869EAPap + TgDsskAA77JGAOewTgDusUoA6rBMAPC1QwD0ukUA9rxGAPm9QQDwskkA8rVNAPe+SAD1uk8A+L5IAPWp + UADyqlQA6rRRAO22UgDuuFQA47BbAPCyUQD0vFAA8r5WAPC2XAD4sV0AyZ5nAMSlfwDfr3MA2K19AOWt + YgDltmcA67NgAOm5YQDsu2oA77ptAPW+awDwvm0A+bhpAOizcQDiu34A7Lt9APS9cAD7wEIA+8FGAPnA + SAD4wk4A+MNZAPnEWgD6w2AA/ctkAMOnhQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAABta58AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbc2/a8oAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAKpvpabIawAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWcqgdHaa/awAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAG2JLR8dIM6tXgAAAAAAAAAAAAAAAAAAAAAAAAAAAABlsT0xIx8dLNJzngAAAAAA + AAAAAAAAAAAAAAAAAAAAUq58PDMxIyMdWdVr4gAAAAAAAAAAAAAAAAAAAAAAAJypj0REMzMxJSMdochr + AAAAAAAAAAAAAAAAAAAAAADLcN9KRURERDMxJSMjw69lAAAAAAAAAAAAAAAAAAAAAFDhuH9KSkQzRDMx + JSMq0o1fAAAAAAAAAAAAAAAAAAAY4Nu4gUdHQ0VEM0QlJSNU2XPJAAAAAAAAAAAAAAAAT8TcuNuSTUpK + R0REMzsxJSNd1WsAAAAAAAAAAAAAAJtw3bi425hNTUpKSkRERDMzMSOryGsAAAAAAAAAAADMUd2Vl7i4 + mIFNTU1KSkRERDMzMSXQr2wAAAAAAAAAABfBsJOXmLi4g01NTU1KSkRERDk5MS3ZdJ0AAAAAAAAMz7S0 + urrFxbiETYFNTU1KSo+xlbq6tMfTa9gAAAAAAJoGBgYGCQkL35FLTU2BTU1KthkZKys1NmSgAAAAAAAA + AAAAAAAAAAnfl0pLTU1NgU29FgAAAAAAAAAAAAAAAAAAAAAAAAAABt2VgkpNgU1NTdwVAAAAAAAAAAAA + AAAAAAAAAAAAAAAGxrGPSkpKTU2B2xQAAAAAAAAAAAAAAAAAAAAAAAAAAAbCi5BDREpLTU3cEwAAAAAA + AAAAAAAAAAAAAAAAAAAABMGIi3xAR0pLTdwTAAAAAAAAAAAAAAAAAAAAAAAAAAADsoWKjzlEQ0pL3BEA + AAAAAAAAAAAAAAAAAAAAAAAAAAOrhYWFOztEREq7EQAAAAAAAAAAAAAAAAAAAAAAAAAAA6tdXIV5OTtE + Q7YLAAAAAAAAAAAAAAAAAAAAAAAAAAABpVxcdn0nMztEtgkAAAAAAAAAAAAAAAAAAAAAAAAAAAGhWFpd + di8nMzu1CQAAAAAAAAAAAAAAAAAAAAAAAAAAAaVTWFxdViUnJ7EGAAAAAAAAAAAAAAAAAAAAAAAAAAAB + YFNYWFhcKSQnsAYAAAAAAAAAAAAAAAAAAAAAAAAAAA/XYWBjoaF3VFZWDQAAAAAAAAAAAAAAAAAAAAAA + AAAAAA8BAQEBAQEEBA4AAAAAAAAAAAAAAAD///////x////4P///8D///+Af///gD///wAf//4AD//8A + A//+AAH//gAA//wAAH/4AAB/8AAAP+AAAB/gAAAPwAAAB8AAAA//gAf//4AH//+AB///gAf//4AH//+A + B///gAf//4AH//+AB///gAf//4AH//+AB///gAf//8AP/ygAAAAYAAAAMAAAAAEACAAAAAAAQAIAAAAA + AAAAAAAAAAEAAAABAAAAAAAApWYWAKhpGQCqbBsAqm0dAKxuHgCucCEAsHMjALJ2JgC2eioAuH4uALyC + MgC9gzQAvoU1AN+YEwDklw8A5ZkQAOmdEgDooBIA6aEUAO2hFQDtpRYA8KYXAPGqFwDxpxgA8qoZAPSr + GgD0rRoA86wcAPauHAD3sBoA97AcAPmwGgD4sRwAwIY3AMGJOQDDizwAxIs8AMWNPgDjnSUA5J4nAN6g + MADnoyAA5aAnAOSjKQDgoi8A7awpAPCsIwD6syIA+rcrAOKlMwDqqzIA6Kk3AOSpOgDpqz0A+rozAPq6 + NADytjsA97s+APe8PAD5uzgA36VCAN+sVADgqUQA5axHAOmuQADkrUoA6bNKAO63TgDws0EA9btDAPS6 + RQD6vkEA9LxMAPm+SADhrlUA5LJZAPK7UAD7wEMA+8NOAPbBUAD6xFIA+8VUAPDDaQD0xmwA9shtAPjK + bgD6zW8A8cmCAPPMhAD0zoYA99CHAPDPmQDw0JkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmAAAAAAAA + AAAAAAAAAAAAAAAAAAAAACZcJgAAAAAAAAAAAAAAAAAAAAAAAAAAJjYnXSYAAAAAAAAAAAAAAAAAAAAA + AAAiRREPJ10mAAAAAAAAAAAAAAAAAAAAAAtHFhYQECddJgAAAAAAAAAAAAAAAAAACkobGxYRERAnXSYA + AAAAAAAAAAAAAAAJUjAbGxgbFhEQKF0mAAAAAAAAAAAAAAhSTjEgGxsbFhYRECtdJgAAAAAAAAAABjpI + SDggICAbGBgWERAnXSYAAAAAAAAFOVBSUk84IDAgGxtUW1paWlwmAAAAAAAABQUGBgg8IDAgMBtWCwsL + IiIAAAAAAAAAAAAAAAY6HiAgMCBXCgAAAAAAAAAAAAAAAAAAAAVHGx4wICBXCgAAAAAAAAAAAAAAAAAA + AAVJGxseMCBXCQAAAAAAAAAAAAAAAAAAAAVJLxsbHjBXCAAAAAAAAAAAAAAAAAAAAAFELhYcGx5XCAAA + AAAAAAAAAAAAAAAAAAFDMxMVGxtXBgAAAAAAAAAAAAAAAAAAAAFANCsWFhxVBgAAAAAAAAAAAAAAAAAA + AAE/MisOEBZVBQAAAAAAAAAAAAAAAAAAAAE9KS0OEBNUAwAAAAAAAAAAAAAAAAAAAAE+S0xAND9TAwAA + AAAAAAAAAAAAAAAAAAABAQEBAwEBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP/v + /wD/x/8A/4P/AP8B/wD+AP8A/AB/APgAPwDwAB8A4AAPAMAABwDgAA8A/gD/AP4A/wD+AP8A/gD/AP4A + /wD+AP8A/gD/AP4A/wD+AP8A/gD/AP8B/wD///8AKAAAABAAAAAgAAAAAQAIAAAAAAAAAQAAAAAAAAAA + AAAAAQAAAAEAAAAAAAClZhYAsnYmALN4KQC4fi8A1Y0XANWOGADXkBkA2pUbANuVHADclhwA3poeAOCc + HwDgmyAA46EiAOaiIwDmpiMA56cnAOilIwDppiUA66omAO2rJwDuricA46YsAOyrKADurikA7q4sAPCv + KQDvsS4A8LAqAO2vMQDkpjgA5q8+AOqwOADwszIA4qtBAOi0TwDyvEoA7LlSAOSyXADnt18Aw5ljAMui + bQDqumEA5LhoAOa7cADpv3MA78FlAPDFdgDyyXkA88x6APXNegD20IAA6MeQAOnIkQDpyZcAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAP///wAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAzcCAAAAAAAAAAAAAAAAAycFNQIAAAAA + AAAAAAAAAysLCAY1BAAAAAAAAAAAAy8SDg0IBjUEAAAAAAAAAzMaFBIODQgINQQAAAAAAzQlIhQaEg4f + Li01BAAAKQEBAQEbGhQUMAQEBAQqAAAAAAABGxsbFDMEAAAAAAAAAAAAARwbGxszBAAAAAAAAAAAAAEe + FBsbMwQAAAAAAAAAAAABIRQcHDMEAAAAAAAAAAAAASARFBQzBAAAAAAAAAAAAAEjFw4WMwQAAAAAAAAA + AAABLCgkJjMDAAAAAAAAAAAAAAEBAQEBAAAAAAAA/v8AAPx/AAD4PwAA8B8AAOAPAADABwAAgAMAAAAB + AADwHwAA8B8AAPAfAADwHwAA8B8AAPAfAADwHwAA+D8AACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAADAAAABgAAAAgAAAAGAAAAAwAA + AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAMAAAAFgAA + ABsAAAAWAAAACwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAA + AAwAAAAfAAAAMwAAADwAAAAyAAAAHQAAAAsAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAACAAAACSccDyHPllLiypFQ4M2UUesdFQtZAAAANQAAABoAAAAJAAAAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAEAAAAHAAAAF8aOTb/RlU3z0pVH/82UU/K/iUvcAAAAUAAAADAAAAAWAAAABgAA + AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAATs4BGjtOXUfXLfxn/0pE5/9ikYP7Rl1T3pXdBvQAA + AEoAAAAqAAAAEgAAAAUAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA+RaDhc0ZdR+M6HJv3Legf/yHUA/9aa + Sv/Tn1v51JlU+nxZMZcAAABDAAAAJAAAAA4AAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADFg/ITLPlE/1z4wz+NGC + DP/NewD/y3gA/8l3BP/apVv/zZdV89OYU/hHMxxzAAAAPAAAAB8AAAALAAAAAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAJJxwOIMiO + SuHNj0Dy1YkR/9ODBf/QfwH/zXsA/8t4AP/MfA3/3apl/8yXV/DLklDuHBQLXQAAADYAAAAaAAAACAAA + AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA + AAcAAAAXu4VEvMuPRvPajhf/2osK/9aIBv/UgwX/0YAD/819Af/LeQD/z4Qa/92sZ//OmFfyvYhL2QAA + AE8AAAAvAAAAFQAAAAYAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAABAAAABQAAABOodjyMyY5H9tuTH//ekg7/3Y4K/9qLCP/Whwb/1IMF/9GAA//PfQD/y3kA/9OO + Lf/bqWX90plW96R2QbsAAABJAAAAKQAAABEAAAAFAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAEAAAAD4hfL1rHjEb42ZUq/eOXFf/jlQ7/35IN/92OCv/aiwn/14gG/9SE + Bf/SgQT/z34B/8t6AP/Xm0P/1qNg+dKYU/p6WDCVAAAAQgAAACMAAAAOAAAAAwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAALUzkcMsSJQvPRkTL3550Y/+ecEf/lmBD/45UP/+CS + Df/djgr/24sJ/9eIB//VhAb/0oED/9B+Af/NfAP/26NU/9CcXPPSllP4RzMccwAAADsAAAAeAAAACgAA + AAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAkUDgYeu4I938eLO/Lpnxv/7qIU/+qg + E//onRL/5pkR/+SWDv/gkw3/3o8L/9uMCf/ZiQf/1YUG/9OBBP/QfwP/zn8J/9+sY//Nmlvwy5JQ7RYQ + CVoAAAA0AAAAGQAAAAgAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABwAAABaueDe4wYY98+qq + Mf/vphb/8KYX/+2iFf/roBP/6J0S/+aZEf/klw//4JQO/96QCv/bjQn/2YoI/9WFBv/TgwT/0H8D/9GG + Ff/gr2n/z5pb87qHSdYAAABOAAAALgAAABQAAAAGAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAFAAAAEpxr + MIe9gjr36Ks///azM//zqRj/8agY//CkF//uoxX/66AU/+mdEv/mmhD/5JcP/+GUDf/ekAr/240K/9mJ + B//Whwb/04IE/9B/Af/Ujyb/3q5p/dKZV/ifcj62AAAARwAAACgAAAARAAAABAAAAAEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAMAAAAOfVUkV7p/N/jcoT389rlB//m4Of/1rBv/86oZ//GoGP/wphf/7qMV/+ugE//pnhL/55oR/+SX + EP/hlQ7/3pIL/9yNCf/aiwf/1ocF/9ODBP/RgAP/2Js6/9ioZvjTmFT6dlYukQAAAEEAAAAjAAAADQAA + AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAgAAAAtGMBQvtXsz8sySOPb1uUD/+75B//q8Pf/4sB//9Kwa//OrGv/yqRn/8KYX/+6j + Ff/roBT/6Z4T/+ecEf/kmBD/4ZUO/9+SC//djgn/2ooI/9aHBv/UgwT/0YAC/9ylT//So2Tzz5VR90Mw + GnAAAAA6AAAAHQAAAAoAAAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAACAAAACRIMBR2udS/cvYI08/K3QP/7v0H/+79B//u+Qf/4syX/9q0a//Ws + G//zqxr/8akZ//GmGP/uoxX/7aEU/+qeE//nnBH/5ZgP/+GVDv/fkg3/3I4K/9qLB//WiAf/1IQF/9KE + Cv/hrWD/z55i8MmPTusPCwZXAAAAMwAAABgAAAAIAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAHAAAAFqJtKba0eTDz7LE///q+Qf/7v0H/+79B//vA + Q//6tiz/+K4a//auG//1rRr/9Ksa//KpGf/wpxj/76MX/+2hFP/pnxP/6JwS/+WYD//hlQ//35IN/92O + Cv/aiwn/14gH/9SEBf/ViRP/4rJo/8+cXfS4hEjVAAAATQAAAC0AAAAUAAAABgAAAAEAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAUAAAASjl8jgq91LPfjpjr/+Ls///q+ + Qf/7v0H/+79B//vAQ//7vDb/+bEc//iwHP/2rhz/9a0b//SrGv/yqhn/8agY/++kF//toRT/6p8T/+ic + Ev/lmRD/45YO/9+TDf/djwv/2owI/9eJB//UhQT/2JEj/+Gya/zRmVf5mm48sQAAAEYAAAAnAAAAEAAA + AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAA5zTBtTrXIp+NOY + NPzytz3/+bw+//q9QP/6vkH/+79B//u/Qf/7vj7/+rMg//mxHP/4sBz/9q4c//WsG//0rBr/86oZ//Go + GP/vpBf/7aEV/+qfE//onRH/5ZkQ/+OWD//gkw7/3Y8J/9uMCP/XiQf/1YQG/9uaNv/armz30phU+nJR + LI0AAABAAAAAIgAAAAwAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACzom + DSyobyXxv4Ut9e2wOv/1ujz/+Ls9//m8QP/6vUD/+r5B//u/Qf/7v0L/+rUn//mxG//5sR3/+LAc//au + HP/1rRv/9Kwa//OqGf/xqBj/76QX/+6iFf/roBP/6JwS/+aZEP/klg//4JMN/96OC//bjQn/2YkI/9WF + Bv/fpkz/06Zp8s2TUPY/LRhtAAAAOQAAABwAAAAJAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAEGRAFFKRqI9mwdibx56o3//G0Ov/ztjv/9bo8//a7Pv/5vED/+r1A//q+Qf/7wEP/+rgu//mx + G//5sh3/+bId//ixHP/2sBz/9a0b//SrGv/yqhn/8agY//CmF//uoxX/6qAT/+mdEf/mmRD/5JYP/+CT + Dv/ejwr/3IwK/9mJB//Whwn/4q5d/9GiZ+7Hj0znEg0HSAAAACcAAAAPAAAAAwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAGoGcgpaluIvLdoDP/6q03/++yOf/xtDr/87Y7//S4PP/2uz3/+bw+//m9 + QP/6vkL/+rs3//myHP/5sh3/+bId//myHf/5sR3/+LAc//WtHP/0rRv/9KsZ//KpGP/wphf/7qMV/+ug + E//onhL/55oR/+SXD//hlA3/3pAL/9yNCf/Zigf/2I0S/+S0aP/ToGPwvolJxAAAACcAAAARAAAABQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACiaB9ppmsg9dKVL//nqjX/67A3/+6yOP/wtDr/87Y7//W4 + PP/4uz3/+b0+//m9QP/5vUD/+rw7//myHv/5sh3/+bId//myHf/5sh3/+LEd//iwHP/2rhv/9awb//Or + Gv/xqBn/8KYY/+6jFf/roBP/6p4Q/+icDv/llw3/4ZQK/9+QCf/cjQb/2okF/9mRHf/ismj40ZVQ9MGK + SogAAAALAAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACmaR7PyYgn+uSdL//loDD/56Iy/+qk + M//rpjT/7qk3//CrOP/xrTn/8a05//CxOP/4vD7/+bxA//izJP/4sRz/+bId//myHf/5sh3/+bId//mx + Hf/4sBz/9q4c//WsG//zqxr/8qkY//GrI//xsDr/8bFF//W0Sf/2s0n/9LJI//OwSP/yr0f/8a1G//Cs + R//urEv/5ahV6dGVT+AAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACkaR2XpGoe/6Vq + H/+mayD/pmwh/6hsIv+pbSP/qW4k/6twJf+scCf/rXIn/65zKf/6vDz/+LxA//a1Kv/2sBr/+bEd//my + Hf/5sh3/+bId//myHf/5sR3/+LAc//auHP/1rRv/9Ksa//a3Ov/EiED/xYlB/8aKQ//Hi0T/yY1G/8qO + R//Lj0n/zJBK/82RS//Ok0z/0JRN/9GVTpcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK1yJ//5uzv/9rs+//a3 + Mf/1rhr/9rAc//iyHf/5sh3/+bId//myHf/5sh3/+bEd//iwHP/2rhz/9a0b//m5Ov/Chj//AAAAKwAA + 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 + + \ No newline at end of file diff --git a/SCrawler/Download/DownloadedInfoForm.vb b/SCrawler/Download/DownloadedInfoForm.vb index 8450451..4f85983 100644 --- a/SCrawler/Download/DownloadedInfoForm.vb +++ b/SCrawler/Download/DownloadedInfoForm.vb @@ -161,7 +161,7 @@ Namespace DownloadObjects End Sub Private Sub LIST_DOWN_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_DOWN.MouseDoubleClick Try - If _LatestSelected >= 0 AndAlso _LatestSelected <= _TempUsersList.Count - 1 AndAlso + If _LatestSelected.ValueBetween(0, _TempUsersList.Count - 1) AndAlso Not DirectCast(_TempUsersList(_LatestSelected), UserDataBase).Disposed Then _TempUsersList(_LatestSelected).OpenFolder() Catch ex As Exception End Try diff --git a/SCrawler/Download/Groups/DownloadGroup.vb b/SCrawler/Download/Groups/DownloadGroup.vb index 0c0d9d6..05eb3c9 100644 --- a/SCrawler/Download/Groups/DownloadGroup.vb +++ b/SCrawler/Download/Groups/DownloadGroup.vb @@ -15,9 +15,6 @@ Namespace DownloadObjects.Groups Friend Delegate Sub GroupEventHandler(ByVal Sender As DownloadGroup) Friend Event Deleted As GroupEventHandler Friend Event Updated As GroupEventHandler -#Region "XML Names" - Private Const Name_Name As String = "Name" -#End Region Private WithEvents BTT_EDIT As ToolStripMenuItem Private WithEvents BTT_DELETE As ToolStripMenuItem Private WithEvents BTT_DOWNLOAD As ToolStripMenuItem @@ -25,7 +22,6 @@ Namespace DownloadObjects.Groups Private ReadOnly SEP_1 As ToolStripSeparator Private WithEvents BTT_MENU As ToolStripMenuItem Friend Property NameBefore As String = String.Empty - Friend Property Name As String Private _Key As String = String.Empty Friend ReadOnly Property Key As String Get diff --git a/SCrawler/Download/Groups/GroupDefaults.vb b/SCrawler/Download/Groups/GroupDefaults.vb index bf61391..5717270 100644 --- a/SCrawler/Download/Groups/GroupDefaults.vb +++ b/SCrawler/Download/Groups/GroupDefaults.vb @@ -18,6 +18,7 @@ Namespace DownloadObjects.Groups Private ReadOnly CH_READY_FOR_DOWN As CheckBox Private ReadOnly CH_READY_FOR_DOWN_IGNORE As CheckBox Private WithEvents TXT_LABELS As TextBoxExtended + Friend WithEvents TXT_NAME As TextBoxExtended Private ReadOnly Labels As List(Of String) Public Sub New() Labels = New List(Of String) @@ -30,6 +31,15 @@ Namespace DownloadObjects.Groups .Dock = DockStyle.Fill .EndInit() End With + TXT_NAME = New TextBoxExtended + With TXT_NAME + .BeginInit() + .Buttons.Add(ADB.Clear) + .CaptionText = "Name" + .CaptionWidth = 50 + .Dock = DockStyle.Fill + .EndInit() + End With CH_TEMPORARY = New CheckBox With {.Text = "Temporary", .Name = "CH_TEMPORARY", .ThreeState = True, .CheckState = CheckState.Indeterminate, .Dock = DockStyle.Fill} CH_FAV = New CheckBox With {.Text = "Favorite", .Name = "CH_FAV", .ThreeState = True, .CheckState = CheckState.Indeterminate, .Dock = DockStyle.Fill} CH_READY_FOR_DOWN = New CheckBox With {.Text = "Ready for download", .Name = "CH_READY_FOR_DOWN", .Checked = True, .Dock = DockStyle.Fill} @@ -77,16 +87,18 @@ Namespace DownloadObjects.Groups CellBorderStyle = TableLayoutPanelCellBorderStyle.Single ColumnCount = 1 ColumnStyles.Add(New ColumnStyle(SizeType.Percent, 100)) - RowCount = 5 + RowCount = 6 RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) + RowStyles.Add(New RowStyle(SizeType.Absolute, 28)) RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) RowStyles.Add(New RowStyle(SizeType.Absolute, 25)) RowStyles.Add(New RowStyle(SizeType.Absolute, 28)) RowStyles.Add(New RowStyle(SizeType.Percent, 100)) End If - Controls.Add(TP_1, 0, 1) - Controls.Add(TP_2, 0, 2) - Controls.Add(TXT_LABELS, 0, 3) + Controls.Add(TXT_NAME, 0, 1) + Controls.Add(TP_1, 0, 2) + Controls.Add(TP_2, 0, 3) + Controls.Add(TXT_LABELS, 0, 4) End Sub Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_LABELS.ActionOnButtonClick Select Case Sender.DefaultButton @@ -105,6 +117,7 @@ Namespace DownloadObjects.Groups Friend Sub [Get](ByRef Instance As IGroup) If Not Instance Is Nothing Then With Instance + .Name = TXT_NAME.Text .Temporary = CH_TEMPORARY.CheckState .Favorite = CH_FAV.CheckState .ReadyForDownload = CH_READY_FOR_DOWN.Checked @@ -117,6 +130,7 @@ Namespace DownloadObjects.Groups Friend Sub [Set](ByVal Instance As IGroup) If Not Instance Is Nothing Then With Instance + TXT_NAME.Text = .Name CH_TEMPORARY.CheckState = .Temporary CH_FAV.CheckState = .Favorite CH_READY_FOR_DOWN.Checked = .ReadyForDownload diff --git a/SCrawler/Download/Groups/GroupEditorForm.Designer.vb b/SCrawler/Download/Groups/GroupEditorForm.Designer.vb index a468937..5906b0b 100644 --- a/SCrawler/Download/Groups/GroupEditorForm.Designer.vb +++ b/SCrawler/Download/Groups/GroupEditorForm.Designer.vb @@ -23,15 +23,10 @@ Namespace DownloadObjects.Groups Private Sub InitializeComponent() Dim CONTAINER_MAIN As System.Windows.Forms.ToolStripContainer - Dim ActionButton1 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() - Dim resources As System.ComponentModel.ComponentResourceManager = New System.ComponentModel.ComponentResourceManager(GetType(GroupEditorForm)) Me.DEFS_GROUP = New SCrawler.DownloadObjects.Groups.GroupDefaults() - Me.TXT_NAME = New PersonalUtilities.Forms.Controls.TextBoxExtended() CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() CONTAINER_MAIN.ContentPanel.SuspendLayout() CONTAINER_MAIN.SuspendLayout() - Me.DEFS_GROUP.SuspendLayout() - CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).BeginInit() Me.SuspendLayout() ' 'CONTAINER_MAIN @@ -40,7 +35,7 @@ Namespace DownloadObjects.Groups 'CONTAINER_MAIN.ContentPanel ' CONTAINER_MAIN.ContentPanel.Controls.Add(Me.DEFS_GROUP) - CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 134) + CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(476, 109) CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill CONTAINER_MAIN.LeftToolStripPanelVisible = False CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) @@ -55,35 +50,19 @@ Namespace DownloadObjects.Groups Me.DEFS_GROUP.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.[Single] Me.DEFS_GROUP.ColumnCount = 1 Me.DEFS_GROUP.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - Me.DEFS_GROUP.Controls.Add(Me.TXT_NAME, 0, 0) Me.DEFS_GROUP.Dock = System.Windows.Forms.DockStyle.Fill Me.DEFS_GROUP.Location = New System.Drawing.Point(0, 0) Me.DEFS_GROUP.Name = "DEFS_GROUP" - Me.DEFS_GROUP.RowCount = 5 - Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) + Me.DEFS_GROUP.RowCount = 6 + Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 0!)) + Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 28.0!)) Me.DEFS_GROUP.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - Me.DEFS_GROUP.Size = New System.Drawing.Size(476, 134) + Me.DEFS_GROUP.Size = New System.Drawing.Size(476, 109) Me.DEFS_GROUP.TabIndex = 1 ' - 'TXT_NAME - ' - ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_CLEAR" - Me.TXT_NAME.Buttons.Add(ActionButton1) - Me.TXT_NAME.CaptionText = "Name" - Me.TXT_NAME.CaptionToolTipEnabled = True - Me.TXT_NAME.CaptionToolTipText = "Group name" - Me.TXT_NAME.CaptionWidth = 50.0R - Me.TXT_NAME.Dock = System.Windows.Forms.DockStyle.Fill - Me.TXT_NAME.Location = New System.Drawing.Point(4, 4) - Me.TXT_NAME.Name = "TXT_NAME" - Me.TXT_NAME.Size = New System.Drawing.Size(468, 22) - Me.TXT_NAME.TabIndex = 0 - ' 'GroupEditorForm ' Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) @@ -104,12 +83,9 @@ Namespace DownloadObjects.Groups CONTAINER_MAIN.ContentPanel.ResumeLayout(False) CONTAINER_MAIN.ResumeLayout(False) CONTAINER_MAIN.PerformLayout() - Me.DEFS_GROUP.ResumeLayout(False) - CType(Me.TXT_NAME, System.ComponentModel.ISupportInitialize).EndInit() Me.ResumeLayout(False) End Sub - Private WithEvents TXT_NAME As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents DEFS_GROUP As GroupDefaults End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Download/Groups/GroupEditorForm.resx b/SCrawler/Download/Groups/GroupEditorForm.resx index 7e5ab0d..56d6ce4 100644 --- a/SCrawler/Download/Groups/GroupEditorForm.resx +++ b/SCrawler/Download/Groups/GroupEditorForm.resx @@ -120,13 +120,4 @@ False - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go - tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX - AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC - - \ No newline at end of file diff --git a/SCrawler/Download/Groups/GroupEditorForm.vb b/SCrawler/Download/Groups/GroupEditorForm.vb index 17591d6..269623d 100644 --- a/SCrawler/Download/Groups/GroupEditorForm.vb +++ b/SCrawler/Download/Groups/GroupEditorForm.vb @@ -10,29 +10,33 @@ Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Toolbars Namespace DownloadObjects.Groups Friend Class GroupEditorForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Friend Property MyGroup As DownloadGroup Friend Sub New(ByRef g As DownloadGroup) InitializeComponent() MyGroup = g - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub - Private Class NameChecker : Implements IFieldsCheckerProvider + Friend Class NameChecker : Implements IFieldsCheckerProvider Private Property ErrorMessage As String Implements IFieldsCheckerProvider.ErrorMessage Private Property Name As String Implements IFieldsCheckerProvider.Name Private Property TypeError As Boolean Implements IFieldsCheckerProvider.TypeError Private ReadOnly ExistingGroupName As String - Friend Sub New(ByVal _ExistingGroupName As String) + Private ReadOnly Property Source As IEnumerable(Of IGroup) + Private ReadOnly ParamName As String + Friend Sub New(ByVal _ExistingGroupName As String, ByRef _Source As IEnumerable(Of IGroup), ByVal Param As String) ExistingGroupName = _ExistingGroupName + Source = _Source + ParamName = Param End Sub Private Function Convert(ByVal Value As Object, ByVal DestinationType As Type, ByVal Provider As IFormatProvider, Optional ByVal NothingArg As Object = Nothing, Optional ByVal e As ErrorsDescriber = Nothing) As Object Implements ICustomProvider.Convert If Not ACheck(Value) Then - ErrorMessage = "Group name cannot be empty" + ErrorMessage = $"{ParamName} name cannot be empty" ElseIf Not ExistingGroupName.IsEmptyString AndAlso CStr(Value) = ExistingGroupName Then Return Value - ElseIf Settings.Groups.Count > 0 AndAlso Settings.Groups.LongCount(Function(g) g.Name = CStr(Value)) > 0 Then - ErrorMessage = "A group with the same name already exists" + ElseIf Source.Count > 0 AndAlso Source.LongCount(Function(g) g.Name = CStr(Value)) > 0 Then + ErrorMessage = $"A {ParamName.ToLower} with the same name already exists" Else Return Value End If @@ -48,7 +52,6 @@ Namespace DownloadObjects.Groups .AddOkCancelToolbar() If Not MyGroup Is Nothing Then With MyGroup - TXT_NAME.Text = .Name DEFS_GROUP.Set(MyGroup) Text &= $" { .Name}" End With @@ -56,7 +59,8 @@ Namespace DownloadObjects.Groups Text = "New Group" End If .MyFieldsChecker = New FieldsChecker - DirectCast(.MyFieldsChecker, FieldsChecker).AddControl(Of String)(TXT_NAME, TXT_NAME.CaptionText,, New NameChecker(If(MyGroup?.Name, String.Empty))) + DirectCast(.MyFieldsChecker, FieldsChecker).AddControl(Of String)(DEFS_GROUP.TXT_NAME, DEFS_GROUP.TXT_NAME.CaptionText,, + New NameChecker(If(MyGroup?.Name, String.Empty), Settings.Groups, "Group")) .MyFieldsChecker.EndLoaderOperations() .EndLoaderOperations() End With @@ -66,7 +70,6 @@ Namespace DownloadObjects.Groups If MyGroup Is Nothing Then MyGroup = New DownloadGroup With MyGroup .NameBefore = .Name - .Name = TXT_NAME.Text DEFS_GROUP.Get(MyGroup) End With MyDefs.CloseForm() diff --git a/SCrawler/Download/Groups/GroupParameters.vb b/SCrawler/Download/Groups/GroupParameters.vb index 71a62eb..6de8edc 100644 --- a/SCrawler/Download/Groups/GroupParameters.vb +++ b/SCrawler/Download/Groups/GroupParameters.vb @@ -8,6 +8,7 @@ ' but WITHOUT ANY WARRANTY Namespace DownloadObjects.Groups Friend Interface IGroup + Property Name As String ReadOnly Property Labels As List(Of String) Property Temporary As CheckState Property Favorite As CheckState @@ -15,10 +16,12 @@ Namespace DownloadObjects.Groups Property ReadyForDownloadIgnore As Boolean End Interface Friend Class GroupParameters : Implements IGroup, IDisposable + Protected Const Name_Name As String = "Name" Protected Const Name_Temporary As String = "Temporary" Protected Const Name_Favorite As String = "Favorite" Protected Const Name_ReadyForDownload As String = "RFD" Protected Const Name_ReadyForDownloadIgnore As String = "RFDI" + Friend Property Name As String Implements IGroup.Name Friend ReadOnly Property Labels As List(Of String) Implements IGroup.Labels Friend Property Temporary As CheckState = CheckState.Indeterminate Implements IGroup.Temporary Friend Property Favorite As CheckState = CheckState.Indeterminate Implements IGroup.Favorite diff --git a/SCrawler/Download/Scheduler.vb b/SCrawler/Download/Scheduler.vb new file mode 100644 index 0000000..0132acb --- /dev/null +++ b/SCrawler/Download/Scheduler.vb @@ -0,0 +1,149 @@ +' Copyright (C) 2022 Andy +' This program is free software: you can redistribute it and/or modify +' it under the terms of the GNU General Public License as published by +' the Free Software Foundation, either version 3 of the License, or +' (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY +Imports PersonalUtilities.Functions.XML +Imports PersonalUtilities.Tools +Imports SCrawler.DownloadObjects.Groups +Imports System.Threading +Namespace DownloadObjects + Friend Class Scheduler : Implements IEnumerable(Of AutoDownloader), IMyEnumerator(Of AutoDownloader), IDisposable + Friend Const Name_Plan As String = "Plan" + Friend Event UserFind As AutoDownloader.UserFindEventHandler + Private Sub OnUserFind(ByVal Key As String, ByVal Activate As Boolean) + RaiseEvent UserFind(Key, Activate) + End Sub + Private ReadOnly Plans As List(Of AutoDownloader) + Private ReadOnly File As SFile = $"Settings\AutoDownload.xml" + Private ReadOnly PlanWorking As Predicate(Of AutoDownloader) = Function(Plan) Plan.Working + Private ReadOnly PlanDownloading As Predicate(Of AutoDownloader) = Function(Plan) Plan.Downloading + Private ReadOnly PlansWaiter As Action(Of Predicate(Of AutoDownloader)) = Sub(ByVal Predicate As Predicate(Of AutoDownloader)) + While Plans.Exists(Predicate) : Thread.Sleep(200) : End While + End Sub + Friend Sub New() + Plans = New List(Of AutoDownloader) + If File.Exists Then + Using x As New XmlFile(File,, False) With {.AllowSameNames = True} + x.LoadData() + If x.Contains(Name_Plan) Then + For Each e In x : Plans.Add(New AutoDownloader(e)) : Next + Else + Plans.Add(New AutoDownloader(x)) + End If + End Using + End If + If Plans.Count > 0 Then Plans.ForEach(Sub(p) + p.Source = Me + AddHandler p.UserFind, AddressOf OnUserFind + End Sub) + End Sub + Default Friend ReadOnly Property Item(ByVal Index As Integer) As AutoDownloader Implements IMyEnumerator(Of AutoDownloader).MyEnumeratorObject + Get + Return Plans(Index) + End Get + End Property + Friend ReadOnly Property Count As Integer Implements IMyEnumerator(Of AutoDownloader).MyEnumeratorCount + Get + Return Plans.Count + End Get + End Property + Friend Function NotificationClicked(ByVal Key As String) As Boolean + Return Count > 0 AndAlso Plans.Exists(Function(p) p.NotificationClicked(Key)) + End Function + Friend Sub Add(ByVal Plan As AutoDownloader) + Plan.Source = Me + AddHandler Plan.UserFind, AddressOf OnUserFind + Plans.Add(Plan) + Update() + End Sub + Friend Async Function RemoveAt(ByVal Index As Integer) As Task + If Index.ValueBetween(0, Count - 1) Then + With Plans(Index) + .Stop() + If .Working Then + Await Task.Run(Sub() + While .Working : Thread.Sleep(510) : End While + End Sub) + End If + .Dispose() + End With + Plans.RemoveAt(Index) + Update() + End If + End Function + Private _UpdateRequired As Boolean = False + Friend Sub Update() + _UpdateRequired = True + Try + If Plans.Count > 0 Then + Using x As New XmlFile With {.Name = "Scheduler", .AllowSameNames = True} : x.AddRange(Plans) : x.Save(File) : End Using + Else + File.Delete() + End If + _UpdateRequired = False + Catch + End Try + End Sub +#Region "Groups Support" + Friend Sub GROUPS_Updated(ByVal Sender As DownloadGroup) + If Count > 0 Then Plans.ForEach(Sub(p) p.GROUPS_Updated(Sender)) + End Sub + Friend Sub GROUPS_Deleted(ByVal Sender As DownloadGroup) + If Count > 0 Then Plans.ForEach(Sub(p) p.GROUPS_Deleted(Sender)) + End Sub +#End Region +#Region "Execution" + Friend Async Sub Start(ByVal Init As Boolean) + If Count > 0 Then + If Plans.Exists(PlanDownloading) Then Await Task.Run(Sub() PlansWaiter(PlanDownloading)) + For Each Plan In Plans : Plan.Start(Init) : Thread.Sleep(200) : Next + End If + End Sub + Friend Sub [Stop]() + If Count > 0 Then Plans.ForEach(Sub(p) p.Stop()) + End Sub + Friend Property Pause As Boolean + Get + If Count > 0 Then Return Plans(0).Pause Else Return False + End Get + Set(ByVal p As Boolean) + If Count > 0 Then Plans.ForEach(Sub(pp) pp.Pause = p) + End Set + End Property +#End Region +#Region "IEnumerable Support" + Private Function GetEnumerator() As IEnumerator(Of AutoDownloader) Implements IEnumerable(Of AutoDownloader).GetEnumerator + Return New MyEnumerator(Of AutoDownloader)(Me) + End Function + Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator + Return GetEnumerator() + End Function +#End Region +#Region "IDisposable Support" + Private disposedValue As Boolean = False + Protected Overridable Overloads Sub Dispose(ByVal disposing As Boolean) + If Not disposedValue Then + If disposing Then + [Stop]() + If Plans.Exists(PlanWorking) Then Task.WaitAll(Task.Run(Sub() PlansWaiter(PlanWorking))) + If _UpdateRequired Then Update() + Plans.ListClearDispose + End If + disposedValue = True + End If + End Sub + Protected Overrides Sub Finalize() + Dispose(False) + MyBase.Finalize() + End Sub + Friend Overloads Sub Dispose() Implements IDisposable.Dispose + Dispose(True) + GC.SuppressFinalize(Me) + End Sub +#End Region + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Download/SchedulerEditorForm.Designer.vb b/SCrawler/Download/SchedulerEditorForm.Designer.vb new file mode 100644 index 0000000..ce94c6d --- /dev/null +++ b/SCrawler/Download/SchedulerEditorForm.Designer.vb @@ -0,0 +1,77 @@ +' Copyright (C) 2022 Andy +' This program is free software: you can redistribute it and/or modify +' it under the terms of the GNU General Public License as published by +' the Free Software Foundation, either version 3 of the License, or +' (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY +Namespace DownloadObjects + + Partial Friend Class SchedulerEditorForm : Inherits System.Windows.Forms.Form + + Protected Overrides Sub Dispose(ByVal disposing As Boolean) + Try + If disposing AndAlso components IsNot Nothing Then + components.Dispose() + End If + Finally + MyBase.Dispose(disposing) + End Try + End Sub + Private components As System.ComponentModel.IContainer + + Private Sub InitializeComponent() + Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() + Me.LIST_PLANS = New System.Windows.Forms.ListBox() + Me.CONTAINER_MAIN.ContentPanel.SuspendLayout() + Me.CONTAINER_MAIN.SuspendLayout() + Me.SuspendLayout() + ' + 'CONTAINER_MAIN + ' + Me.CONTAINER_MAIN.BottomToolStripPanelVisible = False + ' + 'CONTAINER_MAIN.ContentPanel + ' + Me.CONTAINER_MAIN.ContentPanel.Controls.Add(Me.LIST_PLANS) + Me.CONTAINER_MAIN.ContentPanel.Size = New System.Drawing.Size(414, 316) + Me.CONTAINER_MAIN.Dock = System.Windows.Forms.DockStyle.Fill + Me.CONTAINER_MAIN.LeftToolStripPanelVisible = False + Me.CONTAINER_MAIN.Location = New System.Drawing.Point(0, 0) + Me.CONTAINER_MAIN.Name = "CONTAINER_MAIN" + Me.CONTAINER_MAIN.RightToolStripPanelVisible = False + Me.CONTAINER_MAIN.Size = New System.Drawing.Size(414, 341) + Me.CONTAINER_MAIN.TabIndex = 0 + ' + 'LIST_PLANS + ' + Me.LIST_PLANS.Dock = System.Windows.Forms.DockStyle.Fill + Me.LIST_PLANS.FormattingEnabled = True + Me.LIST_PLANS.Location = New System.Drawing.Point(0, 0) + Me.LIST_PLANS.Name = "LIST_PLANS" + Me.LIST_PLANS.Size = New System.Drawing.Size(414, 316) + Me.LIST_PLANS.TabIndex = 0 + ' + 'SchedulerEditorForm + ' + Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!) + Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font + Me.ClientSize = New System.Drawing.Size(414, 341) + Me.Controls.Add(Me.CONTAINER_MAIN) + Me.KeyPreview = True + Me.MinimumSize = New System.Drawing.Size(430, 380) + Me.Name = "SchedulerEditorForm" + Me.ShowIcon = False + Me.Text = "Scheduler" + Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False) + Me.CONTAINER_MAIN.ResumeLayout(False) + Me.CONTAINER_MAIN.PerformLayout() + Me.ResumeLayout(False) + + End Sub + + Private WithEvents CONTAINER_MAIN As ToolStripContainer + Private WithEvents LIST_PLANS As ListBox + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Download/SchedulerEditorForm.resx b/SCrawler/Download/SchedulerEditorForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/SCrawler/Download/SchedulerEditorForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/SCrawler/Download/SchedulerEditorForm.vb b/SCrawler/Download/SchedulerEditorForm.vb new file mode 100644 index 0000000..745efc0 --- /dev/null +++ b/SCrawler/Download/SchedulerEditorForm.vb @@ -0,0 +1,117 @@ +' Copyright (C) 2022 Andy +' This program is free software: you can redistribute it and/or modify +' it under the terms of the GNU General Public License as published by +' the Free Software Foundation, either version 3 of the License, or +' (at your option) any later version. +' +' This program is distributed in the hope that it will be useful, +' but WITHOUT ANY WARRANTY +Imports PersonalUtilities.Forms +Imports PersonalUtilities.Forms.Toolbars +Namespace DownloadObjects + Friend Class SchedulerEditorForm : Implements IEditToolbar + Private ReadOnly MyDefs As DefaultFormOptions + Private WithEvents BTT_SKIP As ToolStripButton + Private WithEvents BTT_START As ToolStripButton + Friend Sub New() + InitializeComponent() + MyDefs = New DefaultFormOptions + End Sub + Private Sub SchedulerEditorForm_Load(sender As Object, e As EventArgs) Handles Me.Load + With MyDefs + .MyViewInitialize(Me, Settings.Design) + .AddEditToolbar() + BTT_SKIP = New ToolStripButton With { + .Text = "Skip", + .ToolTipText = "Skip next run", + .AutoToolTip = True, + .DisplayStyle = ToolStripItemDisplayStyle.Text + } + BTT_START = New ToolStripButton With { + .Text = "Start", + .Image = My.Resources.StartPic_01_Green_16, + .ToolTipText = "Run selected plan", + .AutoToolTip = True + } + .MyEditToolbar.ToolStrip.Items.AddRange({BTT_START, BTT_SKIP}) + Refill() + .EndLoaderOperations(False) + End With + End Sub + Private Sub SchedulerEditorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed + BTT_SKIP.Dispose() + End Sub + Private Sub SchedulerEditorForm_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown + If e.KeyCode = Keys.Escape Then Close() + End Sub + Private Sub Refill() Implements IEditToolbar.Update + Try + LIST_PLANS.Items.Clear() + If Settings.Automation.Count > 0 Then + LIST_PLANS.Items.AddRange(Settings.Automation.Select(Function(a) a.ToString()).Cast(Of Object).ToArray) + If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then LIST_PLANS.SelectedIndex = _LatestSelected + Else + _LatestSelected = -1 + End If + Catch ex As Exception + ErrorsDescriber.Execute(EDP.SendInLog, ex) + End Try + End Sub + Private Sub Add() Implements IEditToolbar.Add + Dim a As New AutoDownloader(True) + Using f As New AutoDownloaderEditorForm(a) + f.ShowDialog() + If f.DialogResult = DialogResult.OK Then + Settings.Automation.Add(a) + Refill() + Else + a.Dispose() + End If + End Using + End Sub + Private Sub Edit() Implements IEditToolbar.Edit + If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then + Using f As New AutoDownloaderEditorForm(Settings.Automation(_LatestSelected)) : f.ShowDialog() : End Using + Refill() + Else + MsgBoxE("You have not selected a plan to edit.", vbExclamation) + End If + End Sub + Private _DeleteInProgress As Boolean = False + Private Async Sub Delete() Implements IEditToolbar.Delete + If Not _DeleteInProgress Then + If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then + _DeleteInProgress = True + Dim n$ = Settings.Automation(_LatestSelected).Name + Await Settings.Automation.RemoveAt(_LatestSelected) + Refill() + MsgBoxE($"Plan [{n}] deleted") + _DeleteInProgress = False + Else + MsgBoxE("You have not selected a plan to delete.", vbExclamation) + End If + Else + MsgBoxE({"One of the plans is currently in progress. Wait until this plan is stopped and deleted.", "Deleting a plan"}, vbExclamation) + End If + End Sub + Private _LatestSelected As Integer = -1 + Private Sub LIST_PLANS_SelectedIndexChanged(sender As Object, e As EventArgs) Handles LIST_PLANS.SelectedIndexChanged + _LatestSelected = LIST_PLANS.SelectedIndex + End Sub + Private Sub LIST_PLANS_MouseDoubleClick(sender As Object, e As MouseEventArgs) Handles LIST_PLANS.MouseDoubleClick + Edit() + End Sub + Private Sub BTT_START_Click(sender As Object, e As EventArgs) Handles BTT_START.Click + If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then + With Settings.Automation(_LatestSelected) : .Start(.IsNewPlan) : End With + Refill() + End If + End Sub + Private Sub BTT_SKIP_Click(sender As Object, e As EventArgs) Handles BTT_SKIP.Click + If _LatestSelected.ValueBetween(0, LIST_PLANS.Items.Count - 1) Then + Settings.Automation(_LatestSelected).Skip() + Refill() + End If + End Sub + End Class +End Namespace \ No newline at end of file diff --git a/SCrawler/Download/TDownloader.vb b/SCrawler/Download/TDownloader.vb index 038a54f..0565f67 100644 --- a/SCrawler/Download/TDownloader.vb +++ b/SCrawler/Download/TDownloader.vb @@ -39,14 +39,13 @@ Namespace DownloadObjects End Property #End Region #Region "Automation Support" - Friend Property DisableOpenForms As Boolean = False - Private _DisableCompleteNotification As Boolean = False - Private _AutoDownloaderWorking As Boolean = False - Friend WriteOnly Property AutoDownloaderWorking As Boolean + Private _AutoDownloaderTasks As Integer = 0 + Friend Property AutoDownloaderWorking As Boolean + Private Get + Return _AutoDownloaderTasks > 0 + End Get Set(ByVal adw As Boolean) - _AutoDownloaderWorking = adw - DisableOpenForms = adw - _DisableCompleteNotification = adw + _AutoDownloaderTasks += IIf(adw, 1, -1) End Set End Property Friend Sub InvokeDownloadsChangeEvent() @@ -70,6 +69,9 @@ Namespace DownloadObjects Return Items.Count End Get End Property + Friend Sub Clear() + Items.Clear() + End Sub Friend ReadOnly Property Working As Boolean Get Return _Working OrElse If(Thread?.IsAlive, False) @@ -237,16 +239,17 @@ Namespace DownloadObjects #Region "Thread" Private CheckerThread As Thread Private Sub [Start]() - If Not DisableOpenForms AndAlso MyProgressForm.ReadyToOpen AndAlso Pool.LongCount(Function(p) p.Count > 0) > 1 Then MyProgressForm.Show() : MainFrameObj.Focus() + If Not AutoDownloaderWorking AndAlso MyProgressForm.ReadyToOpen AndAlso Pool.LongCount(Function(p) p.Count > 0) > 1 Then MyProgressForm.Show() : MainFrameObj.Focus() If Not If(CheckerThread?.IsAlive, False) Then MainProgress.Enabled = True - If Not DisableOpenForms AndAlso InfoForm.ReadyToOpen Then InfoForm.Show() : MainFrameObj.Focus() + If Not AutoDownloaderWorking AndAlso InfoForm.ReadyToOpen Then InfoForm.Show() : MainFrameObj.Focus() CheckerThread = New Thread(New ThreadStart(AddressOf JobsChecker)) CheckerThread.SetApartmentState(ApartmentState.MTA) CheckerThread.Start() End If End Sub Private Sub JobsChecker() + RaiseEvent OnDownloading(True) Try MainProgress.TotalCount = 0 MainProgress.CurrentCounter = 0 @@ -257,7 +260,7 @@ Namespace DownloadObjects Next Thread.Sleep(200) Loop - Catch ex As Exception + Catch Finally With MainProgress .TotalCount = 0 @@ -268,15 +271,16 @@ Namespace DownloadObjects MyProgressForm.DisableProgressChange = True If Pool.Count > 0 Then Pool.ForEach(Sub(p) If Not p.Progress Is Nothing Then p.Progress.TotalCount = 0) ExecuteCommand(Settings.DownloadsCompleteCommand) + UpdateJobsLabel() + RaiseEvent OnDownloading(False) End Try End Sub Private Sub StartDownloading(ByRef _Job As Job) - RaiseEvent OnDownloading(True) Dim isSeparated As Boolean = _Job.IsSeparated Dim n$ = _Job.Name Dim pt As Func(Of String, String) = Function(ByVal t As String) As String Dim _t$ = If(isSeparated, $"{n} {Left(t, 1).ToLower}{Right(t, t.Length - 1)}", t) - If Not _DisableCompleteNotification Then RaiseEvent SendNotification(_t) + If Not AutoDownloaderWorking Then RaiseEvent SendNotification(_t) Return _t End Function Try @@ -287,7 +291,7 @@ Namespace DownloadObjects Dim SiteChecked As Boolean = False Do While _Job.Count > 0 _Job.ThrowIfCancellationRequested() - If Not SiteChecked Then _Job.Available(_AutoDownloaderWorking) : SiteChecked = True : Continue Do + If Not SiteChecked Then _Job.Available(AutoDownloaderWorking) : SiteChecked = True : Continue Do UpdateJobsLabel() DownloadData(_Job, _Job.Token) _Job.ThrowIfCancellationRequested() @@ -300,17 +304,12 @@ Namespace DownloadObjects _Job.Progress.InformationTemporary = pt("Downloading error") ErrorsDescriber.Execute(EDP.SendInLog, ex, "TDownloader.Start") Finally + If _Job.Count > 0 Then _Job.Clear() _Job.Stopped() - UpdateJobsLabel() - RaiseEvent OnDownloading(False) End Try End Sub Friend Sub [Stop]() - If Pool.Count > 0 Then - For Each j As Job In Pool - If j.Working Then j.Stop() - Next - End If + If Pool.Count > 0 Then Pool.ForEach(Sub(j) If j.Working Then j.Stop()) End Sub Private Sub UpdateJobsLabel() RaiseEvent OnJobsChange(Count) diff --git a/SCrawler/Editors/CollectionEditorForm.Designer.vb b/SCrawler/Editors/CollectionEditorForm.Designer.vb index f7a9069..2b25ae0 100644 --- a/SCrawler/Editors/CollectionEditorForm.Designer.vb +++ b/SCrawler/Editors/CollectionEditorForm.Designer.vb @@ -44,13 +44,11 @@ 'CMB_COLLECTIONS ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_COMBOBOX_ARROW" - ActionButton1.Visible = False + ActionButton1.Name = "Add" + ActionButton1.ToolTipText = "Add new collection" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_ADD" - ActionButton2.ToolTipText = "Add new collection" + ActionButton2.Name = "ArrowDown" + ActionButton2.Visible = False Me.CMB_COLLECTIONS.Buttons.Add(ActionButton1) Me.CMB_COLLECTIONS.Buttons.Add(ActionButton2) Me.CMB_COLLECTIONS.Dock = System.Windows.Forms.DockStyle.Fill diff --git a/SCrawler/Editors/CollectionEditorForm.resx b/SCrawler/Editors/CollectionEditorForm.resx index 06161e7..9512fa7 100644 --- a/SCrawler/Editors/CollectionEditorForm.resx +++ b/SCrawler/Editors/CollectionEditorForm.resx @@ -119,6 +119,28 @@ + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 + JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE + QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W + h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw + IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H + YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim + Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW + NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq + G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335 + ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP + ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH + SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS + IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3 + Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb + uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY + RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv + MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK + 0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC + + + iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t 3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL @@ -206,28 +228,6 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A AAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 - JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE - QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W - h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw - IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H - YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim - Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW - NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq - G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335 - ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP - ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH - SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS - IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3 - Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb - uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY - RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv - MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK - 0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC \ No newline at end of file diff --git a/SCrawler/Editors/CollectionEditorForm.vb b/SCrawler/Editors/CollectionEditorForm.vb index f7b81a7..a851413 100644 --- a/SCrawler/Editors/CollectionEditorForm.vb +++ b/SCrawler/Editors/CollectionEditorForm.vb @@ -11,12 +11,12 @@ Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Toolbars Namespace Editors Friend Class CollectionEditorForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Private ReadOnly Collections As List(Of String) Friend Property [Collection] As String = String.Empty Friend Sub New() InitializeComponent() - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions Collections = New List(Of String) End Sub Friend Sub New(ByVal CollectionName As String) @@ -32,7 +32,7 @@ Namespace Editors If Collections.ListExists Then Collections.Sort() : CMB_COLLECTIONS.Items.AddRange(From c In Collections Select New ListItem(c)) If Not Collection.IsEmptyString And Collections.Contains(Collection) Then CMB_COLLECTIONS.SelectedIndex = Collections.IndexOf(Collection) .DelegateClosingChecker = False - .EndLoaderOperations(False) + .EndLoaderOperations() End With Catch ex As Exception MyDefs.InvokeLoaderError(ex) diff --git a/SCrawler/Editors/GlobalSettingsForm.Designer.vb b/SCrawler/Editors/GlobalSettingsForm.Designer.vb index db59fad..d50a3db 100644 --- a/SCrawler/Editors/GlobalSettingsForm.Designer.vb +++ b/SCrawler/Editors/GlobalSettingsForm.Designer.vb @@ -37,12 +37,13 @@ Dim TAB_BEHAVIOR As System.Windows.Forms.TabPage Dim TP_BEHAVIOR As System.Windows.Forms.TableLayoutPanel Dim ActionButton7 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim TP_OPEN_INFO As System.Windows.Forms.TableLayoutPanel Dim TP_OPEN_PROGRESS As System.Windows.Forms.TableLayoutPanel Dim TAB_DOWN As System.Windows.Forms.TabPage Dim TP_DOWNLOADING As System.Windows.Forms.TableLayoutPanel - Dim ActionButton8 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Dim ActionButton9 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() + Dim ActionButton10 As PersonalUtilities.Forms.Controls.Base.ActionButton = New PersonalUtilities.Forms.Controls.Base.ActionButton() Me.TXT_GLOBAL_PATH = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_LARGE = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_IMAGE_SMALL = New PersonalUtilities.Forms.Controls.TextBoxExtended() @@ -73,6 +74,7 @@ Me.CH_DOWN_OPEN_PROGRESS_SUSPEND = New System.Windows.Forms.CheckBox() Me.TXT_CHANNELS_ROWS = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_CHANNELS_COLUMNS = New PersonalUtilities.Forms.Controls.TextBoxExtended() + Me.CH_DOWN_IMAGES_NATIVE = New System.Windows.Forms.CheckBox() Me.TXT_CHANNEL_USER_POST_LIMIT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_FOLDER_CMD = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.CH_EXIT_CONFIRM = New System.Windows.Forms.CheckBox() @@ -85,8 +87,6 @@ Me.TXT_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TXT_DOWN_COMPLETE_SCRIPT = New PersonalUtilities.Forms.Controls.TextBoxExtended() Me.TAB_MAIN = New System.Windows.Forms.TabControl() - Me.TAB_AUTO = New System.Windows.Forms.TabPage() - Me.PANEL_AUTO = New System.Windows.Forms.Panel() Me.CONTAINER_MAIN = New System.Windows.Forms.ToolStripContainer() TP_BASIS = New System.Windows.Forms.TableLayoutPanel() TP_IMAGES = New System.Windows.Forms.TableLayoutPanel() @@ -137,7 +137,6 @@ CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit() CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).BeginInit() Me.TAB_MAIN.SuspendLayout() - Me.TAB_AUTO.SuspendLayout() Me.CONTAINER_MAIN.ContentPanel.SuspendLayout() Me.CONTAINER_MAIN.SuspendLayout() Me.SuspendLayout() @@ -176,11 +175,9 @@ 'TXT_GLOBAL_PATH ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_OPEN" + ActionButton1.Name = "Open" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_CLEAR" + ActionButton2.Name = "Clear" Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton1) Me.TXT_GLOBAL_PATH.Buttons.Add(ActionButton2) Me.TXT_GLOBAL_PATH.CaptionText = "Data Path" @@ -244,8 +241,7 @@ 'TXT_COLLECTIONS_PATH ' ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 0 - ActionButton3.Name = "BTT_CLEAR" + ActionButton3.Name = "Clear" Me.TXT_COLLECTIONS_PATH.Buttons.Add(ActionButton3) Me.TXT_COLLECTIONS_PATH.CaptionText = "Collections folder" Me.TXT_COLLECTIONS_PATH.CaptionToolTipEnabled = True @@ -259,8 +255,7 @@ 'TXT_MAX_JOBS_USERS ' ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) - ActionButton4.Index = 0 - ActionButton4.Name = "BTT_REFRESH" + ActionButton4.Name = "Refresh" ActionButton4.ToolTipText = "Set to default" Me.TXT_MAX_JOBS_USERS.Buttons.Add(ActionButton4) Me.TXT_MAX_JOBS_USERS.CaptionSizeType = System.Windows.Forms.SizeType.Percent @@ -279,8 +274,7 @@ 'TXT_MAX_JOBS_CHANNELS ' ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image) - ActionButton5.Index = 0 - ActionButton5.Name = "BTT_REFRESH" + ActionButton5.Name = "Refresh" ActionButton5.ToolTipText = "Set to default" Me.TXT_MAX_JOBS_CHANNELS.Buttons.Add(ActionButton5) Me.TXT_MAX_JOBS_CHANNELS.CaptionSizeType = System.Windows.Forms.SizeType.Percent @@ -310,8 +304,7 @@ 'TXT_IMGUR_CLIENT_ID ' ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) - ActionButton6.Index = 0 - ActionButton6.Name = "BTT_CLEAR" + ActionButton6.Name = "Clear" Me.TXT_IMGUR_CLIENT_ID.Buttons.Add(ActionButton6) Me.TXT_IMGUR_CLIENT_ID.CaptionText = "Imgur Client ID" Me.TXT_IMGUR_CLIENT_ID.Dock = System.Windows.Forms.DockStyle.Fill @@ -687,19 +680,31 @@ TP_DEFS.Controls.Add(Me.CH_DOWN_VIDEOS, 0, 3) TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES, 0, 2) TP_DEFS.Controls.Add(Me.CH_DEF_TEMP, 0, 1) + TP_DEFS.Controls.Add(Me.CH_DOWN_IMAGES_NATIVE, 0, 4) TP_DEFS.Dock = System.Windows.Forms.DockStyle.Fill TP_DEFS.Location = New System.Drawing.Point(3, 3) TP_DEFS.Name = "TP_DEFS" - TP_DEFS.RowCount = 5 + TP_DEFS.RowCount = 6 + TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25.0!)) TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_DEFS.RowStyles.Add(New System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20.0!)) TP_DEFS.Size = New System.Drawing.Size(570, 278) TP_DEFS.TabIndex = 0 ' + 'CH_DOWN_IMAGES_NATIVE + ' + Me.CH_DOWN_IMAGES_NATIVE.AutoSize = True + Me.CH_DOWN_IMAGES_NATIVE.Dock = System.Windows.Forms.DockStyle.Fill + Me.CH_DOWN_IMAGES_NATIVE.Location = New System.Drawing.Point(4, 108) + Me.CH_DOWN_IMAGES_NATIVE.Name = "CH_DOWN_IMAGES_NATIVE" + Me.CH_DOWN_IMAGES_NATIVE.Size = New System.Drawing.Size(562, 19) + Me.CH_DOWN_IMAGES_NATIVE.TabIndex = 4 + Me.CH_DOWN_IMAGES_NATIVE.Text = "Download 'jpg' instead of 'webp'" + Me.CH_DOWN_IMAGES_NATIVE.UseVisualStyleBackColor = True + ' 'TAB_DEFS_CHANNELS ' TAB_DEFS_CHANNELS.Controls.Add(TP_CHANNELS) @@ -799,8 +804,7 @@ Me.TXT_FOLDER_CMD.AutoShowClearButton = True ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image) ActionButton7.Enabled = False - ActionButton7.Index = 0 - ActionButton7.Name = "BTT_CLEAR" + ActionButton7.Name = "Clear" ActionButton7.Visible = False Me.TXT_FOLDER_CMD.Buttons.Add(ActionButton7) Me.TXT_FOLDER_CMD.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox @@ -851,11 +855,18 @@ ' 'TXT_CLOSE_SCRIPT ' + Me.TXT_CLOSE_SCRIPT.AutoShowClearButton = True + ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image) + ActionButton8.Enabled = False + ActionButton8.Name = "Clear" + ActionButton8.Visible = False + Me.TXT_CLOSE_SCRIPT.Buttons.Add(ActionButton8) Me.TXT_CLOSE_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_CLOSE_SCRIPT.CaptionText = "Close cmd" Me.TXT_CLOSE_SCRIPT.CaptionToolTipEnabled = True Me.TXT_CLOSE_SCRIPT.CaptionToolTipText = "This command will be executed when SCrawler is closed" Me.TXT_CLOSE_SCRIPT.Dock = System.Windows.Forms.DockStyle.Fill + Me.TXT_CLOSE_SCRIPT.LeaveDefaultButtons = True Me.TXT_CLOSE_SCRIPT.Location = New System.Drawing.Point(4, 215) Me.TXT_CLOSE_SCRIPT.Name = "TXT_CLOSE_SCRIPT" Me.TXT_CLOSE_SCRIPT.PlaceholderEnabled = True @@ -966,14 +977,12 @@ ' 'TXT_SCRIPT ' - ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image) - ActionButton8.Index = 0 - ActionButton8.Name = "BTT_OPEN" ActionButton9.BackgroundImage = CType(resources.GetObject("ActionButton9.BackgroundImage"), System.Drawing.Image) - ActionButton9.Index = 1 - ActionButton9.Name = "BTT_CLEAR" - Me.TXT_SCRIPT.Buttons.Add(ActionButton8) + ActionButton9.Name = "Open" + ActionButton10.BackgroundImage = CType(resources.GetObject("ActionButton10.BackgroundImage"), System.Drawing.Image) + ActionButton10.Name = "Clear" Me.TXT_SCRIPT.Buttons.Add(ActionButton9) + Me.TXT_SCRIPT.Buttons.Add(ActionButton10) Me.TXT_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox Me.TXT_SCRIPT.CaptionText = "Script" Me.TXT_SCRIPT.CaptionToolTipEnabled = True @@ -1009,7 +1018,6 @@ Me.TAB_MAIN.Controls.Add(TAB_BEHAVIOR) Me.TAB_MAIN.Controls.Add(TAB_DEFAULTS) Me.TAB_MAIN.Controls.Add(TAB_DOWN) - Me.TAB_MAIN.Controls.Add(Me.TAB_AUTO) Me.TAB_MAIN.Controls.Add(TAB_DEFS_CHANNELS) Me.TAB_MAIN.Dock = System.Windows.Forms.DockStyle.Fill Me.TAB_MAIN.Location = New System.Drawing.Point(0, 0) @@ -1018,24 +1026,6 @@ Me.TAB_MAIN.Size = New System.Drawing.Size(584, 310) Me.TAB_MAIN.TabIndex = 1 ' - 'TAB_AUTO - ' - Me.TAB_AUTO.Controls.Add(Me.PANEL_AUTO) - Me.TAB_AUTO.Location = New System.Drawing.Point(4, 22) - Me.TAB_AUTO.Name = "TAB_AUTO" - Me.TAB_AUTO.Size = New System.Drawing.Size(576, 284) - Me.TAB_AUTO.TabIndex = 7 - Me.TAB_AUTO.Text = "Automation" - ' - 'PANEL_AUTO - ' - Me.PANEL_AUTO.AutoSize = True - Me.PANEL_AUTO.Dock = System.Windows.Forms.DockStyle.Fill - Me.PANEL_AUTO.Location = New System.Drawing.Point(0, 0) - Me.PANEL_AUTO.Name = "PANEL_AUTO" - Me.PANEL_AUTO.Size = New System.Drawing.Size(576, 284) - Me.PANEL_AUTO.TabIndex = 0 - ' 'CONTAINER_MAIN ' ' @@ -1109,8 +1099,6 @@ CType(Me.TXT_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit() CType(Me.TXT_DOWN_COMPLETE_SCRIPT, System.ComponentModel.ISupportInitialize).EndInit() Me.TAB_MAIN.ResumeLayout(False) - Me.TAB_AUTO.ResumeLayout(False) - Me.TAB_AUTO.PerformLayout() Me.CONTAINER_MAIN.ContentPanel.ResumeLayout(False) Me.CONTAINER_MAIN.ResumeLayout(False) Me.CONTAINER_MAIN.PerformLayout() @@ -1161,7 +1149,6 @@ Private WithEvents TXT_DOWN_COMPLETE_SCRIPT As PersonalUtilities.Forms.Controls.TextBoxExtended Private WithEvents CH_DOWN_OPEN_INFO_SUSPEND As CheckBox Private WithEvents CH_DOWN_OPEN_PROGRESS_SUSPEND As CheckBox - Private WithEvents TAB_AUTO As TabPage - Private WithEvents PANEL_AUTO As Panel + Private WithEvents CH_DOWN_IMAGES_NATIVE As CheckBox End Class End Namespace \ No newline at end of file diff --git a/SCrawler/Editors/GlobalSettingsForm.resx b/SCrawler/Editors/GlobalSettingsForm.resx index f236247..6055126 100644 --- a/SCrawler/Editors/GlobalSettingsForm.resx +++ b/SCrawler/Editors/GlobalSettingsForm.resx @@ -241,6 +241,14 @@ If checked, videos will be stored in separate folder; otherwise, videos will be xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go + tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX + AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC @@ -255,7 +263,7 @@ If checked, videos will be stored in separate folder; otherwise, videos will be False - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO wwAADsMBx2+oZAAAAR5JREFUOE+VkjFqwzAUhn2D9iShRyi+QhYbGujg3ZATZPKYdC6FQhPwlAMkg3dP @@ -266,7 +274,7 @@ If checked, videos will be stored in separate folder; otherwise, videos will be cMaRN0UdBBkAAAAASUVORK5CYII= - + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go diff --git a/SCrawler/Editors/GlobalSettingsForm.vb b/SCrawler/Editors/GlobalSettingsForm.vb index 17f20fb..0d8ca19 100644 --- a/SCrawler/Editors/GlobalSettingsForm.vb +++ b/SCrawler/Editors/GlobalSettingsForm.vb @@ -11,19 +11,10 @@ Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Forms.Toolbars Namespace Editors Friend Class GlobalSettingsForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps - Private ReadOnly Automation As DownloadObjects.AutoDownloaderEditorForm + Private ReadOnly MyDefs As DefaultFormOptions Friend Sub New() InitializeComponent() - MyDefs = New DefaultFormProps - Automation = New DownloadObjects.AutoDownloaderEditorForm With { - .MaximumSize = New Size(0, 0), - .MinimumSize = New Size(0, 0), - .Dock = DockStyle.Fill, - .FormBorderStyle = FormBorderStyle.None, - .TopLevel = False, - .IsControlForm = True - } + MyDefs = New DefaultFormOptions End Sub Private Sub GlobalSettingsForm_Load(sender As Object, e As EventArgs) Handles Me.Load Try @@ -61,6 +52,7 @@ Namespace Editors CH_DEF_TEMP.Checked = .DefaultTemporary CH_DOWN_IMAGES.Checked = .DefaultDownloadImages CH_DOWN_VIDEOS.Checked = .DefaultDownloadVideos + CH_DOWN_IMAGES_NATIVE.Checked = .DownloadNativeImageFormat 'Downloading CH_UDESCR_UP.Checked = .UpdateUserDescriptionEveryTime TXT_SCRIPT.Checked = .ScriptData.Attribute @@ -85,14 +77,10 @@ Namespace Editors CH_COPY_CHANNEL_USER_IMAGE_ALL.Enabled = CH_COPY_CHANNEL_USER_IMAGE.Checked CH_CHANNELS_USERS_TEMP.Checked = .ChannelsDefaultTemporary End With - PANEL_AUTO.Controls.Add(Automation) - Automation.Show() .MyFieldsChecker = New FieldsChecker With DirectCast(.MyFieldsChecker, FieldsChecker) .AddControl(Of String)(TXT_GLOBAL_PATH, TXT_GLOBAL_PATH.CaptionText) .AddControl(Of String)(TXT_COLLECTIONS_PATH, TXT_COLLECTIONS_PATH.CaptionText) - .AddControl(Of Integer)(Automation.TXT_TIMER, Automation.TXT_TIMER.CaptionText,, - New DownloadObjects.AutoDownloaderEditorForm.AutomationTimerChecker) .EndLoaderOperations() End With .EndLoaderOperations() @@ -102,9 +90,6 @@ Namespace Editors MyDefs.InvokeLoaderError(ex) End Try End Sub - Private Sub GlobalSettingsForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed - Automation.Dispose() - End Sub Private Sub OK() Implements IOkCancelToolbar.OK If MyDefs.MyFieldsChecker.AllParamsOK Then With Settings @@ -167,6 +152,7 @@ Namespace Editors .DefaultTemporary.Value = CH_DEF_TEMP.Checked .DefaultDownloadImages.Value = CH_DOWN_IMAGES.Checked .DefaultDownloadVideos.Value = CH_DOWN_VIDEOS.Checked + .DownloadNativeImageFormat.Value = CH_DOWN_IMAGES_NATIVE.Checked 'Downloading .UpdateUserDescriptionEveryTime.Value = CH_UDESCR_UP.Checked .ScriptData.Value = TXT_SCRIPT.Text @@ -193,8 +179,6 @@ Namespace Editors .ChannelsAddUserImagesFromAllChannels.Value = CH_COPY_CHANNEL_USER_IMAGE_ALL.Checked .ChannelsDefaultTemporary.Value = CH_CHANNELS_USERS_TEMP.Checked - Automation.SaveSettings() - .EndUpdate() End With MyDefs.CloseForm() diff --git a/SCrawler/Editors/LabelsForm.Designer.vb b/SCrawler/Editors/LabelsForm.Designer.vb index d0a572e..bdda142 100644 --- a/SCrawler/Editors/LabelsForm.Designer.vb +++ b/SCrawler/Editors/LabelsForm.Designer.vb @@ -43,17 +43,14 @@ Partial Friend Class LabelsForm : Inherits System.Windows.Forms.Form 'CMB_LABELS ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_COMBOBOX_ARROW" - ActionButton1.Visible = False + ActionButton1.Name = "Add" + ActionButton1.ToolTipText = "Add new label (Insert)" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_ADD" - ActionButton2.ToolTipText = "Add new label (Insert)" + ActionButton2.Name = "Clear" + ActionButton2.ToolTipText = "Clear checked labels" ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 2 - ActionButton3.Name = "BTT_CLEAR" - ActionButton3.ToolTipText = "Clear checked labels" + ActionButton3.Name = "ArrowDown" + ActionButton3.Visible = False Me.CMB_LABELS.Buttons.Add(ActionButton1) Me.CMB_LABELS.Buttons.Add(ActionButton2) Me.CMB_LABELS.Buttons.Add(ActionButton3) diff --git a/SCrawler/Editors/LabelsForm.resx b/SCrawler/Editors/LabelsForm.resx index 22fe23b..6ab9463 100644 --- a/SCrawler/Editors/LabelsForm.resx +++ b/SCrawler/Editors/LabelsForm.resx @@ -119,6 +119,36 @@ + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 + JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE + QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W + h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw + IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H + YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim + Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW + NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq + G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335 + ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP + ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH + SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS + IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3 + Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb + uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY + RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv + MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK + 0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go + tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX + AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC + + + iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABGdBTUEAALGPC/xhBQAAE65JREFUeF7t 3X2sJWddB/DdLi2lQG2hdOHuvfM887J7Cxca4ELTQMDWKigIFpBAEAgi9g+CJpJo9Q8NJhgBiYZIYspL @@ -206,36 +236,6 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6LEtW/4flgYiLD1qeX0A AAAASUVORK5CYII= - - - - - iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGOfPtRkwAAACBjSFJNAAB6 - JQAAgIMAAPn/AACA6QAAdTAAAOpgAAA6mAAAF2+SX8VGAAAACXBIWXMAAAsTAAALEwEAmpwYAAADmUlE - QVRIS62WWWxMURjHL220JW1HausmlFrDFKUhnUGH6bRFzJ2idImlC0Vp2mlji1A8iNhCPIjIRES8EU+W - h2oEtbSDTk3HNNM7S01VKsXjkb/vXBo3k1Ee7sMvmZzzzf//ne/+z50RAAxL1MUIG4G/YAv3HSVhF5Vw - IYNdz3LadVj9RgdTB+HQYYPHIJuE1ocSdlEJFzG+1bPRLQLinglIeCkg+XUkKvz56hnkOfQs/rmA8S9H - YEp7FDI64tAQtKhnsMapZ7zzNHsUFnbGY4VzIk70l6hnIH4wsDR7NBZ3apDrSqL5T8eFgUr1DLZ78lim - Q4N8VzK29MxEpZSBa4M16hnU+c3M9CEFpdJsVHsXos63DDcHrf9nQEXD5VymwW/5USLNwl5vJhp7dTgW - NML2pR7jbsUMS+KdMTa5Q8NQxinfBU4dRFcOyjy52OtbhwOBDTgZLKPPmTgY0ON4MBdNfSbYBupxY8Aq - G10dqMG5/nIc7ytGQ6CQRliAamkTN/g1Ai4e95Qy3iogpX0UtBRDnhRzdxq2SXOxz5eFQ70rScCEU335 - ssGxj0YS06HSm4GN3ekwdE2C1hGH1LZR0JDOJof5jwHvnIvzTa0jlooTYfktvt+fhcOBHDQFTWRgxJGP - ObAGsulZLMLWnjlY756K5c4JmNcRi6T2SGheCIihS2l5ozAo6NRhMolnUAcGV6IcwwqvFrX+JTjYuwKH - SfRAYDms/mzs9y1GFe2VSnOw1j0FejqpLN4WCX4ZufiIBwLMLxQGm12rsLQzgWKYgmLPLNTQw6ynpDSS - IBet8y+TqaVRVdFIeJrWuCcj+/0EzH43BomvIhBLI45uFiDcJ+6QwROFwa6+Amb9bGFNg6Xs9Ncd7Oy3 - Knb2eyU7/20nu9y/m136tIvEl6BC0qKoZwby3alo9JVhj7T5R7m/kJVIIityi8zyXmTiW+I10SqyIQNb - uIgNwYuuf25kFd75KPKkI49OmUWnrfYWyXv/wBb2cijhhVf6a9lGei65XclYRDd6mj0GWz2iLBJaH0rY - RSVc5Eywmhm7kuQXHX+bJlBStrh+zTi0PpSwi0q4yNFAOVvgiEcKJWUsxZn/NhT+znlofShhF5VwkRpv - MUtti4KGYjj6sYCIh5QSu4oG27stjItHU+cjeQzvkcFzFQ2KnSKLoc4FukDCXeI2GbSoaFD4ziyPxNxK - 0AUyNxOP1DOwcaG/8I+/LRB+At7psBnyDBG0AAAAAElFTkSuQmCC - - - - - iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO - xAAADsQBlSsOGwAAAIZJREFUOE+1j10KwCAMgz2b755xl/IsvnaL2K20UfbDAmEako+ZROSTafjE12Go - tbbB43rK5xSAQq1VYFtmeQBoqZTSreVZvgTknM8yyyjA/qodsDF9gspD2Bj6B+DH+NqzhQQAG+POMnSX - AFuc5QFgn6ClHh5iOQVAKNixyucB8NY0vG9JOzzyhrdq5IRgAAAAAElFTkSuQmCC \ No newline at end of file diff --git a/SCrawler/Editors/LabelsForm.vb b/SCrawler/Editors/LabelsForm.vb index e8b914b..df84c07 100644 --- a/SCrawler/Editors/LabelsForm.vb +++ b/SCrawler/Editors/LabelsForm.vb @@ -12,7 +12,7 @@ Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls.Base Imports PersonalUtilities.Functions.Messaging Friend Class LabelsForm : Implements IOkCancelDeleteToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Friend ReadOnly Property LabelsList As List(Of String) Private ReadOnly _Source As IEnumerable(Of String) = Nothing Private ReadOnly Property Source As IEnumerable(Of String) @@ -32,7 +32,7 @@ Friend Class LabelsForm : Implements IOkCancelDeleteToolbar InitializeComponent() LabelsList = New List(Of String) LabelsList.ListAddList(LabelsArr) - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub Friend Sub New(ByVal Current As IEnumerable(Of String), ByVal Source As IEnumerable(Of String)) Me.New(Current) diff --git a/SCrawler/Editors/SiteEditorForm.Designer.vb b/SCrawler/Editors/SiteEditorForm.Designer.vb index 411dbdb..8f58969 100644 --- a/SCrawler/Editors/SiteEditorForm.Designer.vb +++ b/SCrawler/Editors/SiteEditorForm.Designer.vb @@ -62,11 +62,9 @@ 'TXT_PATH ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_OPEN" + ActionButton1.Name = "Open" ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) - ActionButton2.Index = 1 - ActionButton2.Name = "BTT_CLEAR" + ActionButton2.Name = "Clear" Me.TXT_PATH.Buttons.Add(ActionButton1) Me.TXT_PATH.Buttons.Add(ActionButton2) Me.TXT_PATH.CaptionText = "Path" @@ -81,11 +79,9 @@ 'TXT_COOKIES ' ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 0 - ActionButton3.Name = "BTT_EDIT" + ActionButton3.Name = "Edit" ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) - ActionButton4.Index = 1 - ActionButton4.Name = "BTT_CLEAR" + ActionButton4.Name = "Clear" Me.TXT_COOKIES.Buttons.Add(ActionButton3) Me.TXT_COOKIES.Buttons.Add(ActionButton4) Me.TXT_COOKIES.CaptionText = "Cookies" @@ -117,11 +113,9 @@ 'TXT_PATH_SAVED_POSTS ' ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image) - ActionButton5.Index = 0 - ActionButton5.Name = "BTT_OPEN" + ActionButton5.Name = "Open" ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) - ActionButton6.Index = 1 - ActionButton6.Name = "BTT_CLEAR" + ActionButton6.Name = "Clear" Me.TXT_PATH_SAVED_POSTS.Buttons.Add(ActionButton5) Me.TXT_PATH_SAVED_POSTS.Buttons.Add(ActionButton6) Me.TXT_PATH_SAVED_POSTS.CaptionText = "Saved posts path" diff --git a/SCrawler/Editors/SiteEditorForm.vb b/SCrawler/Editors/SiteEditorForm.vb index bddc7d1..5831e66 100644 --- a/SCrawler/Editors/SiteEditorForm.vb +++ b/SCrawler/Editors/SiteEditorForm.vb @@ -18,7 +18,7 @@ Namespace Editors Friend Class SiteEditorForm : Implements IOkCancelToolbar Private ReadOnly LBL_AUTH As Label Private ReadOnly LBL_OTHER As Label - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Private WithEvents SpecialButton As Button #Region "Providers" Private Class SavedPostsChecker : Implements IFieldsCheckerProvider @@ -42,7 +42,7 @@ Namespace Editors Private ReadOnly Property Host As SettingsHost Friend Sub New(ByVal h As SettingsHost) InitializeComponent() - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions Host = h LBL_AUTH = New Label With {.Text = "Authorization", .TextAlign = ContentAlignment.MiddleCenter, .Dock = DockStyle.Fill} LBL_OTHER = New Label With {.Text = "Other Parameters", .TextAlign = ContentAlignment.MiddleCenter, .Dock = DockStyle.Fill} diff --git a/SCrawler/Editors/SiteSelectionForm.Designer.vb b/SCrawler/Editors/SiteSelectionForm.Designer.vb index 4e03089..690e688 100644 --- a/SCrawler/Editors/SiteSelectionForm.Designer.vb +++ b/SCrawler/Editors/SiteSelectionForm.Designer.vb @@ -52,8 +52,7 @@ Namespace Editors 'CMB_SITES ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_COMBOBOX_ARROW" + ActionButton1.Name = "ArrowDown" ActionButton1.Visible = False Me.CMB_SITES.Buttons.Add(ActionButton1) ListColumn1.DisplayMember = True diff --git a/SCrawler/Editors/SiteSelectionForm.vb b/SCrawler/Editors/SiteSelectionForm.vb index 0db5d19..071d3dc 100644 --- a/SCrawler/Editors/SiteSelectionForm.vb +++ b/SCrawler/Editors/SiteSelectionForm.vb @@ -11,13 +11,13 @@ Imports PersonalUtilities.Forms.Toolbars Imports PersonalUtilities.Forms.Controls.Base Namespace Editors Friend Class SiteSelectionForm : Implements IOkCancelToolbar - Private ReadOnly MyDefs As DefaultFormProps + Private ReadOnly MyDefs As DefaultFormOptions Friend ReadOnly Property SelectedSites As List(Of String) Friend Sub New(ByVal s As List(Of String)) InitializeComponent() SelectedSites.ListAddList(s) If SelectedSites Is Nothing Then SelectedSites = New List(Of String) - MyDefs = New DefaultFormProps + MyDefs = New DefaultFormOptions End Sub Private Sub SiteSelectionForm_Load(sender As Object, e As EventArgs) Handles Me.Load With MyDefs @@ -32,7 +32,7 @@ Namespace Editors CMB_SITES.EndUpdate() If l.Count > 0 Then CMB_SITES.ListCheckedIndexes = l : l.Clear() .DelegateClosingChecker = False - .EndLoaderOperations(False) + .EndLoaderOperations() .MyOkCancel.EnableOK = True End With End Sub diff --git a/SCrawler/Editors/UserCreatorForm.Designer.vb b/SCrawler/Editors/UserCreatorForm.Designer.vb index cf46304..1aafee9 100644 --- a/SCrawler/Editors/UserCreatorForm.Designer.vb +++ b/SCrawler/Editors/UserCreatorForm.Designer.vb @@ -125,7 +125,7 @@ TP_SITE.ColumnCount = 3 TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 79.0!)) TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100.0!)) - TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 96.0!)) + TP_SITE.ColumnStyles.Add(New System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 98.0!)) TP_SITE.Controls.Add(Me.CH_IS_CHANNEL, 0, 0) TP_SITE.Controls.Add(Me.CMB_SITE, 1, 0) TP_SITE.Controls.Add(Me.BTT_OTHER_SETTINGS, 2, 0) @@ -152,8 +152,7 @@ 'CMB_SITE ' ActionButton1.BackgroundImage = CType(resources.GetObject("ActionButton1.BackgroundImage"), System.Drawing.Image) - ActionButton1.Index = 0 - ActionButton1.Name = "BTT_COMBOBOX_ARROW" + ActionButton1.Name = "ArrowDown" Me.CMB_SITE.Buttons.Add(ActionButton1) ListColumn1.Name = "_COL_KEY" ListColumn1.Text = "Key" @@ -169,17 +168,17 @@ Me.CMB_SITE.Location = New System.Drawing.Point(84, 3) Me.CMB_SITE.Margin = New System.Windows.Forms.Padding(3, 2, 3, 3) Me.CMB_SITE.Name = "CMB_SITE" - Me.CMB_SITE.Size = New System.Drawing.Size(267, 22) + Me.CMB_SITE.Size = New System.Drawing.Size(265, 22) Me.CMB_SITE.TabIndex = 1 Me.CMB_SITE.TextBoxBorderStyle = System.Windows.Forms.BorderStyle.FixedSingle ' 'BTT_OTHER_SETTINGS ' Me.BTT_OTHER_SETTINGS.Dock = System.Windows.Forms.DockStyle.Fill - Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(356, 2) + Me.BTT_OTHER_SETTINGS.Location = New System.Drawing.Point(354, 2) Me.BTT_OTHER_SETTINGS.Margin = New System.Windows.Forms.Padding(1) Me.BTT_OTHER_SETTINGS.Name = "BTT_OTHER_SETTINGS" - Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(94, 24) + Me.BTT_OTHER_SETTINGS.Size = New System.Drawing.Size(96, 24) Me.BTT_OTHER_SETTINGS.TabIndex = 2 Me.BTT_OTHER_SETTINGS.Text = "Options (F2)" TT_MAIN.SetToolTip(Me.BTT_OTHER_SETTINGS, "Other settings") @@ -272,8 +271,7 @@ ' ActionButton2.BackgroundImage = CType(resources.GetObject("ActionButton2.BackgroundImage"), System.Drawing.Image) ActionButton2.Dock = System.Windows.Forms.DockStyle.Top - ActionButton2.Index = 0 - ActionButton2.Name = "BTT_CLEAR" + ActionButton2.Name = "Clear" Me.TXT_DESCR.Buttons.Add(ActionButton2) Me.TXT_DESCR.CaptionDock = System.Windows.Forms.DockStyle.Top Me.TXT_DESCR.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.None @@ -339,11 +337,9 @@ 'TXT_LABELS ' ActionButton3.BackgroundImage = CType(resources.GetObject("ActionButton3.BackgroundImage"), System.Drawing.Image) - ActionButton3.Index = 0 - ActionButton3.Name = "BTT_OPEN" + ActionButton3.Name = "Open" ActionButton4.BackgroundImage = CType(resources.GetObject("ActionButton4.BackgroundImage"), System.Drawing.Image) - ActionButton4.Index = 1 - ActionButton4.Name = "BTT_CLEAR" + ActionButton4.Name = "Clear" Me.TXT_LABELS.Buttons.Add(ActionButton3) Me.TXT_LABELS.Buttons.Add(ActionButton4) Me.TXT_LABELS.CaptionText = "Labels" @@ -399,12 +395,10 @@ 'TXT_SPEC_FOLDER ' ActionButton5.BackgroundImage = CType(resources.GetObject("ActionButton5.BackgroundImage"), System.Drawing.Image) - ActionButton5.Index = 0 - ActionButton5.Name = "BTT_OPEN" + ActionButton5.Name = "Open" ActionButton5.ToolTipText = "Select a new path in the folder selection dialog" ActionButton6.BackgroundImage = CType(resources.GetObject("ActionButton6.BackgroundImage"), System.Drawing.Image) - ActionButton6.Index = 1 - ActionButton6.Name = "BTT_CLEAR" + ActionButton6.Name = "Clear" ActionButton6.ToolTipText = "Clear" Me.TXT_SPEC_FOLDER.Buttons.Add(ActionButton5) Me.TXT_SPEC_FOLDER.Buttons.Add(ActionButton6) @@ -419,12 +413,10 @@ ' ActionButton7.BackgroundImage = CType(resources.GetObject("ActionButton7.BackgroundImage"), System.Drawing.Image) ActionButton7.Enabled = False - ActionButton7.Index = 0 - ActionButton7.Name = "BTT_OPEN" + ActionButton7.Name = "Open" ActionButton8.BackgroundImage = CType(resources.GetObject("ActionButton8.BackgroundImage"), System.Drawing.Image) ActionButton8.Enabled = False - ActionButton8.Index = 1 - ActionButton8.Name = "BTT_CLEAR" + ActionButton8.Name = "Clear" Me.TXT_SCRIPT.Buttons.Add(ActionButton7) Me.TXT_SCRIPT.Buttons.Add(ActionButton8) Me.TXT_SCRIPT.CaptionMode = PersonalUtilities.Forms.Controls.Base.ICaptionControl.Modes.CheckBox diff --git a/SCrawler/Editors/UserCreatorForm.vb b/SCrawler/Editors/UserCreatorForm.vb index 48b3896..467564c 100644 --- a/SCrawler/Editors/UserCreatorForm.vb +++ b/SCrawler/Editors/UserCreatorForm.vb @@ -6,7 +6,6 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY -Imports System.ComponentModel Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls.Base @@ -18,10 +17,10 @@ Imports SCrawler.Plugin.Hosts Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons Namespace Editors Friend Class UserCreatorForm : Implements IOkCancelToolbar - - Private ReadOnly MyDef As DefaultFormProps + Private ReadOnly MyDef As DefaultFormOptions Friend Property User As UserInfo - Friend Property UserInstance As IUserData + Private Property UserInstance As IUserData +#Region "User options" Friend Property StartIndex As Integer = -1 Friend ReadOnly Property UserTemporary As Boolean Get @@ -77,6 +76,8 @@ Namespace Editors Return TXT_SCRIPT.Text End Get End Property +#End Region +#Region "Exchange, Path, Labels" Friend Property MyExchangeOptions As Object = Nothing Private ReadOnly _SpecPathPattern As RParams = RParams.DM("\w:\\.*", 0, EDP.ReturnValue) Private ReadOnly Property SpecialPath(ByVal s As SettingsHost) As SFile @@ -93,11 +94,13 @@ Namespace Editors End Get End Property Friend ReadOnly Property UserLabels As List(Of String) +#End Region +#Region "Initializers" ''' Create new user Friend Sub New() InitializeComponent() UserLabels = New List(Of String) - MyDef = New DefaultFormProps + MyDef = New DefaultFormOptions End Sub ''' Edit exist user Friend Sub New(ByVal _Instance As IUserData) @@ -107,6 +110,8 @@ Namespace Editors User = DirectCast(UserInstance, UserDataBase).User End If End Sub +#End Region +#Region "Form handlers" Private Sub UserCreatorForm_Load(sender As Object, e As EventArgs) Handles Me.Load Try With MyDef @@ -180,19 +185,11 @@ Namespace Editors End Select If b Then e.Handled = True End Sub - Private Sub UserCreatorForm_Closing(sender As Object, e As CancelEventArgs) Handles Me.Closing - If Not BeforeCloseChecker(MyDef.ChangesDetected) Then - e.Cancel = True - Else - MyDef.Dispose() - End If - End Sub Private Sub UserCreatorForm_Disposed(sender As Object, e As EventArgs) Handles Me.Disposed UserLabels.Clear() End Sub - Private Function GetSiteByCheckers() As SettingsHost - Return If(CMB_SITE.SelectedIndex >= 0, Settings(CStr(CMB_SITE.Items(CMB_SITE.SelectedIndex).Value(0))), Nothing) - End Function +#End Region +#Region "Ok, Cancel" Private Sub OK() Implements IOkCancelToolbar.OK If Not CH_ADD_BY_LIST.Checked Then If MyDef.MyFieldsChecker.AllParamsOK Then @@ -256,6 +253,8 @@ CloseForm: Private Sub Cancel() Implements IOkCancelToolbar.Cancel MyDef.CloseForm(IIf(StartIndex >= 0, DialogResult.OK, DialogResult.Cancel)) End Sub +#End Region +#Region "Controls handlers" Private _TextChangeInvoked As Boolean = False Private Sub TXT_USER_ActionOnTextChange() Handles TXT_USER.ActionOnTextChange Try @@ -284,14 +283,6 @@ CloseForm: Catch ex As Exception End Try End Sub - Private Function GetSiteByText(ByRef TXT As String) As ExchangeOptions - Dim s As ExchangeOptions - For Each p As PluginHost In Settings.Plugins - s = p.Settings.IsMyUser(TXT) - If Not s.UserName.IsEmptyString Then Return s - Next - Return Nothing - End Function Private Sub CMB_SITE_ActionSelectedItemChanged(ByVal _Item As ListViewItem) Handles CMB_SITE.ActionSelectedItemChanged CH_IS_CHANNEL.Checked = False MyExchangeOptions = Nothing @@ -319,30 +310,6 @@ CloseForm: Private Sub CH_FAV_CheckedChanged(sender As Object, e As EventArgs) Handles CH_FAV.CheckedChanged If CH_FAV.Checked Then CH_TEMP.Checked = False End Sub - Private Sub SetParamsBySite() - Dim s As SettingsHost = GetSiteByCheckers() - If Not s Is Nothing Then - With s - CH_TEMP.Checked = .Temporary - CH_DOWN_IMAGES.Checked = .DownloadImages - CH_DOWN_VIDEOS.Checked = .DownloadVideos - CH_PARSE_USER_MEDIA.Checked = .GetUserMediaOnly.Value - CH_READY_FOR_DOWN.Checked = Not CH_TEMP.Checked - If s.HasSpecialOptions Then - BTT_OTHER_SETTINGS.Enabled = True - If UserInstance Is Nothing Then - s.Source.UserOptions(MyExchangeOptions, False) - Else - MyExchangeOptions = DirectCast(UserInstance, UserDataBase).ExchangeOptionsGet - End If - Else - BTT_OTHER_SETTINGS.Enabled = False - End If - End With - Else - BTT_OTHER_SETTINGS.Enabled = False - End If - End Sub Private Sub CH_ADD_BY_LIST_CheckedChanged(sender As Object, e As EventArgs) Handles CH_ADD_BY_LIST.CheckedChanged If CH_ADD_BY_LIST.Checked Then TXT_DESCR.GroupBoxText = "Users list" @@ -366,6 +333,20 @@ CloseForm: BTT_OTHER_SETTINGS.Enabled = True End If End Sub + Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_LABELS.ActionOnButtonClick + Select Case Sender.DefaultButton + Case ADB.Open : ChangeLabels() + Case ADB.Clear : UserLabels.Clear() + End Select + End Sub + Private Sub TXT_SCRIPT_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_SCRIPT.ActionOnButtonClick + SettingsCLS.ScriptTextBoxButtonClick(TXT_SCRIPT, Sender) + End Sub +#End Region +#Region "Functions" + Private Function GetSiteByCheckers() As SettingsHost + Return If(CMB_SITE.SelectedIndex >= 0, Settings(CStr(CMB_SITE.Items(CMB_SITE.SelectedIndex).Value(0))), Nothing) + End Function Private Function CreateUsersByList() As Boolean Try If CH_ADD_BY_LIST.Checked Then @@ -471,11 +452,37 @@ CloseForm: Return ErrorsDescriber.Execute(EDP.LogMessageValue, ex, "Error on adding users by list", False) End Try End Function - Private Sub TXT_LABELS_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_LABELS.ActionOnButtonClick - Select Case Sender.DefaultButton - Case ADB.Open : ChangeLabels() - Case ADB.Clear : UserLabels.Clear() - End Select + Private Function GetSiteByText(ByRef TXT As String) As ExchangeOptions + Dim s As ExchangeOptions + For Each p As PluginHost In Settings.Plugins + s = p.Settings.IsMyUser(TXT) + If Not s.UserName.IsEmptyString Then Return s + Next + Return Nothing + End Function + Private Sub SetParamsBySite() + Dim s As SettingsHost = GetSiteByCheckers() + If Not s Is Nothing Then + With s + CH_TEMP.Checked = .Temporary + CH_DOWN_IMAGES.Checked = .DownloadImages + CH_DOWN_VIDEOS.Checked = .DownloadVideos + CH_PARSE_USER_MEDIA.Checked = .GetUserMediaOnly.Value + CH_READY_FOR_DOWN.Checked = Not CH_TEMP.Checked + If s.HasSpecialOptions Then + BTT_OTHER_SETTINGS.Enabled = True + If UserInstance Is Nothing Then + s.Source.UserOptions(MyExchangeOptions, False) + Else + MyExchangeOptions = DirectCast(UserInstance, UserDataBase).ExchangeOptionsGet + End If + Else + BTT_OTHER_SETTINGS.Enabled = False + End If + End With + Else + BTT_OTHER_SETTINGS.Enabled = False + End If End Sub Private Sub ChangeLabels() Using fl As New LabelsForm(UserLabels) @@ -490,8 +497,6 @@ CloseForm: End If End Using End Sub - Private Sub TXT_SCRIPT_ActionOnButtonClick(ByVal Sender As ActionButton) Handles TXT_SCRIPT.ActionOnButtonClick - SettingsCLS.ScriptTextBoxButtonClick(TXT_SCRIPT, Sender) - End Sub +#End Region End Class End Namespace \ No newline at end of file diff --git a/SCrawler/FDatePickerForm.vb b/SCrawler/FDatePickerForm.vb index b044b44..cc8177c 100644 --- a/SCrawler/FDatePickerForm.vb +++ b/SCrawler/FDatePickerForm.vb @@ -9,7 +9,7 @@ Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Toolbars Friend Class FDatePickerForm : Implements IOkCancelDeleteToolbar - Private MyDefs As DefaultFormProps + Private MyDefs As DefaultFormOptions Friend ReadOnly Property SelectedDate As Date? Get If DT.Checked Then Return DT.Value.Date Else Return Nothing @@ -21,24 +21,20 @@ Friend Class FDatePickerForm : Implements IOkCancelDeleteToolbar _InitialValue = d End Sub Private Sub FDatePickerForm_Load(sender As Object, e As EventArgs) Handles Me.Load - Try - MyDefs = New DefaultFormProps - With MyDefs - .MyViewInitialize(Me, Settings.Design, True) - .AddOkCancelToolbar() - If _InitialValue.HasValue Then - DT.Checked = True - DT.Value = _InitialValue.Value.Date - Else - DT.Checked = False - End If - .DelegateClosingChecker = False - .EndLoaderOperations() - MyDefs.MyOkCancel.EnableOK = True - End With - Catch ex As Exception - MyDefs.InvokeLoaderError(ex) - End Try + MyDefs = New DefaultFormOptions + With MyDefs + .MyViewInitialize(Me, Settings.Design, True) + .AddOkCancelToolbar() + If _InitialValue.HasValue Then + DT.Checked = True + DT.Value = _InitialValue.Value.Date + Else + DT.Checked = False + End If + .DelegateClosingChecker = False + .EndLoaderOperations() + MyDefs.MyOkCancel.EnableOK = True + End With End Sub Private Sub OK() Implements IOkCancelToolbar.OK MyDefs.CloseForm() diff --git a/SCrawler/MainFrame.vb b/SCrawler/MainFrame.vb index 04c52f3..4e3683d 100644 --- a/SCrawler/MainFrame.vb +++ b/SCrawler/MainFrame.vb @@ -15,7 +15,6 @@ Imports SCrawler.API.Base Imports SCrawler.Editors Imports SCrawler.DownloadObjects Imports SCrawler.Plugin.Hosts -Imports PersonalUtilities.Functions.Messaging Public Class MainFrame Private MyView As FormsView Private ReadOnly _VideoDownloadingMode As Boolean = False @@ -95,12 +94,12 @@ Public Class MainFrame For Each ugroup As Groups.DownloadGroup In Settings.Groups : GROUPS_Added(ugroup) : Next End If End With - Settings.Automation = New AutoDownloader + Settings.Automation = New Scheduler AddHandler Settings.Groups.Updated, AddressOf Settings.Automation.GROUPS_Updated AddHandler Settings.Groups.Deleted, AddressOf Settings.Automation.GROUPS_Deleted AddHandler Settings.Automation.UserFind, AddressOf FocusUser _UFinit = False - Settings.Automation.Start() + Settings.Automation.Start(True) GoTo EndFunction FormClosingInvoker: Close() @@ -273,7 +272,6 @@ CloseResume: (Not sg = Settings.ShowGroups And .UseGrouping) Then RefillList() TrayIcon.Visible = .CloseToTray LIST_PROFILES.ShowGroups = .UseGrouping - If Not Settings.Automation.Mode = AutoDownloader.Modes.None Then Settings.Automation.Start() End If End Using End With @@ -426,10 +424,8 @@ CloseResume: End Sub #End Region Private Sub BTT_DOWN_AUTOMATION_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION.Click - Using f As New AutoDownloaderEditorForm - f.ShowDialog() - If f.DialogResult = DialogResult.OK AndAlso Not Settings.Automation.Mode = AutoDownloader.Modes.None Then Settings.Automation.Start() - End Using + Using f As New SchedulerEditorForm : f.ShowDialog() : End Using + Settings.Automation.Start(False) End Sub Private Sub BTT_DOWN_AUTOMATION_PAUSE_Click(sender As Object, e As EventArgs) Handles BTT_DOWN_AUTOMATION_PAUSE.Click Settings.Automation.Pause = Not Settings.Automation.Pause @@ -1198,7 +1194,7 @@ ResumeDownloadingOperation: End If End Sub Private Sub Downloader_OnDownloading(ByVal Value As Boolean) - Dim a As Action = Sub() BTT_DOWN_STOP.Enabled = Value + Dim a As Action = Sub() BTT_DOWN_STOP.Enabled = Value Or Downloader.Working If Toolbar_TOP.InvokeRequired Then Toolbar_TOP.Invoke(a) Else a.Invoke End Sub Private Sub NotificationMessage(ByVal Message As String) diff --git a/SCrawler/MainFrameObjects.vb b/SCrawler/MainFrameObjects.vb index 73182ed..96e7d26 100644 --- a/SCrawler/MainFrameObjects.vb +++ b/SCrawler/MainFrameObjects.vb @@ -23,9 +23,9 @@ Friend Class MainFrameObjects Friend Sub ImageHandler(ByVal User As IUserData, ByVal Add As Boolean) Try If Add Then - AddHandler User.OnUserUpdated, AddressOf MF.User_OnUserUpdated + AddHandler User.UserUpdated, AddressOf MF.User_OnUserUpdated Else - RemoveHandler User.OnUserUpdated, AddressOf MF.User_OnUserUpdated + RemoveHandler User.UserUpdated, AddressOf MF.User_OnUserUpdated End If Catch ex As Exception End Try diff --git a/SCrawler/My Project/AssemblyInfo.vb b/SCrawler/My Project/AssemblyInfo.vb index 28b0db7..df86a96 100644 --- a/SCrawler/My Project/AssemblyInfo.vb +++ b/SCrawler/My Project/AssemblyInfo.vb @@ -32,6 +32,6 @@ Imports System.Runtime.InteropServices ' by using the '*' as shown below: ' - - + + diff --git a/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb b/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb index 5ecece1..e2766fd 100644 --- a/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb +++ b/SCrawler/PluginsEnvironment/Hosts/PropertyValueHost.vb @@ -6,13 +6,13 @@ ' ' This program is distributed in the hope that it will be useful, ' but WITHOUT ANY WARRANTY +Imports System.Reflection +Imports SCrawler.Plugin.Attributes Imports PersonalUtilities.Functions.XML.Base Imports PersonalUtilities.Forms Imports PersonalUtilities.Forms.Controls Imports PersonalUtilities.Forms.Controls.Base Imports ADB = PersonalUtilities.Forms.Controls.Base.ActionButton.DefaultButtons -Imports SCrawler.Plugin.Attributes -Imports System.Reflection Namespace Plugin.Hosts Friend Class PropertyValueHost : Implements IPropertyValue, IComparable(Of PropertyValueHost) Friend Const LeftOffsetDefault As Integer = 100 @@ -41,33 +41,43 @@ Namespace Plugin.Hosts End Property Friend Sub CreateControl(Optional ByVal TT As ToolTip = Nothing) With Options - If Type Is GetType(Boolean) Then - Control = New CheckBox - If Not .ControlToolTip.IsEmptyString And Not TT Is Nothing Then TT.SetToolTip(Control, .ControlToolTip) - DirectCast(Control, CheckBox).ThreeState = .ThreeStates - DirectCast(Control, CheckBox).Text = .ControlText - If .ThreeStates Then - DirectCast(Control, CheckBox).CheckState = CInt(AConvert(Of Integer)(Value, CInt(CheckState.Indeterminate))) - Else - DirectCast(Control, CheckBox).Checked = CBool(AConvert(Of Boolean)(Value, False)) - End If - Control.Padding = New PaddingE(Control.Padding) With {.Left = LeftOffset} - Else - Control = New TextBoxExtended - With DirectCast(Control, TextBoxExtended) - .CaptionText = Options.ControlText - .CaptionToolTipEnabled = Not Options.ControlToolTip.IsEmptyString - .CaptionWidth = LeftOffset - If Not Options.ControlToolTip.IsEmptyString Then .CaptionToolTipText = Options.ControlToolTip : .CaptionToolTipEnabled = True + If .IsInformationLabel Then + Control = New Label + With DirectCast(Control, Label) + .Padding = New PaddingE(Control.Padding) With {.Left = LeftOffset} .Text = CStr(AConvert(Of String)(Value, String.Empty)) - With .Buttons - .BeginInit() - If Not Source Is Nothing And Not UpdateMethod Is Nothing Then .Add(New ActionButton(ADB.Refresh)) - .Add(ADB.Clear) - .EndInit(True) - End With - AddHandler .ActionOnButtonClick, AddressOf TextBoxClick + .TextAlign = Options.LabelTextAlign End With + If Not .ControlToolTip.IsEmptyString And Not TT Is Nothing Then TT.SetToolTip(Control, .ControlToolTip) + Else + If Type Is GetType(Boolean) Then + Control = New CheckBox + If Not .ControlToolTip.IsEmptyString And Not TT Is Nothing Then TT.SetToolTip(Control, .ControlToolTip) + DirectCast(Control, CheckBox).ThreeState = .ThreeStates + DirectCast(Control, CheckBox).Text = .ControlText + If .ThreeStates Then + DirectCast(Control, CheckBox).CheckState = CInt(AConvert(Of Integer)(Value, CInt(CheckState.Indeterminate))) + Else + DirectCast(Control, CheckBox).Checked = CBool(AConvert(Of Boolean)(Value, False)) + End If + Control.Padding = New PaddingE(Control.Padding) With {.Left = LeftOffset} + Else + Control = New TextBoxExtended + With DirectCast(Control, TextBoxExtended) + .CaptionText = Options.ControlText + .CaptionToolTipEnabled = Not Options.ControlToolTip.IsEmptyString + .CaptionWidth = LeftOffset + If Not Options.ControlToolTip.IsEmptyString Then .CaptionToolTipText = Options.ControlToolTip : .CaptionToolTipEnabled = True + .Text = CStr(AConvert(Of String)(Value, String.Empty)) + With .Buttons + .BeginInit() + If Not Source Is Nothing And Not UpdateMethod Is Nothing Then .Add(New ActionButton(ADB.Refresh)) + .Add(ADB.Clear) + .EndInit(True) + End With + AddHandler .ActionOnButtonClick, AddressOf TextBoxClick + End With + End If End If Control.Tag = Name Control.Dock = DockStyle.Fill @@ -89,7 +99,7 @@ Namespace Plugin.Hosts End Try End Sub Friend Sub UpdateValueByControl() - If Not Control Is Nothing Then + If Not Control Is Nothing AndAlso Not TypeOf Control Is Label Then If TypeOf Control Is CheckBox Then With DirectCast(Control, CheckBox) If Options.ThreeStates Then Value = CInt(.CheckState) Else Value = .Checked diff --git a/SCrawler/SCrawler.vbproj b/SCrawler/SCrawler.vbproj index 45ceeb7..77c397f 100644 --- a/SCrawler/SCrawler.vbproj +++ b/SCrawler/SCrawler.vbproj @@ -138,9 +138,7 @@ - - OptionsForm.vb @@ -180,6 +178,13 @@ Form + + + SchedulerEditorForm.vb + + + Form + @@ -339,6 +344,9 @@ GroupEditorForm.vb + + SchedulerEditorForm.vb + CollectionEditorForm.vb diff --git a/SCrawler/SettingsCLS.vb b/SCrawler/SettingsCLS.vb index 0a53473..229b9a5 100644 --- a/SCrawler/SettingsCLS.vb +++ b/SCrawler/SettingsCLS.vb @@ -34,7 +34,7 @@ Friend Class SettingsCLS : Implements IDisposable Friend Property Channels As Reddit.ChannelsCollection Friend ReadOnly Property Labels As LabelsKeeper Friend ReadOnly Property Groups As Groups.DownloadGroupCollection - Friend Property Automation As AutoDownloader + Friend Property Automation As Scheduler Friend ReadOnly Property BlackList As List(Of UserBan) Private ReadOnly BlackListFile As SFile = $"{SettingsFolderName}\BlackList.txt" Private ReadOnly UsersSettingsFile As SFile = $"{SettingsFolderName}\Users.xml" @@ -62,6 +62,7 @@ Friend Class SettingsCLS : Implements IDisposable DefaultDownloadImages = New XMLValue(Of Boolean)("DownloadImages", True, MyXML, n) DefaultDownloadVideos = New XMLValue(Of Boolean)("DownloadVideos", True, MyXML, n) ChangeReadyForDownOnTempChange = New XMLValue(Of Boolean)("ChangeReadyForDownOnTempChange", True, MyXML, n) + DownloadNativeImageFormat = New XMLValue(Of Boolean)("DownloadNativeImageFormat", True, MyXML, n) Plugins.AddRange(PluginHost.GetMyHosts(MyXML, GlobalPath.Value, DefaultTemporary, DefaultDownloadImages, DefaultDownloadVideos)) Dim tmpPluginList As IEnumerable(Of PluginHost) = PluginHost.GetPluginsHosts(MyXML, GlobalPath.Value, DefaultTemporary, @@ -390,6 +391,7 @@ Friend Class SettingsCLS : Implements IDisposable Friend ReadOnly Property DefaultDownloadImages As XMLValue(Of Boolean) Friend ReadOnly Property DefaultDownloadVideos As XMLValue(Of Boolean) Friend ReadOnly Property ChangeReadyForDownOnTempChange As XMLValue(Of Boolean) + Friend ReadOnly Property DownloadNativeImageFormat As XMLValue(Of Boolean) #End Region #Region "User data" Friend ReadOnly Property FromChannelDownloadTop As XMLValue(Of Integer)