diff --git a/README.RU.md b/README.RU.md index 16b5e97..e252caf 100644 --- a/README.RU.md +++ b/README.RU.md @@ -7,7 +7,7 @@ ![](https://user-images.githubusercontent.com/9499881/43281249-45db3712-9124-11e8-84f0-69d508b30764.PNG) ## Загрузка ->Версия для Windows XP, 7, 8.1, 10.
+>Версия для Windows 7, 8.1, 10.
**[Загрузить](https://github.com/r57zone/Podcast-Easy-for-Windows/releases)**
>Версия для Python и QPython (Android)
**[Загрузить](https://github.com/r57zone/Podcast-Easy-for-python)**
diff --git a/README.md b/README.md index 62d730c..0637877 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Application for download podcasts. Enter rss feeds manually or import OPML file ![](https://user-images.githubusercontent.com/9499881/43281281-58622af8-9124-11e8-8e4b-66f21e9511aa.PNG) ## Download ->Version for Windows XP, 7, 8.1, 10.
+>Version for Windows 7, 8.1, 10.
**[Download](https://github.com/r57zone/Podcast-Easy-for-Windows/releases)**
>Version for Python and QPython (Android)
**[Download](https://github.com/r57zone/Podcast-Easy-for-python)**
diff --git a/Source/Downloaded.txt b/Source/Downloaded.txt deleted file mode 100644 index e69de29..0000000 diff --git a/Source/Languages/English.ini b/Source/Languages/English.ini index fdfd98f..9950e49 100644 --- a/Source/Languages/English.ini +++ b/Source/Languages/English.ini @@ -1,9 +1,10 @@ [Main] ID_REFRESH=Refresh +ID_CANCEL=Cancel ID_DOWNLOADS=Downloads ID_CHECK_FEED=Checking news feeds: %d of %d ID_NEW_PODCAST=Found new podcast on -ID_DOWNLOAD_PODCASTS=Downloading podcasts: %d of %d +ID_DOWNLOAD_PODCASTS=Downloading podcasts: %d of %d, current %d%% ID_PODCASTS_DOWNLOADED=All podcasts downloaded ID_PODCASTS_SKIPPED=All podcasts skipped ID_PODCASTS_NOT_FOUND=New podcasts not found diff --git a/Source/Languages/Russian.ini b/Source/Languages/Russian.ini index b57663e..d95aba4 100644 --- a/Source/Languages/Russian.ini +++ b/Source/Languages/Russian.ini @@ -1,9 +1,10 @@ [Main] ID_REFRESH= +ID_CANCEL= ID_DOWNLOADS= ID_CHECK_FEED= : %d %d ID_NEW_PODCAST= -ID_DOWNLOAD_PODCASTS= : %d %d +ID_DOWNLOAD_PODCASTS= : %d %d, %d%% ID_PODCASTS_DOWNLOADED= ID_PODCASTS_SKIPPED= ID_PODCASTS_NOT_FOUND= diff --git a/Source/Unit1.dfm b/Source/Unit1.dfm index 34ee070..343ea63 100644 --- a/Source/Unit1.dfm +++ b/Source/Unit1.dfm @@ -16,14 +16,58 @@ object Main: TMain Position = poScreenCenter OnClose = FormClose OnCreate = FormCreate + OnKeyDown = FormKeyDown PixelsPerInch = 96 TextHeight = 13 - object SettingsBtn: TSpeedButton + object RefreshBtn: TButton + Left = 7 + Top = 6 + Width = 75 + Height = 25 + Caption = #1054#1073#1085#1086#1074#1080#1090#1100 + TabOrder = 0 + OnClick = RefreshBtnClick + end + object RSSListMemo: TMemo + Left = 7 + Top = 38 + Width = 281 + Height = 102 + Font.Charset = RUSSIAN_CHARSET + Font.Color = clWindowText + Font.Height = -11 + Font.Name = 'MS Sans Serif' + Font.Style = [] + ParentFont = False + ScrollBars = ssBoth + TabOrder = 2 + OnChange = RSSListMemoChange + OnKeyDown = RSSListMemoKeyDown + end + object StatusBar: TStatusBar + Left = 0 + Top = 143 + Width = 294 + Height = 19 + Panels = <> + SimplePanel = True + end + object OpenFolderBtn: TButton + Left = 86 + Top = 6 + Width = 75 + Height = 25 + Caption = #1047#1072#1075#1088#1091#1079#1082#1080 + TabOrder = 1 + OnClick = OpenFolderBtnClick + end + object SettingsBtn: TBitBtn Left = 264 Top = 6 Width = 25 Height = 25 - Flat = True + TabOrder = 4 + OnClick = SettingsBtnClick Glyph.Data = { 36060000424D3606000000000000360000002800000020000000100000000100 18000000000000060000120B0000120B00000000000000000000FF00FFFF00FF @@ -76,59 +120,19 @@ object Main: TMain FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFADADADC0 C0C0ADADADFF00FFFF00FFFF00FFFF00FFFF00FFFF00FFFF00FF} NumGlyphs = 2 - OnClick = SettingsBtnClick - end - object RefreshBtn: TButton - Left = 7 - Top = 6 - Width = 75 - Height = 25 - Caption = #1054#1073#1085#1086#1074#1080#1090#1100 - TabOrder = 0 - OnClick = RefreshBtnClick end - object RSSListMemo: TMemo + object CancelBtn: TButton Left = 7 - Top = 38 - Width = 281 - Height = 102 - Font.Charset = RUSSIAN_CHARSET - Font.Color = clWindowText - Font.Height = -11 - Font.Name = 'MS Sans Serif' - Font.Style = [] - ParentFont = False - ScrollBars = ssBoth - TabOrder = 2 - OnChange = RSSListMemoChange - end - object StatusBar: TStatusBar - Left = 0 - Top = 143 - Width = 294 - Height = 19 - Panels = <> - SimplePanel = True - OnClick = StatusBarClick - end - object OpenFolderBtn: TButton - Left = 86 Top = 6 Width = 75 Height = 25 - Caption = #1047#1072#1075#1088#1091#1079#1082#1080 - TabOrder = 1 - OnClick = OpenFolderBtnClick + Caption = #1054#1090#1084#1077#1085#1072 + TabOrder = 5 + Visible = False + OnClick = CancelBtnClick end object XPManifest: TXPManifest - Left = 200 - Top = 8 - end - object Timer: TTimer - Enabled = False - Interval = 100 - OnTimer = TimerTimer - Left = 232 - Top = 8 + Left = 16 + Top = 48 end end diff --git a/Source/Unit1.pas b/Source/Unit1.pas index 7d162ae..1358019 100644 --- a/Source/Unit1.pas +++ b/Source/Unit1.pas @@ -1,5 +1,8 @@ unit Unit1; +{ Podcast Easy by r57zone +https://github.com/r57zone/Podcast-Easy } + interface uses @@ -14,19 +17,21 @@ TMain = class(TForm) StatusBar: TStatusBar; XPManifest: TXPManifest; OpenFolderBtn: TButton; - Timer: TTimer; - SettingsBtn: TSpeedButton; + SettingsBtn: TBitBtn; + CancelBtn: TButton; procedure RefreshBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure OpenFolderBtnClick(Sender: TObject); - procedure TimerTimer(Sender: TObject); - procedure StatusBarClick(Sender: TObject); procedure CheckDownloadedLinks; procedure RSSListMemoChange(Sender: TObject); + procedure RSSListMemoKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); procedure SettingsBtnClick(Sender: TObject); + procedure CancelBtnClick(Sender: TObject); private - procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA; { Private declarations } public { Public declarations } @@ -34,10 +39,8 @@ TMain = class(TForm) var Main: TMain; - DownloadPath, LangFile, ModuleWndID: string; - SyncList: TStringList; - hTargetWnd: hWnd; - DownloadPodcasts, RssChanged: boolean; + DownloadPath, LangFile: string; + StopDownload, DownloadPodcasts, RssChanged: boolean; // / Translate //Main @@ -118,7 +121,7 @@ function HTTPCheck(const URL: string): boolean; function HTTPGet(URL: string): string; var hSession, hUrl: HINTERNET; - Buffer: array [0..1023] of Byte; + Buffer: array [1..8192] of Byte; dwFlags, BufferLen: DWORD; StrStream: TStringStream; begin @@ -195,14 +198,17 @@ function GetFileSize(const FileName: string): int64; FindClose(FoundData); end; -function HTTPDownloadFile(const URL, Path: string; out DownloadedFileName: string): boolean; +function HTTPDownloadFile(const URL, Path: string; out DownloadedFileName: string; DownloadIndex, DownloadCount: integer): boolean; var hSession, hFile: HINTERNET; - Buffer: array[0..1023] of Byte; + Buffer: array[1..8192] of Byte; BufferLen: DWORD; F: file; FileSize, FileExistsCounter: int64; + CopySize: int64; begin + FileSize:=HTTPGetSize(URL); // + hSession:=InternetOpen('Mozilla/4.0 (MSIE 6.0; Windows NT 5.1)', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0); if Assigned(hSession) then begin @@ -226,9 +232,13 @@ function HTTPDownloadFile(const URL, Path: string; out DownloadedFileName: strin end; ReWrite(F, 1); repeat - if InternetReadFile(hFile, @Buffer, SizeOf(Buffer), BufferLen) then - BlockWrite(F, Buffer, BufferLen) - else + if InternetReadFile(hFile, @Buffer, SizeOf(Buffer), BufferLen) then begin + BlockWrite(F, Buffer, BufferLen); + CopySize:=CopySize + SizeOf(Buffer); + Main.StatusBar.SimpleText:=' ' + Format(ID_DOWNLOAD_PODCASTS, [DownloadIndex, DownloadCount, Round( CopySize / (FileSize / 100) )]); + if StopDownload then // + break; + end else Break; Application.ProcessMessages; until BufferLen = 0; @@ -243,7 +253,6 @@ function HTTPDownloadFile(const URL, Path: string; out DownloadedFileName: strin end; // / Checking file size - FileSize:=HTTPGetSize(URL); if FileSize <> GetFileSize(Path + DownloadedFileName) then begin // / Delete the incomplete file DeleteFile(Path + DownloadedFileName); @@ -251,37 +260,6 @@ function HTTPDownloadFile(const URL, Path: string; out DownloadedFileName: strin end else Result:=true; end; -// / Standart modular program - https://github.com/r57zone/Standard-modular-program -// / Send messages to modular programs -procedure SendMessageToHandle(TargetWND: HWND; MsgToHandle: string); -var - CDS: TCopyDataStruct; -begin - CDS.dwData:=0; - CDS.cbData:=(Length(MsgToHandle) + 1) * SizeOf(Char); - CDS.lpData:=PChar(MsgToHandle); - SendMessage(TargetWND, WM_COPYDATA, Integer(Application.Handle), Integer(@CDS)); -end; - -function FindWindowExtd(PartTitle: string): HWND; -var - hWndN: HWND; - TitleLen: integer; - CurTitleWnd: array [0..254] of Char; - TitleWnd: string; -begin - hWndN:=FindWindow(nil, nil); - while hWndN <> 0 do begin - TitleLen:=GetWindowText(hWndN, CurTitleWnd, 255); - TitleWnd:=AnsiLowerCase(Copy(CurTitleWnd, 1, TitleLen)); - PartTitle:=AnsiLowerCase(PartTitle); - if Pos(PartTitle, TitleWnd) <> 0 then - Break; - hWndN:=GetWindow(hWndN, GW_HWNDNEXT); - end; - Result:=hWndN; -end; - procedure TMain.RefreshBtnClick(Sender: TObject); const PodcastExt = 'mp3|aac|ogg|mp4'; @@ -292,7 +270,7 @@ procedure TMain.RefreshBtnClick(Sender: TObject); Error: boolean; DownloadedFileName: string; begin - // / Skip download new podcasts for new feed + // / Skip download new podcasts for new feed if RssChanged then case MessageBox(Handle, PChar(StringReplace(ID_NEW_FEED_QUESTION, '\n', #13#10, [rfReplaceAll])), PChar(Caption), MB_YESNO + MB_ICONQUESTION) of 6: DownloadPodcasts:=false; @@ -300,13 +278,14 @@ procedure TMain.RefreshBtnClick(Sender: TObject); end; RegExp:=TRegExpr.Create; - RegExp.ModifierG:=false; // / None greedy mode - Error:=false; // / Error downloaded files - ErrorCount:=0; // / Counter incomplete files - DownloadCount:=0; // / Counter files to download - GetRss:=TStringList.Create; // / Rss - Downloaded:=TStringList.Create; // / List of links downloaded podcasts + RegExp.ModifierG:=false; // / None greedy mode + Error:=false; // / Error downloaded files + ErrorCount:=0; // / Counter incomplete files + DownloadCount:=0; // / Counter files to download + GetRss:=TStringList.Create; // / Rss + Downloaded:=TStringList.Create; // / List of links downloaded podcasts Download:=TStringList.Create; + StopDownload:=false; // // / Disable buttons RefreshBtn.Enabled:=false; RssListMemo.ReadOnly:=true; @@ -366,6 +345,10 @@ procedure TMain.RefreshBtnClick(Sender: TObject); end; + RefreshBtn.Visible:=false; + CancelBtn.Visible:=true; + Main.Refresh; + // / Download files if Download.Count > 0 then begin @@ -374,21 +357,13 @@ procedure TMain.RefreshBtnClick(Sender: TObject); for i:=Download.Count - 1 downto 0 do begin Inc(DownloadIndex); - StatusBar.SimpleText:=' ' + Format(ID_DOWNLOAD_PODCASTS, [DownloadIndex, DownloadCount]); if DownloadPodcasts then // / Permission to download - if HTTPDownloadFile(Download.Strings[i], DownloadPath, DownloadedFileName) = false then begin // / If error + if HTTPDownloadFile(Download.Strings[i], DownloadPath, DownloadedFileName, DownloadIndex, DownloadCount) = false then begin // / If error Download.Delete(i); // , / Remove from list to save the file, which is not fully downloaded Error:=true; - inc(ErrorCount); - end else - if ModuleWndID <> '' then begin // / Standart modular program - https://github.com/r57zone/Standard-modular-program - if Assigned(SyncList) = false then begin - SyncList:=TStringList.Create; - SyncList.Add('FILES TO SYNC'); - end; - SyncList.Add(DownloadPath + DownloadedFileName); - end; + Inc(ErrorCount); + end; end; if Error = false then begin @@ -399,7 +374,7 @@ procedure TMain.RefreshBtnClick(Sender: TObject); StatusBar.SimpleText:=' ' + ID_PODCASTS_SKIPPED; // // All Podcasts skipped end else - StatusBar.SimpleText:=' ' + Format(ID_DOWNLOAD_ERROR, [Download.Count, DownloadCount]); // / Download error + StatusBar.SimpleText:=' ' + Format(ID_DOWNLOAD_ERROR, [DownloadCount - ErrorCount, DownloadCount]); // / Download error // , / Save links to downloaded podcasts to not download them again Downloaded.Add(Download.Text); @@ -412,15 +387,14 @@ procedure TMain.RefreshBtnClick(Sender: TObject); end else StatusBar.SimpleText:=' ' + ID_PODCASTS_NOT_FOUND; // / Not found new podcasts + RefreshBtn.Visible:=true; + CancelBtn.Visible:=false; + // / Enable buttons RefreshBtn.Enabled:=true; RssListMemo.ReadOnly:=false; SettingsBtn.Enabled:=true; - // / Standard modular program - if Assigned(SyncList) then - Timer.Enabled:=true; - Download.Free; GetRss.Free; Downloaded.Free; @@ -438,7 +412,6 @@ procedure TMain.FormCreate(Sender: TObject); DownloadPath:=Ini.ReadString('Main', 'Path', ''); if Trim(DownloadPath) = '' then DownloadPath:=GetEnvironmentVariable('USERPROFILE') + '\Desktop\'; - ModuleWndID:=Ini.ReadString('Main', 'ModuleWndID', ''); Ini.Free; Application.Title:=Caption; @@ -456,6 +429,7 @@ procedure TMain.FormCreate(Sender: TObject); Ini:=TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'Languages\' + LangFile); RefreshBtn.Caption:=Ini.ReadString('Main', 'ID_REFRESH', ''); + CancelBtn.Caption:=Ini.ReadString('Main', 'ID_CANCEL', ''); OpenFolderBtn.Caption:=Ini.ReadString('Main', 'ID_DOWNLOADS', ''); ID_NEW_FEED_QUESTION:=Ini.ReadString('Main', 'ID_NEW_FEED_QUESTION', ''); @@ -483,8 +457,6 @@ procedure TMain.FormClose(Sender: TObject; var Action: TCloseAction); begin if RssChanged then RssListMemo.Lines.SaveToFile(ExtractFilePath(ParamStr(0)) + 'RSS.txt'); - if Assigned(SyncList) then - SyncList.Free; end; procedure TMain.OpenFolderBtnClick(Sender: TObject); @@ -492,44 +464,6 @@ procedure TMain.OpenFolderBtnClick(Sender: TObject); ShellExecute(Handle, nil, PChar(DownloadPath), nil, nil, SW_SHOWNORMAL); end; -procedure TMain.WMCopyData(var Msg: TWMCopyData); -var - i: integer; -begin - if (Assigned(SyncList)) and (PChar(TWMCopyData(msg).CopyDataStruct.lpData) = 'YES') and - (SyncList.Count > 0) and (hTargetWnd <> 0) then - SendMessageToHandle(hTargetWnd, SyncList.Text); - - if PChar(TWMCopyData(Msg).CopyDataStruct.lpData) = 'GOOD' then begin - SyncList.Delete(0); - for i:=0 to SyncList.Count - 1 do - if FileExists(SyncList.Strings[i]) then - DeleteFile(SyncList.Strings[i]); - FreeAndNil(SyncList); - StatusBar.SimpleText:=' ' + ID_UPLOADED_PODCASTS_TO_DEVICE; - end; - //SendMessageToHandle(Msg.From, 'YES'); - Msg.Result:=Integer(True); -end; - -procedure TMain.TimerTimer(Sender: TObject); -begin - // / Standard modular program - hTargetWnd:=FindWindowExtd(ModuleWndID); - if hTargetWnd <> 0 then begin - SendMessageToHandle(hTargetWnd, 'WORK'); - Timer.Enabled:=false; - end; -end; - -procedure TMain.StatusBarClick(Sender: TObject); -begin - Application.MessageBox(PChar(Caption + ' 0.9.5' + #13#10 + - ID_LAST_UPDATE + ' 07.01.2018' + #13#10 + - 'https://r57zone.github.io' + #13#10 + - 'r57zone@gmail.com'), PChar(ID_ABOUT_TITLE), MB_ICONINFORMATION); -end; - procedure TMain.CheckDownloadedLinks; var i, j: integer; @@ -587,9 +521,30 @@ procedure TMain.RSSListMemoChange(Sender: TObject); RssChanged:=true; end; +procedure TMain.RSSListMemoKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + // + if Key = VK_MENU then + Key:=0; +end; + +procedure TMain.FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + // + if Key = VK_MENU then + Key:=0; +end; + procedure TMain.SettingsBtnClick(Sender: TObject); begin Settings.ShowModal; end; +procedure TMain.CancelBtnClick(Sender: TObject); +begin + StopDownload:=true; +end; + end. diff --git a/Source/Unit2.dfm b/Source/Unit2.dfm index 41ed339..80ff0e6 100644 --- a/Source/Unit2.dfm +++ b/Source/Unit2.dfm @@ -4,7 +4,7 @@ object Settings: TSettings BorderIcons = [biSystemMenu] BorderStyle = bsSingle Caption = #1053#1072#1089#1090#1088#1086#1081#1082#1080 - ClientHeight = 245 + ClientHeight = 244 ClientWidth = 376 Color = clBtnFace Font.Charset = DEFAULT_CHARSET @@ -15,6 +15,7 @@ object Settings: TSettings OldCreateOrder = False Position = poScreenCenter OnCreate = FormCreate + OnKeyDown = FormKeyDown OnShow = FormShow PixelsPerInch = 96 TextHeight = 13 @@ -83,12 +84,13 @@ object Settings: TSettings Height = 21 ReadOnly = True TabOrder = 0 + OnKeyDown = EditPathKeyDown end object ChooseBtn: TButton Left = 182 - Top = 40 + Top = 39 Width = 75 - Height = 21 + Height = 23 Caption = #1042#1099#1073#1088#1072#1090#1100 TabOrder = 1 OnClick = ChooseBtnClick @@ -142,6 +144,15 @@ object Settings: TSettings Visible = False end end + object AboutBtn: TButton + Left = 344 + Top = 211 + Width = 25 + Height = 25 + Caption = '?' + TabOrder = 5 + OnClick = AboutBtnClick + end object OpenDialog: TOpenDialog Filter = 'OPML '#1092#1072#1081#1083#1099'|*.opml' Left = 144 diff --git a/Source/Unit2.pas b/Source/Unit2.pas index 8b5754a..b4232c1 100644 --- a/Source/Unit2.pas +++ b/Source/Unit2.pas @@ -25,6 +25,7 @@ TSettings = class(TForm) DownloadedPodcastsDescLbl: TLabel; DownloadedPodcastsGB: TGroupBox; StatusLbl: TLabel; + AboutBtn: TButton; procedure OkBtnClick(Sender: TObject); procedure ChooseBtnClick(Sender: TObject); procedure FormCreate(Sender: TObject); @@ -33,6 +34,11 @@ TSettings = class(TForm) procedure ExportBtnClick(Sender: TObject); procedure RemLinksBtnClick(Sender: TObject); procedure FormShow(Sender: TObject); + procedure FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure EditPathKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); + procedure AboutBtnClick(Sender: TObject); private { Private declarations } public @@ -197,4 +203,28 @@ procedure TSettings.FormShow(Sender: TObject); DownloadPodcastsCB.Checked:=DownloadPodcasts; end; +procedure TSettings.FormKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + // + if Key = VK_MENU then + Key:=0; +end; + +procedure TSettings.EditPathKeyDown(Sender: TObject; var Key: Word; + Shift: TShiftState); +begin + // + if Key = VK_MENU then + Key:=0; +end; + +procedure TSettings.AboutBtnClick(Sender: TObject); +begin + Application.MessageBox(PChar(Caption + ' 1.0' + #13#10 + + ID_LAST_UPDATE + ' 18.12.2020' + #13#10 + + 'https://r57zone.github.io' + #13#10 + + 'r57zone@gmail.com'), PChar(ID_ABOUT_TITLE), MB_ICONINFORMATION); +end; + end.