From 2dc8bd90d95f18402076ab736cc37681574fa395 Mon Sep 17 00:00:00 2001 From: libgenapps <33476799+libgenapps@users.noreply.github.com> Date: Mon, 11 May 2020 02:38:56 +0300 Subject: [PATCH] 1.4.0 --- .editorconfig | 16 + LibgenDesktop.Setup/AppFiles.cs | 3 + LibgenDesktop.Setup/Constants.cs | 4 +- .../LibgenDesktop.Setup.csproj | 29 +- LibgenDesktop.Setup/Utils.cs | 3 +- LibgenDesktop.Setup/packages.config | 4 +- LibgenDesktop.sln | 9 +- LibgenDesktop/App.config | 3 + LibgenDesktop/App.xaml | 6 +- LibgenDesktop/App.xaml.cs | 103 ++- LibgenDesktop/Common/Constants.cs | 37 +- LibgenDesktop/Common/Environment.cs | 4 +- LibgenDesktop/Infrastructure/FuncCommand.cs | 20 +- .../Infrastructure/IWindowContext.cs | 6 + .../Infrastructure/RegisteredWindows.cs | 8 +- .../Infrastructure/ViewModelEvent.cs | 3 +- LibgenDesktop/Infrastructure/WindowContext.cs | 40 +- .../Infrastructure/WindowExtensions.cs | 88 +++ LibgenDesktop/Infrastructure/WindowManager.cs | 72 +- LibgenDesktop/LibgenDesktop.csproj | 367 +++++++-- .../Models/Database/LocalDatabase.cs | 577 ++++---------- LibgenDesktop/Models/Database/Migration.cs | 58 +- .../Models/Database/SearchQueryParser.cs | 58 +- LibgenDesktop/Models/Database/SqlScripts.cs | 154 ++-- .../{Downloader.cs => DownloadManager.cs} | 325 ++++---- ...gs.cs => DownloadManagerBatchEventArgs.cs} | 4 +- ...entArgs.cs => DownloadManagerEventArgs.cs} | 0 ...rage.cs => DownloadManagerQueueStorage.cs} | 2 +- .../Models/Download/DownloadUtils.cs | 263 +++++++ .../Models/Download/LibgenDumpDownloader.cs | 201 +++++ .../Models/Entities/DatabaseMetadata.cs | 10 + LibgenDesktop/Models/Entities/FictionBook.cs | 185 +---- LibgenDesktop/Models/Export/CsvExporter.cs | 4 +- LibgenDesktop/Models/Export/Exporter.cs | 3 +- .../Models/Export/FictionExportObject.cs | 12 +- .../Models/Export/NonFictionExportObject.cs | 4 +- .../Models/Export/SciMagExportObject.cs | 4 +- .../Models/Export/XlsxExportWriter.cs | 1 + LibgenDesktop/Models/Export/XlsxExporter.cs | 4 +- .../Models/Import/FictionImporter.cs | 2 +- LibgenDesktop/Models/Import/Importer.cs | 10 +- LibgenDesktop/Models/JsonApi/JsonApiClient.cs | 20 +- LibgenDesktop/Models/Localization/Language.cs | 45 +- .../Models/Localization/LanguageFormatter.cs | 30 +- .../Localization/LocalizationStorage.cs | 114 ++- .../Localizators/AboutWindowLocalizator.cs | 41 - .../ApplicationUpdateLocalizator.cs | 48 -- .../CommonDetailsTabLocalizator.cs | 44 -- .../CreateDatabaseWindowLocalizator.cs | 49 -- .../Localizators/DatabaseWindowLocalizator.cs | 60 -- .../Localizators/DetailsTabLocalizator.cs | 49 -- .../DownloadManagerLocalizator.cs | 116 --- .../Localizators/ErrorWindowLocalizator.cs | 27 - .../Export/ExportPanelLocalizator.cs | 89 +++ .../Export/ExporterLocalizator.cs | 48 ++ .../Export/FictionExporterLocalizator.cs | 60 ++ .../Export/NonFictionExporterLocalizator.cs | 112 +++ .../Export/SciMagExporterLocalizator.cs | 88 +++ .../Localizators/ExportPanelLocalizator.cs | 91 --- .../Localizators/ExporterLocalizator.cs | 52 -- .../FictionDetailsTabLocalizator.cs | 70 -- .../FictionExporterLocalizator.cs | 64 -- ...tionSearchResultsGridColumnsLocalizator.cs | 36 - .../FictionSearchResultsTabLocalizator.cs | 26 - .../Localizators/ImportLocalizator.cs | 110 --- .../Localizators/LibraryTabLocalizator.cs | 59 -- .../Localization/Localizators/Localizator.cs | 17 +- .../Localizators/MainWindowLocalizator.cs | 48 -- .../Localizators/MessageBoxLocalizator.cs | 25 - .../NonFictionDetailsTabLocalizator.cs | 136 ---- .../NonFictionExporterLocalizator.cs | 110 --- ...tionSearchResultsGridColumnsLocalizator.cs | 37 - .../NonFictionSearchResultsTabLocalizator.cs | 26 - .../SciMagDetailsTabLocalizator.cs | 100 --- .../Localizators/SciMagExporterLocalizator.cs | 93 --- ...iMagSearchResultsGridColumnsLocalizator.cs | 33 - .../SciMagSearchResultsTabLocalizator.cs | 26 - ...tionSearchResultsGridColumnsLocalizator.cs | 32 + ...tionSearchResultsGridColumnsLocalizator.cs | 33 + ...iMagSearchResultsGridColumnsLocalizator.cs | 27 + .../SearchResultsTabLocalizator.cs | 54 -- .../Localizators/SearchTabLocalizator.cs | 53 -- .../Localizators/SettingsWindowLocalizator.cs | 143 ---- .../CollectionsSetupStepLocalizator.cs | 45 ++ .../ConfirmationSetupStepLocalizator.cs | 25 + .../CreateDatabaseSetupStepLocalizator.cs | 37 + .../DatabaseOperationSetupStepLocalizator.cs | 19 + .../DownloadDumpInfoSetupStepLocalizator.cs | 23 + .../DownloadDumpLinksSetupStepLocalizator.cs | 35 + .../DownloadDumpsSetupStepLocalizator.cs | 38 + .../DownloadModeSetupStepLocalizator.cs | 23 + .../ImportDumpsSetupStepLocalizator.cs | 37 + .../LanguageSetupStepLocalizator.cs | 15 + .../SetupModeSetupStepLocalizator.cs | 19 + .../StepListSetupStepLocalizator.cs | 25 + .../SqlDebuggerWindowLocalizator.cs | 27 - .../SynchronizationLocalizator.cs | 93 --- .../Tabs/CommonDetailsTabLocalizator.cs | 45 ++ .../Tabs/DetailsTabLocalizator.cs | 55 ++ .../Tabs/DownloadManagerTabLocalizator.cs | 132 ++++ .../Tabs/FictionDetailsTabLocalizator.cs | 62 ++ .../FictionSearchResultsTabLocalizator.cs | 22 + .../Tabs/LibraryTabLocalizator.cs | 57 ++ .../Tabs/NonFictionDetailsTabLocalizator.cs | 132 ++++ .../NonFictionSearchResultsTabLocalizator.cs | 22 + .../Tabs/SciMagDetailsTabLocalizator.cs | 90 +++ .../Tabs/SciMagSearchResultsTabLocalizator.cs | 22 + .../Tabs/SearchResultsTabLocalizator.cs | 66 ++ .../Localizators/Tabs/SearchTabLocalizator.cs | 49 ++ .../Windows/AboutWindowLocalizator.cs | 36 + .../ApplicationUpdateWindowLocalizator.cs | 43 + .../Windows/DatabaseErrorWindowLocalizator.cs | 39 + .../Windows/DatabaseWindowLocalizator.cs | 59 ++ .../Windows/ErrorWindowLocalizator.cs | 21 + .../Windows/ImportWindowLocalizator.cs | 126 +++ .../Windows/MainWindowLocalizator.cs | 40 + .../Windows/MessageBoxLocalizator.cs | 19 + .../Windows/SettingsWindowLocalizator.cs | 157 ++++ ...tupWizardProxySettingsWindowLocalizator.cs | 37 + .../Windows/SetupWizardWindowLocalizator.cs | 62 ++ .../Windows/SqlDebuggerWindowLocalizator.cs | 21 + .../SynchronizationWindowLocalizator.cs | 99 +++ .../Models/Localization/Translation.cs | 227 +++++- LibgenDesktop/Models/MainModel.cs | 463 +++++------ .../ProgressArgs/DownloadFileProgress.cs | 6 +- .../ProgressArgs/ImportObjectsProgress.cs | 16 +- .../ImportWrongTableDefinitionProgress.cs | 14 + LibgenDesktop/Models/Settings/AppSettings.cs | 79 +- LibgenDesktop/Models/Settings/Mirrors.cs | 11 + .../Models/SqlDump/PositioningStreamReader.cs | 6 + LibgenDesktop/Models/SqlDump/SqlDumpReader.cs | 20 +- .../Models/SqlDump/TableDefinitions.cs | 59 +- LibgenDesktop/Models/Update/Updater.cs | 43 +- LibgenDesktop/Models/Utils/FileUtils.cs | 2 +- LibgenDesktop/Models/Utils/UrlGenerator.cs | 244 +++--- LibgenDesktop/Resources/Languages/English.lng | 207 ++++- LibgenDesktop/Resources/Languages/French.lng | 22 - LibgenDesktop/Resources/Languages/Italian.lng | 745 ++++++++++++++++++ .../Resources/Languages/Portuguse_BR.lng | 745 ++++++++++++++++++ .../Resources/Languages/Romanian.lng | 23 - LibgenDesktop/Resources/Languages/Russian.lng | 207 ++++- .../Languages/Simplified Chinese.lng | 23 - LibgenDesktop/Resources/Languages/Spanish.lng | 22 - LibgenDesktop/Resources/Languages/Turkish.lng | 23 - .../Resources/Languages/Ukrainian.lng | 22 - .../Mirrors/genlibrusec_dbdumps.xslt | 25 + .../Resources/Mirrors/mirrors.config | 15 +- LibgenDesktop/Styles/Common.xaml | 71 ++ .../Controls/ExportPanel.xaml} | 0 .../Controls/ImportLogPanel.xaml} | 0 .../Controls/Tab.xaml} | 2 +- .../Controls/Toolbar.xaml} | 0 .../Styles/SetupSteps/Collections.xaml | 51 ++ .../Styles/SetupSteps/Confirmation.xaml | 37 + .../Styles/SetupSteps/CreateDatabase.xaml | 27 + .../Styles/SetupSteps/DatabaseOperation.xaml | 14 + .../Styles/SetupSteps/DownloadDumpInfo.xaml | 32 + .../Styles/SetupSteps/DownloadDumpLinks.xaml | 30 + .../Styles/SetupSteps/DownloadDumps.xaml | 46 ++ .../Styles/SetupSteps/DownloadMode.xaml | 25 + .../Styles/SetupSteps/ImportDumps.xaml | 19 + LibgenDesktop/Styles/SetupSteps/Language.xaml | 16 + .../Styles/SetupSteps/SetupMode.xaml | 15 + LibgenDesktop/Styles/SetupSteps/StepList.xaml | 21 + .../Tabs/DownloadManager.xaml} | 8 +- .../Tabs/FictionDetails.xaml} | 0 .../Tabs/FictionSearchResults.xaml} | 4 +- .../Tabs/Library.xaml} | 2 +- .../Tabs/NonFictionDetails.xaml} | 0 .../Tabs/NonFictionSearchResults.xaml} | 4 +- .../Tabs/SciMagDetails.xaml} | 0 .../Tabs/SciMagSearchResults.xaml} | 2 +- .../Tabs/Search.xaml} | 2 +- .../TabStyles.xaml => Styles/Tabs/Tab.xaml} | 0 .../Windows/About.xaml} | 0 .../Windows/ApplicationUpdate.xaml} | 0 .../Windows/Database.xaml} | 0 .../Windows/DatabaseError.xaml} | 4 +- .../Windows/Error.xaml} | 0 .../Windows/Import.xaml} | 0 .../Windows/Main.xaml} | 3 - .../Windows/MessageBox.xaml} | 0 .../Windows/Settings.xaml} | 47 +- LibgenDesktop/Styles/Windows/SetupWizard.xaml | 39 + .../Windows/SetupWizardProxySettings.xaml | 35 + .../Windows/SqlDebugger.xaml} | 0 .../Windows/Synchronization.xaml} | 0 .../Windows/Windows.xaml} | 28 +- .../FictionDetailsItemViewModel.cs | 24 +- .../NonFictionDetailsItemViewModel.cs | 2 +- .../SciMagDetailsItemViewModel.cs | 5 +- .../Library/FictionScanResultItemViewModel.cs | 4 +- .../NonFictionScanResultItemViewModel.cs | 4 +- .../ViewModels/Panels/ExportPanelViewModel.cs | 50 +- .../FictionSearchResultItemViewModel.cs | 7 + .../NonFictionSearchResultItemViewModel.cs | 9 +- .../SciMagSearchResultItemViewModel.cs | 8 +- .../SearchResultItemViewModel.cs | 21 +- .../Settings/LanguageItemViewModel.cs | 20 + .../SetupSteps/CollectionsPageViewModel.cs | 392 +++++++++ .../SetupSteps/ConfirmationPageViewModel.cs | 121 +++ .../SetupSteps/CreateDatabasePageViewModel.cs | 269 +++++++ .../DatabaseOperationPageViewModel.cs | 85 ++ .../DownloadDumpInfoPageViewModel.cs | 240 ++++++ .../DownloadDumpLinksPageViewModel.cs | 175 ++++ .../SetupSteps/DownloadDumpsPageViewModel.cs | 463 +++++++++++ .../SetupSteps/DownloadModePageViewModel.cs | 178 +++++ .../SetupSteps/ImportDumpsPageViewModel.cs | 361 +++++++++ .../SetupSteps/LanguagePageViewModel.cs | 72 ++ .../SetupSteps/SetupModePageViewModel.cs | 78 ++ .../SetupSteps/SetupStepPageViewModel.cs | 219 +++++ .../ViewModels/SetupSteps/SetupWizardStep.cs | 19 + .../SetupSteps/SharedSetupContext.cs | 82 ++ .../SetupSteps/StepListPageViewModel.cs | 65 ++ .../ViewModels/Tabs/DetailsTabViewModel.cs | 40 +- .../Tabs/DownloadManagerTabViewModel.cs | 109 +-- .../Tabs/FictionDetailsTabViewModel.cs | 7 +- .../Tabs/FictionSearchResultsTabViewModel.cs | 14 +- .../ViewModels/Tabs/LibraryTabViewModel.cs | 2 +- .../Tabs/NonFictionDetailsTabViewModel.cs | 2 +- .../NonFictionSearchResultsTabViewModel.cs | 14 +- .../Tabs/SciMagDetailsTabViewModel.cs | 2 +- .../Tabs/SciMagSearchResultsTabViewModel.cs | 2 +- .../Tabs/SearchResultsTabViewModel.cs | 39 +- .../ViewModels/Tabs/SearchTabViewModel.cs | 15 +- .../Windows/AboutWindowViewModel.cs | 2 +- .../ApplicationUpdateWindowViewModel.cs | 32 +- .../Windows/CreateDatabaseWindowViewModel.cs | 192 ----- .../Windows/DatabaseErrorWindowViewModel.cs | 185 +++++ .../Windows/DatabaseWindowViewModel.cs | 124 ++- .../Windows/ErrorWindowViewModel.cs | 12 +- .../Windows/ImportWindowViewModel.cs | 158 +++- .../Windows/LibgenWindowViewModel.cs | 3 +- .../ViewModels/Windows/MainWindowViewModel.cs | 60 +- .../Windows/SettingsWindowViewModel.cs | 41 +- ...SetupWizardProxySettingsWindowViewModel.cs | 207 +++++ .../Windows/SetupWizardWindowViewModel.cs | 204 +++++ .../Windows/SqlDebuggerWindowViewModel.cs | 8 +- .../Windows/SynchronizationWindowViewModel.cs | 8 +- .../Controls/BookAttributeValueLabel.xaml | 4 +- .../Controls/BookDataGridContextMenu.xaml | 14 + .../Views/Controls/ControlExtensions.cs | 3 +- ...erListBox.cs => DownloadManagerListBox.cs} | 13 +- LibgenDesktop/Views/Controls/ExportPanel.xaml | 2 +- .../Views/Controls/ImportLogPanel.xaml | 2 +- .../Views/Controls/LanguageComboBox.xaml | 97 +++ .../Views/Controls/LanguageComboBox.xaml.cs | 28 + .../Views/Controls/LibgenDesktopWindow.cs | 39 +- LibgenDesktop/Views/Controls/Link.xaml | 20 + LibgenDesktop/Views/Controls/Link.xaml.cs | 76 ++ LibgenDesktop/Views/Controls/Toolbar.xaml | 4 +- LibgenDesktop/Views/Controls/Toolbar.xaml.cs | 4 +- .../Views/SetupSteps/CollectionsPage.xaml | 52 ++ .../Views/SetupSteps/CollectionsPage.xaml.cs | 12 + .../Views/SetupSteps/ConfirmationPage.xaml | 21 + .../Views/SetupSteps/ConfirmationPage.xaml.cs | 12 + .../Views/SetupSteps/CreateDatabasePage.xaml | 25 + .../SetupSteps/CreateDatabasePage.xaml.cs | 12 + .../SetupSteps/DatabaseOperationPage.xaml | 14 + .../SetupSteps/DatabaseOperationPage.xaml.cs | 12 + .../SetupSteps/DownloadDumpInfoPage.xaml | 25 + .../SetupSteps/DownloadDumpInfoPage.xaml.cs | 12 + .../SetupSteps/DownloadDumpLinksPage.xaml | 28 + .../SetupSteps/DownloadDumpLinksPage.xaml.cs | 12 + .../Views/SetupSteps/DownloadDumpsPage.xaml | 74 ++ .../SetupSteps/DownloadDumpsPage.xaml.cs | 12 + .../Views/SetupSteps/DownloadModePage.xaml | 22 + .../Views/SetupSteps/DownloadModePage.xaml.cs | 12 + .../Views/SetupSteps/ImportDumpsPage.xaml | 38 + .../Views/SetupSteps/ImportDumpsPage.xaml.cs | 12 + .../Views/SetupSteps/LanguagePage.xaml | 13 + .../Views/SetupSteps/LanguagePage.xaml.cs | 12 + .../Views/SetupSteps/SetupModePage.xaml | 14 + .../Views/SetupSteps/SetupModePage.xaml.cs | 12 + .../Views/SetupSteps/StepListPage.xaml | 28 + .../Views/SetupSteps/StepListPage.xaml.cs | 12 + LibgenDesktop/Views/Styles/CommonStyles.xaml | 27 - .../Views/Tabs/DownloadManagerTab.xaml | 13 +- .../Views/Tabs/DownloadManagerTab.xaml.cs | 4 +- .../Views/Tabs/FictionDetailsTab.xaml | 42 +- .../Views/Tabs/FictionDetailsTab.xaml.cs | 18 +- .../Views/Tabs/FictionSearchResultsTab.xaml | 7 +- LibgenDesktop/Views/Tabs/LibraryTab.xaml | 2 +- .../Views/Tabs/NonFictionDetailsTab.xaml | 2 +- .../Views/Tabs/NonFictionDetailsTab.xaml.cs | 18 +- .../Tabs/NonFictionSearchResultsTab.xaml | 7 +- .../Views/Tabs/SciMagDetailsTab.xaml | 2 +- .../Views/Tabs/SciMagDetailsTab.xaml.cs | 18 +- .../Views/Tabs/SciMagSearchResultsTab.xaml | 2 +- LibgenDesktop/Views/Tabs/SearchTab.xaml | 2 +- .../Views/Utils/DataGridExtensions.cs | 4 +- .../Views/Utils/PasswordBoxExtensions.cs | 33 +- LibgenDesktop/Views/Windows/AboutWindow.xaml | 2 +- .../Windows/ApplicationUpdateWindow.xaml | 2 +- .../Views/Windows/CreateDatabaseWindow.xaml | 26 - .../Views/Windows/DatabaseErrorWindow.xaml | 23 + ...ow.xaml.cs => DatabaseErrorWindow.xaml.cs} | 4 +- .../Views/Windows/DatabaseWindow.xaml | 3 +- LibgenDesktop/Views/Windows/ErrorWindow.xaml | 2 +- LibgenDesktop/Views/Windows/ImportWindow.xaml | 4 +- LibgenDesktop/Views/Windows/MainWindow.xaml | 2 +- .../Views/Windows/MessageBoxWindow.xaml | 2 +- .../Views/Windows/MessageBoxWindow.xaml.cs | 3 +- .../Views/Windows/SettingsWindow.xaml | 6 +- .../SetupWizardProxySettingsWindow.xaml | 50 ++ .../SetupWizardProxySettingsWindow.xaml.cs | 20 + .../Views/Windows/SetupWizardWindow.xaml | 61 ++ .../Views/Windows/SetupWizardWindow.xaml.cs | 10 + .../Views/Windows/SqlDebuggerWindow.xaml | 2 +- .../Views/Windows/SynchronizationWindow.xaml | 2 +- LibgenDesktop/app.manifest | 6 + 311 files changed, 12245 insertions(+), 4519 deletions(-) create mode 100644 .editorconfig create mode 100644 LibgenDesktop/Infrastructure/WindowExtensions.cs rename LibgenDesktop/Models/Download/{Downloader.cs => DownloadManager.cs} (90%) rename LibgenDesktop/Models/Download/{DownloaderBatchEventArgs.cs => DownloadManagerBatchEventArgs.cs} (91%) rename LibgenDesktop/Models/Download/{DownloaderEventArgs.cs => DownloadManagerEventArgs.cs} (100%) rename LibgenDesktop/Models/Download/{DownloadQueueStorage.cs => DownloadManagerQueueStorage.cs} (99%) create mode 100644 LibgenDesktop/Models/Download/DownloadUtils.cs create mode 100644 LibgenDesktop/Models/Download/LibgenDumpDownloader.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/AboutWindowLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/ApplicationUpdateLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/CommonDetailsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/CreateDatabaseWindowLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/DatabaseWindowLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/DetailsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/DownloadManagerLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/ErrorWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Export/ExportPanelLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Export/ExporterLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Export/FictionExporterLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Export/NonFictionExporterLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Export/SciMagExporterLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/ExportPanelLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/ExporterLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/FictionDetailsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/FictionExporterLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsGridColumnsLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/ImportLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/MessageBoxLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/NonFictionDetailsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/NonFictionExporterLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsGridColumnsLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SciMagDetailsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SciMagExporterLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsGridColumnsLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/FictionSearchResultsGridColumnsLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/NonFictionSearchResultsGridColumnsLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/SciMagSearchResultsGridColumnsLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SearchResultsTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SearchTabLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SettingsWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/CollectionsSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/ConfirmationSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/CreateDatabaseSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/DatabaseOperationSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpInfoSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpLinksSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpsSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadModeSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/ImportDumpsSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/LanguageSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/SetupModeSetupStepLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/SetupSteps/StepListSetupStepLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SqlDebuggerWindowLocalizator.cs delete mode 100644 LibgenDesktop/Models/Localization/Localizators/SynchronizationLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/CommonDetailsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/DetailsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/DownloadManagerTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/FictionDetailsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/FictionSearchResultsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/LibraryTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionDetailsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionSearchResultsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagDetailsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagSearchResultsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/SearchResultsTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Tabs/SearchTabLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/AboutWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/ApplicationUpdateWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseErrorWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/ErrorWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/ImportWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/MainWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/MessageBoxLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/SettingsWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardProxySettingsWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/SqlDebuggerWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/Localization/Localizators/Windows/SynchronizationWindowLocalizator.cs create mode 100644 LibgenDesktop/Models/ProgressArgs/ImportWrongTableDefinitionProgress.cs create mode 100644 LibgenDesktop/Resources/Languages/Italian.lng create mode 100644 LibgenDesktop/Resources/Languages/Portuguse_BR.lng create mode 100644 LibgenDesktop/Resources/Mirrors/genlibrusec_dbdumps.xslt create mode 100644 LibgenDesktop/Styles/Common.xaml rename LibgenDesktop/{Views/Styles/ExportPanelStyles.xaml => Styles/Controls/ExportPanel.xaml} (100%) rename LibgenDesktop/{Views/Styles/ImportLogPanelStyles.xaml => Styles/Controls/ImportLogPanel.xaml} (100%) rename LibgenDesktop/{Views/Styles/TabControlStyles.xaml => Styles/Controls/Tab.xaml} (99%) rename LibgenDesktop/{Views/Styles/ToolbarStyles.xaml => Styles/Controls/Toolbar.xaml} (100%) create mode 100644 LibgenDesktop/Styles/SetupSteps/Collections.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/Confirmation.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/CreateDatabase.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/DatabaseOperation.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/DownloadDumpInfo.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/DownloadDumpLinks.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/DownloadDumps.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/DownloadMode.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/ImportDumps.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/Language.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/SetupMode.xaml create mode 100644 LibgenDesktop/Styles/SetupSteps/StepList.xaml rename LibgenDesktop/{Views/Styles/DownloadManagerTabStyles.xaml => Styles/Tabs/DownloadManager.xaml} (95%) rename LibgenDesktop/{Views/Styles/FictionDetailsTabStyles.xaml => Styles/Tabs/FictionDetails.xaml} (100%) rename LibgenDesktop/{Views/Styles/FictionSearchResultsTabStyles.xaml => Styles/Tabs/FictionSearchResults.xaml} (89%) rename LibgenDesktop/{Views/Styles/LibraryTabStyles.xaml => Styles/Tabs/Library.xaml} (95%) rename LibgenDesktop/{Views/Styles/NonFictionDetailsTabStyles.xaml => Styles/Tabs/NonFictionDetails.xaml} (100%) rename LibgenDesktop/{Views/Styles/NonFictionSearchResultsTabStyles.xaml => Styles/Tabs/NonFictionSearchResults.xaml} (90%) rename LibgenDesktop/{Views/Styles/SciMagDetailsTabStyles.xaml => Styles/Tabs/SciMagDetails.xaml} (100%) rename LibgenDesktop/{Views/Styles/SciMagSearchResultsTabStyles.xaml => Styles/Tabs/SciMagSearchResults.xaml} (97%) rename LibgenDesktop/{Views/Styles/SearchTabStyles.xaml => Styles/Tabs/Search.xaml} (97%) rename LibgenDesktop/{Views/Styles/TabStyles.xaml => Styles/Tabs/Tab.xaml} (100%) rename LibgenDesktop/{Views/Styles/AboutWindowStyles.xaml => Styles/Windows/About.xaml} (100%) rename LibgenDesktop/{Views/Styles/ApplicationUpdateWindowStyles.xaml => Styles/Windows/ApplicationUpdate.xaml} (100%) rename LibgenDesktop/{Views/Styles/DatabaseWindowStyles.xaml => Styles/Windows/Database.xaml} (100%) rename LibgenDesktop/{Views/Styles/CreateDatabaseWindowStyles.xaml => Styles/Windows/DatabaseError.xaml} (90%) rename LibgenDesktop/{Views/Styles/ErrorWindowStyles.xaml => Styles/Windows/Error.xaml} (100%) rename LibgenDesktop/{Views/Styles/ImportWindowStyles.xaml => Styles/Windows/Import.xaml} (100%) rename LibgenDesktop/{Views/Styles/MainWindowStyles.xaml => Styles/Windows/Main.xaml} (88%) rename LibgenDesktop/{Views/Styles/MessageBoxWindowStyles.xaml => Styles/Windows/MessageBox.xaml} (100%) rename LibgenDesktop/{Views/Styles/SettingsWindowStyles.xaml => Styles/Windows/Settings.xaml} (75%) create mode 100644 LibgenDesktop/Styles/Windows/SetupWizard.xaml create mode 100644 LibgenDesktop/Styles/Windows/SetupWizardProxySettings.xaml rename LibgenDesktop/{Views/Styles/SqlDebuggerWindowStyles.xaml => Styles/Windows/SqlDebugger.xaml} (100%) rename LibgenDesktop/{Views/Styles/SynchronizationWindowStyles.xaml => Styles/Windows/Synchronization.xaml} (100%) rename LibgenDesktop/{Views/Styles/WindowStyles.xaml => Styles/Windows/Windows.xaml} (85%) create mode 100644 LibgenDesktop/ViewModels/Settings/LanguageItemViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/CollectionsPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/ConfirmationPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/CreateDatabasePageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/DatabaseOperationPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/DownloadDumpInfoPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/DownloadDumpLinksPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/DownloadDumpsPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/DownloadModePageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/ImportDumpsPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/LanguagePageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/SetupModePageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/SetupStepPageViewModel.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/SetupWizardStep.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/SharedSetupContext.cs create mode 100644 LibgenDesktop/ViewModels/SetupSteps/StepListPageViewModel.cs delete mode 100644 LibgenDesktop/ViewModels/Windows/CreateDatabaseWindowViewModel.cs create mode 100644 LibgenDesktop/ViewModels/Windows/DatabaseErrorWindowViewModel.cs create mode 100644 LibgenDesktop/ViewModels/Windows/SetupWizardProxySettingsWindowViewModel.cs create mode 100644 LibgenDesktop/ViewModels/Windows/SetupWizardWindowViewModel.cs rename LibgenDesktop/Views/Controls/{DownloaderListBox.cs => DownloadManagerListBox.cs} (91%) create mode 100644 LibgenDesktop/Views/Controls/LanguageComboBox.xaml create mode 100644 LibgenDesktop/Views/Controls/LanguageComboBox.xaml.cs create mode 100644 LibgenDesktop/Views/Controls/Link.xaml create mode 100644 LibgenDesktop/Views/Controls/Link.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/CollectionsPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/CollectionsPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/ConfirmationPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/ConfirmationPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/CreateDatabasePage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/CreateDatabasePage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/DatabaseOperationPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/DatabaseOperationPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpInfoPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpInfoPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpLinksPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpLinksPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpsPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadDumpsPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadModePage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/DownloadModePage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/ImportDumpsPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/ImportDumpsPage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/LanguagePage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/LanguagePage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/SetupModePage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/SetupModePage.xaml.cs create mode 100644 LibgenDesktop/Views/SetupSteps/StepListPage.xaml create mode 100644 LibgenDesktop/Views/SetupSteps/StepListPage.xaml.cs delete mode 100644 LibgenDesktop/Views/Styles/CommonStyles.xaml delete mode 100644 LibgenDesktop/Views/Windows/CreateDatabaseWindow.xaml create mode 100644 LibgenDesktop/Views/Windows/DatabaseErrorWindow.xaml rename LibgenDesktop/Views/Windows/{CreateDatabaseWindow.xaml.cs => DatabaseErrorWindow.xaml.cs} (57%) create mode 100644 LibgenDesktop/Views/Windows/SetupWizardProxySettingsWindow.xaml create mode 100644 LibgenDesktop/Views/Windows/SetupWizardProxySettingsWindow.xaml.cs create mode 100644 LibgenDesktop/Views/Windows/SetupWizardWindow.xaml create mode 100644 LibgenDesktop/Views/Windows/SetupWizardWindow.xaml.cs diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3a8bbb3 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,16 @@ +[*.cs] + +# CA1810: Initialize reference type static fields inline +dotnet_diagnostic.CA1810.severity = none + +# CA1031: Do not catch general exception types +dotnet_diagnostic.CA1031.severity = none + +# IDE0039: Use local function +csharp_style_pattern_local_over_anonymous_function = true:none + +# CA2100: Review SQL queries for security vulnerabilities +dotnet_diagnostic.CA2100.severity = none + +# IDE0049: Simplify Names +dotnet_style_predefined_type_for_locals_parameters_members = false:silent diff --git a/LibgenDesktop.Setup/AppFiles.cs b/LibgenDesktop.Setup/AppFiles.cs index e2b99ce..64397bb 100644 --- a/LibgenDesktop.Setup/AppFiles.cs +++ b/LibgenDesktop.Setup/AppFiles.cs @@ -27,6 +27,8 @@ static AppFiles() X64.Add(new AppFile(@"x64\SQLite.Interop.dll", "SQLite.Interop.dll")); AddFile(@"Languages\English.lng"); AddFile(@"Languages\French.lng"); + AddFile(@"Languages\Italian.lng"); + AddFile(@"Languages\Portuguse_BR.lng"); AddFile(@"Languages\Romanian.lng"); AddFile(@"Languages\Russian.lng"); AddFile(@"Languages\Simplified Chinese.lng"); @@ -39,6 +41,7 @@ static AppFiles() AddFile(@"Mirrors\booklid_org_step2.xslt"); AddFile(@"Mirrors\booksc_org_step1.xslt"); AddFile(@"Mirrors\booksc_org_step2.xslt"); + AddFile(@"Mirrors\genlibrusec_dbdumps.xslt"); AddFile(@"Mirrors\libgen_lc_fiction.xslt"); AddFile(@"Mirrors\libgen_lc_nonfiction.xslt"); AddFile(@"Mirrors\libgen_lc_scimag.xslt"); diff --git a/LibgenDesktop.Setup/Constants.cs b/LibgenDesktop.Setup/Constants.cs index ebc1e3b..e463b4a 100644 --- a/LibgenDesktop.Setup/Constants.cs +++ b/LibgenDesktop.Setup/Constants.cs @@ -2,8 +2,8 @@ { internal static class Constants { - public const string CURRENT_VERSION = "1.3.5"; - public const string TITLE_VERSION = "1.3.5"; + public const string CURRENT_VERSION = "1.4.0"; + public const string TITLE_VERSION = "1.4.0"; public const string PRODUCT_TITLE_FORMAT = "Libgen Desktop " + TITLE_VERSION + " ({0}-bit)"; public const string SHORTCUT_TITLE_FORMAT = "Libgen Desktop ({0}-bit)"; public const string PRODUCT_COMPANY = "Libgen Apps"; diff --git a/LibgenDesktop.Setup/LibgenDesktop.Setup.csproj b/LibgenDesktop.Setup/LibgenDesktop.Setup.csproj index df7d341..ac26cfe 100644 --- a/LibgenDesktop.Setup/LibgenDesktop.Setup.csproj +++ b/LibgenDesktop.Setup/LibgenDesktop.Setup.csproj @@ -11,7 +11,8 @@ WixSharp Setup v3.5 512 - + + AnyCPU @@ -43,10 +44,10 @@ - ..\packages\WixSharp.bin.1.9.2\lib\BootstrapperCore.dll + ..\packages\WixSharp.bin.1.14.3\lib\BootstrapperCore.dll - ..\packages\WixSharp.bin.1.9.2\lib\Microsoft.Deployment.WindowsInstaller.dll + ..\packages\WixSharp.bin.1.14.3\lib\Microsoft.Deployment.WindowsInstaller.dll ..\packages\SharpCompress.0.22.0\lib\net35\SharpCompress.dll @@ -57,14 +58,14 @@ - - ..\packages\WixSharp.bin.1.9.2\lib\WixSharp.dll + + ..\packages\WixSharp.bin.1.14.3\lib\WixSharp.dll - - ..\packages\WixSharp.bin.1.9.2\lib\WixSharp.Msi.dll + + ..\packages\WixSharp.bin.1.14.3\lib\WixSharp.Msi.dll - - ..\packages\WixSharp.bin.1.9.2\lib\WixSharp.UI.dll + + ..\packages\WixSharp.bin.1.14.3\lib\WixSharp.UI.dll @@ -92,14 +93,14 @@ --> - + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - + + - - + \ No newline at end of file diff --git a/LibgenDesktop.Setup/Utils.cs b/LibgenDesktop.Setup/Utils.cs index 62690ca..d917ca1 100644 --- a/LibgenDesktop.Setup/Utils.cs +++ b/LibgenDesktop.Setup/Utils.cs @@ -1,5 +1,4 @@ -using System.Collections.Generic; -using System.IO; +using System.IO; namespace LibgenDesktop.Setup { diff --git a/LibgenDesktop.Setup/packages.config b/LibgenDesktop.Setup/packages.config index b1dc5fa..2ec7426 100644 --- a/LibgenDesktop.Setup/packages.config +++ b/LibgenDesktop.Setup/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/LibgenDesktop.sln b/LibgenDesktop.sln index 69123a8..65dafba 100644 --- a/LibgenDesktop.sln +++ b/LibgenDesktop.sln @@ -1,12 +1,17 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27130.2010 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29911.84 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibgenDesktop", "LibgenDesktop\LibgenDesktop.csproj", "{7158E1EB-44F7-4C26-BF9A-DA055F85D0BB}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LibgenDesktop.Setup", "LibgenDesktop.Setup\LibgenDesktop.Setup.csproj", "{44555887-C439-470C-944D-8866EC3D7067}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3DD4F677-B56F-4422-90B9-4A8A1CC6D69B}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug x64|Any CPU = Debug x64|Any CPU diff --git a/LibgenDesktop/App.config b/LibgenDesktop/App.config index 8e15646..7bf9820 100644 --- a/LibgenDesktop/App.config +++ b/LibgenDesktop/App.config @@ -3,4 +3,7 @@ + + + \ No newline at end of file diff --git a/LibgenDesktop/App.xaml b/LibgenDesktop/App.xaml index 12ba901..7e5ae58 100644 --- a/LibgenDesktop/App.xaml +++ b/LibgenDesktop/App.xaml @@ -10,9 +10,9 @@ - - - + + + diff --git a/LibgenDesktop/App.xaml.cs b/LibgenDesktop/App.xaml.cs index b6272de..026fa0c 100644 --- a/LibgenDesktop/App.xaml.cs +++ b/LibgenDesktop/App.xaml.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Threading.Tasks; using System.Windows; using LibgenDesktop.Common; @@ -10,22 +11,106 @@ namespace LibgenDesktop { public partial class App : Application { + private enum DatabaseOpenResult + { + IN_PROGRESS = 1, + DATABASE_OPENED, + SHOW_SETUP_WIZARD, + EXIT_REQUESTED + } + private MainModel mainModel; - protected override void OnStartup(StartupEventArgs e) + protected override async void OnStartup(StartupEventArgs e) { base.OnStartup(e); SetupExceptionHandlers(); try { mainModel = new MainModel(); - if (mainModel.LocalDatabaseStatus == MainModel.DatabaseStatus.OPENED) + string databaseFilePath = mainModel.AppSettings.DatabaseFileName; + bool saveDatabaseFilePathAfterSuccessfulOpen = false; + MainModel.OpenDatabaseOptions openDatabaseOptions = MainModel.OpenDatabaseOptions.NONE; + DatabaseOpenResult databaseOpenResult = DatabaseOpenResult.IN_PROGRESS; + while (databaseOpenResult == DatabaseOpenResult.IN_PROGRESS) { - ShowMainWindow(mainModel); + MainModel.DatabaseStatus databaseStatus = await mainModel.OpenDatabase(databaseFilePath, openDatabaseOptions); + if (databaseStatus == MainModel.DatabaseStatus.OPENED) + { + databaseOpenResult = DatabaseOpenResult.DATABASE_OPENED; + if (saveDatabaseFilePathAfterSuccessfulOpen) + { + mainModel.AppSettings.DatabaseFileName = MainModel.GetDatabaseNormalizedPath(databaseFilePath); + mainModel.SaveSettings(); + } + } + else if (databaseStatus == MainModel.DatabaseStatus.NOT_SET) + { + databaseOpenResult = DatabaseOpenResult.SHOW_SETUP_WIZARD; + } + else + { + DatabaseErrorWindowViewModel.OptionSet optionSet; + switch (databaseStatus) + { + case MainModel.DatabaseStatus.NOT_FOUND: + optionSet = DatabaseErrorWindowViewModel.OptionSet.DATABASE_NOT_FOUND; + break; + case MainModel.DatabaseStatus.POSSIBLE_DUMP_FILE: + optionSet = DatabaseErrorWindowViewModel.OptionSet.DATABASE_DUMP_FILE; + break; + case MainModel.DatabaseStatus.OLD_FICTION_SCHEMA: + optionSet = DatabaseErrorWindowViewModel.OptionSet.OLD_FICTION_SCHEMA; + break; + case MainModel.DatabaseStatus.CORRUPTED: + optionSet = DatabaseErrorWindowViewModel.OptionSet.DATABASE_NOT_VALID; + break; + case MainModel.DatabaseStatus.SERVER_DATABASE: + optionSet = DatabaseErrorWindowViewModel.OptionSet.SERVER_DATABASE; + break; + default: + throw new Exception($"Unknown database status: {databaseStatus}."); + } + DatabaseErrorWindowViewModel databaseErrorWindowViewModel = new DatabaseErrorWindowViewModel(mainModel, optionSet, databaseFilePath); + IWindowContext windowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.DATABASE_ERROR_WINDOW, + databaseErrorWindowViewModel); + windowContext.ShowDialog(); + switch (databaseErrorWindowViewModel.Result) + { + case DatabaseErrorWindowViewModel.DatabaseErrorWindowResult.OPEN_ANOTHER_DATABASE: + OpenFileDialogResult selectDatabaseFileDialogResult = DatabaseWindowViewModel.SelectDatabaseFile(mainModel); + if (selectDatabaseFileDialogResult.DialogResult) + { + databaseFilePath = selectDatabaseFileDialogResult.SelectedFilePaths.First(); + saveDatabaseFilePathAfterSuccessfulOpen = true; + } + break; + case DatabaseErrorWindowViewModel.DatabaseErrorWindowResult.START_SETUP_WIZARD: + databaseOpenResult = DatabaseOpenResult.SHOW_SETUP_WIZARD; + break; + case DatabaseErrorWindowViewModel.DatabaseErrorWindowResult.DELETE_FICTION: + openDatabaseOptions = MainModel.OpenDatabaseOptions.MIGRATE_FICTION; + break; + case DatabaseErrorWindowViewModel.DatabaseErrorWindowResult.EXIT: + case DatabaseErrorWindowViewModel.DatabaseErrorWindowResult.CANCEL: + databaseOpenResult = DatabaseOpenResult.EXIT_REQUESTED; + break; + default: + throw new Exception($"Unknown database error view model result: {databaseErrorWindowViewModel.Result}."); + } + } } - else + switch (databaseOpenResult) { - ShowCreateDatabaseWindow(mainModel); + case DatabaseOpenResult.DATABASE_OPENED: + ShowMainWindow(mainModel); + break; + case DatabaseOpenResult.SHOW_SETUP_WIZARD: + ShowSetupWizardWindow(mainModel); + break; + default: + Close(); + break; } } catch (Exception exception) @@ -44,10 +129,10 @@ private void ShowMainWindow(MainModel mainModel) windowContext.Show(); } - private void ShowCreateDatabaseWindow(MainModel mainModel) + private void ShowSetupWizardWindow(MainModel mainModel) { - CreateDatabaseWindowViewModel createDatabaseWindowViewModel = new CreateDatabaseWindowViewModel(mainModel); - IWindowContext windowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.CREATE_DATABASE_WINDOW, createDatabaseWindowViewModel); + SetupWizardWindowViewModel setupWizardWindowViewModel = new SetupWizardWindowViewModel(mainModel); + IWindowContext windowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.SETUP_WIZARD_WINDOW, setupWizardWindowViewModel); bool? result = windowContext.ShowDialog(); if (result == true) { @@ -101,7 +186,7 @@ private void Close() { if (mainModel != null) { - mainModel.Downloader.Shutdown(); + mainModel.DownloadManager.Shutdown(); mainModel.Dispose(); } Shutdown(); diff --git a/LibgenDesktop/Common/Constants.cs b/LibgenDesktop/Common/Constants.cs index f5bddea..856dd10 100644 --- a/LibgenDesktop/Common/Constants.cs +++ b/LibgenDesktop/Common/Constants.cs @@ -5,10 +5,10 @@ namespace LibgenDesktop.Common internal static class Constants { public const string DATABASE_METADATA_APP_NAME = "LibgenDesktop"; - public const string CURRENT_VERSION = "1.3.5"; - public const string CURRENT_GITHUB_RELEASE_NAME = "1.3.5"; - public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2019, 11, 13); - public const string CURRENT_DATABASE_VERSION = "1.2.1"; + public const string CURRENT_VERSION = "1.4.0"; + public const string CURRENT_GITHUB_RELEASE_NAME = "1.4.0"; + public static readonly DateTime CURRENT_GITHUB_RELEASE_DATE = new DateTime(2020, 05, 10); + public const string CURRENT_DATABASE_VERSION = "1.4"; public const string APP_SETTINGS_FILE_NAME = "libgen.config"; public const string MIRRORS_DIRECTORY_NAME = "Mirrors"; @@ -18,6 +18,7 @@ internal static class Constants public const string DEFAULT_DOWNLOAD_DIRECTORY_NAME = "Downloads"; public const string DOWNLOAD_LIST_FILE_NAME = "downloads.json"; + public const double DEFAULT_FONT_SIZE = 15; public const int MAIN_WINDOW_MIN_WIDTH = 1050; public const int MAIN_WINDOW_MIN_HEIGHT = 500; public const int NON_FICTION_DETAILS_WINDOW_MIN_WIDTH = 1000; @@ -26,6 +27,7 @@ internal static class Constants public const int NON_FICTION_GRID_AUTHORS_COLUMN_MIN_WIDTH = 150; public const int NON_FICTION_GRID_SERIES_COLUMN_MIN_WIDTH = 150; public const int NON_FICTION_GRID_YEAR_COLUMN_MIN_WIDTH = 60; + public const int NON_FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH = 150; public const int NON_FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH = 150; public const int NON_FICTION_GRID_FORMAT_COLUMN_MIN_WIDTH = 80; public const int NON_FICTION_GRID_FILESIZE_COLUMN_MIN_WIDTH = 130; @@ -37,6 +39,7 @@ internal static class Constants public const int FICTION_GRID_AUTHORS_COLUMN_MIN_WIDTH = 150; public const int FICTION_GRID_SERIES_COLUMN_MIN_WIDTH = 150; public const int FICTION_GRID_YEAR_COLUMN_MIN_WIDTH = 60; + public const int FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH = 150; public const int FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH = 150; public const int FICTION_GRID_FORMAT_COLUMN_MIN_WIDTH = 80; public const int FICTION_GRID_FILESIZE_COLUMN_MIN_WIDTH = 130; @@ -59,7 +62,8 @@ internal static class Constants public const int ERROR_WINDOW_MIN_HEIGHT = 300; public const int IMPORT_WINDOW_MIN_WIDTH = 530; public const int IMPORT_WINDOW_MIN_HEIGHT = 400; - public const int CREATE_DATABASE_WINDOW_WIDTH = 500; + public const int SETUP_WIZARD_WINDOW_MIN_WIDTH = 1050; + public const int SETUP_WIZARD_WINDOW_MIN_HEIGHT = 500; public const int LIBRARY_WINDOW_DEFAULT_WIDTH = 760; public const int LIBRARY_WINDOW_DEFAULT_HEIGHT = 550; public const int LIBRARY_WINDOW_MIN_WIDTH = 760; @@ -73,6 +77,7 @@ internal static class Constants public const int SYNCHRONIZATION_WINDOW_MIN_HEIGHT = 400; public const int APPLICATION_UPDATE_WINDOW_WIDTH = 700; public const int DATABASE_WINDOW_WIDTH = 500; + public const int DATABASE_ERROR_WINDOW_WIDTH = 700; public const int ABOUT_WINDOW_WIDTH = 670; public const int MESSAGE_BOX_WINDOW_WIDTH = 500; public const int SQL_DEBUGGER_WINDOW_DEFAULT_WIDTH = 620; @@ -90,6 +95,7 @@ internal static class Constants public const int DEFAULT_NON_FICTION_GRID_AUTHORS_COLUMN_WIDTH = 200; public const int DEFAULT_NON_FICTION_GRID_SERIES_COLUMN_WIDTH = 180; public const int DEFAULT_NON_FICTION_GRID_YEAR_COLUMN_WIDTH = 60; + public const int DEFAULT_NON_FICTION_GRID_LANGUAGE_COLUMN_WIDTH = 180; public const int DEFAULT_NON_FICTION_GRID_PUBLISHER_COLUMN_WIDTH = 180; public const int DEFAULT_NON_FICTION_GRID_FORMAT_COLUMN_WIDTH = 100; public const int DEFAULT_NON_FICTION_GRID_FILESIZE_COLUMN_WIDTH = 150; @@ -101,6 +107,7 @@ internal static class Constants public const int DEFAULT_FICTION_GRID_AUTHORS_COLUMN_WIDTH = 200; public const int DEFAULT_FICTION_GRID_SERIES_COLUMN_WIDTH = 180; public const int DEFAULT_FICTION_GRID_YEAR_COLUMN_WIDTH = 60; + public const int DEFAULT_FICTION_GRID_LANGUAGE_COLUMN_WIDTH = 180; public const int DEFAULT_FICTION_GRID_PUBLISHER_COLUMN_WIDTH = 180; public const int DEFAULT_FICTION_GRID_FORMAT_COLUMN_WIDTH = 100; public const int DEFAULT_FICTION_GRID_FILESIZE_COLUMN_WIDTH = 150; @@ -114,8 +121,11 @@ internal static class Constants public const int DEFAULT_SCI_MAG_GRID_FILESIZE_COLUMN_WIDTH = 150; public const int DEFAULT_SCI_MAG_GRID_DOI_COLUMN_WIDTH = 290; public const int DEFAULT_SCI_MAG_GRID_EXISTS_IN_LIBRARY_COLUMN_WIDTH = 55; + public const int DEFAULT_SETUP_WIZARD_WINDOW_WIDTH = 1050; + public const int DEFAULT_SETUP_WIZARD_WINDOW_HEIGHT = 650; public const string DEFAULT_DOWNLOAD_MIRROR_NAME = "gen.lib.rus.ec"; public const string DEFAULT_SYNCHRONIZATION_MIRROR_NAME = "gen.lib.rus.ec"; + public const string DEFAULT_DATABASE_DUMP_MIRROR_NAME = "gen.lib.rus.ec"; public const int DEFAULT_MAXIMUM_SEARCH_RESULT_COUNT = 50000; public const double SEARCH_PROGRESS_REPORT_INTERVAL = 0.1; @@ -127,7 +137,7 @@ internal static class Constants public const int DATABASE_TRANSACTION_BATCH = 500; public const int MAX_EXPORT_ROWS_PER_FILE = 1048575; public const int LARGE_NUMBER_OF_ITEMS_TO_DOWNLOAD_WARNING_THRESHOLD = 1000; - public const int LARGE_DOWNLOADER_BATCH_UPDATE_ITEM_COUNT = 1000; + public const int LARGE_DOWNLOAD_MANAGER_BATCH_UPDATE_ITEM_COUNT = 1000; public const int MIN_DOWNLOAD_TIMEOUT = 15; public const int MAX_DOWNLOAD_TIMEOUT = 9999; public const int DEFAULT_DOWNLOAD_TIMEOUT = 120; @@ -138,7 +148,20 @@ internal static class Constants public const int MAX_DOWNLOAD_REDIRECT_COUNT = 10; public const int ASYNC_LOG_QUEUE_SIZE = 10000; - public const string GITHUB_RELEASE_API_URL = "https://api.github.com/repos/libgenapps/LibgenDesktop/releases"; + public const decimal NON_FICTION_APPROXIMATE_DOWNLOAD_SIZE_IN_MB = 300; + public const decimal FICTION_APPROXIMATE_DOWNLOAD_SIZE_IN_MB = 800; + public const decimal SCIMAG_APPROXIMATE_DOWNLOAD_SIZE_IN_GB = 10; + public const int NON_FICTION_IMPORT_TIME_IN_MINUTES_FROM = 2; + public const int NON_FICTION_IMPORT_TIME_IN_MINUTES_TO = 16; + public const int FICTION_IMPORT_TIME_IN_MINUTES_FROM = 1; + public const int FICTION_IMPORT_TIME_IN_MINUTES_TO = 8; + public const decimal SCIMAG_IMPORT_TIME_IN_HOURS_FROM = 1.5m; + public const decimal SCIMAG_IMPORT_TIME_IN_HOURS_TO = 12; + public const decimal NON_FICTION_APPROXIMATE_DATABASE_SIZE_IN_GB = 1.6m; + public const decimal FICTION_APPROXIMATE_DATABASE_SIZE_IN_GB = 0.9m; + public const decimal SCIMAG_APPROXIMATE_DATABASE_SIZE_IN_GB = 42; + + public const string DEFAULT_GITHUB_RELEASE_API_URL = "https://api.github.com/repos/libgenapps/LibgenDesktop/releases"; public const string USER_AGENT = "LibgenDesktop/" + CURRENT_VERSION; public const int MIN_PROXY_PORT = 1; public const int MAX_PROXY_PORT = 65535; diff --git a/LibgenDesktop/Common/Environment.cs b/LibgenDesktop/Common/Environment.cs index 983fedf..9120432 100644 --- a/LibgenDesktop/Common/Environment.cs +++ b/LibgenDesktop/Common/Environment.cs @@ -43,11 +43,12 @@ static Environment() Directory.CreateDirectory(AppDataDirectory); } } - string logFileName = $"{DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss")}.log"; + string logFileName = $"{DateTime.Now:yyyy-MM-dd_HH-mm-ss}.log"; LogFilePath = Path.Combine(AppDataDirectory, "Logs", logFileName); AppSettingsFilePath = Path.Combine(AppDataDirectory, APP_SETTINGS_FILE_NAME); MirrorsDirectoryPath = Path.Combine(AppBinariesDirectory, MIRRORS_DIRECTORY_NAME); LanguagesDirectoryPath = Path.Combine(AppBinariesDirectory, LANGUAGES_DIRECTORY_NAME); + TempDirectoryPath = Path.Combine(Path.GetTempPath(), "LibgenDesktop"); OsVersion = GetOsVersion(); NetFrameworkVersion = GetNetFrameworkVersion(); IsIn64BitProcess = System.Environment.Is64BitProcess; @@ -134,6 +135,7 @@ private static string GetNetFrameworkVersion() public static string AppSettingsFilePath { get; } public static string MirrorsDirectoryPath { get; } public static string LanguagesDirectoryPath { get; } + public static string TempDirectoryPath { get; } public static string OsVersion { get; } public static string NetFrameworkVersion { get; } public static bool IsInPortableMode { get; } diff --git a/LibgenDesktop/Infrastructure/FuncCommand.cs b/LibgenDesktop/Infrastructure/FuncCommand.cs index f217f85..195b109 100644 --- a/LibgenDesktop/Infrastructure/FuncCommand.cs +++ b/LibgenDesktop/Infrastructure/FuncCommand.cs @@ -3,11 +3,11 @@ namespace LibgenDesktop.Infrastructure { - public class FuncCommand : ICommand + public class FuncCommand : ICommand { - private readonly Func executeFunction; + private readonly Func executeFunction; - public FuncCommand(Func executeFunction) + public FuncCommand(Func executeFunction) { this.executeFunction = executeFunction; } @@ -21,12 +21,20 @@ public bool CanExecute(object parameter) public void Execute(object parameter) { - Execute(); + switch (parameter) + { + case TParameter typedParameter: + ExecuteWithTypedParameter(typedParameter); + break; + default: + ExecuteWithTypedParameter(default); + break; + } } - public TResult Execute() + public TResult ExecuteWithTypedParameter(TParameter parameter) { - TResult result = executeFunction != null ? executeFunction() : default; + TResult result = executeFunction != null ? executeFunction(parameter) : default; OnCanExecuteChanged(); return result; } diff --git a/LibgenDesktop/Infrastructure/IWindowContext.cs b/LibgenDesktop/Infrastructure/IWindowContext.cs index 2cda478..efc9bda 100644 --- a/LibgenDesktop/Infrastructure/IWindowContext.cs +++ b/LibgenDesktop/Infrastructure/IWindowContext.cs @@ -16,5 +16,11 @@ public interface IWindowContext void Focus(); void Show(int? width = null, int? height = null, bool showMaximized = false); bool? ShowDialog(int? width = null, int? height = null, bool showMaximized = false); + void AddWindowMinimizeButton(); + void AddWindowMaximizeButton(); + void AddWindowCloseButton(); + void RemoveWindowMinimizeButton(); + void RemoveWindowMaximizeButton(); + void RemoveWindowCloseButton(); } } \ No newline at end of file diff --git a/LibgenDesktop/Infrastructure/RegisteredWindows.cs b/LibgenDesktop/Infrastructure/RegisteredWindows.cs index d1428c7..dab7276 100644 --- a/LibgenDesktop/Infrastructure/RegisteredWindows.cs +++ b/LibgenDesktop/Infrastructure/RegisteredWindows.cs @@ -15,12 +15,14 @@ internal enum WindowKey SCI_MAG_DETAILS_WINDOW, ERROR_WINDOW, IMPORT_WINDOW, - CREATE_DATABASE_WINDOW, + SETUP_WIZARD_WINDOW, + SETUP_WIZARD_PROXY_SETTINGS_WINDOW, SETTINGS_WINDOW, SYNCHRONIZATION_WINDOW, APPLICATION_UPDATE_WINDOW, LIBRARY_WINDOW, DATABASE_WINDOW, + DATABASE_ERROR_WINDOW, ABOUT_WINDOW, SQL_DEBUGGER_WINDOW } @@ -48,11 +50,13 @@ static RegisteredWindows() RegisterWindow(WindowKey.SCI_MAG_DETAILS_WINDOW, typeof(SciMagDetailsWindow), typeof(SciMagDetailsWindowViewModel)); RegisterWindow(WindowKey.ERROR_WINDOW, typeof(ErrorWindow), typeof(ErrorWindowViewModel)); RegisterWindow(WindowKey.IMPORT_WINDOW, typeof(ImportWindow), typeof(ImportWindowViewModel)); - RegisterWindow(WindowKey.CREATE_DATABASE_WINDOW, typeof(CreateDatabaseWindow), typeof(CreateDatabaseWindowViewModel)); + RegisterWindow(WindowKey.SETUP_WIZARD_WINDOW, typeof(SetupWizardWindow), typeof(SetupWizardWindowViewModel)); + RegisterWindow(WindowKey.SETUP_WIZARD_PROXY_SETTINGS_WINDOW, typeof(SetupWizardProxySettingsWindow), typeof(SetupWizardProxySettingsWindowViewModel)); RegisterWindow(WindowKey.SETTINGS_WINDOW, typeof(SettingsWindow), typeof(SettingsWindowViewModel)); RegisterWindow(WindowKey.SYNCHRONIZATION_WINDOW, typeof(SynchronizationWindow), typeof(SynchronizationWindowViewModel)); RegisterWindow(WindowKey.APPLICATION_UPDATE_WINDOW, typeof(ApplicationUpdateWindow), typeof(ApplicationUpdateWindowViewModel)); RegisterWindow(WindowKey.DATABASE_WINDOW, typeof(DatabaseWindow), typeof(DatabaseWindowViewModel)); + RegisterWindow(WindowKey.DATABASE_ERROR_WINDOW, typeof(DatabaseErrorWindow), typeof(DatabaseErrorWindowViewModel)); RegisterWindow(WindowKey.ABOUT_WINDOW, typeof(AboutWindow), typeof(AboutWindowViewModel)); RegisterWindow(WindowKey.SQL_DEBUGGER_WINDOW, typeof(SqlDebuggerWindow), typeof(SqlDebuggerWindowViewModel)); MessageBox = new MessageBox(); diff --git a/LibgenDesktop/Infrastructure/ViewModelEvent.cs b/LibgenDesktop/Infrastructure/ViewModelEvent.cs index d0f26fd..e2fd83e 100644 --- a/LibgenDesktop/Infrastructure/ViewModelEvent.cs +++ b/LibgenDesktop/Infrastructure/ViewModelEvent.cs @@ -7,7 +7,8 @@ public enum RegisteredEventId FOCUS_SEARCH_TEXT_BOX = 1, SCROLL_TO_SELECTION, BRING_TO_FRONT, - FOCUS_SQL_QUERY_TEXT_BOX + FOCUS_SQL_QUERY_TEXT_BOX, + FOCUS_SETUP_WIZARD_PROXY_SETTINGS_ADDRESS_TEXT_BOX } public ViewModelEvent(RegisteredEventId eventId) diff --git a/LibgenDesktop/Infrastructure/WindowContext.cs b/LibgenDesktop/Infrastructure/WindowContext.cs index 56949d2..ce94cc2 100644 --- a/LibgenDesktop/Infrastructure/WindowContext.cs +++ b/LibgenDesktop/Infrastructure/WindowContext.cs @@ -94,6 +94,36 @@ public void Focus() Window.Focus(); } + public void AddWindowMinimizeButton() + { + Window.AddWindowMinimizeButton(); + } + + public void AddWindowMaximizeButton() + { + Window.AddWindowMaximizeButton(); + } + + public void AddWindowCloseButton() + { + Window.AddWindowCloseButton(); + } + + public void RemoveWindowMinimizeButton() + { + Window.RemoveWindowMinimizeButton(); + } + + public void RemoveWindowMaximizeButton() + { + Window.RemoveWindowMaximizeButton(); + } + + public void RemoveWindowCloseButton() + { + Window.RemoveWindowCloseButton(); + } + protected virtual void OnActivated() { Activated?.Invoke(this, EventArgs.Empty); @@ -114,6 +144,11 @@ protected virtual void OnClosed() Closed?.Invoke(this, EventArgs.Empty); } + private static WindowState GetWindowState(bool isMaximized) + { + return isMaximized ? WindowState.Maximized : WindowState.Normal; + } + private bool? ShowDialog(bool showMaximized, bool showInTaskbar) { Window.ShowInTaskbar = showInTaskbar; @@ -121,11 +156,6 @@ protected virtual void OnClosed() return Window.ShowDialog(); } - private WindowState GetWindowState(bool isMaximized) - { - return isMaximized ? WindowState.Maximized : WindowState.Normal; - } - private void Window_Activated(object sender, EventArgs e) { OnActivated(); diff --git a/LibgenDesktop/Infrastructure/WindowExtensions.cs b/LibgenDesktop/Infrastructure/WindowExtensions.cs new file mode 100644 index 0000000..584d99d --- /dev/null +++ b/LibgenDesktop/Infrastructure/WindowExtensions.cs @@ -0,0 +1,88 @@ +using System; +using System.Runtime.InteropServices; +using System.Windows; +using System.Windows.Interop; + +namespace LibgenDesktop.Infrastructure +{ + internal static class WindowExtensions + { + private const int GWL_STYLE = -16; + private const int WS_MAXIMIZEBOX = 0x10000; + private const int WS_MINIMIZEBOX = 0x20000; + private const int WS_SYSMENU = 0x80000; + private const int GWL_EXSTYLE = -20; + private const int WS_EX_DLGMODALFRAME = 0x0001; + private const int SWP_NOSIZE = 0x0001; + private const int SWP_NOMOVE = 0x0002; + private const int SWP_NOZORDER = 0x0004; + private const int SWP_FRAMECHANGED = 0x0020; + private const int WM_SETICON = 0x0080; + + [DllImport("user32.dll")] + private static extern int GetWindowLong(IntPtr hWnd, int nIndex); + + [DllImport("user32.dll")] + private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); + + [DllImport("user32.dll")] + private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); + + [DllImport("user32.dll")] + private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags); + + public static void AddWindowMinimizeButton(this Window window) + { + AddWindowStyle(window, WS_MINIMIZEBOX); + } + + public static void AddWindowMaximizeButton(this Window window) + { + AddWindowStyle(window, WS_MAXIMIZEBOX); + } + + public static void AddWindowCloseButton(this Window window) + { + AddWindowStyle(window, WS_SYSMENU); + } + + public static void RemoveWindowMinimizeButton(this Window window) + { + RemoveWindowStyle(window, WS_MINIMIZEBOX); + } + + public static void RemoveWindowMaximizeButton(this Window window) + { + RemoveWindowStyle(window, WS_MAXIMIZEBOX); + } + + public static void RemoveWindowCloseButton(this Window window) + { + RemoveWindowStyle(window, WS_SYSMENU); + } + + public static void RemoveWindowIcon(this Window window) + { + IntPtr windowHandle = new WindowInteropHelper(window).Handle; + int windowExStyle = GetWindowLong(windowHandle, GWL_EXSTYLE); + SetWindowLong(windowHandle, GWL_EXSTYLE, windowExStyle | WS_EX_DLGMODALFRAME); + SendMessage(windowHandle, WM_SETICON, IntPtr.Zero, IntPtr.Zero); + SendMessage(windowHandle, WM_SETICON, new IntPtr(1), IntPtr.Zero); + SetWindowPos(windowHandle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); + } + + private static void AddWindowStyle(Window window, int styleAttribute) + { + IntPtr windowHandle = new WindowInteropHelper(window).Handle; + int windowStyle = GetWindowLong(windowHandle, GWL_STYLE); + SetWindowLong(windowHandle, GWL_STYLE, windowStyle | styleAttribute); + } + + private static void RemoveWindowStyle(Window window, int styleAttribute) + { + IntPtr windowHandle = new WindowInteropHelper(window).Handle; + int windowStyle = GetWindowLong(windowHandle, GWL_STYLE); + SetWindowLong(windowHandle, GWL_STYLE, windowStyle & ~styleAttribute); + } + } +} diff --git a/LibgenDesktop/Infrastructure/WindowManager.cs b/LibgenDesktop/Infrastructure/WindowManager.cs index 0463813..900f0c3 100644 --- a/LibgenDesktop/Infrastructure/WindowManager.cs +++ b/LibgenDesktop/Infrastructure/WindowManager.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Runtime.InteropServices; +using System.Reflection; using System.Windows; -using System.Windows.Interop; using System.Windows.Threading; using Microsoft.Win32; using Microsoft.WindowsAPICodePack.Dialogs; @@ -12,35 +12,15 @@ namespace LibgenDesktop.Infrastructure { internal static class WindowManager { - private const int GWL_STYLE = -16; - private const int WS_MAXIMIZEBOX = 0x10000; - private const int WS_MINIMIZEBOX = 0x20000; - private const int WS_SYSMENU = 0x80000; - private const int GWL_EXSTYLE = -20; - private const int WS_EX_DLGMODALFRAME = 0x0001; - private const int SWP_NOSIZE = 0x0001; - private const int SWP_NOMOVE = 0x0002; - private const int SWP_NOZORDER = 0x0004; - private const int SWP_FRAMECHANGED = 0x0020; - private const int WM_SETICON = 0x0080; - - private static List createdWindowContexts; - - [DllImport("user32.dll")] - private static extern int GetWindowLong(IntPtr hWnd, int nIndex); - - [DllImport("user32.dll")] - private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); - - [DllImport("user32.dll")] - private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); - - [DllImport("user32.dll")] - private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags); + private static readonly List createdWindowContexts; + private static readonly FieldInfo menuDropAlignmentField; static WindowManager() { createdWindowContexts = new List(); + menuDropAlignmentField = typeof(SystemParameters).GetField("_menuDropAlignment", BindingFlags.NonPublic | BindingFlags.Static); + ResetPopupAlignment(); + SystemParameters.StaticPropertyChanged += (sender, e) => ResetPopupAlignment(); } public static int ScreenWidth @@ -59,6 +39,7 @@ public static int ScreenHeight } } + [SuppressMessage("Style", "IDE0019:Use pattern matching")] public static IWindowContext CreateWindow(RegisteredWindows.WindowKey windowKey, object viewModel = null, IWindowContext parentWindowContext = null) { RegisteredWindows.RegisteredWindow registeredWindow = RegisteredWindows.AllWindows[windowKey]; @@ -103,6 +84,7 @@ public static bool ShowPrompt(string title, string text, string yes, string no, return RegisteredWindows.MessageBox.ShowPrompt(title, text, yes, no, parentWindowContext); } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] public static OpenFileDialogResult ShowOpenFileDialog(OpenFileDialogParameters openFileDialogParameters) { if (openFileDialogParameters == null) @@ -129,6 +111,7 @@ public static OpenFileDialogResult ShowOpenFileDialog(OpenFileDialogParameters o return result; } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] public static SaveFileDialogResult ShowSaveFileDialog(SaveFileDialogParameters saveFileDialogParameters) { if (saveFileDialogParameters == null) @@ -159,6 +142,7 @@ public static SaveFileDialogResult ShowSaveFileDialog(SaveFileDialogParameters s return result; } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] public static SelectFolderDialogResult ShowSelectFolderDialog(SelectFolderDialogParameters selectFolderDialogParameters) { using (CommonOpenFileDialog commonOpenFileDialog = new CommonOpenFileDialog()) @@ -173,41 +157,17 @@ public static SelectFolderDialogResult ShowSelectFolderDialog(SelectFolderDialog } } - public static void RemoveWindowMinimizeButton(Window window) - { - RemoveWindowStyle(window, WS_MINIMIZEBOX); - } - - public static void RemoveWindowMaximizeButton(Window window) - { - RemoveWindowStyle(window, WS_MAXIMIZEBOX); - } - - public static void RemoveWindowCloseButton(Window window) - { - RemoveWindowStyle(window, WS_SYSMENU); - } - - public static void RemoveWindowIcon(Window window) - { - IntPtr windowHandle = new WindowInteropHelper(window).Handle; - int windowExStyle = GetWindowLong(windowHandle, GWL_EXSTYLE); - SetWindowLong(windowHandle, GWL_EXSTYLE, windowExStyle | WS_EX_DLGMODALFRAME); - SendMessage(windowHandle, WM_SETICON, IntPtr.Zero, IntPtr.Zero); - SendMessage(windowHandle, WM_SETICON, new IntPtr(1), IntPtr.Zero); - SetWindowPos(windowHandle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); - } - public static void SetClipboardText(string text) { Clipboard.SetDataObject(text); } - private static void RemoveWindowStyle(Window window, int styleAttribute) + private static void ResetPopupAlignment() { - IntPtr windowHandle = new WindowInteropHelper(window).Handle; - int windowStyle = GetWindowLong(windowHandle, GWL_STYLE); - SetWindowLong(windowHandle, GWL_STYLE, windowStyle & ~styleAttribute); + if (SystemParameters.MenuDropAlignment && menuDropAlignmentField != null) + { + menuDropAlignmentField.SetValue(null, false); + } } private static void WindowContext_Closed(object sender, EventArgs e) diff --git a/LibgenDesktop/LibgenDesktop.csproj b/LibgenDesktop/LibgenDesktop.csproj index 27ee3ac..29880a2 100644 --- a/LibgenDesktop/LibgenDesktop.csproj +++ b/LibgenDesktop/LibgenDesktop.csproj @@ -140,21 +140,24 @@ + - - - + + + - + + + @@ -177,44 +180,59 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + @@ -252,10 +270,26 @@ + - + + + + + + + + + + + + + + + + @@ -265,6 +299,7 @@ + @@ -274,6 +309,8 @@ + + @@ -287,7 +324,6 @@ - @@ -296,6 +332,9 @@ + + Link.xaml + BookDataGridContextMenu.xaml @@ -304,6 +343,45 @@ LibraryTabHeader.xaml + + LanguageComboBox.xaml + + + CollectionsPage.xaml + + + DownloadDumpLinksPage.xaml + + + DownloadModePage.xaml + + + DownloadDumpInfoPage.xaml + + + DownloadDumpsPage.xaml + + + ImportDumpsPage.xaml + + + CreateDatabasePage.xaml + + + StepListPage.xaml + + + ConfirmationPage.xaml + + + SetupModePage.xaml + + + LanguagePage.xaml + + + DatabaseOperationPage.xaml + ApplicationUpdateWindow.xaml @@ -315,7 +393,7 @@ CloseTabButton.xaml - + ExportPanel.xaml @@ -332,9 +410,18 @@ LibraryTab.xaml + + DatabaseErrorWindow.xaml + DatabaseWindow.xaml + + SetupWizardProxySettingsWindow.xaml + + + SetupWizardWindow.xaml + SqlDebuggerWindow.xaml @@ -367,9 +454,6 @@ Toolbar.xaml - - CreateDatabaseWindow.xaml - ErrorWindow.xaml @@ -412,6 +496,58 @@ + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + Designer MSBuild:Compile @@ -420,19 +556,83 @@ Designer MSBuild:Compile - + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + + MSBuild:Compile + Designer + + MSBuild:Compile Designer - + MSBuild:Compile Designer - + MSBuild:Compile Designer - + MSBuild:Compile Designer @@ -468,10 +668,22 @@ MSBuild:Compile Designer + + MSBuild:Compile + Designer + MSBuild:Compile Designer + + MSBuild:Compile + Designer + + + Designer + MSBuild:Compile + MSBuild:Compile Designer @@ -480,23 +692,23 @@ MSBuild:Compile Designer - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + MSBuild:Compile Designer - + MSBuild:Compile Designer @@ -532,10 +744,6 @@ Designer MSBuild:Compile - - Designer - MSBuild:Compile - Designer MSBuild:Compile @@ -564,39 +772,39 @@ MainWindow.xaml Code - + MSBuild:Compile Designer - + Designer MSBuild:Compile - + MSBuild:Compile Designer - + MSBuild:Compile Designer - + MSBuild:Compile Designer - + MSBuild:Compile Designer - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -636,39 +844,35 @@ Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile - - MSBuild:Compile - Designer - - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + MSBuild:Compile Designer - + Designer MSBuild:Compile - + Designer MSBuild:Compile - + Designer MSBuild:Compile @@ -701,6 +905,10 @@ PreserveNewest Mirrors\mirrors.config + + PreserveNewest + Mirrors\genlibrusec_dbdumps.xslt + PreserveNewest Mirrors\libgen_lc_nonfiction.xslt @@ -773,6 +981,14 @@ PreserveNewest Languages\Turkish.lng + + PreserveNewest + Languages\Portuguse_BR.lng + + + PreserveNewest + Languages\Italian.lng + @@ -783,6 +999,7 @@ + diff --git a/LibgenDesktop/Models/Database/LocalDatabase.cs b/LibgenDesktop/Models/Database/LocalDatabase.cs index 92625f1..bc0e667 100644 --- a/LibgenDesktop/Models/Database/LocalDatabase.cs +++ b/LibgenDesktop/Models/Database/LocalDatabase.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data; using System.Data.SQLite; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.IO; using System.Runtime.CompilerServices; @@ -659,158 +660,66 @@ public void AddFictionBooks(List books) { insertCommand.CommandText = SqlScripts.INSERT_FICTION; insertCommand.Parameters.AddWithValue("@Id", null); - SQLiteParameter authorFamily1Parameter = insertCommand.Parameters.Add("@AuthorFamily1", DbType.String); - SQLiteParameter authorName1Parameter = insertCommand.Parameters.Add("@AuthorName1", DbType.String); - SQLiteParameter authorSurname1Parameter = insertCommand.Parameters.Add("@AuthorSurname1", DbType.String); - SQLiteParameter role1Parameter = insertCommand.Parameters.Add("@Role1", DbType.String); - SQLiteParameter pseudonim1Parameter = insertCommand.Parameters.Add("@Pseudonim1", DbType.String); - SQLiteParameter authorFamily2Parameter = insertCommand.Parameters.Add("@AuthorFamily2", DbType.String); - SQLiteParameter authorName2Parameter = insertCommand.Parameters.Add("@AuthorName2", DbType.String); - SQLiteParameter authorSurname2Parameter = insertCommand.Parameters.Add("@AuthorSurname2", DbType.String); - SQLiteParameter role2Parameter = insertCommand.Parameters.Add("@Role2", DbType.String); - SQLiteParameter pseudonim2Parameter = insertCommand.Parameters.Add("@Pseudonim2", DbType.String); - SQLiteParameter authorFamily3Parameter = insertCommand.Parameters.Add("@AuthorFamily3", DbType.String); - SQLiteParameter authorName3Parameter = insertCommand.Parameters.Add("@AuthorName3", DbType.String); - SQLiteParameter authorSurname3Parameter = insertCommand.Parameters.Add("@AuthorSurname3", DbType.String); - SQLiteParameter role3Parameter = insertCommand.Parameters.Add("@Role3", DbType.String); - SQLiteParameter pseudonim3Parameter = insertCommand.Parameters.Add("@Pseudonim3", DbType.String); - SQLiteParameter authorFamily4Parameter = insertCommand.Parameters.Add("@AuthorFamily4", DbType.String); - SQLiteParameter authorName4Parameter = insertCommand.Parameters.Add("@AuthorName4", DbType.String); - SQLiteParameter authorSurname4Parameter = insertCommand.Parameters.Add("@AuthorSurname4", DbType.String); - SQLiteParameter role4Parameter = insertCommand.Parameters.Add("@Role4", DbType.String); - SQLiteParameter pseudonim4Parameter = insertCommand.Parameters.Add("@Pseudonim4", DbType.String); - SQLiteParameter series1Parameter = insertCommand.Parameters.Add("@Series1", DbType.String); - SQLiteParameter series2Parameter = insertCommand.Parameters.Add("@Series2", DbType.String); - SQLiteParameter series3Parameter = insertCommand.Parameters.Add("@Series3", DbType.String); - SQLiteParameter series4Parameter = insertCommand.Parameters.Add("@Series4", DbType.String); - SQLiteParameter titleParameter = insertCommand.Parameters.Add("@Title", DbType.String); - SQLiteParameter formatParameter = insertCommand.Parameters.Add("@Format", DbType.String); - SQLiteParameter versionParameter = insertCommand.Parameters.Add("@Version", DbType.String); - SQLiteParameter sizeInBytesParameter = insertCommand.Parameters.Add("@SizeInBytes", DbType.Int64); SQLiteParameter md5HashParameter = insertCommand.Parameters.Add("@Md5Hash", DbType.String); - SQLiteParameter pathParameter = insertCommand.Parameters.Add("@Path", DbType.String); + SQLiteParameter titleParameter = insertCommand.Parameters.Add("@Title", DbType.String); + SQLiteParameter authorsParameter = insertCommand.Parameters.Add("@Authors", DbType.String); + SQLiteParameter seriesParameter = insertCommand.Parameters.Add("@Series", DbType.String); + SQLiteParameter editionParameter = insertCommand.Parameters.Add("@Edition", DbType.String); SQLiteParameter languageParameter = insertCommand.Parameters.Add("@Language", DbType.String); - SQLiteParameter pagesParameter = insertCommand.Parameters.Add("@Pages", DbType.String); - SQLiteParameter identifierParameter = insertCommand.Parameters.Add("@Identifier", DbType.String); SQLiteParameter yearParameter = insertCommand.Parameters.Add("@Year", DbType.String); SQLiteParameter publisherParameter = insertCommand.Parameters.Add("@Publisher", DbType.String); - SQLiteParameter editionParameter = insertCommand.Parameters.Add("@Edition", DbType.String); - SQLiteParameter commentaryParameter = insertCommand.Parameters.Add("@Commentary", DbType.String); - SQLiteParameter addedDateTimeParameter = insertCommand.Parameters.Add("@AddedDateTime", DbType.String); - SQLiteParameter lastModifiedDateTimeParameter = insertCommand.Parameters.Add("@LastModifiedDateTime", DbType.String); - SQLiteParameter russianAuthorFamilyParameter = insertCommand.Parameters.Add("@RussianAuthorFamily", DbType.String); - SQLiteParameter russianAuthorNameParameter = insertCommand.Parameters.Add("@RussianAuthorName", DbType.String); - SQLiteParameter russianAuthorSurnameParameter = insertCommand.Parameters.Add("@RussianAuthorSurname", DbType.String); - SQLiteParameter coverParameter = insertCommand.Parameters.Add("@Cover", DbType.String); + SQLiteParameter pagesParameter = insertCommand.Parameters.Add("@Pages", DbType.String); + SQLiteParameter identifierParameter = insertCommand.Parameters.Add("@Identifier", DbType.String); SQLiteParameter googleBookIdParameter = insertCommand.Parameters.Add("@GoogleBookId", DbType.String); SQLiteParameter asinParameter = insertCommand.Parameters.Add("@Asin", DbType.String); - SQLiteParameter authorHashParameter = insertCommand.Parameters.Add("@AuthorHash", DbType.String); - SQLiteParameter titleHashParameter = insertCommand.Parameters.Add("@TitleHash", DbType.String); + SQLiteParameter coverUrlParameter = insertCommand.Parameters.Add("@CoverUrl", DbType.String); + SQLiteParameter formatParameter = insertCommand.Parameters.Add("@Format", DbType.String); + SQLiteParameter sizeInBytesParameter = insertCommand.Parameters.Add("@SizeInBytes", DbType.Int64); + SQLiteParameter libraryParameter = insertCommand.Parameters.Add("@Library", DbType.String); + SQLiteParameter issueParameter = insertCommand.Parameters.Add("@Issue", DbType.String); + SQLiteParameter locatorParameter = insertCommand.Parameters.Add("@Locator", DbType.String); + SQLiteParameter commentaryParameter = insertCommand.Parameters.Add("@Commentary", DbType.String); + SQLiteParameter genericParameter = insertCommand.Parameters.Add("@Generic", DbType.String); SQLiteParameter visibleParameter = insertCommand.Parameters.Add("@Visible", DbType.String); + SQLiteParameter addedDateTimeParameter = insertCommand.Parameters.Add("@AddedDateTime", DbType.String); + SQLiteParameter lastModifiedDateTimeParameter = insertCommand.Parameters.Add("@LastModifiedDateTime", DbType.String); SQLiteParameter libgenIdParameter = insertCommand.Parameters.Add("@LibgenId", DbType.Int32); insertFtsCommand.CommandText = SqlScripts.INSERT_FICTION_FTS_WITHOUT_ID; SQLiteParameter titleFtsParameter = insertFtsCommand.Parameters.Add("@Title", DbType.String); - SQLiteParameter authorFamily1FtsParameter = insertFtsCommand.Parameters.Add("@AuthorFamily1", DbType.String); - SQLiteParameter authorName1FtsParameter = insertFtsCommand.Parameters.Add("@AuthorName1", DbType.String); - SQLiteParameter authorSurname1FtsParameter = insertFtsCommand.Parameters.Add("@AuthorSurname1", DbType.String); - SQLiteParameter pseudonim1FtsParameter = insertFtsCommand.Parameters.Add("@Pseudonim1", DbType.String); - SQLiteParameter authorFamily2FtsParameter = insertFtsCommand.Parameters.Add("@AuthorFamily2", DbType.String); - SQLiteParameter authorName2FtsParameter = insertFtsCommand.Parameters.Add("@AuthorName2", DbType.String); - SQLiteParameter authorSurname2FtsParameter = insertFtsCommand.Parameters.Add("@AuthorSurname2", DbType.String); - SQLiteParameter pseudonim2FtsParameter = insertFtsCommand.Parameters.Add("@Pseudonim2", DbType.String); - SQLiteParameter authorFamily3FtsParameter = insertFtsCommand.Parameters.Add("@AuthorFamily3", DbType.String); - SQLiteParameter authorName3FtsParameter = insertFtsCommand.Parameters.Add("@AuthorName3", DbType.String); - SQLiteParameter authorSurname3FtsParameter = insertFtsCommand.Parameters.Add("@AuthorSurname3", DbType.String); - SQLiteParameter pseudonim3FtsParameter = insertFtsCommand.Parameters.Add("@Pseudonim3", DbType.String); - SQLiteParameter authorFamily4FtsParameter = insertFtsCommand.Parameters.Add("@AuthorFamily4", DbType.String); - SQLiteParameter authorName4FtsParameter = insertFtsCommand.Parameters.Add("@AuthorName4", DbType.String); - SQLiteParameter authorSurname4FtsParameter = insertFtsCommand.Parameters.Add("@AuthorSurname4", DbType.String); - SQLiteParameter pseudonim4FtsParameter = insertFtsCommand.Parameters.Add("@Pseudonim4", DbType.String); - SQLiteParameter russianAuthorFamilyFtsParameter = insertFtsCommand.Parameters.Add("@RussianAuthorFamily", DbType.String); - SQLiteParameter russianAuthorNameFtsParameter = insertFtsCommand.Parameters.Add("@RussianAuthorName", DbType.String); - SQLiteParameter russianAuthorSurnameFtsParameter = insertFtsCommand.Parameters.Add("@RussianAuthorSurname", DbType.String); - SQLiteParameter series1FtsParameter = insertFtsCommand.Parameters.Add("@Series1", DbType.String); - SQLiteParameter series2FtsParameter = insertFtsCommand.Parameters.Add("@Series2", DbType.String); - SQLiteParameter series3FtsParameter = insertFtsCommand.Parameters.Add("@Series3", DbType.String); - SQLiteParameter series4FtsParameter = insertFtsCommand.Parameters.Add("@Series4", DbType.String); + SQLiteParameter authorsFtsParameter = insertFtsCommand.Parameters.Add("@Authors", DbType.String); + SQLiteParameter seriesFtsParameter = insertFtsCommand.Parameters.Add("@Series", DbType.String); SQLiteParameter publisherFtsParameter = insertFtsCommand.Parameters.Add("@Publisher", DbType.String); SQLiteParameter identifierFtsParameter = insertFtsCommand.Parameters.Add("@Identifier", DbType.String); foreach (FictionBook book in books) { - authorFamily1Parameter.Value = book.AuthorFamily1; - authorName1Parameter.Value = book.AuthorName1; - authorSurname1Parameter.Value = book.AuthorSurname1; - role1Parameter.Value = book.Role1; - pseudonim1Parameter.Value = book.Pseudonim1; - authorFamily2Parameter.Value = book.AuthorFamily2; - authorName2Parameter.Value = book.AuthorName2; - authorSurname2Parameter.Value = book.AuthorSurname2; - role2Parameter.Value = book.Role2; - pseudonim2Parameter.Value = book.Pseudonim2; - authorFamily3Parameter.Value = book.AuthorFamily3; - authorName3Parameter.Value = book.AuthorName3; - authorSurname3Parameter.Value = book.AuthorSurname3; - role3Parameter.Value = book.Role3; - pseudonim3Parameter.Value = book.Pseudonim3; - authorFamily4Parameter.Value = book.AuthorFamily4; - authorName4Parameter.Value = book.AuthorName4; - authorSurname4Parameter.Value = book.AuthorSurname4; - role4Parameter.Value = book.Role4; - pseudonim4Parameter.Value = book.Pseudonim4; - series1Parameter.Value = book.Series1; - series2Parameter.Value = book.Series2; - series3Parameter.Value = book.Series3; - series4Parameter.Value = book.Series4; - titleParameter.Value = book.Title; - formatParameter.Value = book.Format; - versionParameter.Value = book.Version; - sizeInBytesParameter.Value = book.SizeInBytes; md5HashParameter.Value = book.Md5Hash; - pathParameter.Value = book.Path; + titleParameter.Value = book.Title; + authorsParameter.Value = book.Authors; + seriesParameter.Value = book.Series; + editionParameter.Value = book.Edition; languageParameter.Value = book.Language; - pagesParameter.Value = book.Pages; - identifierParameter.Value = book.Identifier; yearParameter.Value = book.Year; publisherParameter.Value = book.Publisher; - editionParameter.Value = book.Edition; - commentaryParameter.Value = book.Commentary; - addedDateTimeParameter.Value = book.AddedDateTime?.ToString("s"); - lastModifiedDateTimeParameter.Value = book.LastModifiedDateTime.ToString("s"); - russianAuthorFamilyParameter.Value = book.RussianAuthorFamily; - russianAuthorNameParameter.Value = book.RussianAuthorName; - russianAuthorSurnameParameter.Value = book.RussianAuthorSurname; - coverParameter.Value = book.Cover; + pagesParameter.Value = book.Pages; + identifierParameter.Value = book.Identifier; googleBookIdParameter.Value = book.GoogleBookId; asinParameter.Value = book.Asin; - authorHashParameter.Value = book.AuthorHash; - titleHashParameter.Value = book.TitleHash; + coverUrlParameter.Value = book.CoverUrl; + formatParameter.Value = book.Format; + sizeInBytesParameter.Value = book.SizeInBytes; + libraryParameter.Value = book.Library; + issueParameter.Value = book.Issue; + locatorParameter.Value = book.Locator; + commentaryParameter.Value = book.Commentary; + genericParameter.Value = book.Generic; visibleParameter.Value = book.Visible; + addedDateTimeParameter.Value = book.AddedDateTime?.ToString("s"); + lastModifiedDateTimeParameter.Value = book.LastModifiedDateTime?.ToString("s"); libgenIdParameter.Value = book.LibgenId; insertCommand.ExecuteNonQuery(); titleFtsParameter.Value = book.Title.SeparateCjkCharactersWithSpaces(); - authorFamily1FtsParameter.Value = book.AuthorFamily1.SeparateCjkCharactersWithSpaces(); - authorName1FtsParameter.Value = book.AuthorName1.SeparateCjkCharactersWithSpaces(); - authorSurname1FtsParameter.Value = book.AuthorSurname1.SeparateCjkCharactersWithSpaces(); - pseudonim1FtsParameter.Value = book.Pseudonim1.SeparateCjkCharactersWithSpaces(); - authorFamily2FtsParameter.Value = book.AuthorFamily2.SeparateCjkCharactersWithSpaces(); - authorName2FtsParameter.Value = book.AuthorName2.SeparateCjkCharactersWithSpaces(); - authorSurname2FtsParameter.Value = book.AuthorSurname2.SeparateCjkCharactersWithSpaces(); - pseudonim2FtsParameter.Value = book.Pseudonim2.SeparateCjkCharactersWithSpaces(); - authorFamily3FtsParameter.Value = book.AuthorFamily3.SeparateCjkCharactersWithSpaces(); - authorName3FtsParameter.Value = book.AuthorName3.SeparateCjkCharactersWithSpaces(); - authorSurname3FtsParameter.Value = book.AuthorSurname3.SeparateCjkCharactersWithSpaces(); - pseudonim3FtsParameter.Value = book.Pseudonim3.SeparateCjkCharactersWithSpaces(); - authorFamily4FtsParameter.Value = book.AuthorFamily4.SeparateCjkCharactersWithSpaces(); - authorName4FtsParameter.Value = book.AuthorName4.SeparateCjkCharactersWithSpaces(); - authorSurname4FtsParameter.Value = book.AuthorSurname4.SeparateCjkCharactersWithSpaces(); - pseudonim4FtsParameter.Value = book.Pseudonim4.SeparateCjkCharactersWithSpaces(); - russianAuthorFamilyFtsParameter.Value = book.RussianAuthorFamily; - russianAuthorNameFtsParameter.Value = book.RussianAuthorName; - russianAuthorSurnameFtsParameter.Value = book.RussianAuthorSurname; - series1FtsParameter.Value = book.Series1.SeparateCjkCharactersWithSpaces(); - series2FtsParameter.Value = book.Series2.SeparateCjkCharactersWithSpaces(); - series3FtsParameter.Value = book.Series3.SeparateCjkCharactersWithSpaces(); - series4FtsParameter.Value = book.Series4.SeparateCjkCharactersWithSpaces(); + authorsFtsParameter.Value = book.Authors.SeparateCjkCharactersWithSpaces(); + seriesFtsParameter.Value = book.Series.SeparateCjkCharactersWithSpaces(); publisherFtsParameter.Value = book.Publisher.SeparateCjkCharactersWithSpaces(); identifierFtsParameter.Value = book.Identifier; insertFtsCommand.ExecuteNonQuery(); @@ -831,214 +740,80 @@ public void UpdateFictionBooks(List books) deleteFtsCommand.CommandText = SqlScripts.DELETE_FICTION_FTS; SQLiteParameter idDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Id", DbType.Int32); SQLiteParameter titleDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Title", DbType.String); - SQLiteParameter authorFamily1DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorFamily1", DbType.String); - SQLiteParameter authorName1DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorName1", DbType.String); - SQLiteParameter authorSurname1DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorSurname1", DbType.String); - SQLiteParameter pseudonim1DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Pseudonim1", DbType.String); - SQLiteParameter authorFamily2DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorFamily2", DbType.String); - SQLiteParameter authorName2DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorName2", DbType.String); - SQLiteParameter authorSurname2DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorSurname2", DbType.String); - SQLiteParameter pseudonim2DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Pseudonim2", DbType.String); - SQLiteParameter authorFamily3DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorFamily3", DbType.String); - SQLiteParameter authorName3DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorName3", DbType.String); - SQLiteParameter authorSurname3DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorSurname3", DbType.String); - SQLiteParameter pseudonim3DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Pseudonim3", DbType.String); - SQLiteParameter authorFamily4DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorFamily4", DbType.String); - SQLiteParameter authorName4DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorName4", DbType.String); - SQLiteParameter authorSurname4DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@AuthorSurname4", DbType.String); - SQLiteParameter pseudonim4DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Pseudonim4", DbType.String); - SQLiteParameter russianAuthorFamilyDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@RussianAuthorFamily", DbType.String); - SQLiteParameter russianAuthorNameDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@RussianAuthorName", DbType.String); - SQLiteParameter russianAuthorSurnameDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@RussianAuthorSurname", DbType.String); - SQLiteParameter series1DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Series1", DbType.String); - SQLiteParameter series2DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Series2", DbType.String); - SQLiteParameter series3DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Series3", DbType.String); - SQLiteParameter series4DeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Series4", DbType.String); + SQLiteParameter authorsDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Authors", DbType.String); + SQLiteParameter seriesDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Series", DbType.String); SQLiteParameter publisherDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Publisher", DbType.String); SQLiteParameter identifierDeleteFtsParameter = deleteFtsCommand.Parameters.Add("@Identifier", DbType.String); updateCommand.CommandText = SqlScripts.UPDATE_FICTION; SQLiteParameter idParameter = updateCommand.Parameters.Add("@Id", DbType.Int32); - SQLiteParameter authorFamily1Parameter = updateCommand.Parameters.Add("@AuthorFamily1", DbType.String); - SQLiteParameter authorName1Parameter = updateCommand.Parameters.Add("@AuthorName1", DbType.String); - SQLiteParameter authorSurname1Parameter = updateCommand.Parameters.Add("@AuthorSurname1", DbType.String); - SQLiteParameter role1Parameter = updateCommand.Parameters.Add("@Role1", DbType.String); - SQLiteParameter pseudonim1Parameter = updateCommand.Parameters.Add("@Pseudonim1", DbType.String); - SQLiteParameter authorFamily2Parameter = updateCommand.Parameters.Add("@AuthorFamily2", DbType.String); - SQLiteParameter authorName2Parameter = updateCommand.Parameters.Add("@AuthorName2", DbType.String); - SQLiteParameter authorSurname2Parameter = updateCommand.Parameters.Add("@AuthorSurname2", DbType.String); - SQLiteParameter role2Parameter = updateCommand.Parameters.Add("@Role2", DbType.String); - SQLiteParameter pseudonim2Parameter = updateCommand.Parameters.Add("@Pseudonim2", DbType.String); - SQLiteParameter authorFamily3Parameter = updateCommand.Parameters.Add("@AuthorFamily3", DbType.String); - SQLiteParameter authorName3Parameter = updateCommand.Parameters.Add("@AuthorName3", DbType.String); - SQLiteParameter authorSurname3Parameter = updateCommand.Parameters.Add("@AuthorSurname3", DbType.String); - SQLiteParameter role3Parameter = updateCommand.Parameters.Add("@Role3", DbType.String); - SQLiteParameter pseudonim3Parameter = updateCommand.Parameters.Add("@Pseudonim3", DbType.String); - SQLiteParameter authorFamily4Parameter = updateCommand.Parameters.Add("@AuthorFamily4", DbType.String); - SQLiteParameter authorName4Parameter = updateCommand.Parameters.Add("@AuthorName4", DbType.String); - SQLiteParameter authorSurname4Parameter = updateCommand.Parameters.Add("@AuthorSurname4", DbType.String); - SQLiteParameter role4Parameter = updateCommand.Parameters.Add("@Role4", DbType.String); - SQLiteParameter pseudonim4Parameter = updateCommand.Parameters.Add("@Pseudonim4", DbType.String); - SQLiteParameter series1Parameter = updateCommand.Parameters.Add("@Series1", DbType.String); - SQLiteParameter series2Parameter = updateCommand.Parameters.Add("@Series2", DbType.String); - SQLiteParameter series3Parameter = updateCommand.Parameters.Add("@Series3", DbType.String); - SQLiteParameter series4Parameter = updateCommand.Parameters.Add("@Series4", DbType.String); - SQLiteParameter titleParameter = updateCommand.Parameters.Add("@Title", DbType.String); - SQLiteParameter formatParameter = updateCommand.Parameters.Add("@Format", DbType.String); - SQLiteParameter versionParameter = updateCommand.Parameters.Add("@Version", DbType.String); - SQLiteParameter sizeInBytesParameter = updateCommand.Parameters.Add("@SizeInBytes", DbType.Int64); SQLiteParameter md5HashParameter = updateCommand.Parameters.Add("@Md5Hash", DbType.String); - SQLiteParameter pathParameter = updateCommand.Parameters.Add("@Path", DbType.String); + SQLiteParameter titleParameter = updateCommand.Parameters.Add("@Title", DbType.String); + SQLiteParameter authorsParameter = updateCommand.Parameters.Add("@Authors", DbType.String); + SQLiteParameter seriesParameter = updateCommand.Parameters.Add("@Series", DbType.String); + SQLiteParameter editionParameter = updateCommand.Parameters.Add("@Edition", DbType.String); SQLiteParameter languageParameter = updateCommand.Parameters.Add("@Language", DbType.String); - SQLiteParameter pagesParameter = updateCommand.Parameters.Add("@Pages", DbType.String); - SQLiteParameter identifierParameter = updateCommand.Parameters.Add("@Identifier", DbType.String); SQLiteParameter yearParameter = updateCommand.Parameters.Add("@Year", DbType.String); SQLiteParameter publisherParameter = updateCommand.Parameters.Add("@Publisher", DbType.String); - SQLiteParameter editionParameter = updateCommand.Parameters.Add("@Edition", DbType.String); - SQLiteParameter commentaryParameter = updateCommand.Parameters.Add("@Commentary", DbType.String); - SQLiteParameter addedDateTimeParameter = updateCommand.Parameters.Add("@AddedDateTime", DbType.String); - SQLiteParameter lastModifiedDateTimeParameter = updateCommand.Parameters.Add("@LastModifiedDateTime", DbType.String); - SQLiteParameter russianAuthorFamilyParameter = updateCommand.Parameters.Add("@RussianAuthorFamily", DbType.String); - SQLiteParameter russianAuthorNameParameter = updateCommand.Parameters.Add("@RussianAuthorName", DbType.String); - SQLiteParameter russianAuthorSurnameParameter = updateCommand.Parameters.Add("@RussianAuthorSurname", DbType.String); - SQLiteParameter coverParameter = updateCommand.Parameters.Add("@Cover", DbType.String); + SQLiteParameter pagesParameter = updateCommand.Parameters.Add("@Pages", DbType.String); + SQLiteParameter identifierParameter = updateCommand.Parameters.Add("@Identifier", DbType.String); SQLiteParameter googleBookIdParameter = updateCommand.Parameters.Add("@GoogleBookId", DbType.String); SQLiteParameter asinParameter = updateCommand.Parameters.Add("@Asin", DbType.String); - SQLiteParameter authorHashParameter = updateCommand.Parameters.Add("@AuthorHash", DbType.String); - SQLiteParameter titleHashParameter = updateCommand.Parameters.Add("@TitleHash", DbType.String); + SQLiteParameter coverUrlParameter = updateCommand.Parameters.Add("@CoverUrl", DbType.String); + SQLiteParameter formatParameter = updateCommand.Parameters.Add("@Format", DbType.String); + SQLiteParameter sizeInBytesParameter = updateCommand.Parameters.Add("@SizeInBytes", DbType.Int64); + SQLiteParameter libraryParameter = updateCommand.Parameters.Add("@Library", DbType.String); + SQLiteParameter issueParameter = updateCommand.Parameters.Add("@Issue", DbType.String); + SQLiteParameter locatorParameter = updateCommand.Parameters.Add("@Locator", DbType.String); + SQLiteParameter commentaryParameter = updateCommand.Parameters.Add("@Commentary", DbType.String); + SQLiteParameter genericParameter = updateCommand.Parameters.Add("@Generic", DbType.String); SQLiteParameter visibleParameter = updateCommand.Parameters.Add("@Visible", DbType.String); + SQLiteParameter addedDateTimeParameter = updateCommand.Parameters.Add("@AddedDateTime", DbType.String); + SQLiteParameter lastModifiedDateTimeParameter = updateCommand.Parameters.Add("@LastModifiedDateTime", DbType.String); insertFtsWithIdCommand.CommandText = SqlScripts.INSERT_FICTION_FTS_WITH_ID; SQLiteParameter idFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Id", DbType.Int32); SQLiteParameter titleFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Title", DbType.String); - SQLiteParameter authorFamily1FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorFamily1", DbType.String); - SQLiteParameter authorName1FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorName1", DbType.String); - SQLiteParameter authorSurname1FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorSurname1", DbType.String); - SQLiteParameter pseudonim1FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Pseudonim1", DbType.String); - SQLiteParameter authorFamily2FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorFamily2", DbType.String); - SQLiteParameter authorName2FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorName2", DbType.String); - SQLiteParameter authorSurname2FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorSurname2", DbType.String); - SQLiteParameter pseudonim2FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Pseudonim2", DbType.String); - SQLiteParameter authorFamily3FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorFamily3", DbType.String); - SQLiteParameter authorName3FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorName3", DbType.String); - SQLiteParameter authorSurname3FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorSurname3", DbType.String); - SQLiteParameter pseudonim3FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Pseudonim3", DbType.String); - SQLiteParameter authorFamily4FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorFamily4", DbType.String); - SQLiteParameter authorName4FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorName4", DbType.String); - SQLiteParameter authorSurname4FtsParameter = insertFtsWithIdCommand.Parameters.Add("@AuthorSurname4", DbType.String); - SQLiteParameter pseudonim4FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Pseudonim4", DbType.String); - SQLiteParameter russianAuthorFamilyFtsParameter = insertFtsWithIdCommand.Parameters.Add("@RussianAuthorFamily", DbType.String); - SQLiteParameter russianAuthorNameFtsParameter = insertFtsWithIdCommand.Parameters.Add("@RussianAuthorName", DbType.String); - SQLiteParameter russianAuthorSurnameFtsParameter = insertFtsWithIdCommand.Parameters.Add("@RussianAuthorSurname", DbType.String); - SQLiteParameter series1FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Series1", DbType.String); - SQLiteParameter series2FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Series2", DbType.String); - SQLiteParameter series3FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Series3", DbType.String); - SQLiteParameter series4FtsParameter = insertFtsWithIdCommand.Parameters.Add("@Series4", DbType.String); + SQLiteParameter authorsFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Authors", DbType.String); + SQLiteParameter seriesFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Series", DbType.String); SQLiteParameter publisherFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Publisher", DbType.String); SQLiteParameter identifierFtsParameter = insertFtsWithIdCommand.Parameters.Add("@Identifier", DbType.String); foreach (FictionBook book in books) { idDeleteFtsParameter.Value = book.Id; titleDeleteFtsParameter.Value = book.Title.SeparateCjkCharactersWithSpaces(); - authorFamily1DeleteFtsParameter.Value = book.AuthorFamily1.SeparateCjkCharactersWithSpaces(); - authorName1DeleteFtsParameter.Value = book.AuthorName1.SeparateCjkCharactersWithSpaces(); - authorSurname1DeleteFtsParameter.Value = book.AuthorSurname1.SeparateCjkCharactersWithSpaces(); - pseudonim1DeleteFtsParameter.Value = book.Pseudonim1.SeparateCjkCharactersWithSpaces(); - authorFamily2DeleteFtsParameter.Value = book.AuthorFamily2.SeparateCjkCharactersWithSpaces(); - authorName2DeleteFtsParameter.Value = book.AuthorName2.SeparateCjkCharactersWithSpaces(); - authorSurname2DeleteFtsParameter.Value = book.AuthorSurname2.SeparateCjkCharactersWithSpaces(); - pseudonim2DeleteFtsParameter.Value = book.Pseudonim2.SeparateCjkCharactersWithSpaces(); - authorFamily3DeleteFtsParameter.Value = book.AuthorFamily3.SeparateCjkCharactersWithSpaces(); - authorName3DeleteFtsParameter.Value = book.AuthorName3.SeparateCjkCharactersWithSpaces(); - authorSurname3DeleteFtsParameter.Value = book.AuthorSurname3.SeparateCjkCharactersWithSpaces(); - pseudonim3DeleteFtsParameter.Value = book.Pseudonim3.SeparateCjkCharactersWithSpaces(); - authorFamily4DeleteFtsParameter.Value = book.AuthorFamily4.SeparateCjkCharactersWithSpaces(); - authorName4DeleteFtsParameter.Value = book.AuthorName4.SeparateCjkCharactersWithSpaces(); - authorSurname4DeleteFtsParameter.Value = book.AuthorSurname4.SeparateCjkCharactersWithSpaces(); - pseudonim4DeleteFtsParameter.Value = book.Pseudonim4.SeparateCjkCharactersWithSpaces(); - russianAuthorFamilyDeleteFtsParameter.Value = book.RussianAuthorFamily; - russianAuthorNameDeleteFtsParameter.Value = book.RussianAuthorName; - russianAuthorSurnameDeleteFtsParameter.Value = book.RussianAuthorSurname; - series1DeleteFtsParameter.Value = book.Series1.SeparateCjkCharactersWithSpaces(); - series2DeleteFtsParameter.Value = book.Series2.SeparateCjkCharactersWithSpaces(); - series3DeleteFtsParameter.Value = book.Series3.SeparateCjkCharactersWithSpaces(); - series4DeleteFtsParameter.Value = book.Series4.SeparateCjkCharactersWithSpaces(); + authorsDeleteFtsParameter.Value = book.Authors.SeparateCjkCharactersWithSpaces(); + seriesDeleteFtsParameter.Value = book.Series.SeparateCjkCharactersWithSpaces(); publisherDeleteFtsParameter.Value = book.Publisher.SeparateCjkCharactersWithSpaces(); identifierDeleteFtsParameter.Value = book.Identifier; deleteFtsCommand.ExecuteNonQuery(); idParameter.Value = book.Id; - authorFamily1Parameter.Value = book.AuthorFamily1; - authorName1Parameter.Value = book.AuthorName1; - authorSurname1Parameter.Value = book.AuthorSurname1; - role1Parameter.Value = book.Role1; - pseudonim1Parameter.Value = book.Pseudonim1; - authorFamily2Parameter.Value = book.AuthorFamily2; - authorName2Parameter.Value = book.AuthorName2; - authorSurname2Parameter.Value = book.AuthorSurname2; - role2Parameter.Value = book.Role2; - pseudonim2Parameter.Value = book.Pseudonim2; - authorFamily3Parameter.Value = book.AuthorFamily3; - authorName3Parameter.Value = book.AuthorName3; - authorSurname3Parameter.Value = book.AuthorSurname3; - role3Parameter.Value = book.Role3; - pseudonim3Parameter.Value = book.Pseudonim3; - authorFamily4Parameter.Value = book.AuthorFamily4; - authorName4Parameter.Value = book.AuthorName4; - authorSurname4Parameter.Value = book.AuthorSurname4; - role4Parameter.Value = book.Role4; - pseudonim4Parameter.Value = book.Pseudonim4; - series1Parameter.Value = book.Series1; - series2Parameter.Value = book.Series2; - series3Parameter.Value = book.Series3; - series4Parameter.Value = book.Series4; - titleParameter.Value = book.Title; - formatParameter.Value = book.Format; - versionParameter.Value = book.Version; - sizeInBytesParameter.Value = book.SizeInBytes; md5HashParameter.Value = book.Md5Hash; - pathParameter.Value = book.Path; + titleParameter.Value = book.Title; + authorsParameter.Value = book.Authors; + seriesParameter.Value = book.Series; + editionParameter.Value = book.Edition; languageParameter.Value = book.Language; - pagesParameter.Value = book.Pages; - identifierParameter.Value = book.Identifier; yearParameter.Value = book.Year; publisherParameter.Value = book.Publisher; - editionParameter.Value = book.Edition; - commentaryParameter.Value = book.Commentary; - addedDateTimeParameter.Value = book.AddedDateTime?.ToString("s"); - lastModifiedDateTimeParameter.Value = book.LastModifiedDateTime.ToString("s"); - russianAuthorFamilyParameter.Value = book.RussianAuthorFamily; - russianAuthorNameParameter.Value = book.RussianAuthorName; - russianAuthorSurnameParameter.Value = book.RussianAuthorSurname; - coverParameter.Value = book.Cover; + pagesParameter.Value = book.Pages; + identifierParameter.Value = book.Identifier; googleBookIdParameter.Value = book.GoogleBookId; asinParameter.Value = book.Asin; - authorHashParameter.Value = book.AuthorHash; - titleHashParameter.Value = book.TitleHash; + coverUrlParameter.Value = book.CoverUrl; + formatParameter.Value = book.Format; + sizeInBytesParameter.Value = book.SizeInBytes; + libraryParameter.Value = book.Library; + issueParameter.Value = book.Issue; + locatorParameter.Value = book.Locator; + commentaryParameter.Value = book.Commentary; + genericParameter.Value = book.Generic; visibleParameter.Value = book.Visible; + addedDateTimeParameter.Value = book.AddedDateTime?.ToString("s"); + lastModifiedDateTimeParameter.Value = book.LastModifiedDateTime?.ToString("s"); updateCommand.ExecuteNonQuery(); idFtsParameter.Value = book.Id; titleFtsParameter.Value = book.Title.SeparateCjkCharactersWithSpaces(); - authorFamily1FtsParameter.Value = book.AuthorFamily1.SeparateCjkCharactersWithSpaces(); - authorName1FtsParameter.Value = book.AuthorName1.SeparateCjkCharactersWithSpaces(); - authorSurname1FtsParameter.Value = book.AuthorSurname1.SeparateCjkCharactersWithSpaces(); - pseudonim1FtsParameter.Value = book.Pseudonim1.SeparateCjkCharactersWithSpaces(); - authorFamily2FtsParameter.Value = book.AuthorFamily2.SeparateCjkCharactersWithSpaces(); - authorName2FtsParameter.Value = book.AuthorName2.SeparateCjkCharactersWithSpaces(); - authorSurname2FtsParameter.Value = book.AuthorSurname2.SeparateCjkCharactersWithSpaces(); - pseudonim2FtsParameter.Value = book.Pseudonim2.SeparateCjkCharactersWithSpaces(); - authorFamily3FtsParameter.Value = book.AuthorFamily3.SeparateCjkCharactersWithSpaces(); - authorName3FtsParameter.Value = book.AuthorName3.SeparateCjkCharactersWithSpaces(); - authorSurname3FtsParameter.Value = book.AuthorSurname3.SeparateCjkCharactersWithSpaces(); - pseudonim3FtsParameter.Value = book.Pseudonim3.SeparateCjkCharactersWithSpaces(); - authorFamily4FtsParameter.Value = book.AuthorFamily4.SeparateCjkCharactersWithSpaces(); - authorName4FtsParameter.Value = book.AuthorName4.SeparateCjkCharactersWithSpaces(); - authorSurname4FtsParameter.Value = book.AuthorSurname4.SeparateCjkCharactersWithSpaces(); - pseudonim4FtsParameter.Value = book.Pseudonim4.SeparateCjkCharactersWithSpaces(); - russianAuthorFamilyFtsParameter.Value = book.RussianAuthorFamily; - russianAuthorNameFtsParameter.Value = book.RussianAuthorName; - russianAuthorSurnameFtsParameter.Value = book.RussianAuthorSurname; - series1FtsParameter.Value = book.Series1.SeparateCjkCharactersWithSpaces(); - series2FtsParameter.Value = book.Series2.SeparateCjkCharactersWithSpaces(); - series3FtsParameter.Value = book.Series3.SeparateCjkCharactersWithSpaces(); - series4FtsParameter.Value = book.Series4.SeparateCjkCharactersWithSpaces(); + authorsFtsParameter.Value = book.Authors.SeparateCjkCharactersWithSpaces(); + seriesFtsParameter.Value = book.Series.SeparateCjkCharactersWithSpaces(); publisherFtsParameter.Value = book.Publisher.SeparateCjkCharactersWithSpaces(); identifierFtsParameter.Value = book.Identifier; insertFtsWithIdCommand.ExecuteNonQuery(); @@ -1053,6 +828,12 @@ public List GetFictionIndexList() return GetIndexList(SqlScripts.GET_FICTION_INDEX_LIST); } + public void DropFictionTables() + { + ExecuteCommands(SqlScripts.DROP_FICTION_FTS_TABLE); + ExecuteCommands(SqlScripts.DROP_FICTION_TABLE); + } + public void CreateSciMagTables() { ExecuteCommands(SqlScripts.CREATE_SCIMAG_TABLE); @@ -1277,10 +1058,18 @@ public void CreateFilesTable() ExecuteCommands(SqlScripts.CREATE_FILES_TABLE); } - public void AddFileIdColumns() + public void AddFileIdColumnToNonFictionTable() { ExecuteCommands(SqlScripts.ALTER_NON_FICTION_ADD_FILE_ID); + } + + public void AddFileIdColumnToFictionTable() + { ExecuteCommands(SqlScripts.ALTER_FICTION_ADD_FILE_ID); + } + + public void AddFileIdColumnToSciMagTable() + { ExecuteCommands(SqlScripts.ALTER_SCIMAG_ADD_FILE_ID); } @@ -1430,8 +1219,54 @@ public string RunCustomSqlQuery(string sqlQuery) return resultBuilder.ToString(); } + private static string EscapeSearchQuery(string originalSearchQuery) + { + return SearchQueryParser.GetEscapedQuery(originalSearchQuery.SeparateCjkCharactersWithSpaces()); + } + + private static string GetSearchCommandWithLimit(string searchCommand, int? resultLimit) + { + return searchCommand + (resultLimit.HasValue ? " LIMIT " + resultLimit.Value : String.Empty); + } + + private static int ParseIntScalarResult(object objectResult) + { + return objectResult != DBNull.Value ? (int)(long)objectResult : 0; + } + + private static int? ParseNullableIntScalarResult(object objectResult) + { + return objectResult != DBNull.Value ? (int?)(long)objectResult : null; + } + + private static string ParseNullableDbString(object input) + { + return input != DBNull.Value ? input.ToString() : null; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static DateTime ParseDbDate(string input) + { + return DateTime.ParseExact(input, "s", CultureInfo.InvariantCulture); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] - private NonFictionBook ReadNonFictionBook(SQLiteDataReader dataReader) + private static DateTime? ParseNullableDbDate(object input) + { + if (input is string inputString) + { + if (String.IsNullOrEmpty(inputString)) + { + return null; + } + return ParseDbDate(inputString); + } + return null; + } + + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static NonFictionBook ReadNonFictionBook(SQLiteDataReader dataReader) { NonFictionBook book = new NonFictionBook(); book.Id = dataReader.GetInt32(0); @@ -1486,66 +1321,43 @@ private NonFictionBook ReadNonFictionBook(SQLiteDataReader dataReader) return book; } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - private FictionBook ReadFictionBook(SQLiteDataReader dataReader) + private static FictionBook ReadFictionBook(SQLiteDataReader dataReader) { FictionBook book = new FictionBook(); book.Id = dataReader.GetInt32(0); - book.AuthorFamily1 = dataReader.GetString(1); - book.AuthorName1 = dataReader.GetString(2); - book.AuthorSurname1 = dataReader.GetString(3); - book.Role1 = dataReader.GetString(4); - book.Pseudonim1 = dataReader.GetString(5); - book.AuthorFamily2 = dataReader.GetString(6); - book.AuthorName2 = dataReader.GetString(7); - book.AuthorSurname2 = dataReader.GetString(8); - book.Role2 = dataReader.GetString(9); - book.Pseudonim2 = dataReader.GetString(10); - book.AuthorFamily3 = dataReader.GetString(11); - book.AuthorName3 = dataReader.GetString(12); - book.AuthorSurname3 = dataReader.GetString(13); - book.Role3 = dataReader.GetString(14); - book.Pseudonim3 = dataReader.GetString(15); - book.AuthorFamily4 = dataReader.GetString(16); - book.AuthorName4 = dataReader.GetString(17); - book.AuthorSurname4 = dataReader.GetString(18); - book.Role4 = dataReader.GetString(19); - book.Pseudonim4 = dataReader.GetString(20); - book.Series1 = dataReader.GetString(21); - book.Series2 = dataReader.GetString(22); - book.Series3 = dataReader.GetString(23); - book.Series4 = dataReader.GetString(24); - book.Title = dataReader.GetString(25); - book.Format = dataReader.GetString(26); - book.Version = dataReader.GetString(27); - book.SizeInBytes = dataReader.GetInt64(28); - book.Md5Hash = dataReader.GetString(29); - book.Path = dataReader.GetString(30); - book.Language = dataReader.GetString(31); - book.Pages = dataReader.GetString(32); - book.Identifier = dataReader.GetString(33); - book.Year = dataReader.GetString(34); - book.Publisher = dataReader.GetString(35); - book.Edition = dataReader.GetString(36); - book.Commentary = dataReader.GetString(37); - book.AddedDateTime = ParseNullableDbDate(dataReader.GetValue(38)); - book.LastModifiedDateTime = ParseDbDate(dataReader.GetString(39)); - book.RussianAuthorFamily = dataReader.GetString(40); - book.RussianAuthorName = dataReader.GetString(41); - book.RussianAuthorSurname = dataReader.GetString(42); - book.Cover = dataReader.GetString(43); - book.GoogleBookId = dataReader.GetString(44); - book.Asin = dataReader.GetString(45); - book.AuthorHash = dataReader.GetString(46); - book.TitleHash = dataReader.GetString(47); - book.Visible = dataReader.GetString(48); - book.LibgenId = dataReader.GetInt32(49); - book.FileId = ParseNullableIntScalarResult(dataReader.GetValue(50)); + book.Md5Hash = dataReader.GetString(1); + book.Title = dataReader.GetString(2); + book.Authors = dataReader.GetString(3); + book.Series = dataReader.GetString(4); + book.Edition = dataReader.GetString(5); + book.Language = dataReader.GetString(6); + book.Year = dataReader.GetString(7); + book.Publisher = dataReader.GetString(8); + book.Pages = dataReader.GetString(9); + book.Identifier = dataReader.GetString(10); + book.GoogleBookId = dataReader.GetString(11); + book.Asin = dataReader.GetString(12); + book.CoverUrl = dataReader.GetString(13); + book.Format = dataReader.GetString(14); + book.SizeInBytes = dataReader.GetInt64(15); + book.Library = dataReader.GetString(16); + book.Issue = dataReader.GetString(17); + book.Locator = dataReader.GetString(18); + book.Commentary = dataReader.GetString(19); + book.Generic = dataReader.GetString(20); + book.Visible = dataReader.GetString(21); + book.AddedDateTime = ParseNullableDbDate(dataReader.GetValue(22)); + book.LastModifiedDateTime = ParseNullableDbDate(dataReader.GetValue(23)); + book.LibgenId = dataReader.GetInt32(24); + book.FileId = ParseNullableIntScalarResult(dataReader.GetValue(25)); return book; } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - private SciMagArticle ReadSciMagArticle(SQLiteDataReader dataReader) + private static SciMagArticle ReadSciMagArticle(SQLiteDataReader dataReader) { SciMagArticle article = new SciMagArticle(); article.Id = dataReader.GetInt32(0); @@ -1584,8 +1396,9 @@ private SciMagArticle ReadSciMagArticle(SQLiteDataReader dataReader) return article; } + [SuppressMessage("Style", "IDE0017:Simplify object initialization")] [MethodImpl(MethodImplOptions.AggressiveInlining)] - private LibraryFile ReadFile(SQLiteDataReader dataReader) + private static LibraryFile ReadFile(SQLiteDataReader dataReader) { LibraryFile file = new LibraryFile(); file.Id = dataReader.GetInt32(0); @@ -1596,16 +1409,6 @@ private LibraryFile ReadFile(SQLiteDataReader dataReader) return file; } - private string EscapeSearchQuery(string originalSearchQuery) - { - return SearchQueryParser.GetEscapedQuery(originalSearchQuery.SeparateCjkCharactersWithSpaces()); - } - - private string GetSearchCommandWithLimit(string searchCommand, int? resultLimit) - { - return searchCommand + (resultLimit.HasValue ? " LIMIT " + resultLimit.Value : String.Empty); - } - private void ExecuteCommands(params string[] commands) { using (SQLiteCommand command = connection.CreateCommand()) @@ -1623,11 +1426,6 @@ private int ExecuteIntScalarCommand(string commandText) return ParseIntScalarResult(ExecuteScalarCommand(commandText)); } - private string ExecuteStringScalarCommand(string commandText) - { - return ParseNullableDbString(ExecuteScalarCommand(commandText)); - } - private object ExecuteScalarCommand(string commandText) { using (SQLiteCommand command = connection.CreateCommand()) @@ -1637,41 +1435,6 @@ private object ExecuteScalarCommand(string commandText) } } - private int ParseIntScalarResult(object objectResult) - { - return objectResult != DBNull.Value ? (int)(long)objectResult : 0; - } - - private int? ParseNullableIntScalarResult(object objectResult) - { - return objectResult != DBNull.Value ? (int?)(long)objectResult : null; - } - - private string ParseNullableDbString(object input) - { - return input != DBNull.Value ? input.ToString() : null; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private DateTime ParseDbDate(string input) - { - return DateTime.ParseExact(input, "s", CultureInfo.InvariantCulture); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private DateTime? ParseNullableDbDate(object input) - { - if (input is string inputString) - { - if (String.IsNullOrEmpty(inputString)) - { - return null; - } - return ParseDbDate(inputString); - } - return null; - } - private List GetIndexList(string getIndexListQuery) { List result = new List(); diff --git a/LibgenDesktop/Models/Database/Migration.cs b/LibgenDesktop/Models/Database/Migration.cs index c245b30..3118f23 100644 --- a/LibgenDesktop/Models/Database/Migration.cs +++ b/LibgenDesktop/Models/Database/Migration.cs @@ -16,6 +16,8 @@ public static bool Migrate(LocalDatabase localDatabase, DatabaseMetadata databas return MigrateFrom_1_0(localDatabase, databaseMetadata); case "1.2": return MigrateFrom_1_2(localDatabase, databaseMetadata); + case "1.2.1": + return MigrateFrom_1_2_1(localDatabase, databaseMetadata); case Constants.CURRENT_DATABASE_VERSION: return true; default: @@ -23,19 +25,36 @@ public static bool Migrate(LocalDatabase localDatabase, DatabaseMetadata databas } } + public static bool UsesOldFictionSchema(DatabaseMetadata databaseMetadata) + { + Version metadataVersion = databaseMetadata.GetParsedVersion(); + if (metadataVersion == null) + { + throw new Exception("Database metadata has an invalid version number."); + } + return metadataVersion < new Version("1.4"); + } + private static bool MigrateFrom_0_7(LocalDatabase localDatabase, DatabaseMetadata databaseMetadata) { - return AddFiles(localDatabase) && UpdateMetadata(localDatabase, databaseMetadata); + return AddFilesTable(localDatabase) && RecreateFictionTables(localDatabase) && AddFileIdColumns(localDatabase) && + UpdateMetadata(localDatabase, databaseMetadata); } private static bool MigrateFrom_1_0(LocalDatabase localDatabase, DatabaseMetadata databaseMetadata) { - return AddFiles(localDatabase) && UpdateMetadata(localDatabase, databaseMetadata); + return AddFilesTable(localDatabase) && RecreateFictionTables(localDatabase) && AddFileIdColumns(localDatabase) && + UpdateMetadata(localDatabase, databaseMetadata); } private static bool MigrateFrom_1_2(LocalDatabase localDatabase, DatabaseMetadata databaseMetadata) { - return UpdateMetadata(localDatabase, databaseMetadata); + return RecreateFictionTables(localDatabase) && UpdateMetadata(localDatabase, databaseMetadata); + } + + private static bool MigrateFrom_1_2_1(LocalDatabase localDatabase, DatabaseMetadata databaseMetadata) + { + return RecreateFictionTables(localDatabase) && UpdateMetadata(localDatabase, databaseMetadata); } private static bool UpdateMetadata(LocalDatabase localDatabase, DatabaseMetadata databaseMetadata) @@ -54,12 +73,41 @@ private static bool UpdateMetadata(LocalDatabase localDatabase, DatabaseMetadata } } - private static bool AddFiles(LocalDatabase localDatabase) + private static bool AddFilesTable(LocalDatabase localDatabase) { try { localDatabase.CreateFilesTable(); - localDatabase.AddFileIdColumns(); + return true; + } + catch (Exception exception) + { + Logger.Exception(exception); + return false; + } + } + + private static bool AddFileIdColumns(LocalDatabase localDatabase) + { + try + { + localDatabase.AddFileIdColumnToNonFictionTable(); + localDatabase.AddFileIdColumnToSciMagTable(); + return true; + } + catch (Exception exception) + { + Logger.Exception(exception); + return false; + } + } + + private static bool RecreateFictionTables(LocalDatabase localDatabase) + { + try + { + localDatabase.DropFictionTables(); + localDatabase.CreateFictionTables(); return true; } catch (Exception exception) diff --git a/LibgenDesktop/Models/Database/SearchQueryParser.cs b/LibgenDesktop/Models/Database/SearchQueryParser.cs index 42091d3..09adc3f 100644 --- a/LibgenDesktop/Models/Database/SearchQueryParser.cs +++ b/LibgenDesktop/Models/Database/SearchQueryParser.cs @@ -17,6 +17,35 @@ public static string GetEscapedQuery(string originalSearchQuery) return new SearchQueryParser(originalSearchQuery).GetEscapedQuery(); } + private static void AddSearchQueryPart(List searchQueryBuilder, string searchQueryPart) + { + if (searchQueryPart.StartsWith("\"")) + { + searchQueryBuilder.Add(searchQueryPart); + } + else + { + switch (searchQueryPart) + { + case "AND": + case "OR": + case "NOT": + searchQueryBuilder.Add(searchQueryPart); + break; + default: + if (searchQueryPart.Length > 1 && searchQueryPart.EndsWith("*")) + { + searchQueryBuilder.Add($"\"{searchQueryPart.Substring(0, searchQueryPart.Length - 1)}\"*"); + } + else + { + searchQueryBuilder.Add($"\"{searchQueryPart}\""); + } + break; + } + } + } + private string GetEscapedQuery() { List searchQueryBuilder = new List(); @@ -87,34 +116,5 @@ private string GetEscapedQuery() } return String.Join(" ", searchQueryBuilder); } - - private void AddSearchQueryPart(List searchQueryBuilder, string searchQueryPart) - { - if (searchQueryPart.StartsWith("\"")) - { - searchQueryBuilder.Add(searchQueryPart); - } - else - { - switch (searchQueryPart) - { - case "AND": - case "OR": - case "NOT": - searchQueryBuilder.Add(searchQueryPart); - break; - default: - if (searchQueryPart.Length > 1 && searchQueryPart.EndsWith("*")) - { - searchQueryBuilder.Add($"\"{searchQueryPart.Substring(0, searchQueryPart.Length - 1)}\"*"); - } - else - { - searchQueryBuilder.Add($"\"{searchQueryPart}\""); - } - break; - } - } - } } } diff --git a/LibgenDesktop/Models/Database/SqlScripts.cs b/LibgenDesktop/Models/Database/SqlScripts.cs index 47f3de0..de35c90 100644 --- a/LibgenDesktop/Models/Database/SqlScripts.cs +++ b/LibgenDesktop/Models/Database/SqlScripts.cs @@ -177,64 +177,36 @@ internal static class SqlScripts public const string CREATE_FICTION_TABLE = "CREATE TABLE IF NOT EXISTS fiction (" + "Id INTEGER PRIMARY KEY NOT NULL," + - "AuthorFamily1 TEXT," + - "AuthorName1 TEXT," + - "AuthorSurname1 TEXT," + - "Role1 TEXT," + - "Pseudonim1 TEXT," + - "AuthorFamily2 TEXT," + - "AuthorName2 TEXT," + - "AuthorSurname2 TEXT," + - "Role2 TEXT," + - "Pseudonim2 TEXT," + - "AuthorFamily3 TEXT," + - "AuthorName3 TEXT," + - "AuthorSurname3 TEXT," + - "Role3 TEXT," + - "Pseudonim3 TEXT," + - "AuthorFamily4 TEXT," + - "AuthorName4 TEXT," + - "AuthorSurname4 TEXT," + - "Role4 TEXT," + - "Pseudonim4 TEXT," + - "Series1 TEXT," + - "Series2 TEXT," + - "Series3 TEXT," + - "Series4 TEXT," + - "Title TEXT," + - "Format TEXT," + - "Version TEXT," + - "SizeInBytes INTEGER NOT NULL," + "Md5Hash TEXT," + - "Path TEXT," + + "Title TEXT," + + "Authors TEXT," + + "Series TEXT," + + "Edition TEXT," + "Language TEXT," + - "Pages TEXT," + - "Identifier TEXT," + "Year TEXT," + "Publisher TEXT," + - "Edition TEXT," + - "Commentary TEXT," + - "AddedDateTime TEXT," + - "LastModifiedDateTime TEXT NOT NULL," + - "RussianAuthorFamily TEXT," + - "RussianAuthorName TEXT," + - "RussianAuthorSurname TEXT," + - "Cover TEXT," + + "Pages TEXT," + + "Identifier TEXT," + "GoogleBookId TEXT," + "Asin TEXT," + - "AuthorHash TEXT," + - "TitleHash TEXT," + + "CoverUrl TEXT," + + "Format TEXT," + + "SizeInBytes INTEGER NOT NULL," + + "Library TEXT," + + "Issue TEXT," + + "Locator TEXT," + + "Commentary TEXT," + + "Generic TEXT," + "Visible TEXT," + + "AddedDateTime TEXT," + + "LastModifiedDateTime TEXT," + "LibgenId INTEGER NOT NULL," + "FileId INTEGER," + "FOREIGN KEY (FileId) REFERENCES files(Id)" + ")"; public const string CREATE_FICTION_FTS_TABLE = - "CREATE VIRTUAL TABLE IF NOT EXISTS fiction_fts USING fts5 (Title, AuthorFamily1, AuthorName1, AuthorSurname1, Pseudonim1, " + - "AuthorFamily2, AuthorName2, AuthorSurname2, Pseudonim2, AuthorFamily3, AuthorName3, AuthorSurname3, Pseudonim3, " + - "AuthorFamily4, AuthorName4, AuthorSurname4, Pseudonim4, RussianAuthorFamily, RussianAuthorName, RussianAuthorSurname, " + - "Series1, Series2, Series3, Series4, Publisher, Identifier, content=fiction, content_rowid=Id)"; + "CREATE VIRTUAL TABLE IF NOT EXISTS fiction_fts USING fts5 (Title, Authors, Series, Publisher, Identifier, content=fiction, content_rowid=Id)"; public const string GET_ALL_FICTION_LIBGEN_IDS = "SELECT LibgenId FROM fiction"; @@ -254,87 +226,45 @@ internal static class SqlScripts public const string SEARCH_FICTION = "SELECT * FROM fiction WHERE Id IN (SELECT rowid FROM fiction_fts WHERE fiction_fts MATCH @SearchQuery) ORDER BY Id"; public const string INSERT_FICTION = - "INSERT INTO fiction VALUES (@Id,@AuthorFamily1,@AuthorName1,@AuthorSurname1,@Role1,@Pseudonim1,@AuthorFamily2,@AuthorName2,@AuthorSurname2,@Role2,@Pseudonim2," + - "@AuthorFamily3,@AuthorName3,@AuthorSurname3,@Role3,@Pseudonim3,@AuthorFamily4,@AuthorName4,@AuthorSurname4,@Role4,@Pseudonim4,@Series1,@Series2,@Series3,@Series4," + - "@Title,@Format,@Version,@SizeInBytes,@Md5Hash,@Path,@Language,@Pages,@Identifier,@Year,@Publisher,@Edition,@Commentary,@AddedDateTime,@LastModifiedDateTime," + - "@RussianAuthorFamily,@RussianAuthorName,@RussianAuthorSurname,@Cover,@GoogleBookId,@Asin,@AuthorHash,@TitleHash,@Visible,@LibgenId,NULL)"; + "INSERT INTO fiction VALUES (@Id,@Md5Hash,@Title,@Authors,@Series,@Edition,@Language,@Year,@Publisher,@Pages,@Identifier,@GoogleBookId,@Asin," + + "@CoverUrl,@Format,@SizeInBytes,@Library,@Issue,@Locator,@Commentary,@Generic,@Visible,@AddedDateTime,@LastModifiedDateTime,@LibgenId,NULL)"; public const string UPDATE_FICTION = "UPDATE fiction SET " + - "AuthorFamily1=@AuthorFamily1," + - "AuthorName1=@AuthorName1," + - "AuthorSurname1=@AuthorSurname1," + - "Role1=@Role1," + - "Pseudonim1=@Pseudonim1," + - "AuthorFamily2=@AuthorFamily2," + - "AuthorName2=@AuthorName2," + - "AuthorSurname2=@AuthorSurname2," + - "Role2=@Role2," + - "Pseudonim2=@Pseudonim2," + - "AuthorFamily3=@AuthorFamily3," + - "AuthorName3=@AuthorName3," + - "AuthorSurname3=@AuthorSurname3," + - "Role3=@Role3," + - "Pseudonim3=@Pseudonim3," + - "AuthorFamily4=@AuthorFamily4," + - "AuthorName4=@AuthorName4," + - "AuthorSurname4=@AuthorSurname4," + - "Role4=@Role4," + - "Pseudonim4=@Pseudonim4," + - "Series1=@Series1," + - "Series2=@Series2," + - "Series3=@Series3," + - "Series4=@Series4," + - "Title=@Title," + - "Format=@Format," + - "Version=@Version," + - "SizeInBytes=@SizeInBytes," + "Md5Hash=@Md5Hash," + - "Path=@Path," + + "Title=@Title," + + "Authors=@Authors," + + "Series=@Series," + + "Edition=@Edition," + "Language=@Language," + - "Pages=@Pages," + - "Identifier=@Identifier," + "Year=@Year," + "Publisher=@Publisher," + - "Edition=@Edition," + - "Commentary=@Commentary," + - "AddedDateTime=@AddedDateTime," + - "LastModifiedDateTime=@LastModifiedDateTime," + - "RussianAuthorFamily=@RussianAuthorFamily," + - "RussianAuthorName=@RussianAuthorName," + - "RussianAuthorSurname=@RussianAuthorSurname," + - "Cover=@Cover," + + "Pages=@Pages," + + "Identifier=@Identifier," + "GoogleBookId=@GoogleBookId," + "Asin=@Asin," + - "AuthorHash=@AuthorHash," + - "TitleHash=@TitleHash," + - "Visible=@Visible " + + "CoverUrl=@CoverUrl," + + "Format=@Format," + + "SizeInBytes=@SizeInBytes" + + "Library=@Library," + + "Issue=@Issue," + + "Locator=@Locator," + + "Commentary=@Commentary," + + "Generic=@Generic," + + "Visible=@Visible," + + "AddedDateTime=@AddedDateTime," + + "LastModifiedDateTime=@LastModifiedDateTime " + "WHERE Id=@Id"; public const string INSERT_FICTION_FTS_WITHOUT_ID = - "INSERT INTO fiction_fts VALUES (@Title,@AuthorFamily1,@AuthorName1,@AuthorSurname1,@Pseudonim1," + - "@AuthorFamily2,@AuthorName2,@AuthorSurname2,@Pseudonim2,@AuthorFamily3,@AuthorName3,@AuthorSurname3,@Pseudonim3," + - "@AuthorFamily4,@AuthorName4,@AuthorSurname4,@Pseudonim4,@RussianAuthorFamily,@RussianAuthorName,@RussianAuthorSurname," + - "@Series1,@Series2,@Series3,@Series4,@Publisher,@Identifier)"; + "INSERT INTO fiction_fts VALUES (@Title,@Authors,@Series,@Publisher,@Identifier)"; public const string INSERT_FICTION_FTS_WITH_ID = - "INSERT INTO fiction_fts (rowid,Title,AuthorFamily1,AuthorName1,AuthorSurname1,Pseudonim1," + - "AuthorFamily2,AuthorName2,AuthorSurname2,Pseudonim2,AuthorFamily3,AuthorName3,AuthorSurname3,Pseudonim3," + - "AuthorFamily4,AuthorName4,AuthorSurname4,Pseudonim4,RussianAuthorFamily,RussianAuthorName,RussianAuthorSurname," + - "Series1,Series2,Series3,Series4,Publisher,Identifier) VALUES (@Id,@Title,@AuthorFamily1,@AuthorName1,@AuthorSurname1,@Pseudonim1," + - "@AuthorFamily2,@AuthorName2,@AuthorSurname2,@Pseudonim2,@AuthorFamily3,@AuthorName3,@AuthorSurname3,@Pseudonim3," + - "@AuthorFamily4,@AuthorName4,@AuthorSurname4,@Pseudonim4,@RussianAuthorFamily,@RussianAuthorName,@RussianAuthorSurname," + - "@Series1,@Series2,@Series3,@Series4,@Publisher,@Identifier)"; + "INSERT INTO fiction_fts (rowid,Title,Authors,Series,Publisher,Identifier) VALUES (@Id,@Title,@Authors,@Series,@Publisher,@Identifier)"; public const string DELETE_FICTION_FTS = - "INSERT INTO fiction_fts (fiction_fts,rowid,Title,AuthorFamily1,AuthorName1,AuthorSurname1,Pseudonim1," + - "AuthorFamily2,AuthorName2,AuthorSurname2,Pseudonim2,AuthorFamily3,AuthorName3,AuthorSurname3,Pseudonim3," + - "AuthorFamily4,AuthorName4,AuthorSurname4,Pseudonim4,RussianAuthorFamily,RussianAuthorName,RussianAuthorSurname," + - "Series1,Series2,Series3,Series4,Publisher,Identifier) "+ - "VALUES ('delete',@Id,@Title,@AuthorFamily1,@AuthorName1,@AuthorSurname1,@Pseudonim1," + - "@AuthorFamily2,@AuthorName2,@AuthorSurname2,@Pseudonim2,@AuthorFamily3,@AuthorName3,@AuthorSurname3,@Pseudonim3," + - "@AuthorFamily4,@AuthorName4,@AuthorSurname4,@Pseudonim4,@RussianAuthorFamily,@RussianAuthorName,@RussianAuthorSurname," + - "@Series1,@Series2,@Series3,@Series4,@Publisher,@Identifier)"; + "INSERT INTO fiction_fts (fiction_fts,rowid,Title,Authors,Series,Publisher,Identifier) " + + "VALUES ('delete',@Id,@Title,@Authors,@Series,@Publisher,@Identifier)"; public const string GET_FICTION_INDEX_LIST = "PRAGMA index_list(fiction)"; @@ -347,6 +277,10 @@ internal static class SqlScripts public const string CREATE_FICTION_LIBGENID_INDEX = "CREATE UNIQUE INDEX " + FICTION_INDEX_PREFIX + "LibgenId ON fiction (LibgenId ASC)"; + public const string DROP_FICTION_FTS_TABLE = "DROP TABLE IF EXISTS fiction_fts"; + + public const string DROP_FICTION_TABLE = "DROP TABLE IF EXISTS fiction"; + public const string CREATE_SCIMAG_TABLE = "CREATE TABLE IF NOT EXISTS scimag (" + "Id INTEGER PRIMARY KEY NOT NULL," + diff --git a/LibgenDesktop/Models/Download/Downloader.cs b/LibgenDesktop/Models/Download/DownloadManager.cs similarity index 90% rename from LibgenDesktop/Models/Download/Downloader.cs rename to LibgenDesktop/Models/Download/DownloadManager.cs index ae77c17..e1a0022 100644 --- a/LibgenDesktop/Models/Download/Downloader.cs +++ b/LibgenDesktop/Models/Download/DownloadManager.cs @@ -10,12 +10,9 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using System.Xml; -using System.Xml.Xsl; -using HtmlAgilityPack; using LibgenDesktop.Common; using LibgenDesktop.Models.Localization; -using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.Localization.Localizators.Tabs; using LibgenDesktop.Models.Utils; using static LibgenDesktop.Common.Constants; using static LibgenDesktop.Models.Settings.AppSettings; @@ -23,29 +20,29 @@ namespace LibgenDesktop.Models.Download { - internal class Downloader : IDisposable + internal class DownloadManager : IDisposable { private readonly object downloadQueueLock; private readonly string downloadQueueFilePath; private readonly List downloadQueue; private readonly Dictionary downloadQueueKeyPairs; - private readonly BlockingCollection eventQueue; + private readonly BlockingCollection eventQueue; private readonly Task downloadTask; private readonly AutoResetEvent downloadTaskResetEvent; - private DownloadManagerLocalizator localization; + private DownloadManagerTabLocalizator localization; private HttpClient httpClient; private DownloadSettings downloadSettings; private bool isInOfflineMode; private bool isShuttingDown; private bool disposed; - public Downloader() + public DownloadManager() { downloadQueueLock = new object(); downloadQueueFilePath = Path.Combine(Environment.AppDataDirectory, DOWNLOAD_LIST_FILE_NAME); - downloadQueue = DownloadQueueStorage.LoadDownloadQueue(downloadQueueFilePath); + downloadQueue = DownloadManagerQueueStorage.LoadDownloadQueue(downloadQueueFilePath); downloadQueueKeyPairs = downloadQueue.ToDictionary(downloadItem => downloadItem.Id); - eventQueue = new BlockingCollection(); + eventQueue = new BlockingCollection(); downloadTaskResetEvent = new AutoResetEvent(false); localization = null; httpClient = null; @@ -57,7 +54,7 @@ public Downloader() disposed = false; } - public event EventHandler DownloaderBatchEvent; + public event EventHandler DownloadManagerBatchEvent; public void Configure(Language currentLanguage, NetworkSettings networkSettings, DownloadSettings downloadSettings) { @@ -77,7 +74,7 @@ public void Configure(Language currentLanguage, NetworkSettings networkSettings, isInOfflineMode = false; ResumeDownloadTask(); } - Logger.Debug("Downloader configuration complete."); + Logger.Debug("Download manager configuration complete."); } public List GetDownloadQueueSnapshot() @@ -98,9 +95,13 @@ public DownloadItem GetDownloadItemByDownloadPageUrl(string downloadPageUrl) public void EnqueueDownloadItems(IEnumerable downloadItemRequests) { + if (isShuttingDown) + { + return; + } lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); foreach (DownloadItemRequest downloadItemRequest in downloadItemRequests) { string fileName = String.Concat(FileUtils.RemoveInvalidFileNameCharacters(downloadItemRequest.FileNameWithoutExtension, @@ -122,10 +123,14 @@ public void EnqueueDownloadItems(IEnumerable downloadItemRe public void StartDownloads(IEnumerable downloadItemIds) { + if (isShuttingDown) + { + return; + } lock (downloadQueueLock) { bool resumeDownloadTask = false; - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); foreach (Guid downloadItemId in downloadItemIds) { if (!downloadQueueKeyPairs.TryGetValue(downloadItemId, out DownloadItem downloadItem)) @@ -161,9 +166,13 @@ public void StartDownloads(IEnumerable downloadItemIds) public void StopDownloads(IEnumerable downloadItemIds) { + if (isShuttingDown) + { + return; + } lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); foreach (Guid downloadItemId in downloadItemIds) { if (!downloadQueueKeyPairs.TryGetValue(downloadItemId, out DownloadItem downloadItem)) @@ -194,9 +203,13 @@ public void StopDownloads(IEnumerable downloadItemIds) public void RemoveDownloads(IEnumerable downloadItemIds) { + if (isShuttingDown) + { + return; + } lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); foreach (Guid downloadItemId in downloadItemIds) { if (!downloadQueueKeyPairs.TryGetValue(downloadItemId, out DownloadItem downloadItem)) @@ -240,7 +253,6 @@ public void Shutdown() SaveDownloadQueue(); foreach (DownloadItem downloadItem in downloadQueue) { - downloadItem.Status = DownloadItemStatus.STOPPED; downloadItem.CancelDownload(); } } @@ -253,7 +265,7 @@ public void Shutdown() { Logger.Exception(exception); } - Logger.Debug("Downloader was shut down successfully."); + Logger.Debug("Download manager was shut down successfully."); } public void Dispose() @@ -262,10 +274,127 @@ public void Dispose() { eventQueue?.Dispose(); downloadTaskResetEvent?.Dispose(); + httpClient?.Dispose(); disposed = true; } } + private static HttpClient CreateNewHttpClient(NetworkSettings networkSettings, DownloadSettings downloadSettings) + { + WebRequestHandler webRequestHandler = new WebRequestHandler + { + Proxy = NetworkUtils.CreateProxy(networkSettings), + UseProxy = true, + AllowAutoRedirect = false, + UseCookies = false, + ReadWriteTimeout = downloadSettings.Timeout * 1000 + }; + return new HttpClient(webRequestHandler) + { + Timeout = Timeout.InfiniteTimeSpan + }; + } + + private static bool IsRedirect(HttpStatusCode statusCode) + { + return (int)statusCode >= 300 && (int)statusCode <= 399; + } + + private static bool GenerateRedirectUrl(string requestUrl, Uri newLocationUri, out string redirectUrl) + { + if (newLocationUri.IsAbsoluteUri) + { + redirectUrl = EncodeInvalidUrlCharacters(newLocationUri.ToString()); + } + else + { + redirectUrl = EncodeInvalidUrlCharacters(new Uri(new Uri(requestUrl), newLocationUri).ToString()); + } + return Uri.IsWellFormedUriString(redirectUrl, UriKind.Absolute); + } + + private static void AppendCookies(Dictionary existingCookies, Uri uri, string cookieHeader) + { + CookieContainer cookieContainer = new CookieContainer(); + cookieContainer.SetCookies(uri, cookieHeader); + foreach (Cookie cookie in cookieContainer.GetCookies(uri)) + { + if (!cookie.Expired) + { + existingCookies[cookie.Name] = cookie.Value; + } + } + } + + private static string GenerateCookieHeader(Dictionary cookies) + { + return String.Join(";", cookies.Select(cookie => $"{cookie.Key}={cookie.Value}")); + } + + private static string GenerateFileName(string directory, string fileNameTemplate, string md5Hash) + { + string mainFileName = fileNameTemplate; + string partFileName = mainFileName + ".part"; + string mainFilePath; + string partFilePath; + string fileExtension = null; + bool isMd5HashFileName = false; + try + { + mainFilePath = Path.GetFullPath(Path.Combine(directory, mainFileName)); + partFilePath = Path.GetFullPath(Path.Combine(directory, partFileName)); + } + catch (PathTooLongException) + { + fileExtension = Path.GetExtension(fileNameTemplate); + fileNameTemplate = md5Hash + fileExtension; + mainFileName = fileNameTemplate; + partFileName = mainFileName + ".part"; + mainFilePath = Path.GetFullPath(Path.Combine(directory, mainFileName)); + partFilePath = Path.GetFullPath(Path.Combine(directory, partFileName)); + isMd5HashFileName = true; + } + string fileNameWithoutExtension = null; + int counter = 0; + while (File.Exists(mainFilePath) || File.Exists(partFilePath)) + { + if (fileNameWithoutExtension == null) + { + fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileNameTemplate); + fileExtension = Path.GetExtension(fileNameTemplate); + } + counter++; + mainFileName = $"{fileNameWithoutExtension} ({counter}){fileExtension}"; + partFileName = mainFileName + ".part"; + try + { + mainFilePath = Path.GetFullPath(Path.Combine(directory, mainFileName)); + partFilePath = Path.GetFullPath(Path.Combine(directory, partFileName)); + } + catch (PathTooLongException) + { + if (isMd5HashFileName) + { + throw; + } + fileNameWithoutExtension = md5Hash; + mainFileName = md5Hash + fileExtension; + partFileName = mainFileName + ".part"; + mainFilePath = Path.GetFullPath(Path.Combine(directory, mainFileName)); + partFilePath = Path.GetFullPath(Path.Combine(directory, partFileName)); + counter = 0; + isMd5HashFileName = true; + } + } + return mainFileName; + } + + private static string EncodeInvalidUrlCharacters(string url) + { + return url.Replace(" ", "%20").Replace("^", "%5E").Replace("`", "%60").Replace("<", "%3C").Replace(">", "%3E"). + Replace("[", "%5B").Replace("]", "%5D").Replace("{", "%7B").Replace("}", "%7D").Replace("|", "%7C"); + } + private void ResumeDownloadTask() { downloadTaskResetEvent.Set(); @@ -290,6 +419,10 @@ private Task StartDownloadTask() { lock (downloadQueueLock) { + if (isShuttingDown) + { + return; + } if (downloadItem == null || downloadItem.Status != DownloadItemStatus.DOWNLOADING) { downloadItem = downloadQueue.FirstOrDefault(item => item.Status == DownloadItemStatus.QUEUED || @@ -338,7 +471,7 @@ private Task StartDownloadTask() try { referer = url; - url = ExecuteTransformation(pageContent, transformationName); + url = DownloadUtils.ExecuteTransformation(pageContent, transformationName, htmlDecode: true); } catch (Exception exception) { @@ -377,6 +510,10 @@ private Task StartDownloadTask() bool skipFileDownload = false; lock (downloadQueueLock) { + if (isShuttingDown) + { + return; + } if (downloadItem.Status == DownloadItemStatus.DOWNLOADING) { downloadItem.DirectFileUrl = url; @@ -420,6 +557,10 @@ private Task StartDownloadTask() { lock (downloadQueueLock) { + if (isShuttingDown) + { + return; + } ReportError(downloadItem, localization.LogLineMaximumDownloadAttempts); SaveDownloadQueue(); } @@ -815,11 +956,6 @@ private async Task DownloadFileAsync(DownloadItem downloadItem, FileStream desti } } - private bool IsRedirect(HttpStatusCode statusCode) - { - return (int)statusCode >= 300 && (int)statusCode <= 399; - } - private async Task SendDownloadRequestAsync(DownloadItem downloadItem, string url, string referer, bool waitForFullContent, long? startPosition = null) { @@ -868,7 +1004,7 @@ private async Task SendDownloadRequestAsync(DownloadItem do HttpResponseMessage response; try { - response = await SendRequestAsync(request, downloadItem.CancellationToken, waitForFullContent); + response = await SendRequestAsync(request, waitForFullContent, downloadItem.CancellationToken); } catch (TimeoutException) { @@ -926,7 +1062,7 @@ private async Task SendDownloadRequestAsync(DownloadItem do return response; } - private Task SendRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken, bool waitForFullContent) + private Task SendRequestAsync(HttpRequestMessage request, bool waitForFullContent, CancellationToken cancellationToken) { return Task.Run(() => { @@ -961,49 +1097,13 @@ private Task SendRequestAsync(HttpRequestMessage request, C }); } - private string ExecuteTransformation(string pageContent, string transformationName) - { - HtmlDocument htmlDocument = new HtmlDocument(); - htmlDocument.LoadHtml(pageContent); - XslCompiledTransform xslTransform = new XslCompiledTransform(); - xslTransform.Load(Path.Combine(Environment.MirrorsDirectoryPath, transformationName + ".xslt")); - XmlWriterSettings outputSettings = xslTransform.OutputSettings.Clone(); - outputSettings.OmitXmlDeclaration = true; - outputSettings.Encoding = new UTF8Encoding(false); - using (MemoryStream memoryStream = new MemoryStream()) - using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, outputSettings)) - { - xslTransform.Transform(htmlDocument, xmlWriter); - string xmlEncodedString = Encoding.UTF8.GetString(memoryStream.ToArray()).Trim(); - return WebUtility.HtmlDecode(xmlEncodedString); - } - } - - private void AppendCookies(Dictionary existingCookies, Uri uri, string cookieHeader) - { - CookieContainer cookieContainer = new CookieContainer(); - cookieContainer.SetCookies(uri, cookieHeader); - foreach (Cookie cookie in cookieContainer.GetCookies(uri)) - { - if (!cookie.Expired) - { - existingCookies[cookie.Name] = cookie.Value; - } - } - } - - private string GenerateCookieHeader(Dictionary cookies) - { - return String.Join(";", cookies.Select(cookie => $"{cookie.Key}={cookie.Value}")); - } - private void StartEventPublisherTask() { Task.Run(() => { while (!eventQueue.IsCompleted) { - DownloaderBatchEventArgs batchEventArgs; + DownloadManagerBatchEventArgs batchEventArgs; try { batchEventArgs = eventQueue.Take(); @@ -1012,32 +1112,16 @@ private void StartEventPublisherTask() { return; } - DownloaderBatchEvent?.Invoke(this, batchEventArgs); + DownloadManagerBatchEvent?.Invoke(this, batchEventArgs); } }); } - private HttpClient CreateNewHttpClient(NetworkSettings networkSettings, DownloadSettings downloadSettings) - { - WebRequestHandler webRequestHandler = new WebRequestHandler - { - Proxy = NetworkUtils.CreateProxy(networkSettings), - UseProxy = true, - AllowAutoRedirect = false, - UseCookies = false, - ReadWriteTimeout = downloadSettings.Timeout * 1000 - }; - return new HttpClient(webRequestHandler) - { - Timeout = Timeout.InfiniteTimeSpan - }; - } - private void SwitchToOfflineMode() { lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); foreach (DownloadItem downloadingItem in downloadQueue.Where(downloadItem => downloadItem.Status == DownloadItemStatus.DOWNLOADING || downloadItem.Status == DownloadItemStatus.RETRY_DELAY)) { @@ -1056,7 +1140,7 @@ private void SaveDownloadQueue() { try { - DownloadQueueStorage.SaveDownloadQueue(downloadQueueFilePath, downloadQueue); + DownloadManagerQueueStorage.SaveDownloadQueue(downloadQueueFilePath, downloadQueue); } catch (Exception exception) { @@ -1064,75 +1148,6 @@ private void SaveDownloadQueue() } } - private string GenerateFileName(string directory, string fileNameTemplate, string md5Hash) - { - string fileName = fileNameTemplate; - string filePath; - string fileExtension = null; - bool isMd5HashFileName = false; - try - { - filePath = Path.GetFullPath(Path.Combine(directory, fileName)); - } - catch (PathTooLongException) - { - fileExtension = Path.GetExtension(fileNameTemplate); - fileNameTemplate = md5Hash + fileExtension; - fileName = fileNameTemplate; - filePath = Path.Combine(directory, fileName); - isMd5HashFileName = true; - } - string fileNameWithoutExtension = null; - int counter = 0; - while (File.Exists(filePath) || File.Exists(filePath + ".part")) - { - if (fileNameWithoutExtension == null) - { - fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileNameTemplate); - fileExtension = Path.GetExtension(fileNameTemplate); - } - counter++; - fileName = $"{fileNameWithoutExtension} ({counter}){fileExtension}"; - try - { - filePath = Path.GetFullPath(Path.Combine(directory, fileName)); - } - catch (PathTooLongException) - { - if (isMd5HashFileName) - { - throw; - } - fileExtension = Path.GetExtension(fileNameTemplate); - fileName = md5Hash + fileExtension; - filePath = Path.Combine(directory, fileName); - counter = 0; - fileNameWithoutExtension = null; - isMd5HashFileName = true; - } - } - return fileName; - } - - private bool GenerateRedirectUrl(string requestUrl, Uri newLocationUri, out string redirectUrl) - { - if (newLocationUri.IsAbsoluteUri) - { - redirectUrl = EncodeInvalidUrlCharacters(newLocationUri.ToString()); - } - else - { - redirectUrl = EncodeInvalidUrlCharacters(new Uri(new Uri(requestUrl), newLocationUri).ToString()); - } - return Uri.IsWellFormedUriString(redirectUrl, UriKind.Absolute); - } - - private string EncodeInvalidUrlCharacters(string url) - { - return url.Replace(" ", "%20").Replace("^", "%5E").Replace("`", "%60").Replace("<", "%3C").Replace(">", "%3E"). - Replace("[", "%5B").Replace("]", "%5D").Replace("{", "%7B").Replace("}", "%7D").Replace("|", "%7C"); - } - private DownloadItemLogLineEventArgs AddLogLine(DownloadItem downloadItem, DownloadItemLogLineType logLineType, string logLine) { lock (downloadQueueLock) @@ -1140,7 +1155,7 @@ private DownloadItemLogLineEventArgs AddLogLine(DownloadItem downloadItem, Downl DownloadItemLogLine downloadItemLogLine = new DownloadItemLogLine(logLineType, DateTime.Now, logLine); int lineIndex = downloadItem.Logs.Count; downloadItem.Logs.Add(downloadItemLogLine); - Logger.Debug($"Downloader log line: type = {logLineType}, text = \"{logLine}\"."); + Logger.Debug($"Download manager log line: type = {logLineType}, text = \"{logLine}\"."); return new DownloadItemLogLineEventArgs(downloadItem.Id, lineIndex, downloadItemLogLine); } } @@ -1149,7 +1164,7 @@ private void ReportLogLine(DownloadItem downloadItem, DownloadItemLogLineType lo { lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); DownloadItemLogLineEventArgs logLineEventArgs = AddLogLine(downloadItem, logLineType, logLine); batchEventArgs.Add(logLineEventArgs); eventQueue.Add(batchEventArgs); @@ -1160,7 +1175,7 @@ private void ReportChange(DownloadItem downloadItem) { lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); batchEventArgs.Add(new DownloadItemChangedEventArgs(downloadItem)); eventQueue.Add(batchEventArgs); } @@ -1170,7 +1185,7 @@ private void ReportStatusChange(DownloadItem downloadItem, DownloadItemStatus ne { lock (downloadQueueLock) { - DownloaderBatchEventArgs batchEventArgs = new DownloaderBatchEventArgs(); + DownloadManagerBatchEventArgs batchEventArgs = new DownloadManagerBatchEventArgs(); DownloadItemLogLineEventArgs logLineEventArgs = AddLogLine(downloadItem, logLineType, logMessage); batchEventArgs.Add(logLineEventArgs); downloadItem.Status = newStatus; diff --git a/LibgenDesktop/Models/Download/DownloaderBatchEventArgs.cs b/LibgenDesktop/Models/Download/DownloadManagerBatchEventArgs.cs similarity index 91% rename from LibgenDesktop/Models/Download/DownloaderBatchEventArgs.cs rename to LibgenDesktop/Models/Download/DownloadManagerBatchEventArgs.cs index 8b1ad07..d3c7f89 100644 --- a/LibgenDesktop/Models/Download/DownloaderBatchEventArgs.cs +++ b/LibgenDesktop/Models/Download/DownloadManagerBatchEventArgs.cs @@ -3,9 +3,9 @@ namespace LibgenDesktop.Models.Download { - internal class DownloaderBatchEventArgs : EventArgs + internal class DownloadManagerBatchEventArgs : EventArgs { - public DownloaderBatchEventArgs() + public DownloadManagerBatchEventArgs() { BatchEvents = new List(); AddEventCount = 0; diff --git a/LibgenDesktop/Models/Download/DownloaderEventArgs.cs b/LibgenDesktop/Models/Download/DownloadManagerEventArgs.cs similarity index 100% rename from LibgenDesktop/Models/Download/DownloaderEventArgs.cs rename to LibgenDesktop/Models/Download/DownloadManagerEventArgs.cs diff --git a/LibgenDesktop/Models/Download/DownloadQueueStorage.cs b/LibgenDesktop/Models/Download/DownloadManagerQueueStorage.cs similarity index 99% rename from LibgenDesktop/Models/Download/DownloadQueueStorage.cs rename to LibgenDesktop/Models/Download/DownloadManagerQueueStorage.cs index 13b6006..be912bb 100644 --- a/LibgenDesktop/Models/Download/DownloadQueueStorage.cs +++ b/LibgenDesktop/Models/Download/DownloadManagerQueueStorage.cs @@ -6,7 +6,7 @@ namespace LibgenDesktop.Models.Download { - internal static class DownloadQueueStorage + internal static class DownloadManagerQueueStorage { internal class StorageDownloadItem { diff --git a/LibgenDesktop/Models/Download/DownloadUtils.cs b/LibgenDesktop/Models/Download/DownloadUtils.cs new file mode 100644 index 0000000..1ebf371 --- /dev/null +++ b/LibgenDesktop/Models/Download/DownloadUtils.cs @@ -0,0 +1,263 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Net.Http.Headers; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Xml; +using System.Xml.Xsl; +using HtmlAgilityPack; +using LibgenDesktop.Common; +using LibgenDesktop.Models.ProgressArgs; +using LibgenDesktop.Models.Utils; +using Environment = LibgenDesktop.Common.Environment; + +namespace LibgenDesktop.Models.Download +{ + internal static class DownloadUtils + { + internal enum DownloadResult + { + COMPLETED = 1, + INCOMPLETE, + CANCELLED, + ERROR + } + + internal class DownloadPageResult + { + public DownloadResult DownloadResult { get; set; } + public HttpStatusCode HttpStatusCode { get; set; } + public string PageContent { get; set; } + } + + public static async Task DownloadPageAsync(HttpClient httpClient, string pageUrl, CancellationToken cancellationToken) + { + DownloadPageResult result = new DownloadPageResult(); + Logger.Debug($"Sending a request to {pageUrl}"); + HttpResponseMessage response; + try + { + response = await httpClient.GetAsync(pageUrl, cancellationToken); + } + catch (TaskCanceledException) + { + Logger.Debug("Page download has been cancelled."); + result.DownloadResult = DownloadResult.CANCELLED; + return result; + } + catch (Exception exception) + { + Logger.Exception(exception); + result.DownloadResult = DownloadResult.ERROR; + return result; + } + Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); + Logger.Debug("Response headers:", response.Headers.ToString().TrimEnd(), response.Content.Headers.ToString().TrimEnd()); + result.HttpStatusCode = response.StatusCode; + result.PageContent = await response.Content.ReadAsStringAsync(); + Logger.Debug("Response content:", result.PageContent); + result.DownloadResult = DownloadResult.COMPLETED; + return result; + } + + public static Task DownloadFileAsync(HttpClient httpClient, string fileUrl, string destinationPath, bool resumeDownload, + IProgress progressHandler, CancellationToken cancellationToken) + { + return Task.Run(async () => + { + Logger.Debug($"Requesting {fileUrl}"); + long? startPosition = null; + HttpRequestMessage request; + try + { + request = new HttpRequestMessage(HttpMethod.Get, fileUrl); + if (resumeDownload && File.Exists(destinationPath)) + { + startPosition = new FileInfo(destinationPath).Length; + if (startPosition > 0) + { + long? totalDownloadSize; + try + { + totalDownloadSize = await GetDownloadContentLength(httpClient, fileUrl, cancellationToken); + } + catch (TaskCanceledException) + { + Logger.Debug("File download has been cancelled."); + return DownloadResult.CANCELLED; + } + if (!totalDownloadSize.HasValue) + { + Logger.Debug("Couldn't retrieve file size."); + return DownloadResult.ERROR; + } + if (startPosition >= totalDownloadSize.Value) + { + if (startPosition > totalDownloadSize.Value) + { + Logger.Debug($"Current file size: {startPosition} bytes is larger " + + "than the total download size: {totalDownloadSize.Value} bytes."); + } + else + { + Logger.Debug("File has already been downloaded."); + } + progressHandler.Report(new DownloadFileProgress(totalDownloadSize.Value, totalDownloadSize.Value)); + return DownloadResult.COMPLETED; + } + request.Headers.Range = new RangeHeaderValue(startPosition.Value, null); + Logger.Debug($"Resuming download from {startPosition.Value} bytes."); + } + else + { + startPosition = null; + } + } + } + catch (Exception exception) + { + Logger.Exception(exception); + return DownloadResult.ERROR; + } + HttpResponseMessage response; + try + { + response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken); + } + catch (TaskCanceledException) + { + Logger.Debug("File download has been cancelled."); + return DownloadResult.CANCELLED; + } + catch (TimeoutException) + { + Logger.Debug("Download timeout."); + return DownloadResult.ERROR; + } + catch (Exception exception) + { + Logger.Exception(exception); + return DownloadResult.ERROR; + } + Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); + Logger.Debug("Response headers:", response.Headers.ToString().TrimEnd(), response.Content.Headers.ToString().TrimEnd()); + if (response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.PartialContent) + { + Logger.Debug($"Server returned {(int)response.StatusCode} {response.StatusCode}."); + return DownloadResult.ERROR; + } + if (response.Content.Headers.ContentType != null && response.Content.Headers.ContentType.MediaType.CompareOrdinalIgnoreCase("text/html")) + { + Logger.Debug($"Server returned HTML page instead of the file."); + return DownloadResult.ERROR; + } + if (startPosition.HasValue && response.StatusCode == HttpStatusCode.OK) + { + Logger.Debug("Server doesn't support partial downloads."); + return DownloadResult.ERROR; + } + else if (!startPosition.HasValue) + { + startPosition = 0; + } + long? contentLength = response.Content.Headers.ContentLength; + if (!contentLength.HasValue) + { + Logger.Debug("Server did not return Content-Length value."); + return DownloadResult.ERROR; + } + long remainingSize = contentLength.Value; + progressHandler.Report(new DownloadFileProgress(startPosition.Value, startPosition.Value + remainingSize)); + if (remainingSize == 0) + { + return DownloadResult.COMPLETED; + } + Logger.Debug($"Remaining download size is {remainingSize} bytes."); + using (Stream downloadStream = await response.Content.ReadAsStreamAsync()) + { + byte[] buffer = new byte[4096]; + long downloadedBytes = 0; + using (FileStream destinationFileStream = new FileStream(destinationPath, resumeDownload ? FileMode.Append : FileMode.Create)) + { + while (true) + { + int bytesRead; + try + { + bytesRead = downloadStream.Read(buffer, 0, buffer.Length); + } + catch (Exception exception) + { + if (cancellationToken.IsCancellationRequested) + { + Logger.Debug("File download has been cancelled."); + return DownloadResult.CANCELLED; + } + Logger.Exception(exception); + return DownloadResult.ERROR; + } + if (bytesRead == 0) + { + bool isCompleted = downloadedBytes == remainingSize; + Logger.Debug($"File download is {(isCompleted ? "complete" : "incomplete")}."); + return isCompleted ? DownloadResult.COMPLETED : DownloadResult.INCOMPLETE; + } + destinationFileStream.Write(buffer, 0, bytesRead); + downloadedBytes += bytesRead; + progressHandler.Report(new DownloadFileProgress(startPosition.Value + downloadedBytes, startPosition.Value + remainingSize)); + } + } + } + }); + } + + public static string ExecuteTransformation(string input, string transformationName, bool htmlDecode) + { + HtmlDocument htmlDocument = new HtmlDocument(); + htmlDocument.LoadHtml(input); + XslCompiledTransform xslTransform = new XslCompiledTransform(); + xslTransform.Load(Path.Combine(Environment.MirrorsDirectoryPath, transformationName + ".xslt")); + XmlWriterSettings outputSettings = xslTransform.OutputSettings.Clone(); + outputSettings.OmitXmlDeclaration = true; + outputSettings.Encoding = new UTF8Encoding(false); + using (MemoryStream memoryStream = new MemoryStream()) + using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, outputSettings)) + { + xslTransform.Transform(htmlDocument, xmlWriter); + string transformationOutput = Encoding.UTF8.GetString(memoryStream.ToArray()).Trim(); + return htmlDecode ? WebUtility.HtmlDecode(transformationOutput) : transformationOutput; + } + } + + private static async Task GetDownloadContentLength(HttpClient httpClient, string fileUrl, CancellationToken cancellationToken) + { + Logger.Debug("Retrieving download size."); + using (HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, fileUrl)) + using (HttpResponseMessage response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) + { + Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); + Logger.Debug("Response headers:", response.Headers.ToString().TrimEnd(), response.Content.Headers.ToString().TrimEnd()); + if (response.StatusCode != HttpStatusCode.OK) + { + Logger.Debug($"Server returned {(int)response.StatusCode} {response.StatusCode}."); + return null; + } + if (response.Content.Headers.ContentType != null && response.Content.Headers.ContentType.MediaType.CompareOrdinalIgnoreCase("text/html")) + { + Logger.Debug($"Server returned HTML page instead of the file."); + return null; + } + long? contentLength = response.Content.Headers.ContentLength; + if (!contentLength.HasValue) + { + Logger.Debug("Server did not return Content-Length value."); + return null; + } + return contentLength.Value; + } + } + } +} diff --git a/LibgenDesktop/Models/Download/LibgenDumpDownloader.cs b/LibgenDesktop/Models/Download/LibgenDumpDownloader.cs new file mode 100644 index 0000000..d1b440e --- /dev/null +++ b/LibgenDesktop/Models/Download/LibgenDumpDownloader.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using LibgenDesktop.Common; + +namespace LibgenDesktop.Models.Download +{ + internal class LibgenDumpDownloader + { + internal enum RoundedSizeUnit + { + BYTES, + KILOBYTES, + MEGABYTES, + GIGABYTES, + TERABYTES + } + + internal class DumpMetadata + { + public string Url { get; set; } + public string FileName { get; set; } + public DateTime LastModified { get; set; } + public decimal RoundedSize { get; set; } + public RoundedSizeUnit RoundedSizeUnit { get; set; } + } + + internal class Dumps + { + public DumpMetadata NonFiction { get; set; } + public DumpMetadata Fiction { get; set; } + public DumpMetadata SciMag { get; set; } + } + + internal enum LoadAndParseStatus + { + COMPLETED = 1, + LOAD_FAILED, + PARSE_FAILED, + CANCELLED + } + + internal class LoadAndParseResult + { + public LoadAndParseStatus Status { get; set; } + public Dumps Dumps { get; set; } + } + + private readonly string databaseDumpPageUrl; + private readonly string databaseDumpPageTransformationName; + private HttpClient httpClient; + + public LibgenDumpDownloader(string databaseDumpPageUrl, string databaseDumpPageTransformationName) + { + this.databaseDumpPageUrl = databaseDumpPageUrl; + this.databaseDumpPageTransformationName = databaseDumpPageTransformationName; + } + + public void Configure(HttpClient httpClient) + { + this.httpClient = httpClient; + } + + public async Task LoadAndParseDumpPageAsync(CancellationToken cancellationToken) + { + LoadAndParseResult result = new LoadAndParseResult(); + DownloadUtils.DownloadPageResult downloadPageResult = await DownloadUtils.DownloadPageAsync(httpClient, databaseDumpPageUrl, cancellationToken); + if (downloadPageResult.DownloadResult == DownloadUtils.DownloadResult.CANCELLED) + { + result.Status = LoadAndParseStatus.CANCELLED; + return result; + } + if ((downloadPageResult.DownloadResult == DownloadUtils.DownloadResult.ERROR) || (downloadPageResult.HttpStatusCode != HttpStatusCode.OK)) + { + result.Status = LoadAndParseStatus.LOAD_FAILED; + return result; + } + string dumpList; + try + { + dumpList = DownloadUtils.ExecuteTransformation(downloadPageResult.PageContent, databaseDumpPageTransformationName, htmlDecode: false); + } + catch (Exception exception) + { + Logger.Debug($"Transformation {databaseDumpPageTransformationName} threw an exception."); + Logger.Exception(exception); + result.Status = LoadAndParseStatus.PARSE_FAILED; + return result; + } + try + { + result.Dumps = ParseDumps(dumpList); + } + catch (Exception exception) + { + Logger.Debug($"Dump metadata parser threw an exception."); + Logger.Exception(exception); + result.Status = LoadAndParseStatus.PARSE_FAILED; + return result; + } + result.Status = LoadAndParseStatus.COMPLETED; + return result; + } + + public Task DownloadDumpAsync(string dumpUrl, string dumpFilePath, IProgress progressHandler, + CancellationToken cancellationToken) + { + return DownloadUtils.DownloadFileAsync(httpClient, dumpUrl, dumpFilePath, true, progressHandler, cancellationToken); + } + + private static decimal ParseRoundedSize(string fileSizeString) + { + if (String.IsNullOrWhiteSpace(fileSizeString)) + { + return 0; + } + if (!Decimal.TryParse(fileSizeString.Substring(0, fileSizeString.Length - 1), NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, + out decimal result)) + { + return 0; + } + return result; + } + + private static RoundedSizeUnit ParseRoundedSizeUnit(string fileSizeString) + { + if (String.IsNullOrWhiteSpace(fileSizeString)) + { + return RoundedSizeUnit.BYTES; + } + char unit = fileSizeString.Last(); + switch (unit) + { + case 'K': + return RoundedSizeUnit.KILOBYTES; + case 'M': + return RoundedSizeUnit.MEGABYTES; + case 'G': + return RoundedSizeUnit.GIGABYTES; + case 'T': + return RoundedSizeUnit.TERABYTES; + default: + return RoundedSizeUnit.BYTES; + } + } + + private static Dumps ParseDumps(string dumpList) + { + Logger.Debug($"Parsing dump list:\r\n{dumpList}"); + List dumpListLines = new List(3); + using (StringReader stringReader = new StringReader(dumpList)) + { + string line; + do + { + line = stringReader.ReadLine(); + if (line != null) + { + dumpListLines.Add(line); + } + } + while (line != null); + } + if (dumpListLines.Count < 3) + { + throw new Exception($"Expected at least 3 dump list lines but got {dumpListLines.Count}."); + } + Dumps result = new Dumps() + { + NonFiction = ParseDumpMetadata(dumpListLines[0]), + Fiction = ParseDumpMetadata(dumpListLines[1]), + SciMag = ParseDumpMetadata(dumpListLines[2]) + }; + return result; + } + + private static DumpMetadata ParseDumpMetadata(string dumpListLine) + { + string[] dumpListLineFields = dumpListLine.Split(new[] { '|' }); + if (dumpListLineFields.Length != 4) + { + throw new Exception($"Expected at least 4 dump line fields but got {dumpListLineFields.Length}."); + } + DumpMetadata result = new DumpMetadata + { + Url = dumpListLineFields[0], + FileName = dumpListLineFields[1], + LastModified = DateTime.ParseExact(dumpListLineFields[2], "yyyy-MM-dd HH:mm", CultureInfo.InvariantCulture), + RoundedSize = ParseRoundedSize(dumpListLineFields[3]), + RoundedSizeUnit = ParseRoundedSizeUnit(dumpListLineFields[3]) + }; + return result; + } + } +} diff --git a/LibgenDesktop/Models/Entities/DatabaseMetadata.cs b/LibgenDesktop/Models/Entities/DatabaseMetadata.cs index f473f1d..20fb877 100644 --- a/LibgenDesktop/Models/Entities/DatabaseMetadata.cs +++ b/LibgenDesktop/Models/Entities/DatabaseMetadata.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; namespace LibgenDesktop.Models.Entities { @@ -49,6 +50,15 @@ public DatabaseMetadata() public bool? FictionFirstImportComplete { get; set; } public bool? SciMagFirstImportComplete { get; set; } + public Version GetParsedVersion() + { + if (!System.Version.TryParse(Version, out Version result)) + { + return null; + } + return result; + } + private static void AddField(string fieldName, Func getter, Action setter) { FieldDefinitions.Add(fieldName.ToLower(), new FieldDefinition(fieldName, getter, setter)); diff --git a/LibgenDesktop/Models/Entities/FictionBook.cs b/LibgenDesktop/Models/Entities/FictionBook.cs index 4dffbfd..fa2adea 100644 --- a/LibgenDesktop/Models/Entities/FictionBook.cs +++ b/LibgenDesktop/Models/Entities/FictionBook.cs @@ -1,189 +1,36 @@ using System; -using System.Runtime.CompilerServices; -using System.Text; namespace LibgenDesktop.Models.Entities { internal class FictionBook : LibgenObject { - private string authors; - private string series; - private string russianAuthor; - public FictionBook() : base(LibgenObjectType.FICTION_BOOK) { - authors = null; - series = null; - russianAuthor = null; } - public string AuthorFamily1 { get; set; } - public string AuthorName1 { get; set; } - public string AuthorSurname1 { get; set; } - public string Role1 { get; set; } - public string Pseudonim1 { get; set; } - public string AuthorFamily2 { get; set; } - public string AuthorName2 { get; set; } - public string AuthorSurname2 { get; set; } - public string Role2 { get; set; } - public string Pseudonim2 { get; set; } - public string AuthorFamily3 { get; set; } - public string AuthorName3 { get; set; } - public string AuthorSurname3 { get; set; } - public string Role3 { get; set; } - public string Pseudonim3 { get; set; } - public string AuthorFamily4 { get; set; } - public string AuthorName4 { get; set; } - public string AuthorSurname4 { get; set; } - public string Role4 { get; set; } - public string Pseudonim4 { get; set; } - public string Series1 { get; set; } - public string Series2 { get; set; } - public string Series3 { get; set; } - public string Series4 { get; set; } - public string Title { get; set; } - public string Format { get; set; } - public string Version { get; set; } - public long SizeInBytes { get; set; } public string Md5Hash { get; set; } - public string Path { get; set; } + public string Title { get; set; } + public string Authors { get; set; } + public string Series { get; set; } + public string Edition { get; set; } public string Language { get; set; } - public string Pages { get; set; } - public string Identifier { get; set; } public string Year { get; set; } public string Publisher { get; set; } - public string Edition { get; set; } - public string Commentary { get; set; } - public DateTime? AddedDateTime { get; set; } - public DateTime LastModifiedDateTime { get; set; } - public string RussianAuthorFamily { get; set; } - public string RussianAuthorName { get; set; } - public string RussianAuthorSurname { get; set; } - public string Cover { get; set; } + public string Pages { get; set; } + public string Identifier { get; set; } public string GoogleBookId { get; set; } public string Asin { get; set; } - public string AuthorHash { get; set; } - public string TitleHash { get; set; } + public string CoverUrl { get; set; } + public string Format { get; set; } + public long SizeInBytes { get; set; } + public string Library { get; set; } + public string Issue { get; set; } + public string Locator { get; set; } + public string Commentary { get; set; } + public string Generic { get; set; } public string Visible { get; set; } - - public string Authors - { - get - { - if (authors == null) - { - StringBuilder authorsStringBuilder = new StringBuilder(); - AppendAuthorString(authorsStringBuilder, AuthorName1, AuthorSurname1, AuthorFamily1, Pseudonim1, Role1); - AppendAuthorString(authorsStringBuilder, AuthorName2, AuthorSurname2, AuthorFamily2, Pseudonim2, Role2); - AppendAuthorString(authorsStringBuilder, AuthorName3, AuthorSurname3, AuthorFamily3, Pseudonim3, Role3); - AppendAuthorString(authorsStringBuilder, AuthorName4, AuthorSurname4, AuthorFamily4, Pseudonim4, Role4); - authors = authorsStringBuilder.ToString(); - } - return authors; - } - } - - public string Series - { - get - { - if (series == null) - { - StringBuilder seriesStringBuilder = new StringBuilder(); - foreach (string seriesItem in new[] { Series1, Series2, Series3, Series4 }) - { - if (!String.IsNullOrWhiteSpace(seriesItem)) - { - if (seriesStringBuilder.Length > 0) - { - seriesStringBuilder.Append("; "); - } - seriesStringBuilder.Append(seriesItem); - } - } - series = seriesStringBuilder.ToString(); - } - return series; - } - } - - public string RussianAuthor - { - get - { - if (russianAuthor == null) - { - StringBuilder russianAuthorStringBuilder = new StringBuilder(); - AppendAuthorString(russianAuthorStringBuilder, RussianAuthorName, RussianAuthorSurname, RussianAuthorFamily, null, null); - russianAuthor = russianAuthorStringBuilder.ToString(); - } - return russianAuthor; - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private void AppendAuthorString(StringBuilder stringBuilder, string name, string surname, string familyName, string pseudonim, string role) - { - bool hasName = !String.IsNullOrWhiteSpace(name); - bool hasSurname = !String.IsNullOrWhiteSpace(surname); - bool hasFamilyName = !String.IsNullOrWhiteSpace(familyName); - bool hasPseudonim = !String.IsNullOrWhiteSpace(pseudonim); - bool hasRole = !String.IsNullOrWhiteSpace(role); - if (hasName || hasSurname || hasFamilyName || hasPseudonim || hasRole) - { - if (stringBuilder.Length > 0) - { - stringBuilder.Append("; "); - } - bool firstPart = true; - if (hasName) - { - stringBuilder.Append(name); - firstPart = false; - } - if (hasSurname) - { - if (!firstPart) - { - stringBuilder.Append(" "); - } - stringBuilder.Append(surname); - firstPart = false; - } - if (hasFamilyName) - { - if (!firstPart) - { - stringBuilder.Append(" "); - } - stringBuilder.Append(familyName); - firstPart = false; - } - if (hasPseudonim) - { - if (!firstPart) - { - stringBuilder.Append(" ("); - } - stringBuilder.Append(pseudonim); - if (!firstPart) - { - stringBuilder.Append(")"); - } - firstPart = false; - } - if (hasRole) - { - if (!firstPart) - { - stringBuilder.Append(" "); - } - stringBuilder.Append("("); - stringBuilder.Append(role); - stringBuilder.Append(")"); - } - } - } + public DateTime? AddedDateTime { get; set; } + public DateTime? LastModifiedDateTime { get; set; } } } diff --git a/LibgenDesktop/Models/Export/CsvExporter.cs b/LibgenDesktop/Models/Export/CsvExporter.cs index 4c06a83..e5f8630 100644 --- a/LibgenDesktop/Models/Export/CsvExporter.cs +++ b/LibgenDesktop/Models/Export/CsvExporter.cs @@ -4,9 +4,9 @@ namespace LibgenDesktop.Models.Export { internal class CsvExporter : Exporter { - public CsvExporter(string filePathTemplate, string fileExtenstion, int? rowsPerFile, bool splitIntoMultipleFiles, char separator, + public CsvExporter(string filePathTemplate, string fileExtension, int? rowsPerFile, bool splitIntoMultipleFiles, char separator, Language currentLanguage) - : base(filePathTemplate, rowsPerFile, splitIntoMultipleFiles, fileExtenstion, currentLanguage, + : base(filePathTemplate, rowsPerFile, splitIntoMultipleFiles, fileExtension, currentLanguage, filePath => new CsvExportWriter(filePath, separator)) { } diff --git a/LibgenDesktop/Models/Export/Exporter.cs b/LibgenDesktop/Models/Export/Exporter.cs index fbea793..b1fd859 100644 --- a/LibgenDesktop/Models/Export/Exporter.cs +++ b/LibgenDesktop/Models/Export/Exporter.cs @@ -56,7 +56,6 @@ private ExportResult Export(IEnumerable(IEnumerable { - private FictionExporterLocalizator localization; + private readonly FictionExporterLocalizator localization; public FictionExportObject(ExportWriter exportWriter, Language currentLanguage) : base(exportWriter) @@ -24,7 +24,6 @@ public override IEnumerable FieldList localization.Id, localization.Title, localization.Authors, - localization.RussianAuthor, localization.Series, localization.Publisher, localization.Edition, @@ -32,8 +31,9 @@ public override IEnumerable FieldList localization.Language, localization.FormatHeader, localization.Pages, - localization.Version, localization.FileSize, + localization.Library, + localization.Issue, localization.Added, localization.LastModified, localization.Md5Hash, @@ -51,7 +51,6 @@ public override void WriteObject(FictionBook book) WriteField(book.Id); WriteField(book.Title); WriteField(book.Authors); - WriteField(book.RussianAuthor); WriteField(book.Series); WriteField(book.Publisher); WriteField(book.Edition); @@ -59,8 +58,9 @@ public override void WriteObject(FictionBook book) WriteField(book.Language); WriteField(book.Format); WriteField(localization.GetPagesString(book.Pages)); - WriteField(book.Version); WriteField(book.SizeInBytes); + WriteField(book.Library); + WriteField(book.Issue); WriteField(book.AddedDateTime); WriteField(book.LastModifiedDateTime); WriteField(book.Md5Hash); diff --git a/LibgenDesktop/Models/Export/NonFictionExportObject.cs b/LibgenDesktop/Models/Export/NonFictionExportObject.cs index bb37cd1..61b1a64 100644 --- a/LibgenDesktop/Models/Export/NonFictionExportObject.cs +++ b/LibgenDesktop/Models/Export/NonFictionExportObject.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using LibgenDesktop.Models.Entities; using LibgenDesktop.Models.Localization; -using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.Localization.Localizators.Export; namespace LibgenDesktop.Models.Export { internal class NonFictionExportObject : ExportObject { - private NonFictionExporterLocalizator localization; + private readonly NonFictionExporterLocalizator localization; public NonFictionExportObject(ExportWriter exportWriter, Language currentLanguage) : base(exportWriter) diff --git a/LibgenDesktop/Models/Export/SciMagExportObject.cs b/LibgenDesktop/Models/Export/SciMagExportObject.cs index 674d6d3..7d91ef8 100644 --- a/LibgenDesktop/Models/Export/SciMagExportObject.cs +++ b/LibgenDesktop/Models/Export/SciMagExportObject.cs @@ -1,13 +1,13 @@ using System.Collections.Generic; using LibgenDesktop.Models.Entities; using LibgenDesktop.Models.Localization; -using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.Localization.Localizators.Export; namespace LibgenDesktop.Models.Export { internal class SciMagExportObject : ExportObject { - private SciMagExporterLocalizator localization; + private readonly SciMagExporterLocalizator localization; public SciMagExportObject(ExportWriter exportWriter, Language currentLanguage) : base(exportWriter) diff --git a/LibgenDesktop/Models/Export/XlsxExportWriter.cs b/LibgenDesktop/Models/Export/XlsxExportWriter.cs index fb404ee..29fb510 100644 --- a/LibgenDesktop/Models/Export/XlsxExportWriter.cs +++ b/LibgenDesktop/Models/Export/XlsxExportWriter.cs @@ -74,6 +74,7 @@ public override void Dispose() if (!disposed) { excelPackage.SaveAs(new FileInfo(filePath)); + worksheet.Dispose(); excelPackage.Dispose(); disposed = true; } diff --git a/LibgenDesktop/Models/Export/XlsxExporter.cs b/LibgenDesktop/Models/Export/XlsxExporter.cs index 335f818..21e9d9f 100644 --- a/LibgenDesktop/Models/Export/XlsxExporter.cs +++ b/LibgenDesktop/Models/Export/XlsxExporter.cs @@ -4,8 +4,8 @@ namespace LibgenDesktop.Models.Export { internal class XlsxExporter : Exporter { - public XlsxExporter(string filePathTemplate, string fileExtenstion, int? rowsPerFile, bool splitIntoMultipleFiles, Language currentLanguage) - : base(filePathTemplate, rowsPerFile, splitIntoMultipleFiles, fileExtenstion, currentLanguage, filePath => new XlsxExportWriter(filePath)) + public XlsxExporter(string filePathTemplate, string fileExtension, int? rowsPerFile, bool splitIntoMultipleFiles, Language currentLanguage) + : base(filePathTemplate, rowsPerFile, splitIntoMultipleFiles, fileExtension, currentLanguage, filePath => new XlsxExportWriter(filePath)) { } } diff --git a/LibgenDesktop/Models/Import/FictionImporter.cs b/LibgenDesktop/Models/Import/FictionImporter.cs index 0296274..a04f661 100644 --- a/LibgenDesktop/Models/Import/FictionImporter.cs +++ b/LibgenDesktop/Models/Import/FictionImporter.cs @@ -18,7 +18,7 @@ public FictionImporter(LocalDatabase localDatabase, BitArray existingLibgenIds) if (IsUpdateMode) { FictionBook lastModifiedFictionBook = LocalDatabase.GetLastModifiedFictionBook(); - lastModifiedDateTime = lastModifiedFictionBook.LastModifiedDateTime; + lastModifiedDateTime = lastModifiedFictionBook.LastModifiedDateTime ?? new DateTime(); lastModifiedLibgenId = lastModifiedFictionBook.LibgenId; } } diff --git a/LibgenDesktop/Models/Import/Importer.cs b/LibgenDesktop/Models/Import/Importer.cs index 07d3905..4977587 100644 --- a/LibgenDesktop/Models/Import/Importer.cs +++ b/LibgenDesktop/Models/Import/Importer.cs @@ -31,7 +31,7 @@ public ImportResult(int addedObjectCount, int updatedObjectCount) } public abstract ImportResult Import(SqlDumpReader sqlDumpReader, ImportProgressReporter progressReporter, double progressUpdateInterval, - CancellationToken cancellationToken, SqlDumpReader.ParsedTableDefinition parsedTableDefinition, string databaseFullPath); + SqlDumpReader.ParsedTableDefinition parsedTableDefinition, string databaseFullPath, CancellationToken cancellationToken); } internal abstract class Importer : Importer where T : LibgenObject, new() @@ -55,16 +55,16 @@ protected Importer(LocalDatabase localDatabase, BitArray existingLibgenIds, Tabl protected bool IsUpdateMode { get; } public override ImportResult Import(SqlDumpReader sqlDumpReader, ImportProgressReporter progressReporter, double progressUpdateInterval, - CancellationToken cancellationToken, SqlDumpReader.ParsedTableDefinition parsedTableDefinition, string databaseFullPath) + SqlDumpReader.ParsedTableDefinition parsedTableDefinition, string databaseFullPath, CancellationToken cancellationToken) { List> sortedColumnSetters = tableDefinition.GetSortedColumnSetters(parsedTableDefinition.Columns.Select(column => column.ColumnName)); - return Import(sqlDumpReader.ParseImportObjects(sortedColumnSetters), progressReporter, progressUpdateInterval, cancellationToken, - databaseFullPath); + return Import(sqlDumpReader.ParseImportObjects(sortedColumnSetters), progressReporter, progressUpdateInterval, databaseFullPath, + cancellationToken); } public ImportResult Import(IEnumerable importingObjects, ImportProgressReporter progressReporter, double progressUpdateInterval, - CancellationToken cancellationToken, string databaseFullPath) + string databaseFullPath, CancellationToken cancellationToken) { DateTime lastProgressUpdateDateTime = DateTime.Now; int addedObjectCount = 0; diff --git a/LibgenDesktop/Models/JsonApi/JsonApiClient.cs b/LibgenDesktop/Models/JsonApi/JsonApiClient.cs index 2538237..8d051fe 100644 --- a/LibgenDesktop/Models/JsonApi/JsonApiClient.cs +++ b/LibgenDesktop/Models/JsonApi/JsonApiClient.cs @@ -33,7 +33,7 @@ public JsonApiClient(HttpClient httpClient, string jsonApiUrl, DateTime lastModi public async Task> DownloadNextBatchAsync(CancellationToken cancellationToken) { - string url = $"{jsonApiUrl}?fields={FIELD_LIST}&timenewer={lastModifiedDateTime.ToString("yyyy-MM-dd HH:mm:ss")}&idnewer={lastLibgenId}&mode=newer"; + string url = $"{jsonApiUrl}?fields={FIELD_LIST}&timenewer={lastModifiedDateTime:yyyy-MM-dd HH:mm:ss}&idnewer={lastLibgenId}&mode=newer"; Logger.Debug($"Sending a request to {url}"); HttpResponseMessage response = await httpClient.GetAsync(url, cancellationToken); Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); @@ -63,6 +63,15 @@ public async Task> DownloadNextBatchAsync(CancellationToken return result; } + private static DateTime ParseDateTime(string input) + { + if (!DateTime.TryParseExact(input, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)) + { + return DateTime.UtcNow; + } + return result; + } + private NonFictionBook ConvertToNonFictionBook(JsonApiNonFictionBook jsonApiNonFictionBook) { return new NonFictionBook @@ -116,14 +125,5 @@ private NonFictionBook ConvertToNonFictionBook(JsonApiNonFictionBook jsonApiNonF LibgenId = jsonApiNonFictionBook.LibgenId }; } - - private DateTime ParseDateTime(string input) - { - if (!DateTime.TryParseExact(input, "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime result)) - { - return DateTime.UtcNow; - } - return result; - } } } diff --git a/LibgenDesktop/Models/Localization/Language.cs b/LibgenDesktop/Models/Localization/Language.cs index 068b561..d974b17 100644 --- a/LibgenDesktop/Models/Localization/Language.cs +++ b/LibgenDesktop/Models/Localization/Language.cs @@ -1,7 +1,9 @@ using System; using System.Collections.Generic; using System.Linq; -using LibgenDesktop.Models.Localization.Localizators; +using LibgenDesktop.Models.Localization.Localizators.Export; +using LibgenDesktop.Models.Localization.Localizators.Tabs; +using LibgenDesktop.Models.Localization.Localizators.Windows; namespace LibgenDesktop.Models.Localization { @@ -9,7 +11,8 @@ internal class Language { private readonly List translations; private MainWindowLocalizator mainWindow; - private CreateDatabaseWindowLocalizator createDatabaseWindow; + private SetupWizardWindowLocalizator setupWizardWindow; + private SetupWizardProxySettingsWindowLocalizator setupWizardProxySettingsWindowLocalizator; private SearchTabLocalizator searchTab; private NonFictionSearchResultsTabLocalizator nonFictionSearchResultsTab; private FictionSearchResultsTabLocalizator fictionSearchResultsTab; @@ -18,27 +21,29 @@ internal class Language private NonFictionDetailsTabLocalizator nonFictionDetailsTab; private FictionDetailsTabLocalizator fictionDetailsTab; private SciMagDetailsTabLocalizator sciMagDetailsTab; - private ImportLocalizator import; + private ImportWindowLocalizator import; private ExportPanelLocalizator exportPanel; private NonFictionExporterLocalizator nonFictionExporter; private FictionExporterLocalizator fictionExporter; private SciMagExporterLocalizator sciMagExporter; - private SynchronizationLocalizator synchronization; + private SynchronizationWindowLocalizator synchronization; private DatabaseWindowLocalizator database; + private DatabaseErrorWindowLocalizator databaseError; private SqlDebuggerWindowLocalizator sqlDebugger; - private DownloadManagerLocalizator downloadManager; - private ApplicationUpdateLocalizator applicationUpdate; + private DownloadManagerTabLocalizator downloadManager; + private ApplicationUpdateWindowLocalizator applicationUpdate; private LibraryTabLocalizator library; private SettingsWindowLocalizator settings; private AboutWindowLocalizator about; private MessageBoxLocalizator messageBox; private ErrorWindowLocalizator errorWindow; - public Language(List prioritizedTranslationList) + public Language(List prioritizedTranslationList, decimal percentTranslated) { translations = prioritizedTranslationList; mainWindow = null; - createDatabaseWindow = null; + setupWizardWindow = null; + setupWizardProxySettingsWindowLocalizator = null; searchTab = null; nonFictionSearchResultsTab = null; fictionSearchResultsTab = null; @@ -54,6 +59,7 @@ public Language(List prioritizedTranslationList) sciMagExporter = null; synchronization = null; database = null; + databaseError = null; sqlDebugger = null; downloadManager = null; applicationUpdate = null; @@ -74,6 +80,7 @@ public Language(List prioritizedTranslationList) } CultureCode = mainTranslation.General?.CultureCode?.Trim() ?? String.Empty; TranslatorName = mainTranslation.General?.TranslatorName ?? "unknown"; + PercentTranslated = percentTranslated; Formatter = new LanguageFormatter(prioritizedTranslationList); } @@ -82,12 +89,16 @@ public Language(List prioritizedTranslationList) public string DisplayName { get; } public string CultureCode { get; } public string TranslatorName { get; } + public decimal PercentTranslated { get; } public LanguageFormatter Formatter { get; } public MainWindowLocalizator MainWindow => mainWindow ?? (mainWindow = new MainWindowLocalizator(translations, Formatter)); - public CreateDatabaseWindowLocalizator CreateDatabaseWindow => - createDatabaseWindow ?? (createDatabaseWindow = new CreateDatabaseWindowLocalizator(translations, Formatter)); + public SetupWizardWindowLocalizator SetupWizardWindow => + setupWizardWindow ?? (setupWizardWindow = new SetupWizardWindowLocalizator(translations, Formatter)); + + public SetupWizardProxySettingsWindowLocalizator SetupWizardProxySettingsWindowLocalizator => + setupWizardProxySettingsWindowLocalizator ?? (setupWizardProxySettingsWindowLocalizator = new SetupWizardProxySettingsWindowLocalizator(translations, Formatter)); public SearchTabLocalizator SearchTab => searchTab ?? (searchTab = new SearchTabLocalizator(translations, Formatter)); @@ -112,7 +123,7 @@ public Language(List prioritizedTranslationList) public SciMagDetailsTabLocalizator SciMagDetailsTab => sciMagDetailsTab ?? (sciMagDetailsTab = new SciMagDetailsTabLocalizator(translations, Formatter)); - public ImportLocalizator Import => import ?? (import = new ImportLocalizator(translations, Formatter)); + public ImportWindowLocalizator Import => import ?? (import = new ImportWindowLocalizator(translations, Formatter)); public ExportPanelLocalizator ExportPanel => exportPanel ?? (exportPanel = new ExportPanelLocalizator(translations, Formatter)); @@ -123,16 +134,20 @@ public Language(List prioritizedTranslationList) public SciMagExporterLocalizator SciMagExporter => sciMagExporter ?? (sciMagExporter = new SciMagExporterLocalizator(translations, Formatter)); - public SynchronizationLocalizator Synchronization => synchronization ?? (synchronization = new SynchronizationLocalizator(translations, Formatter)); + public SynchronizationWindowLocalizator Synchronization => + synchronization ?? (synchronization = new SynchronizationWindowLocalizator(translations, Formatter)); public DatabaseWindowLocalizator Database => database ?? (database = new DatabaseWindowLocalizator(translations, Formatter)); + public DatabaseErrorWindowLocalizator DatabaseError => databaseError ?? (databaseError = new DatabaseErrorWindowLocalizator(translations, Formatter)); + public SqlDebuggerWindowLocalizator SqlDebugger => sqlDebugger ?? (sqlDebugger = new SqlDebuggerWindowLocalizator(translations, Formatter)); - public DownloadManagerLocalizator DownloadManager => downloadManager ?? (downloadManager = new DownloadManagerLocalizator(translations, Formatter)); + public DownloadManagerTabLocalizator DownloadManager => + downloadManager ?? (downloadManager = new DownloadManagerTabLocalizator(translations, Formatter)); - public ApplicationUpdateLocalizator ApplicationUpdate => - applicationUpdate ?? (applicationUpdate = new ApplicationUpdateLocalizator(translations, Formatter)); + public ApplicationUpdateWindowLocalizator ApplicationUpdate => + applicationUpdate ?? (applicationUpdate = new ApplicationUpdateWindowLocalizator(translations, Formatter)); public LibraryTabLocalizator Library => library ?? (library = new LibraryTabLocalizator(translations, Formatter)); diff --git a/LibgenDesktop/Models/Localization/LanguageFormatter.cs b/LibgenDesktop/Models/Localization/LanguageFormatter.cs index a393f11..5da76ac 100644 --- a/LibgenDesktop/Models/Localization/LanguageFormatter.cs +++ b/LibgenDesktop/Models/Localization/LanguageFormatter.cs @@ -39,16 +39,20 @@ public LanguageFormatter(List prioritizedTranslationList) dateFormat = GetTranslationFieldValue(translation => translation?.DateFormat); timeFormat = GetTranslationFieldValue(translation => translation?.TimeFormat); dateTimeFormat = dateFormat + " " + timeFormat; - fileSizePostfixes = new[] - { - GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Byte), - GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Kilobyte), - GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Megabyte), - GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Gigabyte), - GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Terabyte) - }; + BytePostfix = GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Byte); + KilobytePostfix = GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Kilobyte); + MegabytePostfix = GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Megabyte); + GigabytePostfix = GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Gigabyte); + TerabytePostfix = GetTranslationFieldValue(translation => translation?.FileSizePostfixes?.Terabyte); + fileSizePostfixes = new[] { BytePostfix, KilobytePostfix, MegabytePostfix, GigabytePostfix, TerabytePostfix }; } + public string BytePostfix { get; } + public string KilobytePostfix { get; } + public string MegabytePostfix { get; } + public string GigabytePostfix { get; } + public string TerabytePostfix { get; } + public string ToFormattedString(int value) { return value.ToString("N0", numberFormatInfo); @@ -64,6 +68,16 @@ public string ToFormattedString(decimal value) return value.ToString(numberFormatInfo); } + public string ToFormattedString(decimal value, int decimalPlaces) + { + return value.ToString($"N{decimalPlaces}", numberFormatInfo); + } + + public string ToDecimalFormattedString(int value) + { + return value.ToString("D"); + } + public string ToFormattedDateString(DateTime dateTime) { return dateTime.ToString(dateFormat, cultureInfo); diff --git a/LibgenDesktop/Models/Localization/LocalizationStorage.cs b/LibgenDesktop/Models/Localization/LocalizationStorage.cs index 791e701..c6f66d1 100644 --- a/LibgenDesktop/Models/Localization/LocalizationStorage.cs +++ b/LibgenDesktop/Models/Localization/LocalizationStorage.cs @@ -1,8 +1,10 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; using LibgenDesktop.Common; using LibgenDesktop.Models.Utils; using Newtonsoft.Json; @@ -12,6 +14,30 @@ namespace LibgenDesktop.Models.Localization { internal class LocalizationStorage { + internal class TranslationPropertyInfo + { + public TranslationPropertyInfo(PropertyInfo propertyInfo) + { + PropertyInfo = propertyInfo; + IsSection = false; + SectionProperties = null; + } + + public TranslationPropertyInfo(PropertyInfo propertyInfo, List sectionProperties) + { + PropertyInfo = propertyInfo; + IsSection = true; + SectionProperties = sectionProperties; + } + + public PropertyInfo PropertyInfo { get; } + public bool IsSection { get; } + public List SectionProperties { get; } + } + + private static List translationProperties; + private static int totalTranslationPropertyCount; + public LocalizationStorage(string languageDirectoryPath, string selectedLanguageName) { LoadLanguages(languageDirectoryPath, selectedLanguageName); @@ -35,6 +61,38 @@ public void SwitchLanguage(string newLanguageName) } } + private static Translation LoadTranslation(string filePath) + { + JsonSerializer jsonSerializer = new JsonSerializer(); + using (StreamReader streamReader = new StreamReader(filePath)) + using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) + { + return jsonSerializer.Deserialize(jsonTextReader); + } + } + + private static Language CreateLanguage(Translation languageTranslation, List translationList, Translation defaultTranslation) + { + List prioritizedTranslationList = new List { languageTranslation }; + string translationCultureCode = languageTranslation.General?.CultureCode ?? String.Empty; + if (translationCultureCode.Length > 2) + { + string languageCode = translationCultureCode.Substring(0, 2); + Translation baseLanguageTranslation = translationList.FirstOrDefault(translation => (translation != languageTranslation) && + (translation.General?.CultureCode?.StartsWith(languageCode, StringComparison.OrdinalIgnoreCase) ?? false)); + if (baseLanguageTranslation != null) + { + prioritizedTranslationList.Add(baseLanguageTranslation); + } + } + if (defaultTranslation != null) + { + prioritizedTranslationList.Add(defaultTranslation); + } + return new Language(prioritizedTranslationList, CalculatePercentTranslated(languageTranslation)); + } + + private void LoadLanguages(string languageDirectoryPath, string selectedLanguageName) { Languages = new List(); @@ -113,35 +171,57 @@ private void LoadLanguages(string languageDirectoryPath, string selectedLanguage } } - private Translation LoadTranslation(string filePath) + private static decimal CalculatePercentTranslated(Translation translation) { - JsonSerializer jsonSerializer = new JsonSerializer(); - using (StreamReader streamReader = new StreamReader(filePath)) - using (JsonTextReader jsonTextReader = new JsonTextReader(streamReader)) + if (translationProperties == null) { - return jsonSerializer.Deserialize(jsonTextReader); + totalTranslationPropertyCount = 0; + translationProperties = RetrievePropertyInfos(typeof(Translation), ref totalTranslationPropertyCount); } + int translatedPropertyCount = GetTranslatedPropertyCount(translationProperties, translation); + return ((decimal)translatedPropertyCount * 100) / totalTranslationPropertyCount; } - private Language CreateLanguage(Translation languageTranslation, List translationList, Translation defaultTranslation) + private static int GetTranslatedPropertyCount(List translationSectionPropertyInfos, object translationSection) { - List prioritizedTranslationList = new List { languageTranslation }; - string translationCultureCode = languageTranslation.General?.CultureCode ?? String.Empty; - if (translationCultureCode.Length > 2) + int result = 0; + foreach (TranslationPropertyInfo translationPropertyInfo in translationSectionPropertyInfos) { - string languageCode = translationCultureCode.Substring(0, 2); - Translation baseLanguageTranslation = translationList.FirstOrDefault(translation => (translation != languageTranslation) && - (translation.General?.CultureCode?.StartsWith(languageCode, StringComparison.OrdinalIgnoreCase) ?? false)); - if (baseLanguageTranslation != null) + object propertyValue = translationSection != null ? translationPropertyInfo.PropertyInfo.GetValue(translationSection) : null; + if (!translationPropertyInfo.IsSection) { - prioritizedTranslationList.Add(baseLanguageTranslation); + if (propertyValue != null) + { + result++; + } + } + else + { + result += GetTranslatedPropertyCount(translationPropertyInfo.SectionProperties, propertyValue); } } - if (defaultTranslation != null) + return result; + } + + private static List RetrievePropertyInfos(Type type, ref int totalPropertyCount) + { + List result = new List(); + foreach (PropertyInfo propertyInfo in type.GetProperties()) { - prioritizedTranslationList.Add(defaultTranslation); + TranslationPropertyInfo translationPropertyInfo; + if (propertyInfo.PropertyType == typeof(String)) + { + translationPropertyInfo = new TranslationPropertyInfo(propertyInfo); + totalPropertyCount++; + } + else + { + translationPropertyInfo = + new TranslationPropertyInfo(propertyInfo, RetrievePropertyInfos(propertyInfo.PropertyType, ref totalPropertyCount)); + } + result.Add(translationPropertyInfo); } - return new Language(prioritizedTranslationList); + return result; } } } diff --git a/LibgenDesktop/Models/Localization/Localizators/AboutWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/AboutWindowLocalizator.cs deleted file mode 100644 index 45833bf..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/AboutWindowLocalizator.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class AboutWindowLocalizator : Localizator - { - public AboutWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - ApplicationName = Format(translation => translation?.ApplicationName); - CheckForUpdates = Format(translation => translation?.CheckForUpdates); - CheckingUpdates = Format(translation => translation?.CheckingUpdates); - OfflineModeIsOnTooltip = Format(translation => translation?.OfflineModeIsOnTooltip); - LatestVersion = Format(translation => translation?.LatestVersion); - Update = Format(translation => translation?.Update); - Translators = Format(translation => translation?.Translators); - } - - public string WindowTitle { get; } - public string ApplicationName { get; } - public string CheckForUpdates { get; } - public string CheckingUpdates { get; } - public string OfflineModeIsOnTooltip { get; } - public string LatestVersion { get; } - public string Update { get; } - public string Translators { get; } - - public string GetVersionString(string version, DateTime date) => - Format(translation => translation?.Version, new { version, date = Formatter.ToFormattedDateString(date) }); - - public string GetNewVersionAvailableString(string version, DateTime date) => - Format(translation => translation?.NewVersionAvailable, new { version, date = Formatter.ToFormattedDateString(date) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.About), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/ApplicationUpdateLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/ApplicationUpdateLocalizator.cs deleted file mode 100644 index 749243b..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/ApplicationUpdateLocalizator.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class ApplicationUpdateLocalizator : Localizator - { - public ApplicationUpdateLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - UpdateAvailable = Format(translation => translation?.UpdateAvailable); - Download = Format(translation => translation?.Download); - DownloadAndInstall = Format(translation => translation?.DownloadAndInstall); - SkipThisVersion = Format(translation => translation?.SkipThisVersion); - Cancel = Format(translation => translation?.Cancel); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - InterruptPromptTitle = Format(translation => translation?.InterruptPromptTitle); - InterruptPromptText = Format(translation => translation?.InterruptPromptText); - Error = Format(translation => translation?.Error); - IncompleteDownload = Format(translation => translation?.IncompleteDownload); - Close = Format(translation => translation?.Close); - } - - public string WindowTitle { get; } - public string UpdateAvailable { get; } - public string Download { get; } - public string DownloadAndInstall { get; } - public string SkipThisVersion { get; } - public string Cancel { get; } - public string Interrupt { get; } - public string Interrupting { get; } - public string InterruptPromptTitle { get; } - public string InterruptPromptText { get; } - public string Error { get; } - public string IncompleteDownload { get; } - public string Close { get; } - - public string GetNewVersionString(string version, DateTime date) => - Format(translation => translation?.NewVersion, new { version, date = Formatter.ToFormattedDateString(date) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.ApplicationUpdate), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/CommonDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/CommonDetailsTabLocalizator.cs deleted file mode 100644 index 4563fcd..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/CommonDetailsTabLocalizator.cs +++ /dev/null @@ -1,44 +0,0 @@ -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class CommonDetailsTabLocalizator : DetailsTabLocalizator - { - public CommonDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - CoverIsLoading = Format(translation => translation?.CoverIsLoading); - NoCover = Format(translation => translation?.NoCover); - NoCoverMirror = Format(translation => translation?.NoCoverMirror); - NoCoverDueToOfflineMode = Format(translation => translation?.NoCoverDueToOfflineMode); - CoverLoadingError = Format(translation => translation?.CoverLoadingError); - Download = Format(translation => translation?.Download); - Queued = Format(translation => translation?.Queued); - Downloading = Format(translation => translation?.Downloading); - Stopped = Format(translation => translation?.Stopped); - Error = Format(translation => translation?.Error); - Open = Format(translation => translation?.Open); - ErrorMessageTitle = Format(translation => translation?.ErrorMessageTitle); - NoDownloadMirrorTooltip = Format(translation => translation?.NoDownloadMirrorTooltip); - OfflineModeIsOnTooltip = Format(translation => translation?.OfflineModeIsOnTooltip); - } - - public string CoverIsLoading { get; } - public string NoCover { get; } - public string NoCoverMirror { get; } - public string NoCoverDueToOfflineMode { get; } - public string CoverLoadingError { get; } - public string Download { get; } - public string Queued { get; } - public string Downloading { get; } - public string Stopped { get; } - public string Error { get; } - public string Open { get; } - public string ErrorMessageTitle { get; } - public string NoDownloadMirrorTooltip { get; } - public string OfflineModeIsOnTooltip { get; } - - public string GetDownloadFromMirrorText(string mirror) => Format(translation => translation?.DownloadFromMirror, new { mirror }); - public string GetFileNotFoundErrorText(string file) => Format(translation => translation?.FileNotFoundError, new { file }); - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/CreateDatabaseWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/CreateDatabaseWindowLocalizator.cs deleted file mode 100644 index 1c60352..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/CreateDatabaseWindowLocalizator.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class CreateDatabaseWindowLocalizator : Localizator - { - public CreateDatabaseWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - FirstRunMessage = Format(translation => translation?.FirstRunMessage); - ChooseOption = Format(translation => translation?.ChooseOption); - CreateNewDatabase = Format(translation => translation?.CreateNewDatabase); - OpenExistingDatabase = Format(translation => translation?.OpenExistingDatabase); - BrowseNewDatabaseDialogTitle = Format(translation => translation?.BrowseNewDatabaseDialogTitle); - BrowseExistingDatabaseDialogTitle = Format(translation => translation?.BrowseExistingDatabaseDialogTitle); - Databases = Format(translation => translation?.Databases); - AllFiles = Format(translation => translation?.AllFiles); - Error = Format(translation => translation?.Error); - CannotCreateDatabase = Format(translation => translation?.CannotCreateDatabase); - Ok = Format(translation => translation?.Ok); - Cancel = Format(translation => translation?.Cancel); - } - - public string WindowTitle { get; } - public string FirstRunMessage { get; } - public string ChooseOption { get; } - public string CreateNewDatabase { get; } - public string OpenExistingDatabase { get; } - public string BrowseNewDatabaseDialogTitle { get; } - public string BrowseExistingDatabaseDialogTitle { get; } - public string Databases { get; } - public string AllFiles { get; } - public string Error { get; } - public string CannotCreateDatabase { get; } - public string Ok { get; } - public string Cancel { get; } - - public string GetDatabaseNotFoundText(string database) => Format(translation => translation.DatabaseNotFound, new { database }); - public string GetDatabaseCorruptedText(string database) => Format(translation => translation.DatabaseCorrupted, new { database }); - public string GetLibgenServerDatabaseText(string database) => Format(translation => translation.LibgenServerDatabase, new { database }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.CreateDatabaseWindow), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/DatabaseWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/DatabaseWindowLocalizator.cs deleted file mode 100644 index 29730fd..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/DatabaseWindowLocalizator.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class DatabaseWindowLocalizator : Localizator - { - public DatabaseWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - CurrentDatabase = Format(translation => translation?.CurrentDatabase); - NonFiction = Format(translation => translation?.NonFiction); - Fiction = Format(translation => translation?.Fiction); - SciMagArticles = Format(translation => translation?.SciMagArticles); - TotalBooks = Format(translation => translation?.TotalBooks) + ":"; - TotalArticles = Format(translation => translation?.TotalArticles) + ":"; - LastUpdate = Format(translation => translation?.LastUpdate) + ":"; - Never = Format(translation => translation?.Never); - IndexesRequiredTitle = Format(translation => translation?.IndexesRequiredTitle); - IndexesRequiredText = Format(translation => translation?.IndexesRequiredText); - CreatingIndexes = Format(translation => translation?.CreatingIndexes); - ChangeDatabase = Format(translation => translation?.ChangeDatabase); - BrowseDatabaseDialogTitle = Format(translation => translation?.BrowseDatabaseDialogTitle); - Databases = Format(translation => translation?.Databases); - AllFiles = Format(translation => translation?.AllFiles); - Error = Format(translation => translation?.Error); - Close = Format(translation => translation?.Close); - } - - public string WindowTitle { get; } - public string CurrentDatabase { get; } - public string NonFiction { get; } - public string Fiction { get; } - public string SciMagArticles { get; } - public string TotalBooks { get; } - public string TotalArticles { get; } - public string LastUpdate { get; } - public string Never { get; } - public string IndexesRequiredTitle { get; } - public string IndexesRequiredText { get; } - public string CreatingIndexes { get; } - public string ChangeDatabase { get; } - public string BrowseDatabaseDialogTitle { get; } - public string Databases { get; } - public string AllFiles { get; } - public string Error { get; } - public string Close { get; } - - public string GetCannotOpenDatabase(string file) - { - return Format(translation => translation.CannotOpenDatabase, new { file }); - } - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Database), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/DetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/DetailsTabLocalizator.cs deleted file mode 100644 index c069748..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/DetailsTabLocalizator.cs +++ /dev/null @@ -1,49 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal abstract class DetailsTabLocalizator : Localizator - { - public DetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - CopyContextMenu = Format(translation => translation?.CopyContextMenu).Replace("{text}", "{0}"); - Close = Format(translation => translation?.Close); - Yes = Format(translation => translation?.Yes); - No = Format(translation => translation?.No); - Unknown = Format(translation => translation?.Unknown); - Portrait = Format(translation => translation?.Portrait); - Landscape = Format(translation => translation?.Landscape); - } - - public string CopyContextMenu { get; } - public string Close { get; } - protected string Yes { get; } - protected string No { get; } - protected string Unknown { get; } - protected string Portrait { get; } - protected string Landscape { get; } - - protected string StringBooleanToYesNoUnknownString(string value) => StringBooleanToLabelString(value, Yes, No, Unknown); - protected string StringBooleanToOrientationString(string value) => StringBooleanToLabelString(value, Portrait, Landscape, Unknown); - - protected string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.DetailsTabs), templateArguments); - } - - private string StringBooleanToLabelString(string value, string value1Label, string value0Label, string valueUnknownLabel) - { - switch (value) - { - case "0": - return value0Label; - case "1": - return value1Label; - default: - return valueUnknownLabel; - } - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/DownloadManagerLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/DownloadManagerLocalizator.cs deleted file mode 100644 index 5f3f2c9..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/DownloadManagerLocalizator.cs +++ /dev/null @@ -1,116 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class DownloadManagerLocalizator : Localizator - { - public DownloadManagerLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - TabTitle = Format(translation => translation?.TabTitle); - Start = Format(translation => translation?.Start); - Stop = Format(translation => translation?.Stop); - Remove = Format(translation => translation?.Remove); - StartAll = Format(translation => translation?.StartAll); - StopAll = Format(translation => translation?.StopAll); - RemoveCompleted = Format(translation => translation?.RemoveCompleted); - QueuedStatus = Format(translation => translation?.QueuedStatus); - DownloadingStatus = Format(translation => translation?.DownloadingStatus); - StoppedStatus = Format(translation => translation?.StoppedStatus); - RetryDelayStatus = Format(translation => translation?.RetryDelayStatus); - ErrorStatus = Format(translation => translation?.ErrorStatus); - Log = Format(translation => translation?.Log); - TechnicalDetails = Format(translation => translation?.TechnicalDetails); - Copy = Format(translation => translation?.Copy); - FileNotFoundErrorTitle = Format(translation => translation?.FileNotFoundErrorTitle); - LogLineQueued = Format(translation => translation?.LogMessages?.Queued); - LogLineStarted = Format(translation => translation?.LogMessages?.Started); - LogLineStopped = Format(translation => translation?.LogMessages?.Stopped); - LogLineCompleted = Format(translation => translation?.LogMessages?.Completed); - LogLineOfflineModeIsOn = Format(translation => translation?.LogMessages?.OfflineModeIsOn); - LogLineMaximumDownloadAttempts = Format(translation => translation?.LogMessages?.MaximumDownloadAttempts); - LogLineStartingFileDownloadUnknownFileSize = Format(translation => translation?.LogMessages?.StartingFileDownloadUnknownFileSize); - LogLineResumingFileDownloadUnknownFileSize = Format(translation => translation?.LogMessages?.ResumingFileDownloadUnknownFileSize); - LogLineRequest = Format(translation => translation?.LogMessages?.Request); - LogLineResponse = Format(translation => translation?.LogMessages?.Response); - LogLineTooManyRedirects = Format(translation => translation?.LogMessages?.TooManyRedirects); - LogLineHtmlPageReturned = Format(translation => translation?.LogMessages?.HtmlPageReturned); - LogLineNoPartialDownloadSupport = Format(translation => translation?.LogMessages?.NoPartialDownloadSupport); - LogLineNoContentLengthWarning = Format(translation => translation?.LogMessages?.NoContentLengthWarning); - LogLineServerResponseTimeout = Format(translation => translation?.LogMessages?.ServerResponseTimeout); - LogLineDownloadIncompleteError = Format(translation => translation?.LogMessages?.DownloadIncompleteError); - LogLineFileWriteError = Format(translation => translation?.LogMessages?.FileWriteError); - } - - public string TabTitle { get; } - public string Start { get; } - public string Stop { get; } - public string Remove { get; } - public string StartAll { get; } - public string StopAll { get; } - public string RemoveCompleted { get; } - public string QueuedStatus { get; } - public string DownloadingStatus { get; } - public string StoppedStatus { get; } - public string RetryDelayStatus { get; } - public string ErrorStatus { get; } - public string Log { get; } - public string TechnicalDetails { get; } - public string Copy { get; } - public string FileNotFoundErrorTitle { get; } - public string LogLineQueued { get; } - public string LogLineStarted { get; } - public string LogLineStopped { get; } - public string LogLineCompleted { get; } - public string LogLineOfflineModeIsOn { get; } - public string LogLineMaximumDownloadAttempts { get; } - public string LogLineStartingFileDownloadUnknownFileSize { get; } - public string LogLineResumingFileDownloadUnknownFileSize { get; } - public string LogLineRequest { get; } - public string LogLineResponse { get; } - public string LogLineTooManyRedirects { get; } - public string LogLineHtmlPageReturned { get; } - public string LogLineNoPartialDownloadSupport { get; } - public string LogLineNoContentLengthWarning { get; } - public string LogLineServerResponseTimeout { get; } - public string LogLineDownloadIncompleteError { get; } - public string LogLineFileWriteError { get; } - - public string GetDownloadProgressKnownFileSize(long downloaded, long total, int percent) => - Format(translation => translation?.DownloadProgressKnownFileSize, - new { downloaded = Formatter.ToFormattedString(downloaded), total = Formatter.ToFormattedString(total), percent }); - public string GetDownloadProgressUnknownFileSize(long downloaded) => - Format(translation => translation?.DownloadProgressUnknownFileSize, new { downloaded = Formatter.ToFormattedString(downloaded) }); - public string GetFileNotFoundErrorText(string file) => Format(translation => translation?.FileNotFoundErrorText, new { file }); - public string GetLogLineRetryDelay(int count) => Format(translation => translation?.LogMessages?.RetryDelay, new { count }); - public string GetLogLineTransformationError(string transformation) => - Format(translation => translation?.LogMessages?.TransformationError, new { transformation }); - public string GetLogLineTransformationReturnedIncorrectUrl(string transformation) => - Format(translation => translation?.LogMessages?.TransformationReturnedIncorrectUrl, new { transformation }); - public string GetLogLineAttempt(int current, int total) => Format(translation => translation?.LogMessages?.Attempt, new { current, total }); - public string GetLogLineDownloadingPage(string url) => Format(translation => translation?.LogMessages?.DownloadingPage, new { url }); - public string GetLogLineDownloadingFile(string url) => Format(translation => translation?.LogMessages?.DownloadingFile, new { url }); - public string GetLogLineStartingFileDownloadKnownFileSize(long size) => - Format(translation => translation?.LogMessages?.StartingFileDownloadKnownFileSize, new { size }); - public string GetLogLineResumingFileDownloadKnownFileSize(long remaining) => - Format(translation => translation?.LogMessages?.ResumingFileDownloadKnownFileSize, new { remaining }); - public string GetLogLineRedirect(string url) => Format(translation => translation?.LogMessages?.Redirect, new { url }); - public string GetLogLineNonSuccessfulStatusCode(string status) => - Format(translation => translation?.LogMessages?.NonSuccessfulStatusCode, new { status }); - public string GetLogLineCannotCreateDownloadDirectory(string directory) => - Format(translation => translation?.LogMessages?.CannotCreateDownloadDirectory, new { directory }); - public string GetLogLineCannotCreateOrOpenFile(string file) => - Format(translation => translation?.LogMessages?.CannotCreateOrOpenFile, new { file }); - public string GetLogLineCannotRenamePartFile(string source, string destination) => - Format(translation => translation?.LogMessages?.CannotRenamePartFile, new { source, destination }); - public string GetLogLineRequestError(string url) => Format(translation => translation?.LogMessages?.LogLineRequestError, new { url }); - public string GetLogLineIncorrectRedirectUrl(string url) => Format(translation => translation?.LogMessages?.IncorrectRedirectUrl, new { url }); - public string GetLogLineUnexpectedError(string error) => Format(translation => translation?.LogMessages?.UnexpectedError, new { error }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.DownloadManager), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/ErrorWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/ErrorWindowLocalizator.cs deleted file mode 100644 index d497bc6..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/ErrorWindowLocalizator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class ErrorWindowLocalizator : Localizator - { - public ErrorWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - UnexpectedError = Format(translation => translation?.UnexpectedError) + ":"; - Copy = Format(translation => translation?.Copy); - Close = Format(translation => translation?.Close); - } - - public string WindowTitle { get; } - public string UnexpectedError { get; } - public string Copy { get; } - public string Close { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.ErrorWindow)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/Export/ExportPanelLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Export/ExportPanelLocalizator.cs new file mode 100644 index 0000000..16c0dcf --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Export/ExportPanelLocalizator.cs @@ -0,0 +1,89 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Export +{ + internal class ExportPanelLocalizator : Localizator + { + public ExportPanelLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.ExportPanel) + { + Header = Format(section => section?.Header); + FormatLabel = Format(section => section?.Format) + ":"; + Excel = Format(section => section?.Excel); + Csv = Format(section => section?.Csv); + Separator = Format(section => section?.Separator) + ":"; + Comma = Format(section => section?.Comma); + Semicolon = Format(section => section?.Semicolon); + Tab = Format(section => section?.Tab); + SaveAs = Format(section => section?.SaveAs) + ":"; + Browse = Format(section => section?.Browse); + BrowseDialogTitle = Format(section => section?.BrowseDialogTitle); + ExcelFiles = Format(section => section?.ExcelFiles); + CsvFiles = Format(section => section?.CsvFiles); + TsvFiles = Format(section => section?.TsvFiles); + AllFiles = Format(section => section?.AllFiles); + ExportRange = Format(section => section?.ExportRange) + ":"; + NoLimit = Format(section => section?.NoLimit); + Export = Format(section => section?.Export); + Cancel = Format(section => section?.Cancel); + SavingFile = Format(section => section?.SavingFile); + ErrorWarningTitle = Format(section => section?.ErrorWarningTitle); + InvalidExportPath = Format(section => section?.InvalidExportPath); + InvalidExportFileName = Format(section => section?.InvalidExportFileName); + OverwritePromptTitle = Format(section => section?.OverwritePromptTitle); + RowLimitWarningTitle = Format(section => section?.RowLimitWarningTitle); + RowLimitWarningText = Format(section => section?.RowLimitWarningText); + ExportError = Format(section => section?.ExportError); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + ExportInterrupted = Format(section => section?.ExportInterrupted); + Results = Format(section => section?.Results); + Close = Format(section => section?.Close); + } + + public string Header { get; } + public string FormatLabel { get; } + public string Excel { get; } + public string Csv { get; } + public string Separator { get; } + public string Comma { get; } + public string Semicolon { get; } + public string Tab { get; } + public string SaveAs { get; } + public string Browse { get; } + public string BrowseDialogTitle { get; } + public string ExcelFiles { get; } + public string CsvFiles { get; } + public string TsvFiles { get; } + public string AllFiles { get; } + public string ExportRange { get; } + public string NoLimit { get; } + public string Export { get; } + public string Cancel { get; } + public string SavingFile { get; } + public string ErrorWarningTitle { get; } + public string InvalidExportPath { get; } + public string InvalidExportFileName { get; } + public string OverwritePromptTitle { get; } + public string RowLimitWarningTitle { get; } + public string RowLimitWarningText { get; } + public string ExportError { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string ExportInterrupted { get; } + public string Results { get; } + public string Close { get; } + + public string GetLimitString(int count) => Format(section => section?.Limit, new { count = Formatter.ToFormattedString(count) }); + + public string GetRowCountSingleFileString(int rows) => + Format(section => section?.RowCountSingleFile, new { rows = Formatter.ToFormattedString(rows) }); + + public string GetRowCountMultipleFilesString(int rows, int files) => + Format(section => section?.RowCountMultipleFiles, new { rows = Formatter.ToFormattedString(rows), files = Formatter.ToFormattedString(files) }); + + public string GetDirectoryNotFoundString(string directory) => Format(section => section?.DirectoryNotFound, new { directory }); + + public string GetOverwritePromptTextString(string file) => Format(section => section?.OverwritePromptText, new { file }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Export/ExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Export/ExporterLocalizator.cs new file mode 100644 index 0000000..febfbe9 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Export/ExporterLocalizator.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Export +{ + internal abstract class ExporterLocalizator : Localizator where T : class + { + private readonly Func exporterTranslationSectionSelector; + + public ExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter, + Func exporterTranslationSectionSelector) + : base(prioritizedTranslationList, formatter, translation => translation?.Exporter) + { + this.exporterTranslationSectionSelector = exporterTranslationSectionSelector; + Yes = Format(section => section?.Yes); + No = Format(section => section?.No); + Unknown = Format(section => section?.Unknown); + Portrait = Format(section => section?.Portrait); + Landscape = Format(section => section?.Landscape); + } + + protected string Yes { get; } + protected string No { get; } + protected string Unknown { get; } + protected string Portrait { get; } + protected string Landscape { get; } + + protected string StringBooleanToYesNoUnknownString(string value) => StringBooleanToLabelString(value, Yes, No, Unknown); + + protected string StringBooleanToOrientationString(string value) => StringBooleanToLabelString(value, Portrait, Landscape, Unknown); + + protected string Format(Func exporterTranslationSectionFieldSelector, object templateArguments = null) => + Format(translation => exporterTranslationSectionFieldSelector(exporterTranslationSectionSelector(translation)), templateArguments); + + private static string StringBooleanToLabelString(string value, string value1Label, string value0Label, string valueUnknownLabel) + { + switch (value) + { + case "0": + return value0Label; + case "1": + return value1Label; + default: + return valueUnknownLabel; + } + } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Export/FictionExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Export/FictionExporterLocalizator.cs new file mode 100644 index 0000000..5ee04cf --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Export/FictionExporterLocalizator.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Export +{ + internal class FictionExporterLocalizator : ExporterLocalizator + { + public FictionExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Exporter?.FictionColumns) + { + Id = Format(section => section?.Id); + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Series = Format(section => section?.Series); + Publisher = Format(section => section?.Publisher); + Edition = Format(section => section?.Edition); + Year = Format(section => section?.Year); + Language = Format(section => section?.Language); + FormatHeader = Format(section => section?.Format); + Pages = Format(section => section?.Pages); + FileSize = Format(section => section?.FileSize); + Library = Format(section => section?.Library); + Issue = Format(section => section?.Issue); + Added = Format(section => section?.Added); + LastModified = Format(section => section?.LastModified); + Md5Hash = Format(section => section?.Md5Hash); + Comments = Format(section => section?.Comments); + LibgenId = Format(section => section?.LibgenId); + Isbn = Format(section => section?.Isbn); + GoogleBookId = Format(section => section?.GoogleBookId); + Asin = Format(section => section?.Asin); + } + + public string Id { get; } + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Publisher { get; } + public string Edition { get; } + public string Year { get; } + public string Language { get; } + public string FormatHeader { get; } + public string Pages { get; } + public string FileSize { get; } + public string Library { get; } + public string Issue { get; } + public string Added { get; } + public string LastModified { get; } + public string Md5Hash { get; } + public string Comments { get; } + public string LibgenId { get; } + public string Isbn { get; } + public string GoogleBookId { get; } + public string Asin { get; } + + public string GetYearString(string value) => value != "0" ? value : String.Empty; + + public string GetPagesString(string value) => !String.IsNullOrWhiteSpace(value) ? value : Unknown; + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Export/NonFictionExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Export/NonFictionExporterLocalizator.cs new file mode 100644 index 0000000..a92f098 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Export/NonFictionExporterLocalizator.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Export +{ + internal class NonFictionExporterLocalizator : ExporterLocalizator + { + public NonFictionExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Exporter?.NonFictionColumns) + { + Id = Format(section => section?.Id); + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Series = Format(section => section?.Series); + Publisher = Format(section => section?.Publisher); + Year = Format(section => section?.Year); + Language = Format(section => section?.Language); + FormatHeader = Format(section => section?.Format); + Isbn = Format(section => section?.Isbn); + Added = Format(section => section?.Added); + LastModified = Format(section => section?.LastModified); + Library = Format(section => section?.Library); + FileSize = Format(section => section?.FileSize); + Topics = Format(section => section?.Topics); + Volume = Format(section => section?.Volume); + Magazine = Format(section => section?.Magazine); + City = Format(section => section?.City); + Edition = Format(section => section?.Edition); + BodyMatterPages = Format(section => section?.BodyMatterPages); + TotalPages = Format(section => section?.TotalPages); + Tags = Format(section => section?.Tags); + Md5Hash = Format(section => section?.Md5Hash); + Comments = Format(section => section?.Comments); + LibgenId = Format(section => section?.LibgenId); + Issn = Format(section => section?.Issn); + Udc = Format(section => section?.Udc); + Lbc = Format(section => section?.Lbc); + Lcc = Format(section => section?.Lcc); + Ddc = Format(section => section?.Ddc); + Doi = Format(section => section?.Doi); + OpenLibraryId = Format(section => section?.OpenLibraryId); + GoogleBookId = Format(section => section?.GoogleBookId); + Asin = Format(section => section?.Asin); + Dpi = Format(section => section?.Dpi); + Ocr = Format(section => section?.Ocr); + TableOfContents = Format(section => section?.TableOfContents); + Scanned = Format(section => section?.Scanned); + Orientation = Format(section => section?.Orientation); + Paginated = Format(section => section?.Paginated); + Colored = Format(section => section?.Colored); + Cleaned = Format(section => section?.Cleaned); + } + + public string Id { get; } + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Publisher { get; } + public string Year { get; } + public string Language { get; } + public string FormatHeader { get; } + public string Isbn { get; } + public string Added { get; } + public string LastModified { get; } + public string Library { get; } + public string FileSize { get; } + public string Topics { get; } + public string Volume { get; } + public string Magazine { get; } + public string City { get; } + public string Edition { get; } + public string BodyMatterPages { get; } + public string TotalPages { get; } + public string Tags { get; } + public string Md5Hash { get; } + public string Comments { get; } + public string LibgenId { get; } + public string Issn { get; } + public string Udc { get; } + public string Lbc { get; } + public string Lcc { get; } + public string Ddc { get; } + public string Doi { get; } + public string OpenLibraryId { get; } + public string GoogleBookId { get; } + public string Asin { get; } + public string Dpi { get; } + public string Ocr { get; } + public string TableOfContents { get; } + public string Scanned { get; } + public string Orientation { get; } + public string Paginated { get; } + public string Colored { get; } + public string Cleaned { get; } + + public string GetBodyMatterPageCountString(string value) => !String.IsNullOrWhiteSpace(value) ? value : Unknown; + + public string GetOcrString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetBookmarkedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetScannedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetOrientationString(string value) => StringBooleanToOrientationString(value); + + public string GetPaginatedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetColorString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetCleanedString(string value) => StringBooleanToYesNoUnknownString(value); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Export/SciMagExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Export/SciMagExporterLocalizator.cs new file mode 100644 index 0000000..608402e --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Export/SciMagExporterLocalizator.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Export +{ + internal class SciMagExporterLocalizator : ExporterLocalizator + { + public SciMagExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Exporter?.SciMagColumns) + { + Id = Format(section => section?.Id); + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Magazine = Format(section => section?.Magazine); + Year = Format(section => section?.Year); + Month = Format(section => section?.Month); + Day = Format(section => section?.Day); + Volume = Format(section => section?.Volume); + Issue = Format(section => section?.Issue); + Pages = Format(section => section?.Pages); + FileSize = Format(section => section?.FileSize); + AddedDateTime = Format(section => section?.AddedDateTime); + Md5Hash = Format(section => section?.Md5Hash); + AbstractUrl = Format(section => section?.AbstractUrl); + LibgenId = Format(section => section?.LibgenId); + Doi1 = Format(section => section?.Doi1); + Doi2 = Format(section => section?.Doi2); + Isbn = Format(section => section?.Isbn); + MagazineId = Format(section => section?.MagazineId); + Issnp = Format(section => section?.Issnp); + Issne = Format(section => section?.Issne); + PubmedId = Format(section => section?.PubmedId); + Pmc = Format(section => section?.Pmc); + Pii = Format(section => section?.Pii); + Attribute1 = Format(section => section?.Attribute1); + Attribute2 = Format(section => section?.Attribute2); + Attribute3 = Format(section => section?.Attribute3); + Attribute4 = Format(section => section?.Attribute4); + Attribute5 = Format(section => section?.Attribute5); + Attribute6 = Format(section => section?.Attribute6); + } + + public string Id { get; } + public string Title { get; } + public string Authors { get; } + public string Magazine { get; } + public string Year { get; } + public string Month { get; } + public string Day { get; } + public string Volume { get; } + public string Issue { get; } + public string Pages { get; } + public string FileSize { get; } + public string AddedDateTime { get; } + public string Md5Hash { get; } + public string AbstractUrl { get; } + public string LibgenId { get; } + public string Doi1 { get; } + public string Doi2 { get; } + public string Isbn { get; } + public string MagazineId { get; } + public string Issnp { get; } + public string Issne { get; } + public string PubmedId { get; } + public string Pmc { get; } + public string Pii { get; } + public string Attribute1 { get; } + public string Attribute2 { get; } + public string Attribute3 { get; } + public string Attribute4 { get; } + public string Attribute5 { get; } + public string Attribute6 { get; } + + public string GetPagesString(string firstPage, string lastPage) + { + if ((!String.IsNullOrWhiteSpace(firstPage) && firstPage != "0") || (!String.IsNullOrWhiteSpace(lastPage) && lastPage != "0")) + { + firstPage = firstPage != "0" ? firstPage.Trim() + " " : String.Empty; + lastPage = lastPage != "0" ? " " + lastPage.Trim() : String.Empty; + return firstPage + "–" + lastPage; + } + else + { + return Unknown; + } + } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/ExportPanelLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/ExportPanelLocalizator.cs deleted file mode 100644 index 5b3613e..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/ExportPanelLocalizator.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class ExportPanelLocalizator : Localizator - { - public ExportPanelLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Header = Format(translation => translation?.Header); - FormatLabel = Format(translation => translation?.Format) + ":"; - Excel = Format(translation => translation?.Excel); - Csv = Format(translation => translation?.Csv); - Separator = Format(translation => translation?.Separator) + ":"; - Comma = Format(translation => translation?.Comma); - Semicolon = Format(translation => translation?.Semicolon); - Tab = Format(translation => translation?.Tab); - SaveAs = Format(translation => translation?.SaveAs) + ":"; - Browse = Format(translation => translation?.Browse); - BrowseDialogTitle = Format(translation => translation?.BrowseDialogTitle); - ExcelFiles = Format(translation => translation?.ExcelFiles); - CsvFiles = Format(translation => translation?.CsvFiles); - TsvFiles = Format(translation => translation?.TsvFiles); - AllFiles = Format(translation => translation?.AllFiles); - ExportRange = Format(translation => translation?.ExportRange) + ":"; - NoLimit = Format(translation => translation?.NoLimit); - Export = Format(translation => translation?.Export); - Cancel = Format(translation => translation?.Cancel); - SavingFile = Format(translation => translation?.SavingFile); - ErrorWarningTitle = Format(translation => translation?.ErrorWarningTitle); - InvalidExportPath = Format(translation => translation?.InvalidExportPath); - InvalidExportFileName = Format(translation => translation?.InvalidExportFileName); - OverwritePromptTitle = Format(translation => translation?.OverwritePromptTitle); - RowLimitWarningTitle = Format(translation => translation?.RowLimitWarningTitle); - RowLimitWarningText = Format(translation => translation?.RowLimitWarningText); - ExportError = Format(translation => translation?.ExportError); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - ExportInterrupted = Format(translation => translation?.ExportInterrupted); - Results = Format(translation => translation?.Results); - Close = Format(translation => translation?.Close); - } - - public string Header { get; } - public string FormatLabel { get; } - public string Excel { get; } - public string Csv { get; } - public string Separator { get; } - public string Comma { get; } - public string Semicolon { get; } - public string Tab { get; } - public string SaveAs { get; } - public string Browse { get; } - public string BrowseDialogTitle { get; } - public string ExcelFiles { get; } - public string CsvFiles { get; } - public string TsvFiles { get; } - public string AllFiles { get; } - public string ExportRange { get; } - public string NoLimit { get; } - public string Export { get; } - public string Cancel { get; } - public string SavingFile { get; } - public string ErrorWarningTitle { get; } - public string InvalidExportPath { get; } - public string InvalidExportFileName { get; } - public string OverwritePromptTitle { get; } - public string RowLimitWarningTitle { get; } - public string RowLimitWarningText { get; } - public string ExportError { get; } - public string Interrupt { get; } - public string Interrupting { get; } - public string ExportInterrupted { get; } - public string Results { get; } - public string Close { get; } - - public string GetLimitString(int count) => Format(translation => translation?.Limit, new { count = Formatter.ToFormattedString(count) }); - public string GetRowCountSingleFileString(int rows) => - Format(translation => translation?.RowCountSingleFile, new { rows = Formatter.ToFormattedString(rows) }); - public string GetRowCountMultipleFilesString(int rows, int files) => - Format(translation => translation?.RowCountMultipleFiles, new { rows = Formatter.ToFormattedString(rows), files = Formatter.ToFormattedString(files) }); - public string GetDirectoryNotFoundString(string directory) => Format(translation => translation?.DirectoryNotFound, new { directory }); - public string GetOverwritePromptTextString(string file) => Format(translation => translation?.OverwritePromptText, new { file }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.ExportPanel), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/ExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/ExporterLocalizator.cs deleted file mode 100644 index 9f07a62..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/ExporterLocalizator.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal abstract class ExporterLocalizator : Localizator - { - public ExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Yes = Format(translation => translation?.Yes); - No = Format(translation => translation?.No); - Unknown = Format(translation => translation?.Unknown); - Portrait = Format(translation => translation?.Portrait); - Landscape = Format(translation => translation?.Landscape); - } - - protected string Yes { get; } - protected string No { get; } - protected string Unknown { get; } - protected string Portrait { get; } - protected string Landscape { get; } - - protected string StringBooleanToYesNoUnknownString(string value) - { - return StringBooleanToLabelString(value, Yes, No, Unknown); - } - - protected string StringBooleanToOrientationString(string value) - { - return StringBooleanToLabelString(value, Portrait, Landscape, Unknown); - } - - protected string Format(Func field) - { - return Format(translation => field(translation?.Exporter)); - } - - private string StringBooleanToLabelString(string value, string value1Label, string value0Label, string valueUnknownLabel) - { - switch (value) - { - case "0": - return value0Label; - case "1": - return value1Label; - default: - return valueUnknownLabel; - } - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/FictionDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/FictionDetailsTabLocalizator.cs deleted file mode 100644 index 4c15b96..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/FictionDetailsTabLocalizator.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class FictionDetailsTabLocalizator : DetailsTabLocalizator - { - public FictionDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = FormatHeader(translation => translation?.Title); - Authors = FormatHeader(translation => translation?.Authors); - RussianAuthor = FormatHeader(translation => translation?.RussianAuthor); - Series = FormatHeader(translation => translation?.Series); - Publisher = FormatHeader(translation => translation?.Publisher); - Edition = FormatHeader(translation => translation?.Edition); - Year = FormatHeader(translation => translation?.Year); - Language = FormatHeader(translation => translation?.Language); - FormatLabel = FormatHeader(translation => translation?.Format); - Pages = FormatHeader(translation => translation?.Pages); - Version = FormatHeader(translation => translation?.Version); - FileSize = FormatHeader(translation => translation?.FileSize); - Added = FormatHeader(translation => translation?.Added); - LastModified = FormatHeader(translation => translation?.LastModified); - Md5Hash = FormatHeader(translation => translation?.Md5Hash); - Comments = FormatHeader(translation => translation?.Comments); - Identifiers = FormatHeader(translation => translation?.Identifiers); - LibgenId = FormatHeader(translation => translation?.LibgenId); - Isbn = FormatHeader(translation => translation?.Isbn); - GoogleBookId = FormatHeader(translation => translation?.GoogleBookId); - Asin = FormatHeader(translation => translation?.Asin); - } - - public string Title { get; } - public string Authors { get; } - public string RussianAuthor { get; } - public string Series { get; } - public string Publisher { get; } - public string Edition { get; } - public string Year { get; } - public string Language { get; } - public string FormatLabel { get; } - public string Pages { get; } - public string Version { get; } - public string FileSize { get; } - public string Added { get; } - public string LastModified { get; } - public string Md5Hash { get; } - public string Comments { get; } - public string Identifiers { get; } - public string LibgenId { get; } - public string Isbn { get; } - public string GoogleBookId { get; } - public string Asin { get; } - - public string GetYearString(string value) => value != "0" ? value : String.Empty; - public string GetPagesString(string value) => value != "0" ? value : Unknown; - public string GetAddedDateTimeString(DateTime? value) => value.HasValue ? Formatter.ToFormattedDateTimeString(value.Value) : Unknown; - - private string Format(Func field) - { - return Format(translation => field(translation?.FictionDetailsTab)); - } - - private string FormatHeader(Func field) - { - return Format(field) + ":"; - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/FictionExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/FictionExporterLocalizator.cs deleted file mode 100644 index dc1fb29..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/FictionExporterLocalizator.cs +++ /dev/null @@ -1,64 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class FictionExporterLocalizator : ExporterLocalizator - { - public FictionExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Id = Format(translation => translation?.Id); - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - RussianAuthor = Format(translation => translation?.RussianAuthor); - Series = Format(translation => translation?.Series); - Publisher = Format(translation => translation?.Publisher); - Edition = Format(translation => translation?.Edition); - Year = Format(translation => translation?.Year); - Language = Format(translation => translation?.Language); - FormatHeader = Format(translation => translation?.Format); - Pages = Format(translation => translation?.Pages); - Version = Format(translation => translation?.Version); - FileSize = Format(translation => translation?.FileSize); - Added = Format(translation => translation?.Added); - LastModified = Format(translation => translation?.LastModified); - Md5Hash = Format(translation => translation?.Md5Hash); - Comments = Format(translation => translation?.Comments); - LibgenId = Format(translation => translation?.LibgenId); - Isbn = Format(translation => translation?.Isbn); - GoogleBookId = Format(translation => translation?.GoogleBookId); - Asin = Format(translation => translation?.Asin); - } - - public string Id { get; } - public string Title { get; } - public string Authors { get; } - public string RussianAuthor { get; } - public string Series { get; } - public string Publisher { get; } - public string Edition { get; } - public string Year { get; } - public string Language { get; } - public string FormatHeader { get; } - public string Pages { get; } - public string Version { get; } - public string FileSize { get; } - public string Added { get; } - public string LastModified { get; } - public string Md5Hash { get; } - public string Comments { get; } - public string LibgenId { get; } - public string Isbn { get; } - public string GoogleBookId { get; } - public string Asin { get; } - - public string GetYearString(string value) => value != "0" ? value : String.Empty; - public string GetPagesString(string value) => !String.IsNullOrWhiteSpace(value) ? value : Unknown; - - private string Format(Func field) - { - return Format(translation => field(translation?.Exporter?.FictionColumns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsGridColumnsLocalizator.cs deleted file mode 100644 index e2f5ba9..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsGridColumnsLocalizator.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class FictionSearchResultsGridColumnsLocalizator : Localizator - { - public FictionSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - Series = Format(translation => translation?.Series); - Year = Format(translation => translation?.Year); - Publisher = Format(translation => translation?.Publisher); - FormatColumn = Format(translation => translation?.Format); - FileSize = Format(translation => translation?.FileSize); - InLocalLibrary = Format(translation => translation?.InLocalLibrary); - } - - public string Title { get; } - public string Authors { get; } - public string Series { get; } - public string Year { get; } - public string Publisher { get; } - public string FormatColumn { get; } - public string FileSize { get; } - public string Ocr { get; } - public string InLocalLibrary { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.FictionSearchResultsTab?.Columns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsTabLocalizator.cs deleted file mode 100644 index 651b2c5..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/FictionSearchResultsTabLocalizator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class FictionSearchResultsTabLocalizator : SearchResultsTabLocalizator - { - public FictionSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - SearchBoxTooltip = Format(translation => translation?.SearchBoxTooltip); - Columns = new FictionSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); - } - - public string SearchBoxTooltip { get; } - public FictionSearchResultsGridColumnsLocalizator Columns { get; } - - public string GetSearchProgressText(int count) => Format(translation => translation?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); - public string GetStatusBarText(int count) => Format(translation => translation?.StatusBar, new { count = Formatter.ToFormattedString(count) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.FictionSearchResultsTab), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/ImportLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/ImportLocalizator.cs deleted file mode 100644 index 976594b..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/ImportLocalizator.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class ImportLocalizator : Localizator - { - public ImportLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - BrowseImportFileDialogTitle = Format(translation => translation?.BrowseImportFileDialogTitle); - AllSupportedFiles = Format(translation => translation?.AllSupportedFiles); - SqlDumps = Format(translation => translation?.SqlDumps); - Archives = Format(translation => translation?.Archives); - AllFiles = Format(translation => translation?.AllFiles); - Unknown = Format(translation => translation?.Unknown); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - Close = Format(translation => translation?.Close); - StatusDataLookup = FormatStatus(translation => translation?.DataLookup); - StatusCreatingIndexes = FormatStatus(translation => translation?.CreatingIndexes); - StatusLoadingIds = FormatStatus(translation => translation?.LoadingIds); - StatusImportingData = FormatStatus(translation => translation?.ImportingData); - StatusImportComplete = FormatStatus(translation => translation?.ImportComplete); - StatusImportCancelled = FormatStatus(translation => translation?.ImportCancelled); - StatusDataNotFound = FormatStatus(translation => translation?.DataNotFound); - StatusImportError = FormatStatus(translation => translation?.ImportError); - LogLineDataLookup = FormatLogLine(translation => translation?.DataLookup); - LogLineScanning = FormatLogLine(translation => translation?.Scanning); - LogLineNonFictionTableFound = FormatLogLine(translation => translation?.NonFictionTableFound); - LogLineFictionTableFound = FormatLogLine(translation => translation?.FictionTableFound); - LogLineSciMagTableFound = FormatLogLine(translation => translation?.SciMagTableFound); - LogLineCreatingIndexes = FormatLogLine(translation => translation?.CreatingIndexes); - LogLineLoadingIds = FormatLogLine(translation => translation?.LoadingIds); - LogLineImportingData = FormatLogLine(translation => translation?.ImportingData); - LogLineImportSuccessful = FormatLogLine(translation => translation?.ImportSuccessful); - LogLineImportCancelled = FormatLogLine(translation => translation?.ImportCancelled); - LogLineDataNotFound = FormatLogLine(translation => translation?.DataNotFound); - LogLineInsufficientDiskSpace = FormatLogLine(translation => translation?.InsufficientDiskSpace); - LogLineImportError = FormatLogLine(translation => translation?.ImportError); - } - - public string WindowTitle { get; } - public string BrowseImportFileDialogTitle { get; } - public string AllSupportedFiles { get; } - public string SqlDumps { get; } - public string Archives { get; } - public string AllFiles { get; } - public string Unknown { get; set; } - public string Interrupt { get; } - public string Interrupting { get; } - public string Close { get; } - public string StatusDataLookup { get; } - public string StatusCreatingIndexes { get; } - public string StatusLoadingIds { get; } - public string StatusImportingData { get; } - public string StatusImportComplete { get; } - public string StatusImportCancelled { get; } - public string StatusDataNotFound { get; } - public string StatusImportError { get; } - public string LogLineDataLookup { get; } - public string LogLineScanning { get; } - public string LogLineNonFictionTableFound { get; } - public string LogLineFictionTableFound { get; } - public string LogLineSciMagTableFound { get; } - public string LogLineCreatingIndexes { get; } - public string LogLineLoadingIds { get; } - public string LogLineImportingData { get; } - public string LogLineImportSuccessful { get; } - public string LogLineImportCancelled { get; } - public string LogLineDataNotFound { get; } - public string LogLineInsufficientDiskSpace { get; } - public string LogLineImportError { get; } - - public string GetElapsedString(string elapsed) => Format(translation => translation?.Elapsed, new { elapsed }); - public string GetFreeSpaceString(string freeSpace) => Format(translation => translation?.FreeSpace, new { freeSpace }); - public string GetStatusStep(int current, int total) => FormatStatus(translation => translation?.Step, new { current, total }); - public string GetLogLineStep(int step) => FormatLogLine(translation => translation?.Step, new { step }); - public string GetLogLineScannedProgress(decimal percent) => - FormatLogLine(translation => translation?.ScannedProgress, new { percent = Formatter.ToFormattedString(percent) }); - public string GetLogLineCreatingIndexForColumn(string column) => FormatLogLine(translation => translation?.CreatingIndexForColumn, new { column }); - public string GetLogLineLoadingColumnValues(string column) => FormatLogLine(translation => translation?.LoadingColumnValues, new { column }); - public string GetLogLineImportBooksProgressNoUpdate(int added) => - FormatLogLine(translation => translation?.ImportBooksProgressNoUpdate, new { added = Formatter.ToFormattedString(added) }); - public string GetLogLineImportBooksProgressWithUpdate(int added, int updated) => - FormatLogLine(translation => translation?.ImportBooksProgressWithUpdate, - new { added = Formatter.ToFormattedString(added), updated = Formatter.ToFormattedString(updated) }); - public string GetLogLineImportArticlesProgressNoUpdate(int added) => - FormatLogLine(translation => translation?.ImportArticlesProgressNoUpdate, new { added = Formatter.ToFormattedString(added) }); - public string GetLogLineImportArticlesProgressWithUpdate(int added, int updated) => - FormatLogLine(translation => translation?.ImportArticlesProgressWithUpdate, - new { added = Formatter.ToFormattedString(added), updated = Formatter.ToFormattedString(updated) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Import), templateArguments); - } - - private string FormatStatus(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Import?.StatusMessages), templateArguments); - } - - private string FormatLogLine(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Import?.LogMessages), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs deleted file mode 100644 index 8305b1b..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/LibraryTabLocalizator.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class LibraryTabLocalizator : Localizator - { - public LibraryTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - TabTitle = Format(translation => translation?.TabTitle); - ScanNonFiction = Format(translation => translation?.ScanNonFiction); - ScanFiction = Format(translation => translation?.ScanFiction); - ScanSciMag = Format(translation => translation?.ScanSciMag); - BrowseDirectoryDialogTitle = Format(translation => translation?.BrowseDirectoryDialogTitle); - CreatingIndexes = Format(translation => translation?.CreatingIndexes); - ScanLog = Format(translation => translation?.ScanLog); - AddAll = Format(translation => translation?.AddAll); - Adding = Format(translation => translation?.Adding); - Added = Format(translation => translation?.Added); - Error = Format(translation => translation?.Error); - ColumnsFile = Format(translation => translation?.File); - ColumnsAuthors = Format(translation => translation?.Authors); - ColumnsTitle = Format(translation => translation?.Title); - } - - public string TabTitle { get; } - public string ScanNonFiction { get; } - public string ScanFiction { get; } - public string ScanSciMag { get; } - public string BrowseDirectoryDialogTitle { get; } - public string CreatingIndexes { get; } - public string AddAll { get; } - public string Adding { get; } - public string Added { get; } - public string ScanLog { get; } - public string Error { get; } - public string ColumnsFile { get; } - public string ColumnsAuthors { get; } - public string ColumnsTitle { get; } - - public string GetScanStartedString(string directory) => Format(translation => translation?.ScanStarted, new { directory }); - public string GetFoundString(int count) => Format(translation => translation?.Found, new { count }); - public string GetNotFoundString(int count) => Format(translation => translation?.NotFound, new { count }); - public string GetScanCompleteString(int found, int notFound, int errors) => Format(translation => translation?.ScanComplete, - new { found = Formatter.ToFormattedString(found), notFound = Formatter.ToFormattedString(notFound), - errors = Formatter.ToFormattedString(errors) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Library), templateArguments); - } - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Library?.Columns), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/Localizator.cs b/LibgenDesktop/Models/Localization/Localizators/Localizator.cs index f72ce4a..2f9bef0 100644 --- a/LibgenDesktop/Models/Localization/Localizators/Localizator.cs +++ b/LibgenDesktop/Models/Localization/Localizators/Localizator.cs @@ -4,23 +4,30 @@ namespace LibgenDesktop.Models.Localization.Localizators { - internal abstract class Localizator + internal abstract class Localizator where T : class { private readonly List prioritizedTranslationList; + private readonly Func translationSectionSelector; - public Localizator(List prioritizedTranslationList, LanguageFormatter formatter) + public Localizator(List prioritizedTranslationList, LanguageFormatter formatter, Func translationSectionSelector) { this.prioritizedTranslationList = prioritizedTranslationList; Formatter = formatter; + this.translationSectionSelector = translationSectionSelector; } protected LanguageFormatter Formatter { get; } - protected string Format(Func translationField, object templateArguments = null) + protected string Format(Func translationSectionField, object templateArguments = null) + { + return Format(translation => translationSectionField(translationSectionSelector(translation)), templateArguments); + } + + protected string Format(Func translationFieldSelector, object templateArguments = null) { foreach (Translation translation in prioritizedTranslationList) { - string result = translationField(translation)?.Replace("{new-line}", "\r\n"); + string result = translationFieldSelector(translation)?.Replace("{new-line}", "\r\n"); if (result != null) { return templateArguments == null ? result : RenderTemplate(result, templateArguments); @@ -29,7 +36,7 @@ protected string Format(Func translationField, object templ return "Error"; } - private string RenderTemplate(string template, object templateArguments) + private static string RenderTemplate(string template, object templateArguments) { string result = template; foreach (PropertyInfo property in templateArguments.GetType().GetProperties()) diff --git a/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs deleted file mode 100644 index 6560f3c..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/MainWindowLocalizator.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class MainWindowLocalizator : Localizator - { - public MainWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - ToolbarDownloadManagerTooltip = Format(translation => translation?.DownloadManagerTooltip); - ToolbarBookmarksTooltip = Format(translation => translation?.BookmarksTooltip); - ToolbarNoBookmarks = Format(translation => translation?.NoBookmarks); - ToolbarUpdate = Format(translation => translation?.Update); - ToolbarImport = Format(translation => translation?.Import); - ToolbarSynchronize = Format(translation => translation?.Synchronize); - ToolbarLibrary = Format(translation => translation?.Library); - ToolbarDatabase = Format(translation => translation?.Database); - ToolbarSqlDebugger = Format(translation => translation?.SqlDebugger); - ToolbarSettings = Format(translation => translation?.Settings); - ToolbarAbout = Format(translation => translation?.About); - } - - public string WindowTitle { get; } - public string ToolbarDownloadManagerTooltip { get; } - public string ToolbarBookmarksTooltip { get; } - public string ToolbarNoBookmarks { get; } - public string ToolbarUpdate { get; } - public string ToolbarImport { get; } - public string ToolbarSynchronize { get; } - public string ToolbarLibrary { get; } - public string ToolbarDatabase { get; } - public string ToolbarSqlDebugger { get; } - public string ToolbarSettings { get; } - public string ToolbarAbout { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.MainWindow)); - } - - private string Format(Func field) - { - return Format(translation => field(translation?.MainWindow?.MainMenu)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/MessageBoxLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/MessageBoxLocalizator.cs deleted file mode 100644 index 844d950..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/MessageBoxLocalizator.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class MessageBoxLocalizator : Localizator - { - public MessageBoxLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Ok = Format(translation => translation?.Ok); - Yes = Format(translation => translation?.Yes); - No = Format(translation => translation?.No); - } - - public string Ok { get; } - public string Yes { get; } - public string No { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.MessageBox)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/NonFictionDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/NonFictionDetailsTabLocalizator.cs deleted file mode 100644 index bc3e492..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/NonFictionDetailsTabLocalizator.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class NonFictionDetailsTabLocalizator : DetailsTabLocalizator - { - public NonFictionDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = FormatHeader(translation => translation?.Title); - Authors = FormatHeader(translation => translation?.Authors); - Series = FormatHeader(translation => translation?.Series); - Publisher = FormatHeader(translation => translation?.Publisher); - Year = FormatHeader(translation => translation?.Year); - Language = FormatHeader(translation => translation?.Language); - FormatLabel = FormatHeader(translation => translation?.Format); - Isbn = FormatHeader(translation => translation?.Isbn); - Added = FormatHeader(translation => translation?.Added); - LastModified = FormatHeader(translation => translation?.LastModified); - Library = FormatHeader(translation => translation?.Library); - FileSize = FormatHeader(translation => translation?.FileSize); - Topics = FormatHeader(translation => translation?.Topics); - Volume = FormatHeader(translation => translation?.Volume); - Magazine = FormatHeader(translation => translation?.Magazine); - City = FormatHeader(translation => translation?.City); - Edition = FormatHeader(translation => translation?.Edition); - Pages = FormatHeader(translation => translation?.Pages); - Tags = FormatHeader(translation => translation?.Tags); - Md5Hash = FormatHeader(translation => translation?.Md5Hash); - Comments = FormatHeader(translation => translation?.Comments); - Identifiers = FormatHeader(translation => translation?.Identifiers); - LibgenId = FormatHeader(translation => translation?.LibgenId); - Issn = FormatHeader(translation => translation?.Issn); - Udc = FormatHeader(translation => translation?.Udc); - Lbc = FormatHeader(translation => translation?.Lbc); - Lcc = FormatHeader(translation => translation?.Lcc); - Ddc = FormatHeader(translation => translation?.Ddc); - Doi = FormatHeader(translation => translation?.Doi); - OpenLibraryId = FormatHeader(translation => translation?.OpenLibraryId); - GoogleBookId = FormatHeader(translation => translation?.GoogleBookId); - Asin = FormatHeader(translation => translation?.Asin); - AdditionalAttributes = FormatHeader(translation => translation?.AdditionalAttributes); - Dpi = FormatHeader(translation => translation?.Dpi); - Ocr = FormatHeader(translation => translation?.Ocr); - TableOfContents = FormatHeader(translation => translation?.TableOfContents); - Scanned = FormatHeader(translation => translation?.Scanned); - Orientation = FormatHeader(translation => translation?.Orientation); - Paginated = FormatHeader(translation => translation?.Paginated); - Colored = FormatHeader(translation => translation?.Colored); - Cleaned = FormatHeader(translation => translation?.Cleaned); - } - - public string Title { get; } - public string Authors { get; } - public string Series { get; } - public string Publisher { get; } - public string Year { get; } - public string Language { get; } - public string FormatLabel { get; } - public string Isbn { get; } - public string Added { get; } - public string LastModified { get; } - public string Library { get; } - public string FileSize { get; } - public string Topics { get; } - public string Volume { get; } - public string Magazine { get; } - public string City { get; } - public string Edition { get; } - public string Pages { get; } - public string Tags { get; } - public string Md5Hash { get; } - public string Comments { get; } - public string Identifiers { get; } - public string LibgenId { get; } - public string Issn { get; } - public string Udc { get; } - public string Lbc { get; } - public string Lcc { get; } - public string Ddc { get; } - public string Doi { get; } - public string OpenLibraryId { get; } - public string GoogleBookId { get; } - public string Asin { get; } - public string AdditionalAttributes { get; } - public string Dpi { get; } - public string Ocr { get; } - public string TableOfContents { get; } - public string Scanned { get; } - public string Orientation { get; } - public string Paginated { get; } - public string Colored { get; } - public string Cleaned { get; } - - public string GetPagesText(string bodyMatterPages, int totalPages) - { - StringBuilder resultBuilder = new StringBuilder(); - if (!String.IsNullOrWhiteSpace(bodyMatterPages)) - { - resultBuilder.Append(bodyMatterPages); - } - else - { - resultBuilder.Append(Unknown); - } - resultBuilder.Append(" ("); - resultBuilder.Append(Format(translation => translation?.BodyMatterPages)); - resultBuilder.Append(") / "); - resultBuilder.Append(totalPages.ToString()); - resultBuilder.Append(" ("); - resultBuilder.Append(Format(translation => translation?.TotalPages)); - resultBuilder.Append(")"); - return resultBuilder.ToString(); - } - - public string GetOcrString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetBookmarkedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetScannedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetOrientationString(string value) => StringBooleanToOrientationString(value); - public string GetPaginatedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetColorString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetCleanedString(string value) => StringBooleanToYesNoUnknownString(value); - - private string Format(Func field) - { - return Format(translation => field(translation?.NonFictionDetailsTab)); - } - - private string FormatHeader(Func field) - { - return Format(field) + ":"; - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/NonFictionExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/NonFictionExporterLocalizator.cs deleted file mode 100644 index aaaa7fd..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/NonFictionExporterLocalizator.cs +++ /dev/null @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class NonFictionExporterLocalizator : ExporterLocalizator - { - public NonFictionExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Id = Format(translation => translation?.Id); - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - Series = Format(translation => translation?.Series); - Publisher = Format(translation => translation?.Publisher); - Year = Format(translation => translation?.Year); - Language = Format(translation => translation?.Language); - FormatHeader = Format(translation => translation?.Format); - Isbn = Format(translation => translation?.Isbn); - Added = Format(translation => translation?.Added); - LastModified = Format(translation => translation?.LastModified); - Library = Format(translation => translation?.Library); - FileSize = Format(translation => translation?.FileSize); - Topics = Format(translation => translation?.Topics); - Volume = Format(translation => translation?.Volume); - Magazine = Format(translation => translation?.Magazine); - City = Format(translation => translation?.City); - Edition = Format(translation => translation?.Edition); - BodyMatterPages = Format(translation => translation?.BodyMatterPages); - TotalPages = Format(translation => translation?.TotalPages); - Tags = Format(translation => translation?.Tags); - Md5Hash = Format(translation => translation?.Md5Hash); - Comments = Format(translation => translation?.Comments); - LibgenId = Format(translation => translation?.LibgenId); - Issn = Format(translation => translation?.Issn); - Udc = Format(translation => translation?.Udc); - Lbc = Format(translation => translation?.Lbc); - Lcc = Format(translation => translation?.Lcc); - Ddc = Format(translation => translation?.Ddc); - Doi = Format(translation => translation?.Doi); - OpenLibraryId = Format(translation => translation?.OpenLibraryId); - GoogleBookId = Format(translation => translation?.GoogleBookId); - Asin = Format(translation => translation?.Asin); - Dpi = Format(translation => translation?.Dpi); - Ocr = Format(translation => translation?.Ocr); - TableOfContents = Format(translation => translation?.TableOfContents); - Scanned = Format(translation => translation?.Scanned); - Orientation = Format(translation => translation?.Orientation); - Paginated = Format(translation => translation?.Paginated); - Colored = Format(translation => translation?.Colored); - Cleaned = Format(translation => translation?.Cleaned); - } - - public string Id { get; } - public string Title { get; } - public string Authors { get; } - public string Series { get; } - public string Publisher { get; } - public string Year { get; } - public string Language { get; } - public string FormatHeader { get; } - public string Isbn { get; } - public string Added { get; } - public string LastModified { get; } - public string Library { get; } - public string FileSize { get; } - public string Topics { get; } - public string Volume { get; } - public string Magazine { get; } - public string City { get; } - public string Edition { get; } - public string BodyMatterPages { get; } - public string TotalPages { get; } - public string Tags { get; } - public string Md5Hash { get; } - public string Comments { get; } - public string LibgenId { get; } - public string Issn { get; } - public string Udc { get; } - public string Lbc { get; } - public string Lcc { get; } - public string Ddc { get; } - public string Doi { get; } - public string OpenLibraryId { get; } - public string GoogleBookId { get; } - public string Asin { get; } - public string Dpi { get; } - public string Ocr { get; } - public string TableOfContents { get; } - public string Scanned { get; } - public string Orientation { get; } - public string Paginated { get; } - public string Colored { get; } - public string Cleaned { get; } - - public string GetBodyMatterPageCountString(string value) => !String.IsNullOrWhiteSpace(value) ? value : Unknown; - public string GetOcrString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetBookmarkedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetScannedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetOrientationString(string value) => StringBooleanToOrientationString(value); - public string GetPaginatedString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetColorString(string value) => StringBooleanToYesNoUnknownString(value); - public string GetCleanedString(string value) => StringBooleanToYesNoUnknownString(value); - - private string Format(Func field) - { - return Format(translation => field(translation?.Exporter?.NonFictionColumns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsGridColumnsLocalizator.cs deleted file mode 100644 index a9c6bc9..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsGridColumnsLocalizator.cs +++ /dev/null @@ -1,37 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class NonFictionSearchResultsGridColumnsLocalizator : Localizator - { - public NonFictionSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - Series = Format(translation => translation?.Series); - Year = Format(translation => translation?.Year); - Publisher = Format(translation => translation?.Publisher); - FormatColumn = Format(translation => translation?.Format); - FileSize = Format(translation => translation?.FileSize); - Ocr = Format(translation => translation?.Ocr); - InLocalLibrary = Format(translation => translation?.InLocalLibrary); - } - - public string Title { get; } - public string Authors { get; } - public string Series { get; } - public string Year { get; } - public string Publisher { get; } - public string FormatColumn { get; } - public string FileSize { get; } - public string Ocr { get; } - public string InLocalLibrary { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.NonFictionSearchResultsTab?.Columns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsTabLocalizator.cs deleted file mode 100644 index a3bff19..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/NonFictionSearchResultsTabLocalizator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class NonFictionSearchResultsTabLocalizator : SearchResultsTabLocalizator - { - public NonFictionSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - SearchBoxTooltip = Format(translation => translation?.SearchBoxTooltip); - Columns = new NonFictionSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); - } - - public string SearchBoxTooltip { get; } - public NonFictionSearchResultsGridColumnsLocalizator Columns { get; } - - public string GetSearchProgressText(int count) => Format(translation => translation?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); - public string GetStatusBarText(int count) => Format(translation => translation?.StatusBar, new { count = Formatter.ToFormattedString(count) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.NonFictionSearchResultsTab), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SciMagDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SciMagDetailsTabLocalizator.cs deleted file mode 100644 index ba0c346..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SciMagDetailsTabLocalizator.cs +++ /dev/null @@ -1,100 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SciMagDetailsTabLocalizator : DetailsTabLocalizator - { - public SciMagDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = FormatHeader(translation => translation?.Title); - Authors = FormatHeader(translation => translation?.Authors); - Magazine = FormatHeader(translation => translation?.Magazine); - Year = FormatHeader(translation => translation?.Year); - Month = FormatHeader(translation => translation?.Month); - Day = FormatHeader(translation => translation?.Day); - Volume = FormatHeader(translation => translation?.Volume); - Issue = FormatHeader(translation => translation?.Issue); - Pages = FormatHeader(translation => translation?.Pages); - FileSize = FormatHeader(translation => translation?.FileSize); - AddedDateTime = FormatHeader(translation => translation?.AddedDateTime); - Md5Hash = FormatHeader(translation => translation?.Md5Hash); - AbstractUrl = FormatHeader(translation => translation?.AbstractUrl); - Identifiers = FormatHeader(translation => translation?.Identifiers); - LibgenId = FormatHeader(translation => translation?.LibgenId); - Doi = FormatHeader(translation => translation?.Doi); - Isbn = FormatHeader(translation => translation?.Isbn); - MagazineId = FormatHeader(translation => translation?.MagazineId); - Issnp = FormatHeader(translation => translation?.Issnp); - Issne = FormatHeader(translation => translation?.Issne); - PubmedId = FormatHeader(translation => translation?.PubmedId); - Pmc = FormatHeader(translation => translation?.Pmc); - Pii = FormatHeader(translation => translation?.Pii); - AdditionalAttributes = FormatHeader(translation => translation?.AdditionalAttributes); - Attribute1 = FormatHeader(translation => translation?.Attribute1); - Attribute2 = FormatHeader(translation => translation?.Attribute2); - Attribute3 = FormatHeader(translation => translation?.Attribute3); - Attribute4 = FormatHeader(translation => translation?.Attribute4); - Attribute5 = FormatHeader(translation => translation?.Attribute5); - Attribute6 = FormatHeader(translation => translation?.Attribute6); - } - - public string Title { get; } - public string Authors { get; } - public string Magazine { get; } - public string Year { get; } - public string Month { get; } - public string Day { get; } - public string Volume { get; } - public string Issue { get; } - public string Pages { get; } - public string FileSize { get; } - public string AddedDateTime { get; } - public string Md5Hash { get; } - public string AbstractUrl { get; } - public string Identifiers { get; } - public string LibgenId { get; } - public string Doi { get; } - public string Isbn { get; } - public string MagazineId { get; } - public string Issnp { get; } - public string Issne { get; } - public string PubmedId { get; } - public string Pmc { get; } - public string Pii { get; } - public string AdditionalAttributes { get; } - public string Attribute1 { get; } - public string Attribute2 { get; } - public string Attribute3 { get; } - public string Attribute4 { get; } - public string Attribute5 { get; } - public string Attribute6 { get; } - - public string GetPagesString(string firstPage, string lastPage) - { - if ((!String.IsNullOrWhiteSpace(firstPage) && firstPage != "0") || (!String.IsNullOrWhiteSpace(lastPage) && lastPage != "0")) - { - firstPage = firstPage != "0" ? firstPage.Trim() + " " : String.Empty; - lastPage = lastPage != "0" ? " " + lastPage.Trim() : String.Empty; - return firstPage + "–" + lastPage; - } - else - { - return Unknown; - } - } - - public string GetAddedDateTimeString(DateTime? value) => value.HasValue ? Formatter.ToFormattedDateTimeString(value.Value) : Unknown; - - private string Format(Func field) - { - return Format(translation => field(translation?.SciMagDetailsTab)); - } - - private string FormatHeader(Func field) - { - return Format(field) + ":"; - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SciMagExporterLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SciMagExporterLocalizator.cs deleted file mode 100644 index d7667dc..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SciMagExporterLocalizator.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SciMagExporterLocalizator : ExporterLocalizator - { - public SciMagExporterLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Id = Format(translation => translation?.Id); - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - Magazine = Format(translation => translation?.Magazine); - Year = Format(translation => translation?.Year); - Month = Format(translation => translation?.Month); - Day = Format(translation => translation?.Day); - Volume = Format(translation => translation?.Volume); - Issue = Format(translation => translation?.Issue); - Pages = Format(translation => translation?.Pages); - FileSize = Format(translation => translation?.FileSize); - AddedDateTime = Format(translation => translation?.AddedDateTime); - Md5Hash = Format(translation => translation?.Md5Hash); - AbstractUrl = Format(translation => translation?.AbstractUrl); - LibgenId = Format(translation => translation?.LibgenId); - Doi1 = Format(translation => translation?.Doi1); - Doi2 = Format(translation => translation?.Doi2); - Isbn = Format(translation => translation?.Isbn); - MagazineId = Format(translation => translation?.MagazineId); - Issnp = Format(translation => translation?.Issnp); - Issne = Format(translation => translation?.Issne); - PubmedId = Format(translation => translation?.PubmedId); - Pmc = Format(translation => translation?.Pmc); - Pii = Format(translation => translation?.Pii); - Attribute1 = Format(translation => translation?.Attribute1); - Attribute2 = Format(translation => translation?.Attribute2); - Attribute3 = Format(translation => translation?.Attribute3); - Attribute4 = Format(translation => translation?.Attribute4); - Attribute5 = Format(translation => translation?.Attribute5); - Attribute6 = Format(translation => translation?.Attribute6); - } - - public string Id { get; } - public string Title { get; } - public string Authors { get; } - public string Magazine { get; } - public string Year { get; } - public string Month { get; } - public string Day { get; } - public string Volume { get; } - public string Issue { get; } - public string Pages { get; } - public string FileSize { get; } - public string AddedDateTime { get; } - public string Md5Hash { get; } - public string AbstractUrl { get; } - public string LibgenId { get; } - public string Doi1 { get; } - public string Doi2 { get; } - public string Isbn { get; } - public string MagazineId { get; } - public string Issnp { get; } - public string Issne { get; } - public string PubmedId { get; } - public string Pmc { get; } - public string Pii { get; } - public string Attribute1 { get; } - public string Attribute2 { get; } - public string Attribute3 { get; } - public string Attribute4 { get; } - public string Attribute5 { get; } - public string Attribute6 { get; } - - public string GetPagesString(string firstPage, string lastPage) - { - if ((!String.IsNullOrWhiteSpace(firstPage) && firstPage != "0") || (!String.IsNullOrWhiteSpace(lastPage) && lastPage != "0")) - { - firstPage = firstPage != "0" ? firstPage.Trim() + " " : String.Empty; - lastPage = lastPage != "0" ? " " + lastPage.Trim() : String.Empty; - return firstPage + "–" + lastPage; - } - else - { - return Unknown; - } - } - - private string Format(Func field) - { - return Format(translation => field(translation?.Exporter?.SciMagColumns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsGridColumnsLocalizator.cs deleted file mode 100644 index d92603a..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsGridColumnsLocalizator.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SciMagSearchResultsGridColumnsLocalizator : Localizator - { - public SciMagSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - Title = Format(translation => translation?.Title); - Authors = Format(translation => translation?.Authors); - Magazine = Format(translation => translation?.Magazine); - Year = Format(translation => translation?.Year); - FileSize = Format(translation => translation?.FileSize); - Doi = Format(translation => translation?.Doi); - InLocalLibrary = Format(translation => translation?.InLocalLibrary); - } - - public string Title { get; } - public string Authors { get; } - public string Magazine { get; } - public string Year { get; } - public string FileSize { get; } - public string Doi { get; } - public string InLocalLibrary { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.SciMagSearchResultsTab?.Columns)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsTabLocalizator.cs deleted file mode 100644 index 5246a10..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SciMagSearchResultsTabLocalizator.cs +++ /dev/null @@ -1,26 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SciMagSearchResultsTabLocalizator : SearchResultsTabLocalizator - { - public SciMagSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - SearchBoxTooltip = Format(translation => translation?.SearchBoxTooltip); - Columns = new SciMagSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); - } - - public string SearchBoxTooltip { get; } - public SciMagSearchResultsGridColumnsLocalizator Columns { get; } - - public string GetSearchProgressText(int count) => Format(translation => translation?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); - public string GetStatusBarText(int count) => Format(translation => translation?.StatusBar, new { count = Formatter.ToFormattedString(count) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.SciMagSearchResultsTab), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/FictionSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/FictionSearchResultsGridColumnsLocalizator.cs new file mode 100644 index 0000000..e798348 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/FictionSearchResultsGridColumnsLocalizator.cs @@ -0,0 +1,32 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SearchResultGrids +{ + internal class FictionSearchResultsGridColumnsLocalizator : Localizator + { + public FictionSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.FictionSearchResultsTab?.Columns) + { + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Series = Format(section => section?.Series); + Year = Format(section => section?.Year); + Language = Format(section => section?.Language); + Publisher = Format(section => section?.Publisher); + FormatColumn = Format(section => section?.Format); + FileSize = Format(section => section?.FileSize); + InLocalLibrary = Format(section => section?.InLocalLibrary); + } + + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Year { get; } + public string Language { get; } + public string Publisher { get; } + public string FormatColumn { get; } + public string FileSize { get; } + public string Ocr { get; } + public string InLocalLibrary { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/NonFictionSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/NonFictionSearchResultsGridColumnsLocalizator.cs new file mode 100644 index 0000000..37a15f7 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/NonFictionSearchResultsGridColumnsLocalizator.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SearchResultGrids +{ + internal class NonFictionSearchResultsGridColumnsLocalizator : Localizator + { + public NonFictionSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.NonFictionSearchResultsTab?.Columns) + { + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Series = Format(section => section?.Series); + Year = Format(section => section?.Year); + Language = Format(section => section?.Language); + Publisher = Format(section => section?.Publisher); + FormatColumn = Format(section => section?.Format); + FileSize = Format(section => section?.FileSize); + Ocr = Format(section => section?.Ocr); + InLocalLibrary = Format(section => section?.InLocalLibrary); + } + + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Year { get; } + public string Language { get; } + public string Publisher { get; } + public string FormatColumn { get; } + public string FileSize { get; } + public string Ocr { get; } + public string InLocalLibrary { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/SciMagSearchResultsGridColumnsLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/SciMagSearchResultsGridColumnsLocalizator.cs new file mode 100644 index 0000000..e40ba45 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SearchResultGrids/SciMagSearchResultsGridColumnsLocalizator.cs @@ -0,0 +1,27 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SearchResultGrids +{ + internal class SciMagSearchResultsGridColumnsLocalizator : Localizator + { + public SciMagSearchResultsGridColumnsLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SciMagSearchResultsTab?.Columns) + { + Title = Format(section => section?.Title); + Authors = Format(section => section?.Authors); + Magazine = Format(section => section?.Magazine); + Year = Format(section => section?.Year); + FileSize = Format(section => section?.FileSize); + Doi = Format(section => section?.Doi); + InLocalLibrary = Format(section => section?.InLocalLibrary); + } + + public string Title { get; } + public string Authors { get; } + public string Magazine { get; } + public string Year { get; } + public string FileSize { get; } + public string Doi { get; } + public string InLocalLibrary { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SearchResultsTabLocalizator.cs deleted file mode 100644 index dcd671e..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SearchResultsTabLocalizator.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal abstract class SearchResultsTabLocalizator : Localizator - { - public SearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - SearchPlaceHolder = Format(translation => translation?.SearchPlaceHolder); - SearchInProgress = Format(translation => translation?.SearchInProgress); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - AddToBookmarksTooltip = Format(translation => translation?.AddToBookmarksTooltip); - RemoveFromBookmarksTooltip = Format(translation => translation?.RemoveFromBookmarksTooltip); - ExportButtonTooltip = Format(translation => translation?.ExportButtonTooltip); - Details = Format(translation => translation?.Details); - Open = Format(translation => translation?.Open); - Download = Format(translation => translation?.Download); - ErrorMessageTitle = Format(translation => translation?.ErrorMessageTitle); - OfflineModeIsOnMessageTitle = Format(translation => translation?.OfflineModeIsOnMessageTitle); - OfflineModeIsOnMessageText = Format(translation => translation?.OfflineModeIsOnMessageText); - NoDownloadMirrorError = Format(translation => translation?.NoDownloadMirrorError); - LargeNumberOfItemsToDownloadPromptTitle = Format(translation => translation?.LargeNumberOfItemsToDownloadPromptTitle); - } - - public string SearchPlaceHolder { get; } - public string SearchInProgress { get; } - public string Interrupt { get; } - public string Interrupting { get; } - public string AddToBookmarksTooltip { get; } - public string RemoveFromBookmarksTooltip { get; } - public string ExportButtonTooltip { get; } - public string Details { get; } - public string Open { get; } - public string Download { get; } - public string ErrorMessageTitle { get; } - public string OfflineModeIsOnMessageTitle { get; } - public string OfflineModeIsOnMessageText { get; } - public string NoDownloadMirrorError { get; } - public string LargeNumberOfItemsToDownloadPromptTitle { get; } - - public string GetFileNotFoundErrorText(string file) => Format(translation => translation?.FileNotFoundError, new { file }); - - public string GetLargeNumberOfItemsToDownloadPromptText(int number) => - Format(translation => translation?.LargeNumberOfItemsToDownloadPromptText, new { number }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.SearchResultsTabs), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SearchTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SearchTabLocalizator.cs deleted file mode 100644 index 083e7dd..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SearchTabLocalizator.cs +++ /dev/null @@ -1,53 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SearchTabLocalizator : Localizator - { - public SearchTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - TabTitle = Format(translation => translation?.TabTitle); - NonFictionSelector = Format(translation => translation?.NonFictionSelector); - SearchPlaceHolder = Format(translation => translation?.SearchPlaceHolder); - NonFictionSelector = Format(translation => translation?.NonFictionSelector); - FictionSelector = Format(translation => translation?.FictionSelector); - SciMagSelector = Format(translation => translation?.SciMagSelector); - NonFictionSearchBoxTooltip = Format(translation => translation?.NonFictionSearchBoxTooltip); - FictionSearchBoxTooltip = Format(translation => translation?.FictionSearchBoxTooltip); - SciMagSearchBoxTooltip = Format(translation => translation?.SciMagSearchBoxTooltip); - SearchInProgress = Format(translation => translation?.SearchInProgress); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - DatabaseIsEmpty = Format(translation => translation?.DatabaseIsEmpty); - ImportButton = Format(translation => translation?.ImportButton); - } - - public string TabTitle { get; } - public string SearchPlaceHolder { get; } - public string NonFictionSelector { get; } - public string FictionSelector { get; } - public string SciMagSelector { get; } - public string NonFictionSearchBoxTooltip { get; } - public string FictionSearchBoxTooltip { get; } - public string SciMagSearchBoxTooltip { get; } - public string SearchInProgress { get; } - public string Interrupt { get; } - public string Interrupting { get; } - public string DatabaseIsEmpty { get; } - public string ImportButton { get; } - - public string GetNonFictionSearchProgressText(int count) => - Format(translation => translation?.NonFictionSearchProgress, new { count = Formatter.ToFormattedString(count) }); - public string GetFictionSearchProgressText(int count) => - Format(translation => translation?.FictionSearchProgress, new { count = Formatter.ToFormattedString(count) }); - public string GetSciMagSearchProgressText(int count) => - Format(translation => translation?.SciMagSearchProgress, new { count = Formatter.ToFormattedString(count) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.SearchTab), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SettingsWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SettingsWindowLocalizator.cs deleted file mode 100644 index 299d18c..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SettingsWindowLocalizator.cs +++ /dev/null @@ -1,143 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SettingsWindowLocalizator : Localizator - { - public SettingsWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - Ok = Format(translation => translation?.Ok); - Cancel = Format(translation => translation?.Cancel); - DiscardChangesPromptTitle = Format(translation => translation?.DiscardChangesPromptTitle); - DiscardChangesPromptText = Format(translation => translation?.DiscardChangesPromptText); - GeneralTabHeader = Format(translation => translation?.General?.TabHeader); - GeneralLanguage = Format(translation => translation?.General?.Language); - GeneralCheckUpdates = Format(translation => translation?.General?.CheckUpdates); - GeneralUpdateCheckIntervalNever = Format(translation => translation?.General?.UpdateCheckIntervals?.Never); - GeneralUpdateCheckIntervalDaily = Format(translation => translation?.General?.UpdateCheckIntervals?.Daily); - GeneralUpdateCheckIntervalWeekly = Format(translation => translation?.General?.UpdateCheckIntervals?.Weekly); - GeneralUpdateCheckIntervalMonthly = Format(translation => translation?.General?.UpdateCheckIntervals?.Monthly); - NetworkTabHeader = Format(translation => translation?.Network?.TabHeader); - NetworkOfflineMode = Format(translation => translation?.Network?.OfflineMode); - NetworkUseHttpProxy = Format(translation => translation?.Network?.UseHttpProxy); - NetworkProxyAddress = Format(translation => translation?.Network?.ProxyAddress); - NetworkProxyAddressRequired = Format(translation => translation?.Network?.ProxyAddressRequired); - NetworkProxyPort = Format(translation => translation?.Network?.ProxyPort); - NetworkProxyUserName = Format(translation => translation?.Network?.ProxyUserName); - NetworkProxyPassword = Format(translation => translation?.Network?.ProxyPassword); - NetworkProxyPasswordWarning = Format(translation => translation?.Network?.ProxyPasswordWarning); - DownloadTabHeader = Format(translation => translation?.Download?.TabHeader); - DownloadDownloadMode = Format(translation => translation?.Download?.DownloadMode) + ":"; - DownloadOpenInBrowser = Format(translation => translation?.Download?.OpenInBrowser); - DownloadUseDownloadManager = Format(translation => translation?.Download?.UseDownloadManager); - DownloadDownloadDirectory = Format(translation => translation?.Download?.DownloadDirectory) + ":"; - DownloadBrowseDirectoryDialogTitle = Format(translation => translation?.Download?.BrowseDirectoryDialogTitle); - DownloadDownloadDirectoryNotFound = Format(translation => translation?.Download?.DownloadDirectoryNotFound); - DownloadTimeout = Format(translation => translation?.Download?.Timeout); - DownloadSeconds = Format(translation => translation?.Download?.Seconds); - DownloadDownloadAttempts = Format(translation => translation?.Download?.DownloadAttempts); - DownloadTimes = Format(translation => translation?.Download?.Times); - DownloadRetryDelay = Format(translation => translation?.Download?.RetryDelay); - MirrorsTabHeader = Format(translation => translation?.Mirrors?.TabHeader); - MirrorsNonFiction = Format(translation => translation?.Mirrors?.NonFiction); - MirrorsFiction = Format(translation => translation?.Mirrors?.Fiction); - MirrorsSciMagArticles = Format(translation => translation?.Mirrors?.SciMagArticles); - MirrorsBooks = Format(translation => translation?.Mirrors?.Books); - MirrorsArticles = Format(translation => translation?.Mirrors?.Articles); - MirrorsCovers = Format(translation => translation?.Mirrors?.Covers); - MirrorsSynchronization = Format(translation => translation?.Mirrors?.Synchronization); - MirrorsNoMirror = Format(translation => translation?.Mirrors?.NoMirror); - SearchTabHeader = Format(translation => translation?.Search?.TabHeader); - SearchLimitResults = Format(translation => translation?.Search?.LimitResults); - SearchMaximumResults = Format(translation => translation?.Search?.MaximumResults); - SearchPositiveNumbersOnly = Format(translation => translation?.Search?.PositiveNumbersOnly); - SearchOpenDetails = Format(translation => translation?.Search?.OpenDetails) + ":"; - SearchInModalWindow = Format(translation => translation?.Search?.InModalWindow); - SearchInNonModalWindow = Format(translation => translation?.Search?.InNonModalWindow); - SearchInNewTab = Format(translation => translation?.Search?.InNewTab); - ExportTabHeader = Format(translation => translation?.Export?.TabHeader); - ExportOpenResults = Format(translation => translation?.Export?.OpenResults); - ExportSplitIntoMultipleFiles = Format(translation => translation?.Export?.SplitIntoMultipleFiles); - ExportMaximumRowsPerFile = Format(translation => translation?.Export?.MaximumRowsPerFile); - AdvancedTabHeader = Format(translation => translation?.Advanced?.TabHeader); - AdvancedUseLogging = Format(translation => translation?.Advanced?.UseLogging); - AdvancedEnableSqlDebugger = Format(translation => translation?.Advanced?.EnableSqlDebugger); - } - - public string WindowTitle { get; } - public string Ok { get; } - public string Cancel { get; } - public string DiscardChangesPromptTitle { get; } - public string DiscardChangesPromptText { get; } - public string GeneralTabHeader { get; } - public string GeneralLanguage { get; } - public string GeneralCheckUpdates { get; } - public string GeneralUpdateCheckIntervalNever { get; } - public string GeneralUpdateCheckIntervalDaily { get; } - public string GeneralUpdateCheckIntervalWeekly { get; } - public string GeneralUpdateCheckIntervalMonthly { get; } - public string NetworkTabHeader { get; } - public string NetworkOfflineMode { get; } - public string NetworkUseHttpProxy { get; } - public string NetworkProxyAddress { get; } - public string NetworkProxyAddressRequired { get; } - public string NetworkProxyPort { get; } - public string NetworkProxyUserName { get; } - public string NetworkProxyPassword { get; } - public string NetworkProxyPasswordWarning { get; } - public string DownloadTabHeader { get; } - public string DownloadDownloadMode { get; } - public string DownloadOpenInBrowser { get; } - public string DownloadUseDownloadManager { get; } - public string DownloadDownloadDirectory { get; } - public string DownloadBrowseDirectoryDialogTitle { get; } - public string DownloadDownloadDirectoryNotFound { get; } - public string DownloadTimeout { get; } - public string DownloadSeconds { get; } - public string DownloadDownloadAttempts { get; } - public string DownloadTimes { get; } - public string DownloadRetryDelay { get; } - public string MirrorsTabHeader { get; } - public string MirrorsNonFiction { get; } - public string MirrorsFiction { get; } - public string MirrorsSciMagArticles { get; } - public string MirrorsBooks { get; } - public string MirrorsArticles { get; } - public string MirrorsCovers { get; } - public string MirrorsSynchronization { get; } - public string MirrorsNoMirror { get; } - public string SearchTabHeader { get; } - public string SearchLimitResults { get; } - public string SearchMaximumResults { get; } - public string SearchPositiveNumbersOnly { get; } - public string SearchOpenDetails { get; } - public string SearchInModalWindow { get; } - public string SearchInNonModalWindow { get; } - public string SearchInNewTab { get; } - public string ExportTabHeader { get; } - public string ExportOpenResults { get; } - public string ExportSplitIntoMultipleFiles { get; } - public string ExportMaximumRowsPerFile { get; } - public string AdvancedTabHeader { get; } - public string AdvancedUseLogging { get; } - public string AdvancedEnableSqlDebugger { get; } - - public string GetNetworkProxyPortValidation(int min, int max) => Format(translation => translation?.Network?.ProxyPortValidation, new { min, max }); - public string GetDownloadTimeoutValidation(int min, int max) => Format(translation => translation?.Download?.TimeoutValidation, new { min, max }); - public string GetDownloadDownloadAttemptsValidation(int min, int max) => - Format(translation => translation?.Download?.DownloadAttemptsValidation, new { min, max }); - public string GetDownloadRetryDelayValidation(int min, int max) => Format(translation => translation?.Download?.RetryDelayValidation, new { min, max }); - public string GetExportMaximumRowsPerFileValidation(int min, int max) => - Format(translation => translation?.Export?.MaximumRowsPerFileValidation, new { min, max }); - public string GetExportExcelLimitNote(int count) => - Format(translation => translation?.Export?.ExcelLimitNote, new { count = Formatter.ToFormattedString(count) }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Settings), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CollectionsSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CollectionsSetupStepLocalizator.cs new file mode 100644 index 0000000..5608661 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CollectionsSetupStepLocalizator.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class CollectionsSetupStepLocalizator : Localizator + { + public CollectionsSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.CollectionsStep) + { + ChooseCollections = Format(section => section?.ChooseCollections); + NonFiction = Format(section => section?.NonFiction); + Fiction = Format(section => section?.Fiction); + SciMagArticles = Format(section => section?.SciMagArticles); + DownloadInto = Format(section => section?.DownloadInto); + ErrorWarningTitle = Format(section => section?.ErrorWarningTitle); + NoCollectionsSelected = Format(section => section?.NoCollectionsSelected); + } + + public string ChooseCollections { get; } + public string NonFiction { get; } + public string Fiction { get; } + public string SciMagArticles { get; } + public string DownloadInto { get; } + public string BrowseDirectoryDialogTitle { get; } + public string ErrorWarningTitle { get; } + public string NoCollectionsSelected { get; } + + public string GetDownloadSizeExactString(decimal size, string unit) => + Format(section => section?.DownloadSizeExact, new { size = $"{Formatter.ToFormattedString(size)} {unit}" }); + + public string GetDownloadSizeApproximateString(decimal size, string unit) => + Format(section => section?.DownloadSizeApproximate, new { size = $"{Formatter.ToFormattedString(size)} {unit}" }); + + public string GetDatabaseSizeString(decimal size, string unit) => + Format(section => section?.DatabaseSize, new { size = $"{Formatter.ToFormattedString(size)} {unit}" }); + + public string GetImportTimeInMinutesString(int from, int to) => + Format(section => section?.ImportTimeInMinutes, new { from = Formatter.ToFormattedString(from), to = Formatter.ToFormattedString(to) }); + + public string GetImportTimeInHoursString(decimal from, decimal to) => + Format(section => section?.ImportTimeInHours, new { from = Formatter.ToFormattedString(from), to = Formatter.ToFormattedString(to) }); + + public string GetDirectoryNotFoundString(string directory) => Format(section => section?.DirectoryNotFound, new { directory }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ConfirmationSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ConfirmationSetupStepLocalizator.cs new file mode 100644 index 0000000..67bd042 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ConfirmationSetupStepLocalizator.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class ConfirmationSetupStepLocalizator : Localizator + { + public ConfirmationSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.ConfirmationStep) + { + StepHeader = Format(section => section?.StepHeader); + SettingsHeader = Format(section => section?.SettingsHeader); + AllowInternetConnection = Format(section => section?.AllowInternetConnection); + UseDownloadManager = Format(section => section?.UseDownloadManager); + UseBrowser = Format(section => section?.UseBrowser); + YouCanChangeSettings = Format(section => section?.YouCanChangeSettings); + } + + public string StepHeader { get; } + public string SettingsHeader { get; } + public string AllowInternetConnection { get; } + public string UseDownloadManager { get; } + public string UseBrowser { get; } + public string YouCanChangeSettings { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CreateDatabaseSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CreateDatabaseSetupStepLocalizator.cs new file mode 100644 index 0000000..b7f6b30 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/CreateDatabaseSetupStepLocalizator.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class CreateDatabaseSetupStepLocalizator : Localizator + { + public CreateDatabaseSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.CreateDatabaseStep) + { + DatabaseFilePathPrompt = Format(section => section?.DatabaseFilePathPrompt); + DatabaseCreated = Format(section => section?.DatabaseCreated); + CannotCreateDatabase = Format(section => section?.CannotCreateDatabase); + SelectDatabaseFilePathDialogTitle = Format(section => section?.SelectDatabaseFilePathDialogTitle); + Databases = Format(section => section?.Databases); + AllFiles = Format(section => section?.AllFiles); + CreateDatabase = Format(section => section?.CreateDatabase); + CreatingDatabase = Format(section => section?.CreatingDatabase); + DatabaseFileOverwritePromptTitle = Format(section => section?.DatabaseFileOverwritePromptTitle); + } + + public string DatabaseFilePathPrompt { get; } + public string DatabaseCreated { get; } + public string CannotCreateDatabase { get; } + public string SelectDatabaseFilePathDialogTitle { get; } + public string Databases { get; } + public string AllFiles { get; } + public string CreateDatabase { get; } + public string CreatingDatabase { get; } + public string DatabaseFileOverwritePromptTitle { get; } + + public string GetDiskSpaceRequirementsNoteString(decimal sizeInGigabytes) => + Format(section => section?.DiskSpaceRequirementsNote, + new { size = $"{Formatter.ToFormattedString(sizeInGigabytes)} {Formatter.GigabytePostfix}" }); + + public string GetDatabaseFileOverwritePromptTextString(string file) => Format(section => section?.DatabaseFileOverwritePromptText, new { file }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DatabaseOperationSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DatabaseOperationSetupStepLocalizator.cs new file mode 100644 index 0000000..a771705 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DatabaseOperationSetupStepLocalizator.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class DatabaseOperationSetupStepLocalizator : Localizator + { + public DatabaseOperationSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.DatabaseOperationStep) + { + ChooseAction = Format(section => section?.ChooseAction); + CreateNewDatabase = Format(section => section?.CreateNewDatabase); + OpenExistingDatabase = Format(section => section?.OpenExistingDatabase); + } + + public string ChooseAction { get; } + public string CreateNewDatabase { get; } + public string OpenExistingDatabase { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpInfoSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpInfoSetupStepLocalizator.cs new file mode 100644 index 0000000..924bd22 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpInfoSetupStepLocalizator.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class DownloadDumpInfoSetupStepLocalizator : Localizator + { + public DownloadDumpInfoSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.DownloadDumpInfoStep) + { + DownloadingDumpInfo = Format(section => section?.DownloadingDumpInfo); + CannotDownloadDumpInfo = Format(section => section?.CannotDownloadDumpInfo); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + Retry = Format(section => section?.Retry); + } + + public string DownloadingDumpInfo { get; } + public string CannotDownloadDumpInfo { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string Retry { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpLinksSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpLinksSetupStepLocalizator.cs new file mode 100644 index 0000000..4b66343 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpLinksSetupStepLocalizator.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class DownloadDumpLinksSetupStepLocalizator : Localizator + { + public DownloadDumpLinksSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.DownloadDumpLinksStep) + { + OpenPage = Format(section => section?.OpenPage); + CopyLink = Format(section => section?.CopyLink); + DownloadFiles = Format(section => section?.DownloadFiles); + NonFictionDumpName = Format(section => section?.NonFictionDumpName); + FictionDumpName = Format(section => section?.FictionDumpName); + SciMagArticlesDumpName = Format(section => section?.SciMagArticlesDumpName); + YYYY = Format(section => section?.YYYY); + MM = Format(section => section?.MM); + DD = Format(section => section?.DD); + } + + public string OpenPage { get; } + public string CopyLink { get; } + public string DownloadFiles { get; } + public string NonFictionDumpName { get; } + public string FictionDumpName { get; } + public string SciMagArticlesDumpName { get; } + public string YYYY { get; } + public string MM { get; } + public string DD { get; } + + public string GetFileNameString(string file) => Format(section => section?.FileName, new { file }); + + public string GetMostRecentDateNoteString(string dateTemplate) => Format(section => section?.MostRecentDateNote, new { dateTemplate }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpsSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpsSetupStepLocalizator.cs new file mode 100644 index 0000000..e8c0344 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadDumpsSetupStepLocalizator.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class DownloadDumpsSetupStepLocalizator : Localizator + { + public DownloadDumpsSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.DownloadDumpsStep) + { + NonFictionDumpName = Format(section => section?.NonFictionDumpName); + FictionDumpName = Format(section => section?.FictionDumpName); + SciMagArticlesDumpName = Format(section => section?.SciMagArticlesDumpName); + QueuedStatus = Format(section => section?.QueuedStatus); + DownloadingStatus = Format(section => section?.DownloadingStatus); + StoppedStatus = Format(section => section?.StoppedStatus); + ErrorStatus = Format(section => section?.ErrorStatus); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + Retry = Format(section => section?.Retry); + } + + public string NonFictionDumpName { get; } + public string FictionDumpName { get; } + public string SciMagArticlesDumpName { get; } + public string QueuedStatus { get; } + public string DownloadingStatus { get; } + public string StoppedStatus { get; } + public string ErrorStatus { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string Retry { get; } + + public string GetDownloadProgress(long downloaded, long total, int percent) => + Format(section => section?.DownloadProgress, + new { downloaded = Formatter.ToFormattedString(downloaded), total = Formatter.ToFormattedString(total), + percent = Formatter.ToFormattedString(percent) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadModeSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadModeSetupStepLocalizator.cs new file mode 100644 index 0000000..3c570ca --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/DownloadModeSetupStepLocalizator.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class DownloadModeSetupStepLocalizator : Localizator + { + public DownloadModeSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.DownloadModeStep) + { + ChooseDownloadMode = Format(section => section?.ChooseDownloadMode); + DownloadManagerMode = Format(section => section?.DownloadManagerMode); + UseProxyServer = Format(section => section?.UseProxyServer); + ProxySettings = Format(section => section?.ProxySettings); + BrowserMode = Format(section => section?.BrowserMode); + } + + public string ChooseDownloadMode { get; } + public string DownloadManagerMode { get; } + public string UseProxyServer { get; } + public string ProxySettings { get; } + public string BrowserMode { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ImportDumpsSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ImportDumpsSetupStepLocalizator.cs new file mode 100644 index 0000000..1e24e72 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/ImportDumpsSetupStepLocalizator.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class ImportDumpsSetupStepLocalizator : Localizator + { + public ImportDumpsSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.ImportDumpsStep) + { + NonFictionDumpName = Format(section => section?.NonFictionDumpName); + FictionDumpName = Format(section => section?.FictionDumpName); + SciMagArticlesDumpName = Format(section => section?.SciMagArticlesDumpName); + NotImported = Format(section => section?.NotImported); + Importing = Format(section => section?.Importing); + ImportSuccessful = Format(section => section?.ImportSuccessful); + ImportCancelled = Format(section => section?.ImportCancelled); + ImportError = Format(section => section?.ImportError); + ImportButton = Format(section => section?.ImportButton); + ImportingButton = Format(section => section?.ImportingButton); + DeleteDumps = Format(section => section?.DeleteDumps); + } + + public string NonFictionDumpName { get; } + public string FictionDumpName { get; } + public string SciMagArticlesDumpName { get; } + public string NotImported { get; } + public string Importing { get; } + public string ImportSuccessful { get; } + public string ImportCancelled { get; } + public string ImportError { get; } + public string ImportButton { get; } + public string ImportingButton { get; } + public string DeleteDumps { get; } + + public string GetStatusString(string status) => Format(section => section?.Status, new { status }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/LanguageSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/LanguageSetupStepLocalizator.cs new file mode 100644 index 0000000..28a3698 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/LanguageSetupStepLocalizator.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class LanguageSetupStepLocalizator : Localizator + { + public LanguageSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.LanguageStep) + { + ChooseLanguage = Format(section => section?.ChooseLanguage); + } + + public string ChooseLanguage { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/SetupModeSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/SetupModeSetupStepLocalizator.cs new file mode 100644 index 0000000..669a868 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/SetupModeSetupStepLocalizator.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class SetupModeSetupStepLocalizator : Localizator + { + public SetupModeSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.SetupModeStep) + { + WelcomeAndChooseOption = Format(section => section?.WelcomeAndChooseOption); + FirstTimeUser = Format(section => section?.FirstTimeUser); + ExperiencedUser = Format(section => section?.ExperiencedUser); + } + + public string WelcomeAndChooseOption { get; } + public string FirstTimeUser { get; } + public string ExperiencedUser { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SetupSteps/StepListSetupStepLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/StepListSetupStepLocalizator.cs new file mode 100644 index 0000000..8b0f834 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/SetupSteps/StepListSetupStepLocalizator.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.SetupSteps +{ + internal class StepListSetupStepLocalizator : Localizator + { + public StepListSetupStepLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.StepListStep) + { + StepListHeader = Format(section => section?.StepListHeader); + DownloadingDumps = Format(section => section?.DownloadingDumps); + CreatingDatabase = Format(section => section?.CreatingDatabase); + ImportingDumps = Format(section => section?.ImportingDumps); + ClickNextButton = Format(section => section?.ClickNextButton); + } + + public string StepListHeader { get; } + public string DownloadingDumps { get; } + public string CreatingDatabase { get; } + public string ImportingDumps { get; } + public string ClickNextButton { get; } + + public string GetStepString(int step) => Format(section => section?.Step, new { step = Formatter.ToDecimalFormattedString(step) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/SqlDebuggerWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SqlDebuggerWindowLocalizator.cs deleted file mode 100644 index 0c7e8f4..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SqlDebuggerWindowLocalizator.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SqlDebuggerWindowLocalizator : Localizator - { - public SqlDebuggerWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - SqlQueryTextBoxHeader = Format(translation => translation?.SqlQueryTextBoxHeader); - Copy = Format(translation => translation?.Copy); - Close = Format(translation => translation?.Close); - } - - public string WindowTitle { get; } - public string SqlQueryTextBoxHeader { get; } - public string Copy { get; } - public string Close { get; } - - private string Format(Func field) - { - return Format(translation => field(translation?.SqlDebugger)); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/SynchronizationLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/SynchronizationLocalizator.cs deleted file mode 100644 index 1a1370d..0000000 --- a/LibgenDesktop/Models/Localization/Localizators/SynchronizationLocalizator.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace LibgenDesktop.Models.Localization.Localizators -{ - internal class SynchronizationLocalizator : Localizator - { - public SynchronizationLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) - : base(prioritizedTranslationList, formatter) - { - WindowTitle = Format(translation => translation?.WindowTitle); - ErrorMessageTitle = Format(translation => translation?.ErrorMessageTitle); - ImportRequired = Format(translation => translation?.ImportRequired); - NoSynchronizationMirror = Format(translation => translation?.NoSynchronizationMirror); - OfflineModePromptTitle = Format(translation => translation?.OfflineModePromptTitle); - OfflineModePromptText = Format(translation => translation?.OfflineModePromptText); - Unknown = Format(translation => translation?.Unknown); - Interrupt = Format(translation => translation?.Interrupt); - Interrupting = Format(translation => translation?.Interrupting); - Close = Format(translation => translation?.Close); - StatusPreparation = FormatStatus(translation => translation?.Preparation); - StatusCreatingIndexes = FormatStatus(translation => translation?.CreatingIndexes); - StatusLoadingIds = FormatStatus(translation => translation?.LoadingIds); - StatusSynchronizingData = FormatStatus(translation => translation?.SynchronizingData); - StatusSynchronizationComplete = FormatStatus(translation => translation?.SynchronizationComplete); - StatusSynchronizationCancelled = FormatStatus(translation => translation?.SynchronizationCancelled); - StatusSynchronizationError = FormatStatus(translation => translation?.SynchronizationError); - LogLineCreatingIndexes = FormatLogLine(translation => translation?.CreatingIndexes); - LogLineLoadingIds = FormatLogLine(translation => translation?.LoadingIds); - LogLineSynchronizingBookList = FormatLogLine(translation => translation?.SynchronizingBookList); - LogLineDownloadingNewBooks = FormatLogLine(translation => translation?.DownloadingNewBooks); - LogLineSynchronizationSuccessful = FormatLogLine(translation => translation?.SynchronizationSuccessful); - LogLineInsufficientDiskSpace = FormatLogLine(translation => translation?.InsufficientDiskSpace); - LogLineSynchronizationCancelled = FormatLogLine(translation => translation?.SynchronizationCancelled); - } - - public string WindowTitle { get; } - public string ErrorMessageTitle { get; } - public string ImportRequired { get; } - public string NoSynchronizationMirror { get; } - public string OfflineModePromptTitle { get; } - public string OfflineModePromptText { get; } - public string Unknown { get; set; } - public string Interrupt { get; } - public string Interrupting { get; } - public string Close { get; } - public string StatusPreparation { get; set; } - public string StatusCreatingIndexes { get; set; } - public string StatusLoadingIds { get; set; } - public string StatusSynchronizingData { get; set; } - public string StatusSynchronizationComplete { get; set; } - public string StatusSynchronizationCancelled { get; set; } - public string StatusSynchronizationError { get; set; } - public string LogLineCreatingIndexes { get; set; } - public string LogLineLoadingIds { get; set; } - public string LogLineSynchronizingBookList { get; set; } - public string LogLineDownloadingNewBooks { get; set; } - public string LogLineSynchronizationSuccessful { get; set; } - public string LogLineInsufficientDiskSpace { get; } - public string LogLineSynchronizationCancelled { get; set; } - - public string GetElapsedString(string elapsed) => Format(translation => translation?.Elapsed, new { elapsed }); - public string GetFreeSpaceString(string freeSpace) => Format(translation => translation?.FreeSpace, new { freeSpace }); - public string GetStatusStep(int current, int total) => FormatStatus(translation => translation?.Step, new { current, total }); - public string GetLogLineStep(int step) => FormatLogLine(translation => translation?.Step, new { step }); - public string GetLogLineCreatingIndexForColumn(string column) => FormatLogLine(translation => translation?.CreatingIndexForColumn, new { column }); - public string GetLogLineLoadingColumnValues(string column) => FormatLogLine(translation => translation?.LoadingColumnValues, new { column }); - public string GetLogLineSynchronizationProgressNoAddedNoUpdated(int downloaded) => - FormatLogLine(translation => translation?.SynchronizationProgressNoAddedNoUpdated, new { downloaded }); - public string GetLogLineSynchronizationProgressAdded(int downloaded, int added) => - FormatLogLine(translation => translation?.SynchronizationProgressAdded, new { downloaded, added }); - public string GetLogLineSynchronizationProgressUpdated(int downloaded, int updated) => - FormatLogLine(translation => translation?.SynchronizationProgressUpdated, new { downloaded, updated }); - public string GetLogLineSynchronizationProgressAddedAndUpdated(int downloaded, int added, int updated) => - FormatLogLine(translation => translation?.SynchronizationProgressAddedAndUpdated, new { downloaded, added, updated }); - public string GetLogLineSynchronizationError(string error) => FormatLogLine(translation => translation?.SynchronizationError, new { error }); - - private string Format(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Synchronization), templateArguments); - } - - private string FormatStatus(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Synchronization?.StatusMessages), templateArguments); - } - - private string FormatLogLine(Func field, object templateArguments = null) - { - return Format(translation => field(translation?.Synchronization?.LogMessages), templateArguments); - } - } -} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/CommonDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/CommonDetailsTabLocalizator.cs new file mode 100644 index 0000000..5dfe6f7 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/CommonDetailsTabLocalizator.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class CommonDetailsTabLocalizator : DetailsTabLocalizator + { + public CommonDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.DetailsTabs) + { + CoverIsLoading = Format(section => section?.CoverIsLoading); + NoCover = Format(section => section?.NoCover); + NoCoverMirror = Format(section => section?.NoCoverMirror); + NoCoverDueToOfflineMode = Format(section => section?.NoCoverDueToOfflineMode); + CoverLoadingError = Format(section => section?.CoverLoadingError); + Download = Format(section => section?.Download); + Queued = Format(section => section?.Queued); + Downloading = Format(section => section?.Downloading); + Stopped = Format(section => section?.Stopped); + Error = Format(section => section?.Error); + Open = Format(section => section?.Open); + ErrorMessageTitle = Format(section => section?.ErrorMessageTitle); + NoDownloadMirrorTooltip = Format(section => section?.NoDownloadMirrorTooltip); + OfflineModeIsOnTooltip = Format(section => section?.OfflineModeIsOnTooltip); + } + + public string CoverIsLoading { get; } + public string NoCover { get; } + public string NoCoverMirror { get; } + public string NoCoverDueToOfflineMode { get; } + public string CoverLoadingError { get; } + public string Download { get; } + public string Queued { get; } + public string Downloading { get; } + public string Stopped { get; } + public string Error { get; } + public string Open { get; } + public string ErrorMessageTitle { get; } + public string NoDownloadMirrorTooltip { get; } + public string OfflineModeIsOnTooltip { get; } + + public string GetDownloadFromMirrorText(string mirror) => Format(section => section?.DownloadFromMirror, new { mirror }); + + public string GetFileNotFoundErrorText(string file) => Format(section => section?.FileNotFoundError, new { file }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/DetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/DetailsTabLocalizator.cs new file mode 100644 index 0000000..ae3dc1d --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/DetailsTabLocalizator.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal abstract class DetailsTabLocalizator : Localizator where T : class + { + private readonly Func detailsTabTranslationSectionSelector; + + public DetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter, + Func detailsTabTranslationSectionSelector) + : base(prioritizedTranslationList, formatter, translation => translation?.DetailsTabs) + { + this.detailsTabTranslationSectionSelector = detailsTabTranslationSectionSelector; + CopyContextMenu = Format(section => section?.CopyContextMenu).Replace("{text}", "{0}"); + Close = Format(section => section?.Close); + Yes = Format(section => section?.Yes); + No = Format(section => section?.No); + Unknown = Format(section => section?.Unknown); + Portrait = Format(section => section?.Portrait); + Landscape = Format(section => section?.Landscape); + } + + public string CopyContextMenu { get; } + public string Close { get; } + protected string Yes { get; } + protected string No { get; } + protected string Unknown { get; } + protected string Portrait { get; } + protected string Landscape { get; } + + protected string StringBooleanToYesNoUnknownString(string value) => StringBooleanToLabelString(value, Yes, No, Unknown); + + protected string StringBooleanToOrientationString(string value) => StringBooleanToLabelString(value, Portrait, Landscape, Unknown); + + protected string Format(Func detailsTabTranslationSectionFieldSelector, object templateArguments = null) => + Format(translation => detailsTabTranslationSectionFieldSelector(detailsTabTranslationSectionSelector(translation)), templateArguments); + + protected string FormatHeader(Func detailsTabTranslationSectionFieldSelector) => + Format(detailsTabTranslationSectionFieldSelector) + ":"; + + private static string StringBooleanToLabelString(string value, string value1Label, string value0Label, string valueUnknownLabel) + { + switch (value) + { + case "0": + return value0Label; + case "1": + return value1Label; + default: + return valueUnknownLabel; + } + } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/DownloadManagerTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/DownloadManagerTabLocalizator.cs new file mode 100644 index 0000000..adf37a5 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/DownloadManagerTabLocalizator.cs @@ -0,0 +1,132 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class DownloadManagerTabLocalizator : Localizator + { + public DownloadManagerTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.DownloadManager) + { + TabTitle = Format(section => section?.TabTitle); + Start = Format(section => section?.Start); + Stop = Format(section => section?.Stop); + Remove = Format(section => section?.Remove); + StartAll = Format(section => section?.StartAll); + StopAll = Format(section => section?.StopAll); + RemoveCompleted = Format(section => section?.RemoveCompleted); + QueuedStatus = Format(section => section?.QueuedStatus); + DownloadingStatus = Format(section => section?.DownloadingStatus); + StoppedStatus = Format(section => section?.StoppedStatus); + RetryDelayStatus = Format(section => section?.RetryDelayStatus); + ErrorStatus = Format(section => section?.ErrorStatus); + Log = Format(section => section?.Log); + TechnicalDetails = Format(section => section?.TechnicalDetails); + Copy = Format(section => section?.Copy); + FileNotFoundErrorTitle = Format(section => section?.FileNotFoundErrorTitle); + LogLineQueued = Format(section => section?.LogMessages?.Queued); + LogLineStarted = Format(section => section?.LogMessages?.Started); + LogLineStopped = Format(section => section?.LogMessages?.Stopped); + LogLineCompleted = Format(section => section?.LogMessages?.Completed); + LogLineOfflineModeIsOn = Format(section => section?.LogMessages?.OfflineModeIsOn); + LogLineMaximumDownloadAttempts = Format(section => section?.LogMessages?.MaximumDownloadAttempts); + LogLineStartingFileDownloadUnknownFileSize = Format(section => section?.LogMessages?.StartingFileDownloadUnknownFileSize); + LogLineResumingFileDownloadUnknownFileSize = Format(section => section?.LogMessages?.ResumingFileDownloadUnknownFileSize); + LogLineRequest = Format(section => section?.LogMessages?.Request); + LogLineResponse = Format(section => section?.LogMessages?.Response); + LogLineTooManyRedirects = Format(section => section?.LogMessages?.TooManyRedirects); + LogLineHtmlPageReturned = Format(section => section?.LogMessages?.HtmlPageReturned); + LogLineNoPartialDownloadSupport = Format(section => section?.LogMessages?.NoPartialDownloadSupport); + LogLineNoContentLengthWarning = Format(section => section?.LogMessages?.NoContentLengthWarning); + LogLineServerResponseTimeout = Format(section => section?.LogMessages?.ServerResponseTimeout); + LogLineDownloadIncompleteError = Format(section => section?.LogMessages?.DownloadIncompleteError); + LogLineFileWriteError = Format(section => section?.LogMessages?.FileWriteError); + } + + public string TabTitle { get; } + public string Start { get; } + public string Stop { get; } + public string Remove { get; } + public string StartAll { get; } + public string StopAll { get; } + public string RemoveCompleted { get; } + public string QueuedStatus { get; } + public string DownloadingStatus { get; } + public string StoppedStatus { get; } + public string RetryDelayStatus { get; } + public string ErrorStatus { get; } + public string Log { get; } + public string TechnicalDetails { get; } + public string Copy { get; } + public string FileNotFoundErrorTitle { get; } + public string LogLineQueued { get; } + public string LogLineStarted { get; } + public string LogLineStopped { get; } + public string LogLineCompleted { get; } + public string LogLineOfflineModeIsOn { get; } + public string LogLineMaximumDownloadAttempts { get; } + public string LogLineStartingFileDownloadUnknownFileSize { get; } + public string LogLineResumingFileDownloadUnknownFileSize { get; } + public string LogLineRequest { get; } + public string LogLineResponse { get; } + public string LogLineTooManyRedirects { get; } + public string LogLineHtmlPageReturned { get; } + public string LogLineNoPartialDownloadSupport { get; } + public string LogLineNoContentLengthWarning { get; } + public string LogLineServerResponseTimeout { get; } + public string LogLineDownloadIncompleteError { get; } + public string LogLineFileWriteError { get; } + + public string GetDownloadProgressKnownFileSize(long downloaded, long total, int percent) => + Format(section => section?.DownloadProgressKnownFileSize, + new { downloaded = Formatter.ToFormattedString(downloaded), total = Formatter.ToFormattedString(total), + percent = Formatter.ToFormattedString(percent) }); + + public string GetDownloadProgressUnknownFileSize(long downloaded) => + Format(section => section?.DownloadProgressUnknownFileSize, new { downloaded = Formatter.ToFormattedString(downloaded) }); + + public string GetFileNotFoundErrorText(string file) => Format(section => section?.FileNotFoundErrorText, new { file }); + + public string GetLogLineRetryDelay(int count) => + Format(section => section?.LogMessages?.RetryDelay, new { count = Formatter.ToFormattedString(count) }); + + public string GetLogLineTransformationError(string transformation) => + Format(section => section?.LogMessages?.TransformationError, new { transformation }); + + public string GetLogLineTransformationReturnedIncorrectUrl(string transformation) => + Format(section => section?.LogMessages?.TransformationReturnedIncorrectUrl, new { transformation }); + + public string GetLogLineAttempt(int current, int total) => + Format(section => section?.LogMessages?.Attempt, + new { current = Formatter.ToFormattedString(current), total = Formatter.ToFormattedString(total) }); + + public string GetLogLineDownloadingPage(string url) => Format(section => section?.LogMessages?.DownloadingPage, new { url }); + + public string GetLogLineDownloadingFile(string url) => Format(section => section?.LogMessages?.DownloadingFile, new { url }); + + public string GetLogLineStartingFileDownloadKnownFileSize(long size) => + Format(section => section?.LogMessages?.StartingFileDownloadKnownFileSize, new { size = Formatter.ToFormattedString(size) }); + + public string GetLogLineResumingFileDownloadKnownFileSize(long remaining) => + Format(section => section?.LogMessages?.ResumingFileDownloadKnownFileSize, new { remaining = Formatter.ToFormattedString(remaining) }); + + public string GetLogLineRedirect(string url) => Format(section => section?.LogMessages?.Redirect, new { url }); + + public string GetLogLineNonSuccessfulStatusCode(string status) => + Format(section => section?.LogMessages?.NonSuccessfulStatusCode, new { status }); + + public string GetLogLineCannotCreateDownloadDirectory(string directory) => + Format(section => section?.LogMessages?.CannotCreateDownloadDirectory, new { directory }); + + public string GetLogLineCannotCreateOrOpenFile(string file) => + Format(section => section?.LogMessages?.CannotCreateOrOpenFile, new { file }); + + public string GetLogLineCannotRenamePartFile(string source, string destination) => + Format(section => section?.LogMessages?.CannotRenamePartFile, new { source, destination }); + + public string GetLogLineRequestError(string url) => Format(section => section?.LogMessages?.LogLineRequestError, new { url }); + + public string GetLogLineIncorrectRedirectUrl(string url) => Format(section => section?.LogMessages?.IncorrectRedirectUrl, new { url }); + + public string GetLogLineUnexpectedError(string error) => Format(section => section?.LogMessages?.UnexpectedError, new { error }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionDetailsTabLocalizator.cs new file mode 100644 index 0000000..8ed1430 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionDetailsTabLocalizator.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class FictionDetailsTabLocalizator : DetailsTabLocalizator + { + public FictionDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.FictionDetailsTab) + { + Title = FormatHeader(section => section?.Title); + Authors = FormatHeader(section => section?.Authors); + Series = FormatHeader(section => section?.Series); + Publisher = FormatHeader(section => section?.Publisher); + Edition = FormatHeader(section => section?.Edition); + Year = FormatHeader(section => section?.Year); + Language = FormatHeader(section => section?.Language); + FormatLabel = FormatHeader(section => section?.Format); + Pages = FormatHeader(section => section?.Pages); + FileSize = FormatHeader(section => section?.FileSize); + Library = FormatHeader(section => section?.Library); + Issue = FormatHeader(section => section?.Issue); + Added = FormatHeader(section => section?.Added); + LastModified = FormatHeader(section => section?.LastModified); + Md5Hash = FormatHeader(section => section?.Md5Hash); + Comments = FormatHeader(section => section?.Comments); + Identifiers = FormatHeader(section => section?.Identifiers); + LibgenId = FormatHeader(section => section?.LibgenId); + Isbn = FormatHeader(section => section?.Isbn); + GoogleBookId = FormatHeader(section => section?.GoogleBookId); + Asin = FormatHeader(section => section?.Asin); + } + + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Publisher { get; } + public string Edition { get; } + public string Year { get; } + public string Language { get; } + public string FormatLabel { get; } + public string Pages { get; } + public string FileSize { get; } + public string Library { get; } + public string Issue { get; } + public string Added { get; } + public string LastModified { get; } + public string Md5Hash { get; } + public string Comments { get; } + public string Identifiers { get; } + public string LibgenId { get; } + public string Isbn { get; } + public string GoogleBookId { get; } + public string Asin { get; } + + public static string GetYearString(string value) => value != "0" ? value : String.Empty; + + public string GetPagesString(string value) => value != "0" ? value : Unknown; + + public string GetLastModifiedDateTimeString(DateTime? value) => value.HasValue ? Formatter.ToFormattedDateTimeString(value.Value) : Unknown; + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionSearchResultsTabLocalizator.cs new file mode 100644 index 0000000..623a82c --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/FictionSearchResultsTabLocalizator.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using LibgenDesktop.Models.Localization.Localizators.SearchResultGrids; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class FictionSearchResultsTabLocalizator : SearchResultsTabLocalizator + { + public FictionSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.FictionSearchResultsTab) + { + SearchBoxTooltip = Format(section => section?.SearchBoxTooltip); + Columns = new FictionSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); + } + + public string SearchBoxTooltip { get; } + public FictionSearchResultsGridColumnsLocalizator Columns { get; } + + public string GetSearchProgressText(int count) => Format(section => section?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); + + public string GetStatusBarText(int count) => Format(section => section?.StatusBar, new { count = Formatter.ToFormattedString(count) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/LibraryTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/LibraryTabLocalizator.cs new file mode 100644 index 0000000..c1f897e --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/LibraryTabLocalizator.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class LibraryTabLocalizator : Localizator + { + public LibraryTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Library) + { + TabTitle = Format(section => section?.TabTitle); + ScanNonFiction = Format(section => section?.ScanNonFiction); + ScanFiction = Format(section => section?.ScanFiction); + ScanSciMag = Format(section => section?.ScanSciMag); + BrowseDirectoryDialogTitle = Format(section => section?.BrowseDirectoryDialogTitle); + CreatingIndexes = Format(section => section?.CreatingIndexes); + ScanLog = Format(section => section?.ScanLog); + AddAll = Format(section => section?.AddAll); + Adding = Format(section => section?.Adding); + Added = Format(section => section?.Added); + Error = Format(section => section?.Error); + ColumnsFile = Format(section => section?.File); + ColumnsAuthors = Format(section => section?.Authors); + ColumnsTitle = Format(section => section?.Title); + } + + public string TabTitle { get; } + public string ScanNonFiction { get; } + public string ScanFiction { get; } + public string ScanSciMag { get; } + public string BrowseDirectoryDialogTitle { get; } + public string CreatingIndexes { get; } + public string AddAll { get; } + public string Adding { get; } + public string Added { get; } + public string ScanLog { get; } + public string Error { get; } + public string ColumnsFile { get; } + public string ColumnsAuthors { get; } + public string ColumnsTitle { get; } + + public string GetScanStartedString(string directory) => Format(section => section?.ScanStarted, new { directory }); + + public string GetFoundString(int count) => Format(section => section?.Found, new { count = Formatter.ToFormattedString(count) }); + + public string GetNotFoundString(int count) => Format(section => section?.NotFound, new { count = Formatter.ToFormattedString(count) }); + + public string GetScanCompleteString(int found, int notFound, int errors) => Format(section => section?.ScanComplete, + new { found = Formatter.ToFormattedString(found), notFound = Formatter.ToFormattedString(notFound), + errors = Formatter.ToFormattedString(errors) }); + + private string Format(Func field, object templateArguments = null) + { + return Format(translation => field(translation?.Library?.Columns), templateArguments); + } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionDetailsTabLocalizator.cs new file mode 100644 index 0000000..920a14b --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionDetailsTabLocalizator.cs @@ -0,0 +1,132 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class NonFictionDetailsTabLocalizator : DetailsTabLocalizator + { + public NonFictionDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.NonFictionDetailsTab) + { + Title = FormatHeader(section => section?.Title); + Authors = FormatHeader(section => section?.Authors); + Series = FormatHeader(section => section?.Series); + Publisher = FormatHeader(section => section?.Publisher); + Year = FormatHeader(section => section?.Year); + Language = FormatHeader(section => section?.Language); + FormatLabel = FormatHeader(section => section?.Format); + Isbn = FormatHeader(section => section?.Isbn); + Added = FormatHeader(section => section?.Added); + LastModified = FormatHeader(section => section?.LastModified); + Library = FormatHeader(section => section?.Library); + FileSize = FormatHeader(section => section?.FileSize); + Topics = FormatHeader(section => section?.Topics); + Volume = FormatHeader(section => section?.Volume); + Magazine = FormatHeader(section => section?.Magazine); + City = FormatHeader(section => section?.City); + Edition = FormatHeader(section => section?.Edition); + Pages = FormatHeader(section => section?.Pages); + Tags = FormatHeader(section => section?.Tags); + Md5Hash = FormatHeader(section => section?.Md5Hash); + Comments = FormatHeader(section => section?.Comments); + Identifiers = FormatHeader(section => section?.Identifiers); + LibgenId = FormatHeader(section => section?.LibgenId); + Issn = FormatHeader(section => section?.Issn); + Udc = FormatHeader(section => section?.Udc); + Lbc = FormatHeader(section => section?.Lbc); + Lcc = FormatHeader(section => section?.Lcc); + Ddc = FormatHeader(section => section?.Ddc); + Doi = FormatHeader(section => section?.Doi); + OpenLibraryId = FormatHeader(section => section?.OpenLibraryId); + GoogleBookId = FormatHeader(section => section?.GoogleBookId); + Asin = FormatHeader(section => section?.Asin); + AdditionalAttributes = FormatHeader(section => section?.AdditionalAttributes); + Dpi = FormatHeader(section => section?.Dpi); + Ocr = FormatHeader(section => section?.Ocr); + TableOfContents = FormatHeader(section => section?.TableOfContents); + Scanned = FormatHeader(section => section?.Scanned); + Orientation = FormatHeader(section => section?.Orientation); + Paginated = FormatHeader(section => section?.Paginated); + Colored = FormatHeader(section => section?.Colored); + Cleaned = FormatHeader(section => section?.Cleaned); + } + + public string Title { get; } + public string Authors { get; } + public string Series { get; } + public string Publisher { get; } + public string Year { get; } + public string Language { get; } + public string FormatLabel { get; } + public string Isbn { get; } + public string Added { get; } + public string LastModified { get; } + public string Library { get; } + public string FileSize { get; } + public string Topics { get; } + public string Volume { get; } + public string Magazine { get; } + public string City { get; } + public string Edition { get; } + public string Pages { get; } + public string Tags { get; } + public string Md5Hash { get; } + public string Comments { get; } + public string Identifiers { get; } + public string LibgenId { get; } + public string Issn { get; } + public string Udc { get; } + public string Lbc { get; } + public string Lcc { get; } + public string Ddc { get; } + public string Doi { get; } + public string OpenLibraryId { get; } + public string GoogleBookId { get; } + public string Asin { get; } + public string AdditionalAttributes { get; } + public string Dpi { get; } + public string Ocr { get; } + public string TableOfContents { get; } + public string Scanned { get; } + public string Orientation { get; } + public string Paginated { get; } + public string Colored { get; } + public string Cleaned { get; } + + public string GetPagesText(string bodyMatterPages, int totalPages) + { + StringBuilder resultBuilder = new StringBuilder(); + if (!String.IsNullOrWhiteSpace(bodyMatterPages)) + { + resultBuilder.Append(bodyMatterPages); + } + else + { + resultBuilder.Append(Unknown); + } + resultBuilder.Append(" ("); + resultBuilder.Append(Format(section => section?.BodyMatterPages)); + resultBuilder.Append(") / "); + resultBuilder.Append(Formatter.ToFormattedString(totalPages)); + resultBuilder.Append(" ("); + resultBuilder.Append(Format(section => section?.TotalPages)); + resultBuilder.Append(")"); + return resultBuilder.ToString(); + } + + public string GetOcrString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetBookmarkedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetScannedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetOrientationString(string value) => StringBooleanToOrientationString(value); + + public string GetPaginatedString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetColorString(string value) => StringBooleanToYesNoUnknownString(value); + + public string GetCleanedString(string value) => StringBooleanToYesNoUnknownString(value); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionSearchResultsTabLocalizator.cs new file mode 100644 index 0000000..acd6a03 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/NonFictionSearchResultsTabLocalizator.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using LibgenDesktop.Models.Localization.Localizators.SearchResultGrids; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class NonFictionSearchResultsTabLocalizator : SearchResultsTabLocalizator + { + public NonFictionSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.NonFictionSearchResultsTab) + { + SearchBoxTooltip = Format(section => section?.SearchBoxTooltip); + Columns = new NonFictionSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); + } + + public string SearchBoxTooltip { get; } + public NonFictionSearchResultsGridColumnsLocalizator Columns { get; } + + public string GetSearchProgressText(int count) => Format(section => section?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); + + public string GetStatusBarText(int count) => Format(section => section?.StatusBar, new { count = Formatter.ToFormattedString(count) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagDetailsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagDetailsTabLocalizator.cs new file mode 100644 index 0000000..8c4bb4d --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagDetailsTabLocalizator.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class SciMagDetailsTabLocalizator : DetailsTabLocalizator + { + public SciMagDetailsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SciMagDetailsTab) + { + Title = FormatHeader(section => section?.Title); + Authors = FormatHeader(section => section?.Authors); + Magazine = FormatHeader(section => section?.Magazine); + Year = FormatHeader(section => section?.Year); + Month = FormatHeader(section => section?.Month); + Day = FormatHeader(section => section?.Day); + Volume = FormatHeader(section => section?.Volume); + Issue = FormatHeader(section => section?.Issue); + Pages = FormatHeader(section => section?.Pages); + FileSize = FormatHeader(section => section?.FileSize); + AddedDateTime = FormatHeader(section => section?.AddedDateTime); + Md5Hash = FormatHeader(section => section?.Md5Hash); + AbstractUrl = FormatHeader(section => section?.AbstractUrl); + Identifiers = FormatHeader(section => section?.Identifiers); + LibgenId = FormatHeader(section => section?.LibgenId); + Doi = FormatHeader(section => section?.Doi); + Isbn = FormatHeader(section => section?.Isbn); + MagazineId = FormatHeader(section => section?.MagazineId); + Issnp = FormatHeader(section => section?.Issnp); + Issne = FormatHeader(section => section?.Issne); + PubmedId = FormatHeader(section => section?.PubmedId); + Pmc = FormatHeader(section => section?.Pmc); + Pii = FormatHeader(section => section?.Pii); + AdditionalAttributes = FormatHeader(section => section?.AdditionalAttributes); + Attribute1 = FormatHeader(section => section?.Attribute1); + Attribute2 = FormatHeader(section => section?.Attribute2); + Attribute3 = FormatHeader(section => section?.Attribute3); + Attribute4 = FormatHeader(section => section?.Attribute4); + Attribute5 = FormatHeader(section => section?.Attribute5); + Attribute6 = FormatHeader(section => section?.Attribute6); + } + + public string Title { get; } + public string Authors { get; } + public string Magazine { get; } + public string Year { get; } + public string Month { get; } + public string Day { get; } + public string Volume { get; } + public string Issue { get; } + public string Pages { get; } + public string FileSize { get; } + public string AddedDateTime { get; } + public string Md5Hash { get; } + public string AbstractUrl { get; } + public string Identifiers { get; } + public string LibgenId { get; } + public string Doi { get; } + public string Isbn { get; } + public string MagazineId { get; } + public string Issnp { get; } + public string Issne { get; } + public string PubmedId { get; } + public string Pmc { get; } + public string Pii { get; } + public string AdditionalAttributes { get; } + public string Attribute1 { get; } + public string Attribute2 { get; } + public string Attribute3 { get; } + public string Attribute4 { get; } + public string Attribute5 { get; } + public string Attribute6 { get; } + + public string GetPagesString(string firstPage, string lastPage) + { + if ((!String.IsNullOrWhiteSpace(firstPage) && firstPage != "0") || (!String.IsNullOrWhiteSpace(lastPage) && lastPage != "0")) + { + firstPage = firstPage != "0" ? firstPage.Trim() + " " : String.Empty; + lastPage = lastPage != "0" ? " " + lastPage.Trim() : String.Empty; + return firstPage + "–" + lastPage; + } + else + { + return Unknown; + } + } + + public string GetAddedDateTimeString(DateTime? value) => value.HasValue ? Formatter.ToFormattedDateTimeString(value.Value) : Unknown; + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagSearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagSearchResultsTabLocalizator.cs new file mode 100644 index 0000000..61e435d --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/SciMagSearchResultsTabLocalizator.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using LibgenDesktop.Models.Localization.Localizators.SearchResultGrids; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class SciMagSearchResultsTabLocalizator : SearchResultsTabLocalizator + { + public SciMagSearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SciMagSearchResultsTab) + { + SearchBoxTooltip = Format(section => section?.SearchBoxTooltip); + Columns = new SciMagSearchResultsGridColumnsLocalizator(prioritizedTranslationList, formatter); + } + + public string SearchBoxTooltip { get; } + public SciMagSearchResultsGridColumnsLocalizator Columns { get; } + + public string GetSearchProgressText(int count) => Format(section => section?.SearchProgress, new { count = Formatter.ToFormattedString(count) }); + + public string GetStatusBarText(int count) => Format(section => section?.StatusBar, new { count = Formatter.ToFormattedString(count) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchResultsTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchResultsTabLocalizator.cs new file mode 100644 index 0000000..c0d5da4 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchResultsTabLocalizator.cs @@ -0,0 +1,66 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal abstract class SearchResultsTabLocalizator : Localizator + { + public SearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SearchResultsTabs) + { + SearchPlaceHolder = Format(section => section?.SearchPlaceHolder); + SearchInProgress = Format(section => section?.SearchInProgress); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + AddToBookmarksTooltip = Format(section => section?.AddToBookmarksTooltip); + RemoveFromBookmarksTooltip = Format(section => section?.RemoveFromBookmarksTooltip); + ExportButtonTooltip = Format(section => section?.ExportButtonTooltip); + Details = Format(section => section?.Details); + Open = Format(section => section?.Open); + Download = Format(section => section?.Download); + Copy = Format(section => section?.Copy); + ErrorMessageTitle = Format(section => section?.ErrorMessageTitle); + OfflineModeIsOnMessageTitle = Format(section => section?.OfflineModeIsOnMessageTitle); + OfflineModeIsOnMessageText = Format(section => section?.OfflineModeIsOnMessageText); + NoDownloadMirrorError = Format(section => section?.NoDownloadMirrorError); + LargeNumberOfItemsToDownloadPromptTitle = Format(section => section?.LargeNumberOfItemsToDownloadPromptTitle); + } + + public string SearchPlaceHolder { get; } + public string SearchInProgress { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string AddToBookmarksTooltip { get; } + public string RemoveFromBookmarksTooltip { get; } + public string ExportButtonTooltip { get; } + public string Details { get; } + public string Open { get; } + public string Download { get; } + public string Copy { get; } + public string ErrorMessageTitle { get; } + public string OfflineModeIsOnMessageTitle { get; } + public string OfflineModeIsOnMessageText { get; } + public string NoDownloadMirrorError { get; } + public string LargeNumberOfItemsToDownloadPromptTitle { get; } + + public string GetFileNotFoundErrorText(string file) => Format(section => section?.FileNotFoundError, new { file }); + + public string GetLargeNumberOfItemsToDownloadPromptText(int number) => + Format(section => section?.LargeNumberOfItemsToDownloadPromptText, new { number = Formatter.ToFormattedString(number) }); + } + + internal abstract class SearchResultsTabLocalizator : SearchResultsTabLocalizator where T : class + { + private readonly Func searchResultsTabTranslationSectionSelector; + + public SearchResultsTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter, + Func searchResultsTabTranslationSectionSelector) + : base(prioritizedTranslationList, formatter) + { + this.searchResultsTabTranslationSectionSelector = searchResultsTabTranslationSectionSelector; + } + + protected string Format(Func searchResultsTranslationSectionFieldSelector, object templateArguments = null) => + Format(translation => searchResultsTranslationSectionFieldSelector(searchResultsTabTranslationSectionSelector(translation)), templateArguments); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchTabLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchTabLocalizator.cs new file mode 100644 index 0000000..03f294f --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Tabs/SearchTabLocalizator.cs @@ -0,0 +1,49 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Tabs +{ + internal class SearchTabLocalizator : Localizator + { + public SearchTabLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SearchTab) + { + TabTitle = Format(section => section?.TabTitle); + NonFictionSelector = Format(section => section?.NonFictionSelector); + SearchPlaceHolder = Format(section => section?.SearchPlaceHolder); + NonFictionSelector = Format(section => section?.NonFictionSelector); + FictionSelector = Format(section => section?.FictionSelector); + SciMagSelector = Format(section => section?.SciMagSelector); + NonFictionSearchBoxTooltip = Format(section => section?.NonFictionSearchBoxTooltip); + FictionSearchBoxTooltip = Format(section => section?.FictionSearchBoxTooltip); + SciMagSearchBoxTooltip = Format(section => section?.SciMagSearchBoxTooltip); + SearchInProgress = Format(section => section?.SearchInProgress); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + DatabaseIsEmpty = Format(section => section?.DatabaseIsEmpty); + ImportButton = Format(section => section?.ImportButton); + } + + public string TabTitle { get; } + public string SearchPlaceHolder { get; } + public string NonFictionSelector { get; } + public string FictionSelector { get; } + public string SciMagSelector { get; } + public string NonFictionSearchBoxTooltip { get; } + public string FictionSearchBoxTooltip { get; } + public string SciMagSearchBoxTooltip { get; } + public string SearchInProgress { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string DatabaseIsEmpty { get; } + public string ImportButton { get; } + + public string GetNonFictionSearchProgressText(int count) => + Format(section => section?.NonFictionSearchProgress, new { count = Formatter.ToFormattedString(count) }); + + public string GetFictionSearchProgressText(int count) => + Format(section => section?.FictionSearchProgress, new { count = Formatter.ToFormattedString(count) }); + + public string GetSciMagSearchProgressText(int count) => + Format(section => section?.SciMagSearchProgress, new { count = Formatter.ToFormattedString(count) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/AboutWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/AboutWindowLocalizator.cs new file mode 100644 index 0000000..0bfdd9c --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/AboutWindowLocalizator.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class AboutWindowLocalizator : Localizator + { + public AboutWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.About) + { + WindowTitle = Format(section => section?.WindowTitle); + ApplicationName = Format(section => section?.ApplicationName); + CheckForUpdates = Format(section => section?.CheckForUpdates); + CheckingUpdates = Format(section => section?.CheckingUpdates); + OfflineModeIsOnTooltip = Format(section => section?.OfflineModeIsOnTooltip); + LatestVersion = Format(section => section?.LatestVersion); + Update = Format(section => section?.Update); + Translators = Format(section => section?.Translators); + } + + public string WindowTitle { get; } + public string ApplicationName { get; } + public string CheckForUpdates { get; } + public string CheckingUpdates { get; } + public string OfflineModeIsOnTooltip { get; } + public string LatestVersion { get; } + public string Update { get; } + public string Translators { get; } + + public string GetVersionString(string version, DateTime date) => + Format(section => section?.Version, new { version, date = Formatter.ToFormattedDateString(date) }); + + public string GetNewVersionAvailableString(string version, DateTime date) => + Format(section => section?.NewVersionAvailable, new { version, date = Formatter.ToFormattedDateString(date) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/ApplicationUpdateWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/ApplicationUpdateWindowLocalizator.cs new file mode 100644 index 0000000..c83241a --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/ApplicationUpdateWindowLocalizator.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class ApplicationUpdateWindowLocalizator : Localizator + { + public ApplicationUpdateWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.ApplicationUpdate) + { + WindowTitle = Format(section => section?.WindowTitle); + UpdateAvailable = Format(section => section?.UpdateAvailable); + Download = Format(section => section?.Download); + DownloadAndInstall = Format(section => section?.DownloadAndInstall); + SkipThisVersion = Format(section => section?.SkipThisVersion); + Cancel = Format(section => section?.Cancel); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + InterruptPromptTitle = Format(section => section?.InterruptPromptTitle); + InterruptPromptText = Format(section => section?.InterruptPromptText); + Error = Format(section => section?.Error); + IncompleteDownload = Format(section => section?.IncompleteDownload); + Close = Format(section => section?.Close); + } + + public string WindowTitle { get; } + public string UpdateAvailable { get; } + public string Download { get; } + public string DownloadAndInstall { get; } + public string SkipThisVersion { get; } + public string Cancel { get; } + public string Interrupt { get; } + public string Interrupting { get; } + public string InterruptPromptTitle { get; } + public string InterruptPromptText { get; } + public string Error { get; } + public string IncompleteDownload { get; } + public string Close { get; } + + public string GetNewVersionString(string version, DateTime date) => + Format(section => section?.NewVersion, new { version, date = Formatter.ToFormattedDateString(date) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseErrorWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseErrorWindowLocalizator.cs new file mode 100644 index 0000000..bb627de --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseErrorWindowLocalizator.cs @@ -0,0 +1,39 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class DatabaseErrorWindowLocalizator : Localizator + { + public DatabaseErrorWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.DatabaseError) + { + WindowTitle = Format(section => section?.WindowTitle); + OpenAnotherDatabase = Format(section => section?.OpenAnotherDatabase); + StartSetupWizard = Format(section => section?.StartSetupWizard); + DeleteFiction = Format(section => section?.DeleteFiction); + Exit = Format(section => section?.Exit); + Ok = Format(section => section?.Ok); + Cancel = Format(section => section?.Cancel); + } + + public string WindowTitle { get; } + public string OpenAnotherDatabase { get; } + public string StartSetupWizard { get; } + public string DeleteFiction { get; } + public string Exit { get; } + public string Ok { get; } + public string Cancel { get; } + + public string GetDatabaseNotFoundText(string database) => Format(section => section?.DatabaseNotFound, new { database }); + + public string GetDatabaseNotValidText(string file) => Format(section => section?.DatabaseNotValid, new { file }); + + public string GetDatabaseDumpFileText(string file) => Format(section => section?.DatabaseDumpFile, new { file }); + + public string GetLibgenServerDatabaseText(string database) => Format(section => section?.LibgenServerDatabase, new { database }); + + public string GetOldFictionSchemaText(string database) => Format(section => section?.OldFictionSchema, new { database }); + + public string GetHeader(string error) => Format(section => section?.HeaderTemplate, new { error }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseWindowLocalizator.cs new file mode 100644 index 0000000..f431e01 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/DatabaseWindowLocalizator.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class DatabaseWindowLocalizator : Localizator + { + public DatabaseWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Database) + { + WindowTitle = Format(section => section?.WindowTitle); + CurrentDatabase = Format(section => section?.CurrentDatabase); + NonFiction = Format(section => section?.NonFiction); + Fiction = Format(section => section?.Fiction); + SciMagArticles = Format(section => section?.SciMagArticles); + TotalBooks = Format(section => section?.TotalBooks) + ":"; + TotalArticles = Format(section => section?.TotalArticles) + ":"; + LastUpdate = Format(section => section?.LastUpdate) + ":"; + Never = Format(section => section?.Never); + IndexesRequiredTitle = Format(section => section?.IndexesRequiredTitle); + IndexesRequiredText = Format(section => section?.IndexesRequiredText); + CreatingIndexes = Format(section => section?.CreatingIndexes); + ChangeDatabase = Format(section => section?.ChangeDatabase); + BrowseDatabaseDialogTitle = Format(section => section?.BrowseDatabaseDialogTitle); + Databases = Format(section => section?.Databases); + AllFiles = Format(section => section?.AllFiles); + Error = Format(section => section?.Error); + OldFictionSchemaTitle = Format(section => section?.OldFictionSchemaTitle); + Close = Format(section => section?.Close); + } + + public string WindowTitle { get; } + public string CurrentDatabase { get; } + public string NonFiction { get; } + public string Fiction { get; } + public string SciMagArticles { get; } + public string TotalBooks { get; } + public string TotalArticles { get; } + public string LastUpdate { get; } + public string Never { get; } + public string IndexesRequiredTitle { get; } + public string IndexesRequiredText { get; } + public string CreatingIndexes { get; } + public string ChangeDatabase { get; } + public string BrowseDatabaseDialogTitle { get; } + public string Databases { get; } + public string AllFiles { get; } + public string Error { get; } + public string OldFictionSchemaTitle { get; } + public string Close { get; } + + public string GetDatabaseNotValidText(string file) => Format(section => section?.DatabaseNotValid, new { file }); + + public string GetDatabaseDumpFileText(string file) => Format(section => section?.DatabaseDumpFile, new { file }); + + public string GetLibgenServerDatabaseText(string database) => Format(section => section?.LibgenServerDatabase, new { database }); + + public string GetOldFictionSchemaText(string database) => Format(section => section?.OldFictionSchemaText, new { database }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/ErrorWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/ErrorWindowLocalizator.cs new file mode 100644 index 0000000..f7c0206 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/ErrorWindowLocalizator.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class ErrorWindowLocalizator : Localizator + { + public ErrorWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.ErrorWindow) + { + WindowTitle = Format(section => section?.WindowTitle); + UnexpectedError = Format(section => section?.UnexpectedError) + ":"; + Copy = Format(section => section?.Copy); + Close = Format(section => section?.Close); + } + + public string WindowTitle { get; } + public string UnexpectedError { get; } + public string Copy { get; } + public string Close { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/ImportWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/ImportWindowLocalizator.cs new file mode 100644 index 0000000..e62f684 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/ImportWindowLocalizator.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class ImportWindowLocalizator : Localizator + { + public ImportWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Import) + { + WindowTitle = Format(section => section?.WindowTitle); + BrowseImportFileDialogTitle = Format(section => section?.BrowseImportFileDialogTitle); + AllSupportedFiles = Format(section => section?.AllSupportedFiles); + SqlDumps = Format(section => section?.SqlDumps); + Archives = Format(section => section?.Archives); + AllFiles = Format(section => section?.AllFiles); + Unknown = Format(section => section?.Unknown); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + Close = Format(section => section?.Close); + StatusDataLookup = FormatStatus(section => section?.DataLookup); + StatusCreatingIndexes = FormatStatus(section => section?.CreatingIndexes); + StatusLoadingIds = FormatStatus(section => section?.LoadingIds); + StatusImportingData = FormatStatus(section => section?.ImportingData); + StatusImportComplete = FormatStatus(section => section?.ImportComplete); + StatusImportCancelled = FormatStatus(section => section?.ImportCancelled); + StatusDataNotFound = FormatStatus(section => section?.DataNotFound); + StatusImportError = FormatStatus(section => section?.ImportError); + LogLineDataLookup = FormatLogLine(section => section?.DataLookup); + LogLineScanning = FormatLogLine(section => section?.Scanning); + LogLineNonFictionTableFound = FormatLogLine(section => section?.NonFictionTableFound); + LogLineFictionTableFound = FormatLogLine(section => section?.FictionTableFound); + LogLineSciMagTableFound = FormatLogLine(section => section?.SciMagTableFound); + LogLineCreatingIndexes = FormatLogLine(section => section?.CreatingIndexes); + LogLineLoadingIds = FormatLogLine(section => section?.LoadingIds); + LogLineImportingData = FormatLogLine(section => section?.ImportingData); + LogLineImportSuccessful = FormatLogLine(section => section?.ImportSuccessful); + LogLineImportCancelled = FormatLogLine(section => section?.ImportCancelled); + LogLineDataNotFound = FormatLogLine(section => section?.DataNotFound); + LogLineInsufficientDiskSpace = FormatLogLine(section => section?.InsufficientDiskSpace); + LogLineExpectedNonFictionTable = FormatLogLine(section => section?.ExpectedNonFictionTable); + LogLineExpectedFictionTable = FormatLogLine(section => section?.ExpectedFictionTable); + LogLineExpectedSciMagTable = FormatLogLine(section => section?.ExpectedSciMagTable); + LogLineFoundNonFictionTable = FormatLogLine(section => section?.FoundNonFictionTable); + LogLineFoundFictionTable = FormatLogLine(section => section?.FoundFictionTable); + LogLineFoundSciMagTable = FormatLogLine(section => section?.FoundSciMagTable); + LogLineImportError = FormatLogLine(section => section?.ImportError); + } + + public string WindowTitle { get; } + public string BrowseImportFileDialogTitle { get; } + public string AllSupportedFiles { get; } + public string SqlDumps { get; } + public string Archives { get; } + public string AllFiles { get; } + public string Unknown { get; set; } + public string Interrupt { get; } + public string Interrupting { get; } + public string Close { get; } + public string StatusDataLookup { get; } + public string StatusCreatingIndexes { get; } + public string StatusLoadingIds { get; } + public string StatusImportingData { get; } + public string StatusImportComplete { get; } + public string StatusImportCancelled { get; } + public string StatusDataNotFound { get; } + public string StatusImportError { get; } + public string LogLineDataLookup { get; } + public string LogLineScanning { get; } + public string LogLineNonFictionTableFound { get; } + public string LogLineFictionTableFound { get; } + public string LogLineSciMagTableFound { get; } + public string LogLineCreatingIndexes { get; } + public string LogLineLoadingIds { get; } + public string LogLineImportingData { get; } + public string LogLineImportSuccessful { get; } + public string LogLineImportCancelled { get; } + public string LogLineDataNotFound { get; } + public string LogLineInsufficientDiskSpace { get; } + public string LogLineExpectedNonFictionTable { get; } + public string LogLineExpectedFictionTable { get; } + public string LogLineExpectedSciMagTable { get; } + public string LogLineFoundNonFictionTable { get; } + public string LogLineFoundFictionTable { get; } + public string LogLineFoundSciMagTable { get; } + public string LogLineImportError { get; } + + public string GetElapsedString(string elapsed) => Format(section => section?.Elapsed, new { elapsed }); + + public string GetFreeSpaceString(string freeSpace) => Format(section => section?.FreeSpace, new { freeSpace }); + + public string GetStatusStep(int current, int total) => + FormatStatus(section => section?.Step, new { current = Formatter.ToFormattedString(current), total = Formatter.ToFormattedString(total) }); + + public string GetLogLineStep(int step) => FormatLogLine(section => section?.Step, new { step = Formatter.ToDecimalFormattedString(step) }); + + public string GetLogLineScannedProgress(decimal percent) => + FormatLogLine(section => section?.ScannedProgress, new { percent = Formatter.ToFormattedString(percent) }); + + public string GetLogLineCreatingIndexForColumn(string column) => FormatLogLine(section => section?.CreatingIndexForColumn, new { column }); + + public string GetLogLineLoadingColumnValues(string column) => FormatLogLine(section => section?.LoadingColumnValues, new { column }); + + public string GetLogLineImportBooksProgressNoUpdate(int added) => + FormatLogLine(section => section?.ImportBooksProgressNoUpdate, new { added = Formatter.ToFormattedString(added) }); + + public string GetLogLineImportBooksProgressWithUpdate(int added, int updated) => + FormatLogLine(section => section?.ImportBooksProgressWithUpdate, + new { added = Formatter.ToFormattedString(added), updated = Formatter.ToFormattedString(updated) }); + + public string GetLogLineImportArticlesProgressNoUpdate(int added) => + FormatLogLine(section => section?.ImportArticlesProgressNoUpdate, new { added = Formatter.ToFormattedString(added) }); + + public string GetLogLineImportArticlesProgressWithUpdate(int added, int updated) => + FormatLogLine(section => section?.ImportArticlesProgressWithUpdate, + new { added = Formatter.ToFormattedString(added), updated = Formatter.ToFormattedString(updated) }); + + public string GetLogLineWrongTableFound(string expected, string found) => FormatLogLine(section => section?.WrongTableFound, new { expected, found }); + + private string FormatStatus(Func statusFieldSelector, object templateArguments = null) => + Format(translation => statusFieldSelector(translation?.Import?.StatusMessages), templateArguments); + + private string FormatLogLine(Func logLineFieldSelector, object templateArguments = null) => + Format(translation => logLineFieldSelector(translation?.Import?.LogMessages), templateArguments); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/MainWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/MainWindowLocalizator.cs new file mode 100644 index 0000000..f70133a --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/MainWindowLocalizator.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class MainWindowLocalizator : Localizator + { + public MainWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.MainWindow) + { + WindowTitle = Format(section => section?.WindowTitle); + ToolbarDownloadManagerTooltip = Format(section => section?.DownloadManagerTooltip); + ToolbarBookmarksTooltip = Format(section => section?.BookmarksTooltip); + ToolbarNoBookmarks = Format(section => section?.NoBookmarks); + ToolbarUpdate = Format(section => section?.Update); + ToolbarImport = Format(section => section?.Import); + ToolbarSynchronize = Format(section => section?.Synchronize); + ToolbarLibrary = Format(section => section?.Library); + ToolbarDatabase = Format(section => section?.Database); + ToolbarSqlDebugger = Format(section => section?.SqlDebugger); + ToolbarSettings = Format(section => section?.Settings); + ToolbarAbout = Format(section => section?.About); + } + + public string WindowTitle { get; } + public string ToolbarDownloadManagerTooltip { get; } + public string ToolbarBookmarksTooltip { get; } + public string ToolbarNoBookmarks { get; } + public string ToolbarUpdate { get; } + public string ToolbarImport { get; } + public string ToolbarSynchronize { get; } + public string ToolbarLibrary { get; } + public string ToolbarDatabase { get; } + public string ToolbarSqlDebugger { get; } + public string ToolbarSettings { get; } + public string ToolbarAbout { get; } + + private string Format(Func field) => Format(translation => field(translation?.MainWindow?.MainMenu)); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/MessageBoxLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/MessageBoxLocalizator.cs new file mode 100644 index 0000000..9c0e87b --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/MessageBoxLocalizator.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class MessageBoxLocalizator : Localizator + { + public MessageBoxLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.MessageBox) + { + Ok = Format(section => section?.Ok); + Yes = Format(section => section?.Yes); + No = Format(section => section?.No); + } + + public string Ok { get; } + public string Yes { get; } + public string No { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/SettingsWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/SettingsWindowLocalizator.cs new file mode 100644 index 0000000..d2d0633 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/SettingsWindowLocalizator.cs @@ -0,0 +1,157 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class SettingsWindowLocalizator : Localizator + { + public SettingsWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Settings) + { + WindowTitle = Format(section => section?.WindowTitle); + Ok = Format(section => section?.Ok); + Cancel = Format(section => section?.Cancel); + DiscardChangesPromptTitle = Format(section => section?.DiscardChangesPromptTitle); + DiscardChangesPromptText = Format(section => section?.DiscardChangesPromptText); + GeneralTabHeader = Format(section => section?.General?.TabHeader); + GeneralLanguage = Format(section => section?.General?.Language); + GeneralCheckUpdates = Format(section => section?.General?.CheckUpdates); + GeneralUpdateCheckIntervalNever = Format(section => section?.General?.UpdateCheckIntervals?.Never); + GeneralUpdateCheckIntervalDaily = Format(section => section?.General?.UpdateCheckIntervals?.Daily); + GeneralUpdateCheckIntervalWeekly = Format(section => section?.General?.UpdateCheckIntervals?.Weekly); + GeneralUpdateCheckIntervalMonthly = Format(section => section?.General?.UpdateCheckIntervals?.Monthly); + NetworkTabHeader = Format(section => section?.Network?.TabHeader); + NetworkOfflineMode = Format(section => section?.Network?.OfflineMode); + NetworkUseHttpProxy = Format(section => section?.Network?.UseHttpProxy); + NetworkProxyAddress = Format(section => section?.Network?.ProxyAddress); + NetworkProxyAddressRequired = Format(section => section?.Network?.ProxyAddressRequired); + NetworkProxyPort = Format(section => section?.Network?.ProxyPort); + NetworkProxyUserName = Format(section => section?.Network?.ProxyUserName); + NetworkProxyPassword = Format(section => section?.Network?.ProxyPassword); + NetworkProxyPasswordWarning = Format(section => section?.Network?.ProxyPasswordWarning); + DownloadTabHeader = Format(section => section?.Download?.TabHeader); + DownloadDownloadMode = Format(section => section?.Download?.DownloadMode) + ":"; + DownloadOpenInBrowser = Format(section => section?.Download?.OpenInBrowser); + DownloadUseDownloadManager = Format(section => section?.Download?.UseDownloadManager); + DownloadDownloadDirectory = Format(section => section?.Download?.DownloadDirectory) + ":"; + DownloadBrowseDirectoryDialogTitle = Format(section => section?.Download?.BrowseDirectoryDialogTitle); + DownloadDownloadDirectoryNotFound = Format(section => section?.Download?.DownloadDirectoryNotFound); + DownloadTimeout = Format(section => section?.Download?.Timeout); + DownloadSeconds = Format(section => section?.Download?.Seconds); + DownloadDownloadAttempts = Format(section => section?.Download?.DownloadAttempts); + DownloadTimes = Format(section => section?.Download?.Times); + DownloadRetryDelay = Format(section => section?.Download?.RetryDelay); + MirrorsTabHeader = Format(section => section?.Mirrors?.TabHeader); + MirrorsNonFiction = Format(section => section?.Mirrors?.NonFiction); + MirrorsFiction = Format(section => section?.Mirrors?.Fiction); + MirrorsSciMagArticles = Format(section => section?.Mirrors?.SciMagArticles); + MirrorsBooks = Format(section => section?.Mirrors?.Books); + MirrorsArticles = Format(section => section?.Mirrors?.Articles); + MirrorsCovers = Format(section => section?.Mirrors?.Covers); + MirrorsSynchronization = Format(section => section?.Mirrors?.Synchronization); + MirrorsNoMirror = Format(section => section?.Mirrors?.NoMirror); + SearchTabHeader = Format(section => section?.Search?.TabHeader); + SearchLimitResults = Format(section => section?.Search?.LimitResults); + SearchMaximumResults = Format(section => section?.Search?.MaximumResults); + SearchPositiveNumbersOnly = Format(section => section?.Search?.PositiveNumbersOnly); + SearchOpenDetails = Format(section => section?.Search?.OpenDetails) + ":"; + SearchInModalWindow = Format(section => section?.Search?.InModalWindow); + SearchInNonModalWindow = Format(section => section?.Search?.InNonModalWindow); + SearchInNewTab = Format(section => section?.Search?.InNewTab); + ExportTabHeader = Format(section => section?.Export?.TabHeader); + ExportOpenResults = Format(section => section?.Export?.OpenResults); + ExportSplitIntoMultipleFiles = Format(section => section?.Export?.SplitIntoMultipleFiles); + ExportMaximumRowsPerFile = Format(section => section?.Export?.MaximumRowsPerFile); + AdvancedTabHeader = Format(section => section?.Advanced?.TabHeader); + AdvancedUseLogging = Format(section => section?.Advanced?.UseLogging); + AdvancedEnableSqlDebugger = Format(section => section?.Advanced?.EnableSqlDebugger); + } + + public string WindowTitle { get; } + public string Ok { get; } + public string Cancel { get; } + public string DiscardChangesPromptTitle { get; } + public string DiscardChangesPromptText { get; } + public string GeneralTabHeader { get; } + public string GeneralLanguage { get; } + public string GeneralCheckUpdates { get; } + public string GeneralUpdateCheckIntervalNever { get; } + public string GeneralUpdateCheckIntervalDaily { get; } + public string GeneralUpdateCheckIntervalWeekly { get; } + public string GeneralUpdateCheckIntervalMonthly { get; } + public string NetworkTabHeader { get; } + public string NetworkOfflineMode { get; } + public string NetworkUseHttpProxy { get; } + public string NetworkProxyAddress { get; } + public string NetworkProxyAddressRequired { get; } + public string NetworkProxyPort { get; } + public string NetworkProxyUserName { get; } + public string NetworkProxyPassword { get; } + public string NetworkProxyPasswordWarning { get; } + public string DownloadTabHeader { get; } + public string DownloadDownloadMode { get; } + public string DownloadOpenInBrowser { get; } + public string DownloadUseDownloadManager { get; } + public string DownloadDownloadDirectory { get; } + public string DownloadBrowseDirectoryDialogTitle { get; } + public string DownloadDownloadDirectoryNotFound { get; } + public string DownloadTimeout { get; } + public string DownloadSeconds { get; } + public string DownloadDownloadAttempts { get; } + public string DownloadTimes { get; } + public string DownloadRetryDelay { get; } + public string MirrorsTabHeader { get; } + public string MirrorsNonFiction { get; } + public string MirrorsFiction { get; } + public string MirrorsSciMagArticles { get; } + public string MirrorsBooks { get; } + public string MirrorsArticles { get; } + public string MirrorsCovers { get; } + public string MirrorsSynchronization { get; } + public string MirrorsNoMirror { get; } + public string SearchTabHeader { get; } + public string SearchLimitResults { get; } + public string SearchMaximumResults { get; } + public string SearchPositiveNumbersOnly { get; } + public string SearchOpenDetails { get; } + public string SearchInModalWindow { get; } + public string SearchInNonModalWindow { get; } + public string SearchInNewTab { get; } + public string ExportTabHeader { get; } + public string ExportOpenResults { get; } + public string ExportSplitIntoMultipleFiles { get; } + public string ExportMaximumRowsPerFile { get; } + public string AdvancedTabHeader { get; } + public string AdvancedUseLogging { get; } + public string AdvancedEnableSqlDebugger { get; } + + public string GetGeneralPercentTranslated(decimal percent) + { + percent = Decimal.Truncate(percent * 10) / 10; + return Format(section => section?.General?.PercentTranslated, new { percent = Formatter.ToFormattedString(percent) }); + } + + public string GetNetworkProxyPortValidation(int min, int max) => + Format(section => section?.Network?.ProxyPortValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + + public string GetDownloadTimeoutValidation(int min, int max) => + Format(section => section?.Download?.TimeoutValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + + public string GetDownloadDownloadAttemptsValidation(int min, int max) => + Format(section => section?.Download?.DownloadAttemptsValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + + public string GetDownloadRetryDelayValidation(int min, int max) => + Format(section => section?.Download?.RetryDelayValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + + public string GetExportMaximumRowsPerFileValidation(int min, int max) => + Format(section => section?.Export?.MaximumRowsPerFileValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + + public string GetExportExcelLimitNote(int count) => + Format(section => section?.Export?.ExcelLimitNote, new { count = Formatter.ToFormattedString(count) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardProxySettingsWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardProxySettingsWindowLocalizator.cs new file mode 100644 index 0000000..6d1b751 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardProxySettingsWindowLocalizator.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class SetupWizardProxySettingsWindowLocalizator : Localizator + { + public SetupWizardProxySettingsWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow?.ProxySettingsWindow) + { + WindowTitle = Format(section => section?.WindowTitle); + ProxyAddress = Format(section => section?.ProxyAddress); + ProxyAddressRequired = Format(section => section?.ProxyAddressRequired); + ProxyPort = Format(section => section?.ProxyPort); + ProxyPortValidation = Format(section => section?.ProxyPortValidation); + ProxyUserName = Format(section => section?.ProxyUserName); + ProxyPassword = Format(section => section?.ProxyPassword); + ProxyPasswordWarning = Format(section => section?.ProxyPasswordWarning); + Ok = Format(section => section?.Ok); + Cancel = Format(section => section?.Cancel); + } + + public string WindowTitle { get; } + public string ProxyAddress { get; } + public string ProxyAddressRequired { get; } + public string ProxyPort { get; } + public string ProxyPortValidation { get; } + public string ProxyUserName { get; } + public string ProxyPassword { get; } + public string ProxyPasswordWarning { get; } + public string Ok { get; } + public string Cancel { get; } + + public string GetProxyPortValidation(int min, int max) => + Format(section => section?.ProxyPortValidation, + new { min = Formatter.ToDecimalFormattedString(min), max = Formatter.ToDecimalFormattedString(max) }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardWindowLocalizator.cs new file mode 100644 index 0000000..f038451 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/SetupWizardWindowLocalizator.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using LibgenDesktop.Models.Localization.Localizators.SetupSteps; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class SetupWizardWindowLocalizator : Localizator + { + public SetupWizardWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SetupWizardWindow) + { + WindowTitle = Format(section => section?.WindowTitle); + DownloadingDumpsStepHeader = Format(section => section?.DownloadingDumpsStepHeader); + CreatingDatabaseStepHeader = Format(section => section?.CreatingDatabaseStepHeader); + ImportingDumpsStepHeader = Format(section => section?.ImportingDumpsStepHeader); + Back = Format(section => section?.Back); + Next = Format(section => section?.Next); + Finish = Format(section => section?.Finish); + Cancel = Format(section => section?.Cancel); + ExitSetupTitle = Format(section => section?.ExitSetupTitle); + ExitSetupText = Format(section => section?.ExitSetupText); + LanguageStep = new LanguageSetupStepLocalizator(prioritizedTranslationList, formatter); + SetupModeStep = new SetupModeSetupStepLocalizator(prioritizedTranslationList, formatter); + DatabaseOperationStep = new DatabaseOperationSetupStepLocalizator(prioritizedTranslationList, formatter); + StepListStep = new StepListSetupStepLocalizator(prioritizedTranslationList, formatter); + DownloadModeStep = new DownloadModeSetupStepLocalizator(prioritizedTranslationList, formatter); + DownloadDumpInfoStep = new DownloadDumpInfoSetupStepLocalizator(prioritizedTranslationList, formatter); + CollectionsStep = new CollectionsSetupStepLocalizator(prioritizedTranslationList, formatter); + DownloadDumpsStep = new DownloadDumpsSetupStepLocalizator(prioritizedTranslationList, formatter); + DownloadDumpLinksStep = new DownloadDumpLinksSetupStepLocalizator(prioritizedTranslationList, formatter); + ImportDumpsStep = new ImportDumpsSetupStepLocalizator(prioritizedTranslationList, formatter); + CreateDatabaseStep = new CreateDatabaseSetupStepLocalizator(prioritizedTranslationList, formatter); + ConfirmationStep = new ConfirmationSetupStepLocalizator(prioritizedTranslationList, formatter); + } + + public string WindowTitle { get; } + public string DownloadingDumpsStepHeader { get; } + public string CreatingDatabaseStepHeader { get; } + public string ImportingDumpsStepHeader { get; } + public string Back { get; } + public string Next { get; } + public string Finish { get; } + public string Cancel { get; } + public string ExitSetupTitle { get; } + public string ExitSetupText { get; } + public LanguageSetupStepLocalizator LanguageStep { get; } + public SetupModeSetupStepLocalizator SetupModeStep { get; } + public DatabaseOperationSetupStepLocalizator DatabaseOperationStep { get; } + public StepListSetupStepLocalizator StepListStep { get; } + public DownloadModeSetupStepLocalizator DownloadModeStep { get; } + public DownloadDumpInfoSetupStepLocalizator DownloadDumpInfoStep { get; } + public CollectionsSetupStepLocalizator CollectionsStep { get; } + public DownloadDumpsSetupStepLocalizator DownloadDumpsStep { get; } + public DownloadDumpLinksSetupStepLocalizator DownloadDumpLinksStep { get; } + public ImportDumpsSetupStepLocalizator ImportDumpsStep { get; } + public CreateDatabaseSetupStepLocalizator CreateDatabaseStep { get; } + public ConfirmationSetupStepLocalizator ConfirmationStep { get; } + + public string GetStepHeader(int current, int total, string header) => + Format(section => section?.StepHeaderTemplate, + new { current = Formatter.ToDecimalFormattedString(current), total = Formatter.ToDecimalFormattedString(total), header }); + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/SqlDebuggerWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/SqlDebuggerWindowLocalizator.cs new file mode 100644 index 0000000..5e34090 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/SqlDebuggerWindowLocalizator.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class SqlDebuggerWindowLocalizator : Localizator + { + public SqlDebuggerWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.SqlDebugger) + { + WindowTitle = Format(section => section?.WindowTitle); + SqlQueryTextBoxHeader = Format(section => section?.SqlQueryTextBoxHeader); + Copy = Format(section => section?.Copy); + Close = Format(section => section?.Close); + } + + public string WindowTitle { get; } + public string SqlQueryTextBoxHeader { get; } + public string Copy { get; } + public string Close { get; } + } +} diff --git a/LibgenDesktop/Models/Localization/Localizators/Windows/SynchronizationWindowLocalizator.cs b/LibgenDesktop/Models/Localization/Localizators/Windows/SynchronizationWindowLocalizator.cs new file mode 100644 index 0000000..53883f0 --- /dev/null +++ b/LibgenDesktop/Models/Localization/Localizators/Windows/SynchronizationWindowLocalizator.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; + +namespace LibgenDesktop.Models.Localization.Localizators.Windows +{ + internal class SynchronizationWindowLocalizator : Localizator + { + public SynchronizationWindowLocalizator(List prioritizedTranslationList, LanguageFormatter formatter) + : base(prioritizedTranslationList, formatter, translation => translation?.Synchronization) + { + WindowTitle = Format(section => section?.WindowTitle); + ErrorMessageTitle = Format(section => section?.ErrorMessageTitle); + ImportRequired = Format(section => section?.ImportRequired); + NoSynchronizationMirror = Format(section => section?.NoSynchronizationMirror); + OfflineModePromptTitle = Format(section => section?.OfflineModePromptTitle); + OfflineModePromptText = Format(section => section?.OfflineModePromptText); + Unknown = Format(section => section?.Unknown); + Interrupt = Format(section => section?.Interrupt); + Interrupting = Format(section => section?.Interrupting); + Close = Format(section => section?.Close); + StatusPreparation = FormatStatus(section => section?.Preparation); + StatusCreatingIndexes = FormatStatus(section => section?.CreatingIndexes); + StatusLoadingIds = FormatStatus(section => section?.LoadingIds); + StatusSynchronizingData = FormatStatus(section => section?.SynchronizingData); + StatusSynchronizationComplete = FormatStatus(section => section?.SynchronizationComplete); + StatusSynchronizationCancelled = FormatStatus(section => section?.SynchronizationCancelled); + StatusSynchronizationError = FormatStatus(section => section?.SynchronizationError); + LogLineCreatingIndexes = FormatLogLine(section => section?.CreatingIndexes); + LogLineLoadingIds = FormatLogLine(section => section?.LoadingIds); + LogLineSynchronizingBookList = FormatLogLine(section => section?.SynchronizingBookList); + LogLineDownloadingNewBooks = FormatLogLine(section => section?.DownloadingNewBooks); + LogLineSynchronizationSuccessful = FormatLogLine(section => section?.SynchronizationSuccessful); + LogLineInsufficientDiskSpace = FormatLogLine(section => section?.InsufficientDiskSpace); + LogLineSynchronizationCancelled = FormatLogLine(section => section?.SynchronizationCancelled); + } + + public string WindowTitle { get; } + public string ErrorMessageTitle { get; } + public string ImportRequired { get; } + public string NoSynchronizationMirror { get; } + public string OfflineModePromptTitle { get; } + public string OfflineModePromptText { get; } + public string Unknown { get; set; } + public string Interrupt { get; } + public string Interrupting { get; } + public string Close { get; } + public string StatusPreparation { get; set; } + public string StatusCreatingIndexes { get; set; } + public string StatusLoadingIds { get; set; } + public string StatusSynchronizingData { get; set; } + public string StatusSynchronizationComplete { get; set; } + public string StatusSynchronizationCancelled { get; set; } + public string StatusSynchronizationError { get; set; } + public string LogLineCreatingIndexes { get; set; } + public string LogLineLoadingIds { get; set; } + public string LogLineSynchronizingBookList { get; set; } + public string LogLineDownloadingNewBooks { get; set; } + public string LogLineSynchronizationSuccessful { get; set; } + public string LogLineInsufficientDiskSpace { get; } + public string LogLineSynchronizationCancelled { get; set; } + + public string GetElapsedString(string elapsed) => Format(section => section?.Elapsed, new { elapsed }); + + public string GetFreeSpaceString(string freeSpace) => Format(section => section?.FreeSpace, new { freeSpace }); + + public string GetStatusStep(int current, int total) => + FormatStatus(section => section?.Step, new { current = Formatter.ToFormattedString(current), total = Formatter.ToFormattedString(total) }); + + public string GetLogLineStep(int step) => FormatLogLine(section => section?.Step, new { step = Formatter.ToDecimalFormattedString(step) }); + + public string GetLogLineCreatingIndexForColumn(string column) => FormatLogLine(section => section?.CreatingIndexForColumn, new { column }); + + public string GetLogLineLoadingColumnValues(string column) => FormatLogLine(section => section?.LoadingColumnValues, new { column }); + + public string GetLogLineSynchronizationProgressNoAddedNoUpdated(int downloaded) => + FormatLogLine(section => section?.SynchronizationProgressNoAddedNoUpdated, new { downloaded = Formatter.ToFormattedString(downloaded) }); + + public string GetLogLineSynchronizationProgressAdded(int downloaded, int added) => + FormatLogLine(section => section?.SynchronizationProgressAdded, + new { downloaded = Formatter.ToFormattedString(downloaded), added = Formatter.ToFormattedString(added) }); + + public string GetLogLineSynchronizationProgressUpdated(int downloaded, int updated) => + FormatLogLine(section => section?.SynchronizationProgressUpdated, + new { downloaded = Formatter.ToFormattedString(downloaded), updated = Formatter.ToFormattedString(updated) }); + + public string GetLogLineSynchronizationProgressAddedAndUpdated(int downloaded, int added, int updated) => + FormatLogLine(section => section?.SynchronizationProgressAddedAndUpdated, + new { downloaded = Formatter.ToFormattedString(downloaded), added = Formatter.ToFormattedString(added), + updated = Formatter.ToFormattedString(updated) }); + + public string GetLogLineSynchronizationError(string error) => FormatLogLine(section => section?.SynchronizationError, new { error }); + + private string FormatStatus(Func field, object templateArguments = null) => + Format(translation => field(translation?.Synchronization?.StatusMessages), templateArguments); + + private string FormatLogLine(Func field, object templateArguments = null) => + Format(translation => field(translation?.Synchronization?.LogMessages), templateArguments); + } +} diff --git a/LibgenDesktop/Models/Localization/Translation.cs b/LibgenDesktop/Models/Localization/Translation.cs index 15e9bf3..4a8d054 100644 --- a/LibgenDesktop/Models/Localization/Translation.cs +++ b/LibgenDesktop/Models/Localization/Translation.cs @@ -49,24 +49,182 @@ internal class MainWindowTranslation public MainMenuTranslation MainMenu { get; set; } } - internal class CreateDatabaseWindowTranslation + internal class LanguageStepTranslation { - public string WindowTitle { get; set; } - public string FirstRunMessage { get; set; } - public string DatabaseNotFound { get; set; } - public string DatabaseCorrupted { get; set; } - public string LibgenServerDatabase { get; set; } - public string ChooseOption { get; set; } + public string ChooseLanguage { get; set; } + } + + internal class SetupModeStepTranslation + { + public string WelcomeAndChooseOption { get; set; } + public string FirstTimeUser { get; set; } + public string ExperiencedUser { get; set; } + } + + internal class DatabaseOperationStepTranslation + { + public string ChooseAction { get; set; } public string CreateNewDatabase { get; set; } public string OpenExistingDatabase { get; set; } - public string BrowseNewDatabaseDialogTitle { get; set; } - public string BrowseExistingDatabaseDialogTitle { get; set; } + } + + internal class StepListStepTranslation + { + public string StepListHeader { get; set; } + public string Step { get; set; } + public string DownloadingDumps { get; set; } + public string CreatingDatabase { get; set; } + public string ImportingDumps { get; set; } + public string ClickNextButton { get; set; } + } + + internal class DownloadModeStepTranslation + { + public string ChooseDownloadMode { get; set; } + public string DownloadManagerMode { get; set; } + public string UseProxyServer { get; set; } + public string ProxySettings { get; set; } + public string BrowserMode { get; set; } + } + + internal class SetupWizardProxySettingsWindowTranslation + { + public string WindowTitle { get; set; } + public string ProxyAddress { get; set; } + public string ProxyAddressRequired { get; set; } + public string ProxyPort { get; set; } + public string ProxyPortValidation { get; set; } + public string ProxyUserName { get; set; } + public string ProxyPassword { get; set; } + public string ProxyPasswordWarning { get; set; } + public string Ok { get; set; } + public string Cancel { get; set; } + } + + internal class DownloadDumpInfoStepTranslation + { + public string DownloadingDumpInfo { get; set; } + public string CannotDownloadDumpInfo { get; set; } + public string Interrupt { get; set; } + public string Interrupting { get; set; } + public string Retry { get; set; } + } + + internal class CollectionsStepTranslation + { + public string ChooseCollections { get; set; } + public string NonFiction { get; set; } + public string Fiction { get; set; } + public string SciMagArticles { get; set; } + public string DownloadSizeExact { get; set; } + public string DownloadSizeApproximate { get; set; } + public string DatabaseSize { get; set; } + public string ImportTimeInMinutes { get; set; } + public string ImportTimeInHours { get; set; } + public string DownloadInto { get; set; } + public string BrowseDirectoryDialogTitle { get; set; } + public string ErrorWarningTitle { get; set; } + public string NoCollectionsSelected { get; set; } + public string DirectoryNotFound { get; set; } + } + + internal class DownloadDumpsStepTranslation + { + public string NonFictionDumpName { get; set; } + public string FictionDumpName { get; set; } + public string SciMagArticlesDumpName { get; set; } + public string QueuedStatus { get; set; } + public string DownloadingStatus { get; set; } + public string StoppedStatus { get; set; } + public string ErrorStatus { get; set; } + public string DownloadProgress { get; set; } + public string Interrupt { get; set; } + public string Interrupting { get; set; } + public string Retry { get; set; } + } + + internal class DownloadDumpLinksStepTranslation + { + public string OpenPage { get; set; } + public string CopyLink { get; set; } + public string DownloadFiles { get; set; } + public string NonFictionDumpName { get; set; } + public string FictionDumpName { get; set; } + public string SciMagArticlesDumpName { get; set; } + public string FileName { get; set; } + public string YYYY { get; set; } + public string MM { get; set; } + public string DD { get; set; } + public string MostRecentDateNote { get; set; } + } + + internal class CreateDatabaseStepTranslation + { + public string DatabaseFilePathPrompt { get; set; } + public string DatabaseCreated { get; set; } + public string CannotCreateDatabase { get; set; } + public string DiskSpaceRequirementsNote { get; set; } + public string SelectDatabaseFilePathDialogTitle { get; set; } public string Databases { get; set; } public string AllFiles { get; set; } - public string Error { get; set; } - public string CannotCreateDatabase { get; set; } - public string Ok { get; set; } + public string CreateDatabase { get; set; } + public string CreatingDatabase { get; set; } + public string DatabaseFileOverwritePromptTitle { get; set; } + public string DatabaseFileOverwritePromptText { get; set; } + } + + internal class ImportDumpsStepTranslation + { + public string NonFictionDumpName { get; set; } + public string FictionDumpName { get; set; } + public string SciMagArticlesDumpName { get; set; } + public string Status { get; set; } + public string NotImported { get; set; } + public string Importing { get; set; } + public string ImportSuccessful { get; set; } + public string ImportCancelled { get; set; } + public string ImportError { get; set; } + public string ImportButton { get; set; } + public string ImportingButton { get; set; } + public string DeleteDumps { get; set; } + } + + internal class ConfirmationStepTranslation + { + public string StepHeader { get; set; } + public string SettingsHeader { get; set; } + public string AllowInternetConnection { get; set; } + public string UseDownloadManager { get; set; } + public string UseBrowser { get; set; } + public string YouCanChangeSettings { get; set; } + } + + internal class SetupWizardWindowTranslation + { + public string WindowTitle { get; set; } + public LanguageStepTranslation LanguageStep { get; set; } + public SetupModeStepTranslation SetupModeStep { get; set; } + public DatabaseOperationStepTranslation DatabaseOperationStep { get; set; } + public StepListStepTranslation StepListStep { get; set; } + public DownloadModeStepTranslation DownloadModeStep { get; set; } + public SetupWizardProxySettingsWindowTranslation ProxySettingsWindow { get; set; } + public DownloadDumpInfoStepTranslation DownloadDumpInfoStep { get; set; } + public CollectionsStepTranslation CollectionsStep { get; set; } + public DownloadDumpsStepTranslation DownloadDumpsStep { get; set; } + public DownloadDumpLinksStepTranslation DownloadDumpLinksStep { get; set; } + public CreateDatabaseStepTranslation CreateDatabaseStep { get; set; } + public ImportDumpsStepTranslation ImportDumpsStep { get; set; } + public ConfirmationStepTranslation ConfirmationStep { get; set; } + public string StepHeaderTemplate { get; set; } + public string DownloadingDumpsStepHeader { get; set; } + public string CreatingDatabaseStepHeader { get; set; } + public string ImportingDumpsStepHeader { get; set; } + public string Back { get; set; } + public string Next { get; set; } + public string Finish { get; set; } public string Cancel { get; set; } + public string ExitSetupTitle { get; set; } + public string ExitSetupText { get; set; } } internal class SearchTabTranslation @@ -101,6 +259,7 @@ internal class SearchResultsTabsTranslation public string Details { get; set; } public string Open { get; set; } public string Download { get; set; } + public string Copy { get; set; } public string ErrorMessageTitle { get; set; } public string FileNotFoundError { get; set; } public string OfflineModeIsOnMessageTitle { get; set; } @@ -116,6 +275,7 @@ internal class NonFictionSearchResultsGridColumnsTranslation public string Authors { get; set; } public string Series { get; set; } public string Year { get; set; } + public string Language { get; set; } public string Publisher { get; set; } public string Format { get; set; } public string FileSize { get; set; } @@ -137,6 +297,7 @@ internal class FictionSearchResultsGridColumnsTranslation public string Authors { get; set; } public string Series { get; set; } public string Year { get; set; } + public string Language { get; set; } public string Publisher { get; set; } public string Format { get; set; } public string FileSize { get; set; } @@ -248,7 +409,6 @@ internal class FictionDetailsTabTranslation { public string Title { get; set; } public string Authors { get; set; } - public string RussianAuthor { get; set; } public string Series { get; set; } public string Publisher { get; set; } public string Edition { get; set; } @@ -256,8 +416,9 @@ internal class FictionDetailsTabTranslation public string Language { get; set; } public string Format { get; set; } public string Pages { get; set; } - public string Version { get; set; } public string FileSize { get; set; } + public string Library { get; set; } + public string Issue { get; set; } public string Added { get; set; } public string LastModified { get; set; } public string Md5Hash { get; set; } @@ -338,6 +499,13 @@ internal class ImportLogMessagesTranslation public string ImportCancelled { get; set; } public string DataNotFound { get; set; } public string InsufficientDiskSpace { get; set; } + public string WrongTableFound { get; set; } + public string ExpectedNonFictionTable { get; set; } + public string ExpectedFictionTable { get; set; } + public string ExpectedSciMagTable { get; set; } + public string FoundNonFictionTable { get; set; } + public string FoundFictionTable { get; set; } + public string FoundSciMagTable { get; set; } public string ImportError { get; set; } } @@ -450,7 +618,6 @@ internal class FictionExporterColumnsTranslation public string Id { get; set; } public string Title { get; set; } public string Authors { get; set; } - public string RussianAuthor { get; set; } public string Series { get; set; } public string Publisher { get; set; } public string Edition { get; set; } @@ -458,8 +625,9 @@ internal class FictionExporterColumnsTranslation public string Language { get; set; } public string Format { get; set; } public string Pages { get; set; } - public string Version { get; set; } public string FileSize { get; set; } + public string Library { get; set; } + public string Issue { get; set; } public string Added { get; set; } public string LastModified { get; set; } public string Md5Hash { get; set; } @@ -611,10 +779,31 @@ internal class DatabaseTranslation public string Databases { get; set; } public string AllFiles { get; set; } public string Error { get; set; } - public string CannotOpenDatabase { get; set; } + public string DatabaseNotValid { get; set; } + public string DatabaseDumpFile { get; set; } + public string LibgenServerDatabase { get; set; } + public string OldFictionSchemaTitle { get; set; } + public string OldFictionSchemaText { get; set; } public string Close { get; set; } } + internal class DatabaseErrorTranslation + { + public string WindowTitle { get; set; } + public string DatabaseNotFound { get; set; } + public string DatabaseNotValid { get; set; } + public string DatabaseDumpFile { get; set; } + public string LibgenServerDatabase { get; set; } + public string OldFictionSchema { get; set; } + public string HeaderTemplate { get; set; } + public string OpenAnotherDatabase { get; set; } + public string StartSetupWizard { get; set; } + public string DeleteFiction { get; set; } + public string Exit { get; set; } + public string Ok { get; set; } + public string Cancel { get; set; } + } + internal class SqlDebuggerWindowTranslation { public string WindowTitle { get; set; } @@ -714,6 +903,7 @@ internal class GeneralSettingsTranslation { public string TabHeader { get; set; } public string Language { get; set; } + public string PercentTranslated { get; set; } public string CheckUpdates { get; set; } public UpdateCheckIntervalTranslation UpdateCheckIntervals { get; set; } } @@ -841,7 +1031,7 @@ internal class ErrorWindowTranslation public GeneralInfo General { get; set; } public FormattingInfo Formatting { get; set; } public MainWindowTranslation MainWindow { get; set; } - public CreateDatabaseWindowTranslation CreateDatabaseWindow { get; set; } + public SetupWizardWindowTranslation SetupWizardWindow { get; set; } public SearchTabTranslation SearchTab { get; set; } public SearchResultsTabsTranslation SearchResultsTabs { get; set; } public NonFictionSearchResultsTabTranslation NonFictionSearchResultsTab { get; set; } @@ -856,6 +1046,7 @@ internal class ErrorWindowTranslation public ExporterTranslation Exporter { get; set; } public SynchronizationTranslation Synchronization { get; set; } public DatabaseTranslation Database { get; set; } + public DatabaseErrorTranslation DatabaseError { get; set; } public SqlDebuggerWindowTranslation SqlDebugger { get; set; } public DownloadManagerTranslation DownloadManager { get; set; } public ApplicationUpdateTranslation ApplicationUpdate { get; set; } diff --git a/LibgenDesktop/Models/MainModel.cs b/LibgenDesktop/Models/MainModel.cs index d3ade15..3323423 100644 --- a/LibgenDesktop/Models/MainModel.cs +++ b/LibgenDesktop/Models/MainModel.cs @@ -33,16 +33,26 @@ internal enum DatabaseStatus OPENED = 1, NOT_FOUND, NOT_SET, + POSSIBLE_DUMP_FILE, + OLD_FICTION_SCHEMA, CORRUPTED, SERVER_DATABASE } + [Flags] + internal enum OpenDatabaseOptions + { + NONE = 0, + MIGRATE_FICTION = 1 + } + internal enum ImportSqlDumpResult { COMPLETED = 1, CANCELLED, DATA_NOT_FOUND, - LOW_DISK_SPACE + LOW_DISK_SPACE, + ERROR } internal enum SynchronizationResult @@ -52,14 +62,6 @@ internal enum SynchronizationResult LOW_DISK_SPACE } - internal enum DownloadFileResult - { - COMPLETED = 1, - INCOMPLETE, - CANCELLED - } - - private readonly Updater updater; private LocalDatabase localDatabase; private bool disposed; @@ -77,25 +79,28 @@ public MainModel() ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; CreateNewHttpClient(); - OpenDatabase(AppSettings.DatabaseFileName); LastApplicationUpdateCheckDateTime = AppSettings.LastUpdate.LastCheckedAt; LastApplicationUpdateCheckResult = null; - updater = new Updater(); - updater.UpdateCheck += ApplicationUpdateCheck; + Updater = new Updater(); + Updater.UpdateCheck += ApplicationUpdateCheck; ConfigureUpdater(); - Downloader = new Downloader(); - ConfigureDownloader(); + DownloadManager = new DownloadManager(); + ConfigureDownloadManager(); + Mirrors.MirrorConfiguration defaultDatabaseDumpMirror = Mirrors[DEFAULT_DATABASE_DUMP_MIRROR_NAME]; + LibgenDumpDownloader = new LibgenDumpDownloader(defaultDatabaseDumpMirror.DatabaseDumpPageUrl, defaultDatabaseDumpMirror.DatabaseDumpPageTransformation); + ConfigureLibgenDumpDownloader(); CoverCache = new CoverCache(COVER_CACHE_CAPACITY, HttpClient, AppSettings.Network.OfflineMode); disposed = false; } public AppSettings AppSettings { get; } - public DatabaseStatus LocalDatabaseStatus { get; private set; } public DatabaseMetadata DatabaseMetadata { get; private set; } public Mirrors Mirrors { get; } public LocalizationStorage Localization { get; } public HttpClient HttpClient { get; private set; } - public Downloader Downloader { get; } + public Updater Updater { get; } + public DownloadManager DownloadManager { get; } + public LibgenDumpDownloader LibgenDumpDownloader { get; } public CoverCache CoverCache { get; } public int NonFictionBookCount { get; private set; } public int FictionBookCount { get; private set; } @@ -107,6 +112,47 @@ public MainModel() public event EventHandler AppSettingsChanged; public event EventHandler BookmarksChanged; + public static void EnableLogging() + { + Logger.EnableLogging(); + } + + public static void DisableLogging() + { + Logger.DisableLogging(); + } + + public static string GetDatabaseNormalizedPath(string databaseFullPath) + { + if (Environment.IsInPortableMode) + { + if (databaseFullPath.ToLower().StartsWith(Environment.AppDataDirectory.ToLower())) + { + return databaseFullPath.Substring(Environment.AppDataDirectory.Length + 1); + } + else + { + return databaseFullPath; + } + } + else + { + return databaseFullPath; + } + } + + public static string GetDatabaseFullPath(string databaseNormalizedPath) + { + if (Path.IsPathRooted(databaseNormalizedPath)) + { + return databaseNormalizedPath; + } + else + { + return Path.GetFullPath(Path.Combine(Environment.AppDataDirectory, databaseNormalizedPath)); + } + } + public Task> SearchNonFictionAsync(string searchQuery, IProgress progressHandler, CancellationToken cancellationToken) { @@ -185,7 +231,8 @@ public Task LoadSciMagArticleAsync(int articleId) return LoadItemAsync(localDatabase.GetSciMagArticleById, articleId); } - public Task ImportSqlDumpAsync(string sqlDumpFilePath, IProgress progressHandler, CancellationToken cancellationToken) + public Task ImportSqlDumpAsync(string sqlDumpFilePath, TableType? expectedTableType, IProgress progressHandler, + CancellationToken cancellationToken) { return Task.Run(() => { @@ -233,6 +280,11 @@ public Task ImportSqlDumpAsync(string sqlDumpFilePath, IPro { continue; } + if (expectedTableType.HasValue && tableType != expectedTableType.Value) + { + progressHandler.Report(new ImportWrongTableDefinitionProgress(expectedTableType.Value, tableType)); + return ImportSqlDumpResult.ERROR; + } progressHandler.Report(new ImportTableDefinitionFoundProgress(tableType)); bool insertFound = false; while (sqlDumpReader.ReadLine()) @@ -318,7 +370,7 @@ public Task ImportSqlDumpAsync(string sqlDumpFilePath, IPro }; Logger.Debug("Importing data."); Importer.ImportResult importResult = importer.Import(sqlDumpReader, importProgressReporter, IMPORT_PROGRESS_UPDATE_INTERVAL, - cancellationToken, parsedTableDefinition, localDatabase.DatabaseFullPath); + parsedTableDefinition, localDatabase.DatabaseFullPath, cancellationToken); switch (tableType) { case TableType.NON_FICTION: @@ -436,7 +488,7 @@ public Task SynchronizeNonFictionAsync(IProgress } Logger.Debug("Importing downloaded batch."); importResult = importer.Import(currentBatch, importProgressReporter, SYNCHRONIZATION_PROGRESS_UPDATE_INTERVAL, - cancellationToken, localDatabase.DatabaseFullPath); + localDatabase.DatabaseFullPath, cancellationToken); totalAddedBookCount += importResult.AddedObjectCount; totalUpdatedBookCount += importResult.UpdatedObjectCount; Logger.Debug($"Batch has been imported, total added book count = {totalAddedBookCount}, total updated book count = {totalUpdatedBookCount}."); @@ -461,70 +513,6 @@ public Task SynchronizeNonFictionAsync(IProgress }); } - public Task DownloadFileAsync(string fileUrl, string destinationPath, IProgress progressHandler, - CancellationToken cancellationToken) - { - return Task.Run(async () => - { - Logger.Debug($"Requesting {fileUrl}"); - HttpResponseMessage response; - try - { - response = await HttpClient.GetAsync(fileUrl, HttpCompletionOption.ResponseHeadersRead, cancellationToken); - } - catch (TaskCanceledException) - { - Logger.Debug("File download has been cancelled."); - return DownloadFileResult.CANCELLED; - } - Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); - Logger.Debug("Response headers:", response.Headers.ToString().TrimEnd(), response.Content.Headers.ToString().TrimEnd()); - if (response.StatusCode != HttpStatusCode.OK) - { - throw new Exception($"Server returned {(int)response.StatusCode} {response.StatusCode}."); - } - long? contentLength = response.Content.Headers.ContentLength; - if (!contentLength.HasValue) - { - throw new Exception($"Server did not return Content-Length value."); - } - int fileSize = (int)contentLength.Value; - Logger.Debug($"File size is {fileSize} bytes."); - Stream downloadStream = await response.Content.ReadAsStreamAsync(); - byte[] buffer = new byte[4096]; - int downloadedBytes = 0; - using (FileStream destinationFileStream = new FileStream(destinationPath, FileMode.Create)) - { - while (true) - { - int bytesRead; - try - { - bytesRead = downloadStream.Read(buffer, 0, buffer.Length); - } - catch - { - if (cancellationToken.IsCancellationRequested) - { - Logger.Debug("File download has been cancelled."); - return DownloadFileResult.CANCELLED; - } - throw; - } - if (bytesRead == 0) - { - bool isCompleted = downloadedBytes == fileSize; - Logger.Debug($"File download is {(isCompleted ? "complete" : "incomplete")}."); - return isCompleted ? DownloadFileResult.COMPLETED : DownloadFileResult.INCOMPLETE; - } - destinationFileStream.Write(buffer, 0, bytesRead); - downloadedBytes += bytesRead; - progressHandler.Report(new DownloadFileProgress(downloadedBytes, fileSize)); - } - } - }); - } - public Task ScanNonFictionAsync(string scanDirectory, IProgress progressHandler) { return ScanAsync(scanDirectory, progressHandler, NonFictionBookCount, localDatabase.GetNonFictionIndexList, @@ -648,7 +636,7 @@ public Task GetDatabaseStatsAsync() public async Task CheckForApplicationUpdateAsync() { - Updater.UpdateCheckResult result = await updater.CheckForUpdateAsync(ignoreSpecifiedRelease: false); + Updater.UpdateCheckResult result = await Updater.CheckForUpdateAsync(ignoreSpecifiedRelease: false); if (result != null && result.NewReleaseName != AppSettings.LastUpdate.IgnoreReleaseName) { LastApplicationUpdateCheckResult = result; @@ -714,163 +702,136 @@ public void ReconfigureSettingsDependencies() Localization.SwitchLanguage(AppSettings.General.Language); CreateNewHttpClient(); ConfigureUpdater(); - ConfigureDownloader(); + ConfigureDownloadManager(); + ConfigureLibgenDumpDownloader(); ConfigureCoverCache(); } - public string GetDatabaseNormalizedPath(string databaseFullPath) + public Task OpenDatabase(string databaseFilePath, OpenDatabaseOptions openDatabaseOptions = OpenDatabaseOptions.NONE) { - if (Environment.IsInPortableMode) + return Task.Run(() => { - if (databaseFullPath.ToLower().StartsWith(Environment.AppDataDirectory.ToLower())) + if (localDatabase != null) { - return databaseFullPath.Substring(Environment.AppDataDirectory.Length + 1); + localDatabase.Dispose(); + localDatabase = null; } - else + if (!String.IsNullOrWhiteSpace(databaseFilePath)) { - return databaseFullPath; - } - } - else - { - return databaseFullPath; - } - } - - public string GetDatabaseFullPath(string databaseNormalizedPath) - { - if (Path.IsPathRooted(databaseNormalizedPath)) - { - return databaseNormalizedPath; - } - else - { - return Path.GetFullPath(Path.Combine(Environment.AppDataDirectory, databaseNormalizedPath)); - } - } - - public bool OpenDatabase(string databaseFilePath) - { - if (localDatabase != null) - { - localDatabase.Dispose(); - localDatabase = null; - } - if (!String.IsNullOrWhiteSpace(databaseFilePath)) - { - if (File.Exists(databaseFilePath)) - { - try + if (File.Exists(databaseFilePath)) { - string databaseFullPath = GetDatabaseFullPath(databaseFilePath); - localDatabase = LocalDatabase.OpenDatabase(databaseFullPath); - if (!localDatabase.CheckIfMetadataExists()) - { - LocalDatabaseStatus = DatabaseStatus.CORRUPTED; - return false; - } - DatabaseMetadata = localDatabase.GetMetadata(); - if (!String.IsNullOrEmpty(DatabaseMetadata.AppName) && - DatabaseMetadata.AppName.CompareOrdinalIgnoreCase(LIBGEN_SERVER_DATABASE_METADATA_APP_NAME)) - { - LocalDatabaseStatus = DatabaseStatus.SERVER_DATABASE; - return false; - } - if (String.IsNullOrEmpty(DatabaseMetadata.Version)) + try { - LocalDatabaseStatus = DatabaseStatus.CORRUPTED; - return false; + string databaseFullPath = GetDatabaseFullPath(databaseFilePath); + localDatabase = LocalDatabase.OpenDatabase(databaseFullPath); + if (!localDatabase.CheckIfMetadataExists()) + { + return DatabaseStatus.CORRUPTED; + } + DatabaseMetadata = localDatabase.GetMetadata(); + if (!String.IsNullOrEmpty(DatabaseMetadata.AppName) && + DatabaseMetadata.AppName.CompareOrdinalIgnoreCase(LIBGEN_SERVER_DATABASE_METADATA_APP_NAME)) + { + return DatabaseStatus.SERVER_DATABASE; + } + if (DatabaseMetadata.GetParsedVersion() == null) + { + return DatabaseStatus.CORRUPTED; + } + if (!openDatabaseOptions.HasFlag(OpenDatabaseOptions.MIGRATE_FICTION) && Migration.UsesOldFictionSchema(DatabaseMetadata) && + localDatabase.CountFictionBooks() > 0) + { + return DatabaseStatus.OLD_FICTION_SCHEMA; + } + if (!Migration.Migrate(localDatabase, DatabaseMetadata)) + { + return DatabaseStatus.CORRUPTED; + } + UpdateNonFictionBookCount(); + UpdateFictionBookCount(); + UpdateSciMagArticleCount(); } - if (!Migration.Migrate(localDatabase, DatabaseMetadata)) + catch (Exception exception) { - LocalDatabaseStatus = DatabaseStatus.CORRUPTED; - return false; + string databaseFileExtension = Path.GetExtension(databaseFilePath).ToLower(); + if (SqlDumpReader.SUPPORTED_DUMP_FILE_EXTENSIONS.Contains(databaseFileExtension)) + { + return DatabaseStatus.POSSIBLE_DUMP_FILE; + } + Logger.Exception(exception); + return DatabaseStatus.CORRUPTED; } - UpdateNonFictionBookCount(); - UpdateFictionBookCount(); - UpdateSciMagArticleCount(); + return DatabaseStatus.OPENED; } - catch (Exception exception) + else { - Logger.Exception(exception); - LocalDatabaseStatus = DatabaseStatus.CORRUPTED; - return false; + return DatabaseStatus.NOT_FOUND; } - LocalDatabaseStatus = DatabaseStatus.OPENED; - return true; } else { - LocalDatabaseStatus = DatabaseStatus.NOT_FOUND; + return DatabaseStatus.NOT_SET; } - } - else - { - LocalDatabaseStatus = DatabaseStatus.NOT_SET; - } - return false; + }); } - public bool CreateDatabase(string databaseFilePath) + public Task CreateDatabaseAsync(string databaseFilePath) { - if (localDatabase != null) - { - localDatabase.Dispose(); - localDatabase = null; - } - try + return Task.Run(() => { - string databaseFullPath = GetDatabaseFullPath(databaseFilePath); - localDatabase = LocalDatabase.CreateDatabase(databaseFullPath); - localDatabase.CreateMetadataTable(); - localDatabase.CreateFilesTable(); - localDatabase.CreateNonFictionTables(); - localDatabase.CreateFictionTables(); - localDatabase.CreateSciMagTables(); - DatabaseMetadata = new DatabaseMetadata + if (localDatabase != null) { - Version = CURRENT_DATABASE_VERSION, - NonFictionFirstImportComplete = false, - FictionFirstImportComplete = false, - SciMagFirstImportComplete = false - }; - localDatabase.AddMetadata(DatabaseMetadata); - NonFictionBookCount = 0; - FictionBookCount = 0; - SciMagArticleCount = 0; - return true; - } - catch (Exception exception) - { - Logger.Exception(exception); - LocalDatabaseStatus = DatabaseStatus.CORRUPTED; - return false; - } + localDatabase.Dispose(); + localDatabase = null; + } + try + { + string databaseFullPath = GetDatabaseFullPath(databaseFilePath); + localDatabase = LocalDatabase.CreateDatabase(databaseFullPath); + localDatabase.CreateMetadataTable(); + localDatabase.CreateFilesTable(); + localDatabase.CreateNonFictionTables(); + localDatabase.CreateFictionTables(); + localDatabase.CreateSciMagTables(); + DatabaseMetadata = new DatabaseMetadata + { + AppName = DATABASE_METADATA_APP_NAME, + Version = CURRENT_DATABASE_VERSION, + NonFictionFirstImportComplete = false, + FictionFirstImportComplete = false, + SciMagFirstImportComplete = false + }; + localDatabase.AddMetadata(DatabaseMetadata); + NonFictionBookCount = 0; + FictionBookCount = 0; + SciMagArticleCount = 0; + return true; + } + catch (Exception exception) + { + Logger.Exception(exception); + return false; + } + }); } public void CreateNewHttpClient() { - HttpClientHandler httpClientHandler = new HttpClientHandler + WebRequestHandler webRequestHandler = new WebRequestHandler { Proxy = NetworkUtils.CreateProxy(AppSettings.Network), UseProxy = true, AllowAutoRedirect = true, - UseCookies = false + UseCookies = false, + ReadWriteTimeout = AppSettings.Download.Timeout * 1000 + }; + HttpClient = new HttpClient(webRequestHandler) + { + Timeout = Timeout.InfiniteTimeSpan }; - HttpClient = new HttpClient(httpClientHandler); HttpClient.DefaultRequestHeaders.UserAgent.ParseAdd(USER_AGENT); } - public void EnableLogging() - { - Logger.EnableLogging(); - } - - public void DisableLogging() - { - Logger.DisableLogging(); - } - public void ConfigureUpdater() { DateTime? nextUpdateCheck; @@ -902,12 +863,17 @@ public void ConfigureUpdater() } } } - updater.Configure(HttpClient, nextUpdateCheck, AppSettings.LastUpdate.IgnoreReleaseName); + Updater.Configure(HttpClient, AppSettings.General.UpdateUrl, nextUpdateCheck, AppSettings.LastUpdate.IgnoreReleaseName); + } + + public void ConfigureDownloadManager() + { + DownloadManager.Configure(Localization.CurrentLanguage, AppSettings.Network, AppSettings.Download); } - public void ConfigureDownloader() + public void ConfigureLibgenDumpDownloader() { - Downloader.Configure(Localization.CurrentLanguage, AppSettings.Network, AppSettings.Download); + LibgenDumpDownloader.Configure(HttpClient); } public void ConfigureCoverCache() @@ -927,11 +893,52 @@ public void Dispose() { if (!disposed) { - Downloader?.Dispose(); + DownloadManager?.Dispose(); + localDatabase?.Dispose(); disposed = true; } } + private static TableType DetectImportTableType(SqlDumpReader.ParsedTableDefinition parsedTableDefinition) + { + if (TableDefinitions.AllTables.TryGetValue(parsedTableDefinition.TableName, out TableDefinition tableDefinition)) + { + foreach (SqlDumpReader.ParsedColumnDefinition parsedColumnDefinition in parsedTableDefinition.Columns) + { + if (tableDefinition.Columns.TryGetValue(parsedColumnDefinition.ColumnName.ToLower(), out ColumnDefinition columnDefinition)) + { + if (columnDefinition.ColumnType == parsedColumnDefinition.ColumnType) + { + continue; + } + } + return TableType.UNKNOWN; + } + return tableDefinition.TableType; + } + return TableType.UNKNOWN; + } + + private static void CheckAndCreateIndex(List existingIndexes, string prefix, string fieldName, IProgress progressHandler, + Action createIndexAction) + { + if (!CheckIfIndexExists(existingIndexes, prefix, fieldName)) + { + Logger.Debug($"Index on {fieldName} doesn't exist, creating it."); + if (progressHandler != null) + { + progressHandler.Report(new ImportCreateIndexProgress(fieldName)); + } + createIndexAction(); + Logger.Debug("Index has been created."); + } + } + + private static bool CheckIfIndexExists(List existingIndexes, string prefix, string fieldName) + { + return existingIndexes.Contains(prefix + fieldName); + } + private Task> SearchItemsAsync(Func> searchFunction, string searchQuery, IProgress progressHandler, CancellationToken cancellationToken) { @@ -1024,26 +1031,6 @@ private Task LoadItemAsync(Func loadFunction, int itemId) }); } - private TableType DetectImportTableType(SqlDumpReader.ParsedTableDefinition parsedTableDefinition) - { - if (TableDefinitions.AllTables.TryGetValue(parsedTableDefinition.TableName, out TableDefinition tableDefinition)) - { - foreach (SqlDumpReader.ParsedColumnDefinition parsedColumnDefinition in parsedTableDefinition.Columns) - { - if (tableDefinition.Columns.TryGetValue(parsedColumnDefinition.ColumnName.ToLower(), out ColumnDefinition columnDefinition)) - { - if (columnDefinition.ColumnType == parsedColumnDefinition.ColumnType) - { - continue; - } - } - return TableType.UNKNOWN; - } - return tableDefinition.TableType; - } - return TableType.UNKNOWN; - } - private Task ScanAsync(string scanDirectory, IProgress progressHandler, int objectsInDatabaseCount, Func> indexRetrievalFunction, string indexPrefix, Action indexCreationAction, Func getObjectByMd5HashFunction) where T : LibgenObject @@ -1193,26 +1180,6 @@ private void CheckAndCreateSciMagIndexes(IProgress progressHandler, Canc CheckAndCreateIndex(sciMagIndexes, SqlScripts.SCIMAG_INDEX_PREFIX, "AddedDateTime", progressHandler, localDatabase.CreateSciMagAddedDateTimeIndex); } - private bool CheckIfIndexExists(List existingIndexes, string prefix, string fieldName) - { - return existingIndexes.Contains(prefix + fieldName); - } - - private void CheckAndCreateIndex(List existingIndexes, string prefix, string fieldName, IProgress progressHandler, - Action createIndexAction) - { - if (!CheckIfIndexExists(existingIndexes, prefix, fieldName)) - { - Logger.Debug($"Index on {fieldName} doesn't exist, creating it."); - if (progressHandler != null) - { - progressHandler.Report(new ImportCreateIndexProgress(fieldName)); - } - createIndexAction(); - Logger.Debug("Index has been created."); - } - } - private void UpdateNonFictionBookCount() { Logger.Debug("Updating non-fiction book count."); diff --git a/LibgenDesktop/Models/ProgressArgs/DownloadFileProgress.cs b/LibgenDesktop/Models/ProgressArgs/DownloadFileProgress.cs index 25fa407..79c373d 100644 --- a/LibgenDesktop/Models/ProgressArgs/DownloadFileProgress.cs +++ b/LibgenDesktop/Models/ProgressArgs/DownloadFileProgress.cs @@ -2,13 +2,13 @@ { internal class DownloadFileProgress { - public DownloadFileProgress(int downloadedBytes, int fileSize) + public DownloadFileProgress(long downloadedBytes, long fileSize) { DownloadedBytes = downloadedBytes; FileSize = fileSize; } - public int DownloadedBytes { get; } - public int FileSize { get; } + public long DownloadedBytes { get; } + public long FileSize { get; } } } diff --git a/LibgenDesktop/Models/ProgressArgs/ImportObjectsProgress.cs b/LibgenDesktop/Models/ProgressArgs/ImportObjectsProgress.cs index e8db6b2..70d9d2f 100644 --- a/LibgenDesktop/Models/ProgressArgs/ImportObjectsProgress.cs +++ b/LibgenDesktop/Models/ProgressArgs/ImportObjectsProgress.cs @@ -1,14 +1,16 @@ -namespace LibgenDesktop.Models.ProgressArgs +using LibgenDesktop.Models.SqlDump; + +namespace LibgenDesktop.Models.ProgressArgs { - internal class ImportObjectsProgress + internal class ImportWrongTableDefinitionProgress { - public ImportObjectsProgress(int objectsAdded, int objectsUpdated) + public ImportWrongTableDefinitionProgress(TableType expectedTableType, TableType actualTableType) { - ObjectsAdded = objectsAdded; - ObjectsUpdated = objectsUpdated; + ExpectedTableType = expectedTableType; + ActualTableType = actualTableType; } - public int ObjectsAdded { get; } - public int ObjectsUpdated { get; } + public TableType ExpectedTableType { get; } + public TableType ActualTableType { get; } } } diff --git a/LibgenDesktop/Models/ProgressArgs/ImportWrongTableDefinitionProgress.cs b/LibgenDesktop/Models/ProgressArgs/ImportWrongTableDefinitionProgress.cs new file mode 100644 index 0000000..e8db6b2 --- /dev/null +++ b/LibgenDesktop/Models/ProgressArgs/ImportWrongTableDefinitionProgress.cs @@ -0,0 +1,14 @@ +namespace LibgenDesktop.Models.ProgressArgs +{ + internal class ImportObjectsProgress + { + public ImportObjectsProgress(int objectsAdded, int objectsUpdated) + { + ObjectsAdded = objectsAdded; + ObjectsUpdated = objectsUpdated; + } + + public int ObjectsAdded { get; } + public int ObjectsUpdated { get; } + } +} diff --git a/LibgenDesktop/Models/Settings/AppSettings.cs b/LibgenDesktop/Models/Settings/AppSettings.cs index 266bece..165c1b3 100644 --- a/LibgenDesktop/Models/Settings/AppSettings.cs +++ b/LibgenDesktop/Models/Settings/AppSettings.cs @@ -32,7 +32,7 @@ public static MainWindowSettings Default public int Height { get; set; } } - internal class ExportPanelSettngs + internal class ExportPanelSettings { internal enum ExportFormat { @@ -47,11 +47,11 @@ internal enum CsvSeparator TAB } - public static ExportPanelSettngs Default + public static ExportPanelSettings Default { get { - return new ExportPanelSettngs + return new ExportPanelSettings { ExportDirectory = null, Format = ExportFormat.XLSX, @@ -100,6 +100,7 @@ public static NonFictionColumnSettings Default AuthorsColumnWidth = DEFAULT_NON_FICTION_GRID_AUTHORS_COLUMN_WIDTH, SeriesColumnWidth = DEFAULT_NON_FICTION_GRID_SERIES_COLUMN_WIDTH, YearColumnWidth = DEFAULT_NON_FICTION_GRID_YEAR_COLUMN_WIDTH, + LanguageColumnWidth = DEFAULT_NON_FICTION_GRID_LANGUAGE_COLUMN_WIDTH, PublisherColumnWidth = DEFAULT_NON_FICTION_GRID_PUBLISHER_COLUMN_WIDTH, FormatColumnWidth = DEFAULT_NON_FICTION_GRID_FORMAT_COLUMN_WIDTH, FileSizeColumnWidth = DEFAULT_NON_FICTION_GRID_FILESIZE_COLUMN_WIDTH, @@ -113,6 +114,7 @@ public static NonFictionColumnSettings Default public int AuthorsColumnWidth { get; set; } public int SeriesColumnWidth { get; set; } public int YearColumnWidth { get; set; } + public int LanguageColumnWidth { get; set; } public int PublisherColumnWidth { get; set; } public int FormatColumnWidth { get; set; } public int FileSizeColumnWidth { get; set; } @@ -130,14 +132,14 @@ public static NonFictionSettings Default { DetailsWindow = NonFictionDetailsWindowSettings.Default, Columns = NonFictionColumnSettings.Default, - ExportPanel = ExportPanelSettngs.Default + ExportPanel = ExportPanelSettings.Default }; } } public NonFictionDetailsWindowSettings DetailsWindow { get; set; } public NonFictionColumnSettings Columns { get; set; } - public ExportPanelSettngs ExportPanel { get; set; } + public ExportPanelSettings ExportPanel { get; set; } } internal class FictionDetailsWindowSettings : DetailsWindowSettings @@ -167,6 +169,7 @@ public static FictionColumnSettings Default AuthorsColumnWidth = DEFAULT_FICTION_GRID_AUTHORS_COLUMN_WIDTH, SeriesColumnWidth = DEFAULT_FICTION_GRID_SERIES_COLUMN_WIDTH, YearColumnWidth = DEFAULT_FICTION_GRID_YEAR_COLUMN_WIDTH, + LanguageColumnWidth = DEFAULT_FICTION_GRID_LANGUAGE_COLUMN_WIDTH, PublisherColumnWidth = DEFAULT_FICTION_GRID_PUBLISHER_COLUMN_WIDTH, FormatColumnWidth = DEFAULT_FICTION_GRID_FORMAT_COLUMN_WIDTH, FileSizeColumnWidth = DEFAULT_FICTION_GRID_FILESIZE_COLUMN_WIDTH, @@ -179,6 +182,7 @@ public static FictionColumnSettings Default public int AuthorsColumnWidth { get; set; } public int SeriesColumnWidth { get; set; } public int YearColumnWidth { get; set; } + public int LanguageColumnWidth { get; set; } public int PublisherColumnWidth { get; set; } public int FormatColumnWidth { get; set; } public int FileSizeColumnWidth { get; set; } @@ -195,14 +199,14 @@ public static FictionSettings Default { DetailsWindow = FictionDetailsWindowSettings.Default, Columns = FictionColumnSettings.Default, - ExportPanel = ExportPanelSettngs.Default + ExportPanel = ExportPanelSettings.Default }; } } public FictionDetailsWindowSettings DetailsWindow { get; set; } public FictionColumnSettings Columns { get; set; } - public ExportPanelSettngs ExportPanel { get; set; } + public ExportPanelSettings ExportPanel { get; set; } } internal class SciMagDetailsWindowSettings : DetailsWindowSettings @@ -258,14 +262,14 @@ public static SciMagSettings Default { DetailsWindow = SciMagDetailsWindowSettings.Default, Columns = SciMagColumnSettings.Default, - ExportPanel = ExportPanelSettngs.Default + ExportPanel = ExportPanelSettings.Default }; } } public SciMagDetailsWindowSettings DetailsWindow { get; set; } public SciMagColumnSettings Columns { get; set; } - public ExportPanelSettngs ExportPanel { get; set; } + public ExportPanelSettings ExportPanel { get; set; } } internal class DownloadManagerTabSettings @@ -344,13 +348,15 @@ public static GeneralSettings Default return new GeneralSettings { Language = null, - UpdateCheck = UpdateCheckInterval.NEVER + UpdateCheck = UpdateCheckInterval.NEVER, + UpdateUrl = DEFAULT_GITHUB_RELEASE_API_URL }; } } public string Language { get; set; } public UpdateCheckInterval UpdateCheck { get; set; } + public string UpdateUrl { get; set; } } internal class NetworkSettings @@ -562,6 +568,26 @@ public static AppSettings ValidateAndCorrect(AppSettings appSettings) } } + private static ExportPanelSettings ValidateAndCorrectExportPanelSettings(ExportPanelSettings exportPanelSettings) + { + if (exportPanelSettings == null) + { + exportPanelSettings = ExportPanelSettings.Default; + } + else + { + if (!Enum.IsDefined(typeof(ExportPanelSettings.ExportFormat), exportPanelSettings.Format)) + { + exportPanelSettings.Format = ExportPanelSettings.ExportFormat.XLSX; + } + if (!Enum.IsDefined(typeof(ExportPanelSettings.CsvSeparator), exportPanelSettings.Separator)) + { + exportPanelSettings.Separator = ExportPanelSettings.CsvSeparator.COMMA; + } + } + return exportPanelSettings; + } + private void ValidateAndCorrectDatabaseFileName() { if (DatabaseFileName == null) @@ -652,6 +678,10 @@ private void ValidateAndCorrectNonFictionSettings() { nonFictionColumns.YearColumnWidth = NON_FICTION_GRID_YEAR_COLUMN_MIN_WIDTH; } + if (nonFictionColumns.LanguageColumnWidth < NON_FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH) + { + nonFictionColumns.LanguageColumnWidth = NON_FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH; + } if (nonFictionColumns.PublisherColumnWidth < NON_FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH) { nonFictionColumns.PublisherColumnWidth = NON_FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH; @@ -724,6 +754,10 @@ private void ValidateAndCorrectFictionSettings() { fictionColumns.YearColumnWidth = FICTION_GRID_YEAR_COLUMN_MIN_WIDTH; } + if (fictionColumns.LanguageColumnWidth < FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH) + { + fictionColumns.LanguageColumnWidth = FICTION_GRID_LANGUAGE_COLUMN_MIN_WIDTH; + } if (fictionColumns.PublisherColumnWidth < FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH) { fictionColumns.PublisherColumnWidth = FICTION_GRID_PUBLISHER_COLUMN_MIN_WIDTH; @@ -824,26 +858,6 @@ private void ValidateAndCorrectDownloadManagerTabSettings() } } - private ExportPanelSettngs ValidateAndCorrectExportPanelSettings(ExportPanelSettngs exportPanelSettngs) - { - if (exportPanelSettngs == null) - { - exportPanelSettngs = ExportPanelSettngs.Default; - } - else - { - if (!Enum.IsDefined(typeof(ExportPanelSettngs.ExportFormat), exportPanelSettngs.Format)) - { - exportPanelSettngs.Format = ExportPanelSettngs.ExportFormat.XLSX; - } - if (!Enum.IsDefined(typeof(ExportPanelSettngs.CsvSeparator), exportPanelSettngs.Separator)) - { - exportPanelSettngs.Separator = ExportPanelSettngs.CsvSeparator.COMMA; - } - } - return exportPanelSettngs; - } - private void ValidateAndCorrectLastUpdateSettings() { if (LastUpdate == null) @@ -891,6 +905,11 @@ private void ValidateAndCorrectGeneralSettings() { General.UpdateCheck = GeneralSettings.UpdateCheckInterval.NEVER; } + if (String.IsNullOrWhiteSpace(General.UpdateUrl) || !Uri.IsWellFormedUriString(General.UpdateUrl, UriKind.Absolute) || + (!General.UpdateUrl.ToLower().StartsWith("http://") && !General.UpdateUrl.ToLower().StartsWith("https://"))) + { + General.UpdateUrl = DEFAULT_GITHUB_RELEASE_API_URL; + } } } diff --git a/LibgenDesktop/Models/Settings/Mirrors.cs b/LibgenDesktop/Models/Settings/Mirrors.cs index cc6cc0e..2338970 100644 --- a/LibgenDesktop/Models/Settings/Mirrors.cs +++ b/LibgenDesktop/Models/Settings/Mirrors.cs @@ -4,6 +4,14 @@ namespace LibgenDesktop.Models.Settings { internal class Mirrors : Dictionary { + internal class DatabaseDumpManualDownloadConfiguration + { + public string NonFictionFileNameTemplate { get; set; } + public string FictionFileNameTemplate { get; set; } + public string SciMagFileNameTemplate { get; set; } + public string DateTemplate { get; set; } + } + internal class MirrorConfiguration { public string NonFictionDownloadUrl { get; set; } @@ -16,6 +24,9 @@ internal class MirrorConfiguration public string SciMagDownloadUrl { get; set; } public string SciMagDownloadTransformations { get; set; } public bool RestartSessionOnTimeout { get; set; } + public string DatabaseDumpPageUrl { get; set; } + public string DatabaseDumpPageTransformation { get; set; } + public DatabaseDumpManualDownloadConfiguration DatabaseDumpManualDownload { get; set; } } } } diff --git a/LibgenDesktop/Models/SqlDump/PositioningStreamReader.cs b/LibgenDesktop/Models/SqlDump/PositioningStreamReader.cs index 2ddac02..081bc9d 100644 --- a/LibgenDesktop/Models/SqlDump/PositioningStreamReader.cs +++ b/LibgenDesktop/Models/SqlDump/PositioningStreamReader.cs @@ -54,5 +54,11 @@ public override void Write(byte[] buffer, int offset, int count) { throw new NotImplementedException(); } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + baseStream?.Dispose(); + } } } diff --git a/LibgenDesktop/Models/SqlDump/SqlDumpReader.cs b/LibgenDesktop/Models/SqlDump/SqlDumpReader.cs index 3af67f7..ae61942 100644 --- a/LibgenDesktop/Models/SqlDump/SqlDumpReader.cs +++ b/LibgenDesktop/Models/SqlDump/SqlDumpReader.cs @@ -37,6 +37,8 @@ public ParsedColumnDefinition(string columnName, ColumnType columnType) public ColumnType ColumnType { get; set; } } + public static string[] SUPPORTED_DUMP_FILE_EXTENSIONS = new[] { ".zip", ".rar", ".gz", ".7z", ".sql" }; + private readonly StreamReader streamReader; private readonly ZipArchive zipArchive; private readonly RarArchive rarArchive; @@ -47,7 +49,11 @@ public ParsedColumnDefinition(string columnName, ColumnType columnType) public SqlDumpReader(string filePath) { - string fileExtension = Path.GetExtension(filePath); + string fileExtension = Path.GetExtension(filePath).ToLower(); + if (!SUPPORTED_DUMP_FILE_EXTENSIONS.Contains(fileExtension)) + { + throw new Exception($"{fileExtension} is not in the list of supported database dump file extensions."); + } switch (fileExtension.ToLower()) { case ".zip": @@ -118,9 +124,11 @@ public bool ReadLine() public ParsedTableDefinition ParseTableDefinition() { - ParsedTableDefinition result = new ParsedTableDefinition(); - result.TableName = ParseTableName(CurrentLine); - result.Columns = new List(); + ParsedTableDefinition result = new ParsedTableDefinition + { + TableName = ParseTableName(CurrentLine), + Columns = new List() + }; bool tableParsed = false; while (ReadLine()) { @@ -226,7 +234,7 @@ protected virtual void Dispose(bool disposing) } } - private string ParseTableName(string line) + private static string ParseTableName(string line) { int position = "CREATE TABLE".Length; int tableNameStartPosition = 0; @@ -257,7 +265,7 @@ private string ParseTableName(string line) throw new Exception($"Couldn't parse table name from the line:\r\n{line}"); } - private string ParseString(string line, ref int position) + private static string ParseString(string line, ref int position) { bool openQuote = false; bool closingQuote = false; diff --git a/LibgenDesktop/Models/SqlDump/TableDefinitions.cs b/LibgenDesktop/Models/SqlDump/TableDefinitions.cs index a0fb11d..acc947f 100644 --- a/LibgenDesktop/Models/SqlDump/TableDefinitions.cs +++ b/LibgenDesktop/Models/SqlDump/TableDefinitions.cs @@ -63,57 +63,32 @@ public NonFictionTableDefinition() internal class FictionTableDefinition : TableDefinition { public FictionTableDefinition() - : base("main", TableType.FICTION) + : base("fiction", TableType.FICTION) { AddColumn("ID", ColumnType.INT, (book, value) => book.LibgenId = ParseInt(value)); - AddColumn("AuthorFamily1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorFamily1 = value); - AddColumn("AuthorName1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorName1 = value); - AddColumn("AuthorSurname1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorSurname1 = value); - AddColumn("Role1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Role1 = value); - AddColumn("Pseudonim1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pseudonim1 = value); - AddColumn("AuthorFamily2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorFamily2 = value); - AddColumn("AuthorName2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorName2 = value); - AddColumn("AuthorSurname2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorSurname2 = value); - AddColumn("Role2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Role2 = value); - AddColumn("Pseudonim2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pseudonim2 = value); - AddColumn("AuthorFamily3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorFamily3 = value); - AddColumn("AuthorName3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorName3 = value); - AddColumn("AuthorSurname3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorSurname3 = value); - AddColumn("Role3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Role3 = value); - AddColumn("Pseudonim3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pseudonim3 = value); - AddColumn("AuthorFamily4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorFamily4 = value); - AddColumn("AuthorName4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorName4 = value); - AddColumn("AuthorSurname4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorSurname4 = value); - AddColumn("Role4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Role4 = value); - AddColumn("Pseudonim4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pseudonim4 = value); - AddColumn("Series1", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Series1 = value); - AddColumn("Series2", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Series2 = value); - AddColumn("Series3", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Series3 = value); - AddColumn("Series4", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Series4 = value); - AddColumn("Title", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Title = value); - AddColumn("Extension", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Format = value); - AddColumn("Version", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Version = value); - AddColumn("Filesize", ColumnType.INT, (book, value) => book.SizeInBytes = ParseLong(value)); AddColumn("MD5", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Md5Hash = value); - AddColumn("Path", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Path = value); + AddColumn("Title", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Title = value); + AddColumn("Author", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Authors = value); + AddColumn("Series", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Series = value); + AddColumn("Edition", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Edition = value); AddColumn("Language", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Language = value); - AddColumn("Pages", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pages = value); - AddColumn("Identifier", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Identifier = value); AddColumn("Year", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Year = value); AddColumn("Publisher", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Publisher = value); - AddColumn("Edition", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Edition = value); - AddColumn("Commentary", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Commentary = value); - AddColumn("TimeAdded", ColumnType.TIMESTAMP, (book, value) => book.AddedDateTime = ParseNullableDateTime(value)); - AddColumn("TimeLastModified", ColumnType.TIMESTAMP, (book, value) => book.LastModifiedDateTime = ParseDateTime(value)); - AddColumn("RussianAuthorFamily", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.RussianAuthorFamily = value); - AddColumn("RussianAuthorName", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.RussianAuthorName = value); - AddColumn("RussianAuthorSurname", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.RussianAuthorSurname = value); - AddColumn("Cover", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Cover = value); + AddColumn("Pages", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Pages = value); + AddColumn("Identifier", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Identifier = value); AddColumn("GooglebookID", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.GoogleBookId = value); AddColumn("ASIN", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Asin = value); - AddColumn("AuthorHash", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.AuthorHash = value); - AddColumn("TitleHash", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.TitleHash = value); + AddColumn("Coverurl", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.CoverUrl = value); + AddColumn("Extension", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Format = value); + AddColumn("Filesize", ColumnType.INT, (book, value) => book.SizeInBytes = ParseInt(value)); + AddColumn("Library", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Library = value); + AddColumn("Issue", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Issue = value); + AddColumn("Locator", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Locator = value); + AddColumn("Commentary", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Commentary = value); + AddColumn("Generic", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Generic = value); AddColumn("Visible", ColumnType.CHAR_OR_VARCHAR, (book, value) => book.Visible = value); + AddColumn("TimeAdded", ColumnType.TIMESTAMP, (book, value) => book.AddedDateTime = ParseNullableDateTime(value)); + AddColumn("TimeLastModified", ColumnType.TIMESTAMP, (book, value) => book.LastModifiedDateTime = ParseNullableDateTime(value)); } } diff --git a/LibgenDesktop/Models/Update/Updater.cs b/LibgenDesktop/Models/Update/Updater.cs index f5390f8..2821755 100644 --- a/LibgenDesktop/Models/Update/Updater.cs +++ b/LibgenDesktop/Models/Update/Updater.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; using LibgenDesktop.Common; +using LibgenDesktop.Models.Download; using Newtonsoft.Json; using static LibgenDesktop.Common.Constants; using Environment = LibgenDesktop.Common.Environment; @@ -47,8 +49,15 @@ public UpdateCheckEventArgs(UpdateCheckResult result) public UpdateCheckResult Result { get; } } + internal class UpdateDownloadResult + { + public DownloadUtils.DownloadResult DownloadResult { get; set; } + public string DownloadFilePath { get; set; } + } + private readonly string expectedAssetName; private HttpClient httpClient; + private string updateUrl; private Timer timer; private string ignoreReleaseName; private bool disposed; @@ -57,6 +66,7 @@ public Updater() { expectedAssetName = GetExpectedAssetName(); httpClient = null; + updateUrl = null; timer = null; ignoreReleaseName = null; disposed = false; @@ -64,9 +74,10 @@ public Updater() public event EventHandler UpdateCheck; - public void Configure(HttpClient httpClient, DateTime? nextUpdateCheck, string ignoreReleaseName) + public void Configure(HttpClient httpClient, string updateUrl, DateTime? nextUpdateCheck, string ignoreReleaseName) { this.httpClient = httpClient; + this.updateUrl = updateUrl; this.ignoreReleaseName = ignoreReleaseName; if (timer != null) { @@ -102,21 +113,16 @@ public async Task CheckForUpdateAsync(bool ignoreSpecifiedRel UpdateCheckResult result = null; if (httpClient != null) { - string url = GITHUB_RELEASE_API_URL; - Logger.Debug($"Sending a request to {url}"); - HttpResponseMessage response = await httpClient.GetAsync(url); - Logger.Debug($"Response status code: {(int)response.StatusCode} {response.StatusCode}."); - Logger.Debug("Response headers:", response.Headers.ToString().TrimEnd(), response.Content.Headers.ToString().TrimEnd()); - if (response.StatusCode != HttpStatusCode.OK) + DownloadUtils.DownloadPageResult downloadPageResult = await DownloadUtils.DownloadPageAsync(httpClient, updateUrl, + CancellationToken.None); + if (downloadPageResult.HttpStatusCode != HttpStatusCode.OK) { - throw new Exception($"GitHub API returned {(int)response.StatusCode} {response.StatusCode}."); + throw new Exception($"GitHub API returned {(int)downloadPageResult.HttpStatusCode} {downloadPageResult.HttpStatusCode}."); } - string responseContent = await response.Content.ReadAsStringAsync(); - Logger.Debug("Response content:", responseContent); List releases; try { - releases = JsonConvert.DeserializeObject>(responseContent); + releases = JsonConvert.DeserializeObject>(downloadPageResult.PageContent); } catch (Exception exception) { @@ -141,6 +147,21 @@ public async Task CheckForUpdateAsync(bool ignoreSpecifiedRel return result; } + public async Task DownloadUpdateAsync(UpdateCheckResult updateCheckResult, IProgress progressHandler, + CancellationToken cancellationToken) + { + UpdateDownloadResult result = new UpdateDownloadResult(); + string downloadDirectory = Path.Combine(Environment.AppDataDirectory, "Updates"); + if (!Directory.Exists(downloadDirectory)) + { + Directory.CreateDirectory(downloadDirectory); + } + result.DownloadFilePath = Path.Combine(downloadDirectory, updateCheckResult.FileName); + result.DownloadResult = await DownloadUtils.DownloadFileAsync(httpClient, updateCheckResult.DownloadUrl, result.DownloadFilePath, false, + progressHandler, cancellationToken); + return result; + } + private void TimerTick() { UpdateCheckResult updateCheckResult; diff --git a/LibgenDesktop/Models/Utils/FileUtils.cs b/LibgenDesktop/Models/Utils/FileUtils.cs index ba87711..f728958 100644 --- a/LibgenDesktop/Models/Utils/FileUtils.cs +++ b/LibgenDesktop/Models/Utils/FileUtils.cs @@ -38,7 +38,7 @@ public static string RemoveInvalidFileNameCharacters(string fileName, string emp } } - [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] + [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName, out ulong lpFreeBytesAvailable, out ulong lpTotalNumberOfBytes, out ulong lpTotalNumberOfFreeBytes); diff --git a/LibgenDesktop/Models/Utils/UrlGenerator.cs b/LibgenDesktop/Models/Utils/UrlGenerator.cs index 12fac09..2a312ad 100644 --- a/LibgenDesktop/Models/Utils/UrlGenerator.cs +++ b/LibgenDesktop/Models/Utils/UrlGenerator.cs @@ -18,148 +18,120 @@ static UrlGenerator() regex = new Regex("{([^}]+)}"); nonFictionTransformations = new Dictionary> { - { "id", book => book.LibgenId.ToString() }, - { "title", book => book.Title }, - { "volume", book => book.VolumeInfo }, - { "series", book => book.Series }, - { "periodical", book => book.Periodical }, - { "authors", book => book.Authors }, - { "year", book => book.Year }, - { "edition", book => book.Edition }, - { "publisher", book => book.Publisher }, - { "city", book => book.City }, - { "pages", book => book.Pages }, - { "pages-in-file", book => book.PagesInFile.ToString() }, - { "language", book => book.Language }, - { "topic", book => book.Topic }, - { "library", book => book.Library }, - { "issue", book => book.Issue }, - { "isbn", book => book.Identifier }, - { "issn", book => book.Issn }, - { "asin", book => book.Asin }, - { "udc", book => book.Udc }, - { "lbc", book => book.Lbc }, - { "ddc", book => book.Ddc }, - { "lcc", book => book.Lcc }, - { "doi", book => book.Doi }, - { "google-book-id", book => book.GoogleBookId }, - { "open-library-id", book => book.OpenLibraryId }, - { "commentary", book => book.Commentary }, - { "dpi", book => book.Dpi.ToString() }, - { "color", book => book.Color }, - { "cleaned", book => book.Cleaned }, - { "orientation", book => book.Orientation }, - { "paginated", book => book.Paginated }, - { "scanned", book => book.Scanned }, - { "bookmarked", book => book.Bookmarked }, - { "searchable", book => book.Searchable }, - { "size", book => book.SizeInBytes.ToString() }, - { "ext", book => book.Format }, - { "md5", book => book.Md5Hash }, - { "generic", book => book.Generic }, - { "visible", book => book.Visible }, - { "locator", book => book.Locator }, - { "local", book => book.Local.ToString() }, - { "added", book => book.AddedDateTime.ToString("yyyy-MM-dd HH:mm:ss") }, - { "last-modified", book => book.LastModifiedDateTime.ToString("yyyy-MM-dd HH:mm:ss") }, - { "cover-url", book => book.CoverUrl }, - { "tags", book => book.Tags }, - { "isbn-plain", book => book.IdentifierPlain }, - { "thousand-index", book => (book.LibgenId / 1000).ToString("D4") }, - { "thousand-bucket", book => (book.LibgenId / 1000 * 1000).ToString() } + ["id"] = book => book.LibgenId.ToString(), + ["title"] = book => book.Title, + ["volume"] = book => book.VolumeInfo, + ["series"] = book => book.Series, + ["periodical"] = book => book.Periodical, + ["authors"] = book => book.Authors, + ["year"] = book => book.Year, + ["edition"] = book => book.Edition, + ["publisher"] = book => book.Publisher, + ["city"] = book => book.City, + ["pages"] = book => book.Pages, + ["pages-in-file"] = book => book.PagesInFile.ToString(), + ["language"] = book => book.Language, + ["topic"] = book => book.Topic, + ["library"] = book => book.Library, + ["issue"] = book => book.Issue, + ["isbn"] = book => book.Identifier, + ["issn"] = book => book.Issn, + ["asin"] = book => book.Asin, + ["udc"] = book => book.Udc, + ["lbc"] = book => book.Lbc, + ["ddc"] = book => book.Ddc, + ["lcc"] = book => book.Lcc, + ["doi"] = book => book.Doi, + ["google-book-id"] = book => book.GoogleBookId, + ["open-library-id"] = book => book.OpenLibraryId, + ["commentary"] = book => book.Commentary, + ["dpi"] = book => book.Dpi.ToString(), + ["color"] = book => book.Color, + ["cleaned"] = book => book.Cleaned, + ["orientation"] = book => book.Orientation, + ["paginated"] = book => book.Paginated, + ["scanned"] = book => book.Scanned, + ["bookmarked"] = book => book.Bookmarked, + ["searchable"] = book => book.Searchable, + ["size"] = book => book.SizeInBytes.ToString(), + ["ext"] = book => book.Format, + ["md5"] = book => book.Md5Hash, + ["generic"] = book => book.Generic, + ["visible"] = book => book.Visible, + ["locator"] = book => book.Locator, + ["local"] = book => book.Local.ToString(), + ["added"] = book => book.AddedDateTime.ToString("yyyy-MM-dd HH:mm:ss"), + ["last-modified"] = book => book.LastModifiedDateTime.ToString("yyyy-MM-dd HH:mm:ss"), + ["cover-url"] = book => book.CoverUrl, + ["tags"] = book => book.Tags, + ["isbn-plain"] = book => book.IdentifierPlain, + ["thousand-index"] = book => (book.LibgenId / 1000).ToString("D4"), + ["thousand-bucket"] = book => (book.LibgenId / 1000 * 1000).ToString() }; fictionTransformations = new Dictionary> { - { "id", book => book.LibgenId.ToString() }, - { "title", book => book.Title }, - { "authors", book => book.Authors }, - { "series", book => book.Series }, - { "russian-author", book => book.RussianAuthor }, - { "author1-last-name", book => book.AuthorFamily1 }, - { "author1-first-name", book => book.AuthorName1 }, - { "author1-surname", book => book.AuthorSurname1 }, - { "author1-role", book => book.Role1 }, - { "author1-pseudonim", book => book.Pseudonim1 }, - { "author2-last-name", book => book.AuthorFamily2 }, - { "author2-first-name", book => book.AuthorName2 }, - { "author2-surname", book => book.AuthorSurname2 }, - { "author2-role", book => book.Role2 }, - { "author2-pseudonim", book => book.Pseudonim2 }, - { "author3-last-name", book => book.AuthorFamily3 }, - { "author3-first-name", book => book.AuthorName3 }, - { "author3-surname", book => book.AuthorSurname3 }, - { "author3-role", book => book.Role3 }, - { "author3-pseudonim", book => book.Pseudonim3 }, - { "author4-last-name", book => book.AuthorFamily4 }, - { "author4-first-name", book => book.AuthorName4 }, - { "author4-surname", book => book.AuthorSurname4 }, - { "author4-role", book => book.Role4 }, - { "author4-pseudonim", book => book.Pseudonim4 }, - { "series1", book => book.Series1 }, - { "series2", book => book.Series2 }, - { "series3", book => book.Series3 }, - { "series4", book => book.Series4 }, - { "ext", book => book.Format }, - { "version", book => book.Version }, - { "size", book => book.SizeInBytes.ToString() }, - { "md5", book => book.Md5Hash }, - { "path", book => book.Path }, - { "language", book => book.Language }, - { "pages", book => book.Pages }, - { "isbn", book => book.Identifier }, - { "year", book => book.Year }, - { "publisher", book => book.Publisher }, - { "edition", book => book.Edition }, - { "commentary", book => book.Commentary }, - { "added", book => book.AddedDateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? String.Empty }, - { "last-modified", book => book.LastModifiedDateTime.ToString("yyyy-MM-dd HH:mm:ss") }, - { "russian-author-last-name", book => book.RussianAuthorFamily }, - { "russian-author-first-name", book => book.RussianAuthorName }, - { "russian-author-surname", book => book.RussianAuthorSurname }, - { "cover", book => book.Cover }, - { "google-book-id", book => book.GoogleBookId }, - { "asin", book => book.Asin }, - { "author-hash", book => book.AuthorHash }, - { "title-hash", book => book.TitleHash }, - { "visible", book => book.Visible }, - { "thousand-index", book => (book.LibgenId / 1000).ToString("D4") }, - { "thousand-bucket", book => (book.LibgenId / 1000 * 1000).ToString() } + ["id"] = book => book.LibgenId.ToString(), + ["md5"] = book => book.Md5Hash, + ["title"] = book => book.Title, + ["authors"] = book => book.Authors, + ["series"] = book => book.Series, + ["edition"] = book => book.Edition, + ["language"] = book => book.Language, + ["year"] = book => book.Year, + ["publisher"] = book => book.Publisher, + ["pages"] = book => book.Pages, + ["isbn"] = book => book.Identifier, + ["google-book-id"] = book => book.GoogleBookId, + ["asin"] = book => book.Asin, + ["cover-url"] = book => book.CoverUrl, + ["ext"] = book => book.Format, + ["size"] = book => book.SizeInBytes.ToString(), + ["library"] = book => book.Library, + ["issue"] = book => book.Issue, + ["locator"] = book => book.Locator, + ["commentary"] = book => book.Commentary, + ["generic"] = book => book.Generic, + ["visible"] = book => book.Visible, + ["added"] = book => book.AddedDateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? String.Empty, + ["last-modified"] = book => book.LastModifiedDateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? String.Empty, + ["thousand-index"] = book => (book.LibgenId / 1000).ToString("D4"), + ["thousand-bucket"] = book => (book.LibgenId / 1000 * 1000).ToString() }; sciMagTransformations = new Dictionary> { - { "id", article => article.LibgenId.ToString() }, - { "title", article => article.Title }, - { "authors", article => article.Authors }, - { "doi", article => article.Doi }, - { "doi2", article => article.Doi2 }, - { "year", article => article.Year }, - { "month", article => article.Month }, - { "day", article => article.Day }, - { "volume", article => article.Volume }, - { "issue", article => article.Issue }, - { "first-page", article => article.FirstPage }, - { "last-page", article => article.LastPage }, - { "journal", article => article.Journal }, - { "isbn", article => article.Isbn }, - { "issnp", article => article.Issnp }, - { "issne", article => article.Issne }, - { "md5", article => article.Md5Hash }, - { "size", article => article.SizeInBytes.ToString() }, - { "added", article => article.AddedDateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? String.Empty }, - { "journal-id", article => article.JournalId }, - { "abstract-url", article => article.AbstractUrl }, - { "attribute1", article => article.Attribute1 }, - { "attribute2", article => article.Attribute2 }, - { "attribute3", article => article.Attribute3 }, - { "attribute4", article => article.Attribute4 }, - { "attribute5", article => article.Attribute5 }, - { "attribute6", article => article.Attribute6 }, - { "visible", article => article.Visible }, - { "pubmed-id", article => article.PubmedId }, - { "pmc", article => article.Pmc }, - { "pii", article => article.Pii }, - { "thousand-index", book => (book.LibgenId / 1000).ToString("D4") }, - { "thousand-bucket", book => (book.LibgenId / 1000 * 1000).ToString() } + ["id"] = article => article.LibgenId.ToString(), + ["title"] = article => article.Title, + ["authors"] = article => article.Authors, + ["doi"] = article => article.Doi, + ["doi2"] = article => article.Doi2, + ["year"] = article => article.Year, + ["month"] = article => article.Month, + ["day"] = article => article.Day, + ["volume"] = article => article.Volume, + ["issue"] = article => article.Issue, + ["first-page"] = article => article.FirstPage, + ["last-page"] = article => article.LastPage, + ["journal"] = article => article.Journal, + ["isbn"] = article => article.Isbn, + ["issnp"] = article => article.Issnp, + ["issne"] = article => article.Issne, + ["md5"] = article => article.Md5Hash, + ["size"] = article => article.SizeInBytes.ToString(), + ["added"] = article => article.AddedDateTime?.ToString("yyyy-MM-dd HH:mm:ss") ?? String.Empty, + ["journal-id"] = article => article.JournalId, + ["abstract-url"] = article => article.AbstractUrl, + ["attribute1"] = article => article.Attribute1, + ["attribute2"] = article => article.Attribute2, + ["attribute3"] = article => article.Attribute3, + ["attribute4"] = article => article.Attribute4, + ["attribute5"] = article => article.Attribute5, + ["attribute6"] = article => article.Attribute6, + ["visible"] = article => article.Visible, + ["pubmed-id"] = article => article.PubmedId, + ["pmc"] = article => article.Pmc, + ["pii"] = article => article.Pii, + ["thousand-index"] = book => (book.LibgenId / 1000).ToString("D4"), + ["thousand-bucket"] = book => (book.LibgenId / 1000 * 1000).ToString() }; } diff --git a/LibgenDesktop/Resources/Languages/English.lng b/LibgenDesktop/Resources/Languages/English.lng index 0487d07..27da70e 100644 --- a/LibgenDesktop/Resources/Languages/English.lng +++ b/LibgenDesktop/Resources/Languages/English.lng @@ -39,24 +39,156 @@ "About": "About" } }, - "CreateDatabaseWindow": + "SetupWizardWindow": { "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Welcome to Libgen Desktop.", - "DatabaseNotFound": "Database {database} not found.", - "DatabaseCorrupted": "Database {database} is corrupted.", - "LibgenServerDatabase": "Database {database} is a Libgen Server database which is not compatible with the Libgen Desktop database structure.", - "ChooseOption": "Choose an action", - "CreateNewDatabase": "Create a new database", - "OpenExistingDatabase": "Open an existing database", - "BrowseNewDatabaseDialogTitle": "New database location", - "BrowseExistingDatabaseDialogTitle": "Existing database location", - "Databases": "Databases", - "AllFiles": "All files", - "Error": "Error", - "CannotCreateDatabase": "Couldn't create database.", - "Ok": "OK", - "Cancel": "CANCEL" + "LanguageStep": + { + "ChooseLanguage": "Please choose your language:" + }, + "SetupModeStep": + { + "WelcomeAndChooseOption": "Welcome to Libgen Desktop. Choose an option:", + "FirstTimeUser": "I am running Libgen Desktop for the first time", + "ExperiencedUser": "I am an experienced Libgen Desktop user" + }, + "DatabaseOperationStep": + { + "ChooseAction": "Please choose an action:", + "CreateNewDatabase": "Create a new database", + "OpenExistingDatabase": "Open an existing database" + }, + "DownloadModeStep": + { + "ChooseDownloadMode": "Choose the way you want to download database dumps:", + "DownloadManagerMode": "Let Libgen Desktop download them", + "UseProxyServer": "Use proxy server", + "ProxySettings": "SETTINGS...", + "BrowserMode": "I want to download them myself" + }, + "StepListStep": + { + "StepListHeader": "Libgen Desktop first time setup", + "Step": "Step {step}", + "DownloadingDumps": "Downloading database dumps", + "CreatingDatabase": "Creating a Libgen Desktop database", + "ImportingDumps": "Importing database dumps into the Libgen Desktop database", + "ClickNextButton": "Click Next button to start the setup." + }, + "ProxySettingsWindow": + { + "WindowTitle": "Proxy server settings", + "ProxyAddress": "Address", + "ProxyAddressRequired": "Required field", + "ProxyPort": "Port", + "ProxyPortValidation": "Numbers from {min} to {max}", + "ProxyUserName": "User name", + "ProxyPassword": "Password", + "ProxyPasswordWarning": "Storing the password here is not secure.", + "Ok": "OK", + "Cancel": "CANCEL" + }, + "DownloadDumpInfoStep": + { + "DownloadingDumpInfo": "Please wait. Downloading database dump information...", + "CannotDownloadDumpInfo": "Couldn't download database dump information.", + "Interrupt": "INTERRUPT", + "Interrupting": "INTERRUPTING...", + "Retry": "RETRY" + }, + "CollectionsStep": + { + "ChooseCollections": "Choose collections you want to use in Libgen Desktop:", + "NonFiction": "Non-fiction books", + "Fiction": "Fiction books", + "SciMagArticles": "Scientific articles", + "DownloadSizeExact": "Download size: {size}", + "DownloadSizeApproximate": "Download size: approximately {size}", + "DatabaseSize": "Database size: approximately {size}", + "ImportTimeInMinutes": "Import time: {from}–{to} minutes", + "ImportTimeInHours": "Import time: {from}–{to} hours", + "DownloadInto": "Download into:", + "BrowseDirectoryDialogTitle": "Download database dumps into...", + "ErrorWarningTitle": "Error", + "NoCollectionsSelected": "At least one collection needs to be selected.", + "DirectoryNotFound": "Directory {directory} doesn't exist. Please choose a different directory." + }, + "DownloadDumpsStep": + { + "NonFictionDumpName": "Non-fiction books database dump", + "FictionDumpName": "Fiction books database dump", + "SciMagArticlesDumpName": "Scientific articles database dump", + "QueuedStatus": "Queued", + "DownloadingStatus": "Downloading", + "StoppedStatus": "Stopped", + "ErrorStatus": "Error", + "DownloadProgress": "Downloaded {downloaded} of {total} bytes ({percent}%)", + "Interrupt": "INTERRUPT", + "Interrupting": "INTERRUPTING...", + "Retry": "RETRY" + }, + "DownloadDumpLinksStep": + { + "OpenPage": "Open the database dump list page in your browser:", + "CopyLink": "Copy link", + "DownloadFiles": "Then download the following files:", + "NonFictionDumpName": "Non-fiction books database dump", + "FictionDumpName": "Fiction books database dump", + "SciMagArticlesDumpName": "Scientific articles database dump", + "FileName": "File name: {file}", + "YYYY": "YYYY", + "MM": "MM", + "DD": "DD", + "MostRecentDateNote": "where {dateTemplate} is the most recent date available in the list." + }, + "CreateDatabaseStep": + { + "DatabaseFilePathPrompt": "Please choose the path where you want to store the new database file:", + "DatabaseCreated": "Libgen Desktop database has been successfully created.", + "CannotCreateDatabase": "Couldn't create Libgen Desktop database.", + "DiskSpaceRequirementsNote": "You will need approximately {size} of free disk space.", + "SelectDatabaseFilePathDialogTitle": "New Libgen Desktop database location", + "Databases": "Databases", + "AllFiles": "All files", + "CreateDatabase": "CREATE DATABASE", + "CreatingDatabase": "CREATING DATABASE...", + "DatabaseFileOverwritePromptTitle": "Overwrite database file?", + "DatabaseFileOverwritePromptText": "File {file} already exists. Do you want to overwrite it?" + }, + "ImportDumpsStep": + { + "NonFictionDumpName": "Non-fiction books database dump", + "FictionDumpName": "Fiction books database dump", + "SciMagArticlesDumpName": "Scientific articles database dump", + "Status": "Status: {status}", + "NotImported": "not imported yet", + "Importing": "importing...", + "ImportSuccessful": "imported successfully", + "ImportCancelled": "import cancelled", + "ImportError": "import error", + "ImportButton": "IMPORT...", + "ImportingButton": "IMPORTING...", + "DeleteDumps": "Delete database dump files after successful import" + }, + "ConfirmationStep": + { + "StepHeader": "Setup is complete", + "SettingsHeader": "Some settings for you to consider before you finish the setup:", + "AllowInternetConnection": "Allow Libgen Desktop to connect to the internet", + "UseDownloadManager": "Use built-in download manager to download books and articles", + "UseBrowser": "Open download URLs in a browser", + "YouCanChangeSettings": "You can change these settings at any time." + }, + "StepHeaderTemplate": "Step {current} of {total}: {header}", + "DownloadingDumpsStepHeader": "Downloading database dumps", + "CreatingDatabaseStepHeader": "Creating a Libgen Desktop database", + "ImportingDumpsStepHeader": "Importing database dumps into the Libgen Desktop database", + "Back": "BACK", + "Next": "NEXT", + "Finish": "FINISH", + "Cancel": "CANCEL", + "ExitSetupTitle": "Exit setup", + "ExitSetupText": "The setup hasn't been completed yet. Are you sure you want to exit?" }, "SearchTab": { @@ -89,6 +221,7 @@ "Details": "Details", "Open": "Open", "Download": "Download", + "Copy": "Copy", "ErrorMessageTitle": "Error", "FileNotFoundError": "File {file} not found.", "OfflineModeIsOnMessageTitle": "Offline mode is on", @@ -108,6 +241,7 @@ "Authors": "Authors", "Series": "Series", "Year": "Year", + "Language": "Language", "Publisher": "Publisher", "Format": "Format", "FileSize": "File Size", @@ -126,6 +260,7 @@ "Authors": "Authors", "Series": "Series", "Year": "Year", + "Language": "Language", "Publisher": "Publisher", "Format": "Format", "FileSize": "File Size", @@ -224,7 +359,6 @@ { "Title": "Title", "Authors": "Authors", - "RussianAuthor": "Author in Russian", "Series": "Series", "Publisher": "Publisher", "Edition": "Edition", @@ -232,8 +366,9 @@ "Language": "Language", "Format": "Format", "Pages": "Pages", - "Version": "Version", "FileSize": "File Size", + "Library": "Library", + "Issue": "Issue", "Added": "Added", "LastModified": "Last Modified", "Md5Hash": "MD5 hash", @@ -325,6 +460,13 @@ "ImportCancelled": "Import has been cancelled by the user.", "DataNotFound": "Couldn't find the data to import.", "InsufficientDiskSpace": "Insufficient disk space.", + "WrongTableFound": "Expected to find {expected} but found {found}.", + "ExpectedNonFictionTable": "non-fiction book table", + "ExpectedFictionTable": "fiction book table", + "ExpectedSciMagTable": "scientific article table", + "FoundNonFictionTable": "non-fiction book table", + "FoundFictionTable": "fiction book table", + "FoundSciMagTable": "scientific article table", "ImportError": "An error occurred during the import." } }, @@ -424,7 +566,6 @@ "Id": "ID", "Title": "Title", "Authors": "Authors", - "RussianAuthor": "Author in Russian", "Series": "Series", "Publisher": "Publisher", "Edition": "Edition", @@ -432,8 +573,9 @@ "Language": "Language", "Format": "Format", "Pages": "Pages", - "Version": "Version", "FileSize": "File Size", + "Library": "Library", + "Issue": "Issue", "Added": "Added", "LastModified": "Last Modified", "Md5Hash": "MD5 hash", @@ -564,9 +706,29 @@ "Databases": "Databases", "AllFiles": "All files", "Error": "Error", - "CannotOpenDatabase": "An error occurred while trying to open database file: {file}", + "DatabaseNotValid": "File {file} is not a valid Libgen Desktop database.", + "DatabaseDumpFile": "It seems that {file} is a database dump and not a Libgen Desktop database file.", + "LibgenServerDatabase": "Database {database} is a Libgen Server database which is not compatible with the Libgen Desktop database structure.", + "OldFictionSchemaTitle": "Delete fiction collection?", + "OldFictionSchemaText": "Database {database} has an outdated database structure. Starting from February 2020 the main Libgen mirror uses a new database structure for its fiction collection. You need to download and import a new fiction database dump in order to continue using this collection in Libgen Desktop. Do you want to delete the fiction collection from this database now?", "Close": "CLOSE" }, + "DatabaseError": + { + "WindowTitle": "Libgen Desktop", + "DatabaseNotFound": "Database {database} not found.", + "DatabaseNotValid": "File {file} is not a valid Libgen Desktop database.", + "DatabaseDumpFile": "It seems that {file} is a database dump and not a Libgen Desktop database file. Start setup wizard to import it.", + "LibgenServerDatabase": "Database {database} is a Libgen Server database which is not compatible with the Libgen Desktop database structure.", + "OldFictionSchema": "Database {database} has an outdated database structure. Starting from February 2020 the main Libgen mirror uses a new database structure for its fiction collection. You need to download and import a new fiction database dump in order to continue using this collection in Libgen Desktop.", + "HeaderTemplate": "{error} Choose an action:", + "OpenAnotherDatabase": "Open another database", + "StartSetupWizard": "Start setup wizard", + "DeleteFiction": "Delete current fiction collection and continue", + "Exit": "Exit Libgen Desktop", + "Ok": "OK", + "Cancel": "CANCEL" + }, "SqlDebugger": { "WindowTitle": "SQL debugger", @@ -660,6 +822,7 @@ { "TabHeader": "General", "Language": "Language", + "PercentTranslated": "{percent}% translated", "CheckUpdates": "Check for the application updates", "UpdateCheckIntervals": { @@ -680,7 +843,7 @@ "ProxyPortValidation": "Numbers from {min} to {max}", "ProxyUserName": "User name", "ProxyPassword": "Password", - "ProxyPasswordWarning": "Storing the password here is insecure." + "ProxyPasswordWarning": "Storing password here is not secure." }, "Download": { diff --git a/LibgenDesktop/Resources/Languages/French.lng b/LibgenDesktop/Resources/Languages/French.lng index 048667e..2edcc02 100644 --- a/LibgenDesktop/Resources/Languages/French.lng +++ b/LibgenDesktop/Resources/Languages/French.lng @@ -38,24 +38,6 @@ "About": "À propos" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Bienvenue dans Libgen Desktop.", - "DatabaseNotFound": "La base de données {database} est introuvable.", - "DatabaseCorrupted": "La base de données {database} est corrompue.", - "ChooseOption": "Choisissez une action ", - "CreateNewDatabase": "Créer une nouvelle base de donnée", - "OpenExistingDatabase": "Ouvrir une base de données existante", - "BrowseNewDatabaseDialogTitle": "Emplacement de la nouvelle base de données", - "BrowseExistingDatabaseDialogTitle": "Emplacement de la base de données existante", - "Databases": "Bases de données", - "AllFiles": "Tous les fichiers", - "Error": "Erreur", - "CannotCreateDatabase": "La base de données n'a pas pu être créée.", - "Ok": "OK", - "Cancel": "ANNULER" - }, "SearchTab": { "TabTitle": "Recherche", @@ -212,7 +194,6 @@ { "Title": "Titre ", "Authors": "Auteurs ", - "RussianAuthor": "Auteur en russe ", "Series": "Série ", "Publisher": "Éditeur ", "Edition": "Édition ", @@ -220,7 +201,6 @@ "Language": "Langue ", "Format": "Format ", "Pages": "Pages ", - "Version": "Version ", "FileSize": "Taille du fichier ", "Added": "Ajouté ", "LastModified": "Dernière modification ", @@ -410,7 +390,6 @@ "Id": "ID", "Title": "Titre", "Authors": "Auteurs", - "RussianAuthor": "Auteur en russe", "Series": "Série", "Publisher": "Éditeur", "Edition": "Édition", @@ -418,7 +397,6 @@ "Language": "Langue", "Format": "Format", "Pages": "Pages", - "Version": "Version", "FileSize": "Taille du fichier", "Added": "Ajouté", "LastModified": "Dernière modification", diff --git a/LibgenDesktop/Resources/Languages/Italian.lng b/LibgenDesktop/Resources/Languages/Italian.lng new file mode 100644 index 0000000..65974db --- /dev/null +++ b/LibgenDesktop/Resources/Languages/Italian.lng @@ -0,0 +1,745 @@ +{ + "General": + { + "Name": "Italian", + "LocalizedName": "Italiano", + "CultureCode": "it-IT", + "TranslatorName": "k4mp" + }, + "Formatting": + { + "DecimalSeparator": ".", + "ThousandsSeparator": ",", + "DateFormat": "MM/dd/yyyy", + "TimeFormat": "hh:mm:ss tt", + "FileSizePostfixes": + { + "Byte": "bytes", + "Kilobyte": "KB", + "Megabyte": "MB", + "Gigabyte": "GB", + "Terabyte": "TB" + } + }, + "MainWindow": + { + "WindowTitle": "Libgen Desktop", + "MainMenu": + { + "DownloadManagerTooltip": "Gestore Download", + "BookmarksTooltip": "Preferiti", + "NoBookmarks": "Nessun preferito", + "Update": "Aggiorna...", + "Import": "Importa...", + "Synchronize": "Sincronizza...", + "Library": "BIblioteca", + "Database": "Database...", + "SqlDebugger": "SQL debugger", + "Settings": "Impostazioni", + "About": "Info" + } + }, + "SearchTab": + { + "TabTitle": "Cerca", + "SearchPlaceHolder": "Cerca", + "NonFictionSelector": "Libri", + "FictionSelector": "Romanzi", + "SciMagSelector": "Articoli scientifici", + "NonFictionSearchBoxTooltip": "Cerca per titolo, autori, serie, editore, e ISBN senza -", + "FictionSearchBoxTooltip": "Cerca per titolo, autori, serie, editore, e ISBN con -", + "SciMagSearchBoxTooltip": "Cerca per titolo, autori, nome della rivista, DOI, Pubmed ID, e ISSN (p/e)", + "SearchInProgress": "Ricerca in corso...", + "NonFictionSearchProgress": "Libri trovati: {count}", + "FictionSearchProgress": "Romanzi trovati: {count}", + "SciMagSearchProgress": "Articoli trovati: {count}", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE IN CORSO...", + "DatabaseIsEmpty": "Il database è vuoto. Scarica un dump del database dal sito Library Genesis e importalo.", + "ImportButton": "Importa" + }, + "SearchResultsTabs": + { + "SearchPlaceHolder": "Cerca", + "SearchInProgress": "Ricerca in corso...", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE IN CORSO...", + "AddToBookmarksTooltip": "Aggiungi ai preferiti", + "RemoveFromBookmarksTooltip": "Rimuovi dai preferiti", + "ExportButtonTooltip": "Esporta i risultati della ricerca in un file", + "Details": "Dettagli", + "Open": "Apri", + "Download": "Download", + "ErrorMessageTitle": "Errore", + "FileNotFoundError": "File {file} non trovato.", + "OfflineModeIsOnMessageTitle": "Modalità offline attiva", + "OfflineModeIsOnMessageText": "Il download è disabilitato in modalità offline. Puoi disattivarla da Impostazioni.", + "NoDownloadMirrorError": "Non è stato selezionato un mirror di download. Per favore selezionare un mirror da Impostazioni.", + "LargeNumberOfItemsToDownloadPromptTitle": "Numero di elementi da scaricare elevato", + "LargeNumberOfItemsToDownloadPromptText": "Stai per scaricare {number} elementi. Vuoi proseguire?" + }, + "NonFictionSearchResultsTab": + { + "SearchBoxTooltip": "Cerca per titolo, autori, serie, editore, e ISBN senza -", + "SearchProgress": "Libri trovati: {count}", + "StatusBar": "Libri trovati: {count}", + "Columns": + { + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Year": "Anno", + "Publisher": "Editore", + "Format": "Formato", + "FileSize": "Dimensioni", + "Ocr": "OCR", + "InLocalLibrary": "Nella biblioteca locale" + } + }, + "FictionSearchResultsTab": + { + "SearchBoxTooltip": "Cerca per titolo, autori, serie, editore, e ISBN con -", + "SearchProgress": "Romanzi trovati: {count}", + "StatusBar": "Romanzi trovati: {count}", + "Columns": + { + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Year": "Anno", + "Publisher": "Editore", + "Format": "Formato", + "FileSize": "Dimensioni", + "InLocalLibrary": "Nella biblioteca locale" + } + }, + "SciMagSearchResultsTab": + { + "SearchBoxTooltip": "Cerca per titolo, autori, nome della rivista, DOI, Pubmed ID, e ISSN (p/e)", + "SearchProgress": "Articoli trovati: {count}", + "StatusBar": "Articoli trovati: {count}", + "Columns": + { + "Title": "Titolo", + "Authors": "Autori", + "Magazine": "Rivista", + "Year": "Anno", + "FileSize": "Dimensioni", + "Doi": "DOI", + "InLocalLibrary": "Nella biblioteca locale" + } + }, + "DetailsTabs": + { + "CoverIsLoading": "Capicamento copertina...", + "NoCover": "Nessuna copertina disponibile", + "NoCoverMirror": "Non è stat selezionato un mirror{new-line}per caricare questa copertina", + "NoCoverDueToOfflineMode": "modalità offline attiva.{new-line}copertina non caricata.", + "CoverLoadingError": "Impossibile caricare copertina", + "Yes": "sì", + "No": "no", + "Unknown": "sconosciuto", + "Portrait": "verticale", + "Landscape": "orizzontale", + "CopyContextMenu": "Copia \"{text}\"", + "Download": "DOWNLOAD", + "DownloadFromMirror": "DOWNLOAD DA {mirror}", + "Queued": "IN CODA", + "Downloading": "IN DOWNLOAD", + "Stopped": "FERMO", + "Error": "ERRORE DI DOWNLOAD", + "Open": "APRI FILE", + "ErrorMessageTitle": "Errore", + "FileNotFoundError": "File {file} non trovato.", + "NoDownloadMirrorTooltip": "non è stato selezionato un mirror", + "OfflineModeIsOnTooltip": "modalità offline attiva", + "Close": "CHIUDI" + }, + "NonFictionDetailsTab": + { + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Publisher": "Editore", + "Year": "Anno", + "Language": "LIngua", + "Format": "Formato", + "Isbn": "ISBN", + "Added": "Aggiunto", + "LastModified": "Ultima modifica", + "Library": "Biblioteca", + "FileSize": "Dimensione", + "Topics": "Argomenti", + "Volume": "Volume", + "Magazine": "Rivista", + "City": "Città", + "Edition": "Edizione", + "Pages": "Pagine", + "BodyMatterPages": "Contenuti", + "TotalPages": "totali", + "Tags": "Tags", + "Md5Hash": "MD5 hash", + "Comments": "Commenti", + "Identifiers": "Identificatori", + "LibgenId": "Libgen ID", + "Issn": "ISSN", + "Udc": "UDC", + "Lbc": "LBC", + "Lcc": "LCC", + "Ddc": "DDC", + "Doi": "DOI", + "OpenLibraryId": "Open Library ID", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN", + "AdditionalAttributes": "Attributi aggiuntivi", + "Dpi": "DPI", + "Ocr": "OCR", + "TableOfContents": "Tabella dei contenuti", + "Scanned": "Scansione", + "Orientation": "Orientatamento", + "Paginated": "Impaginazione", + "Colored": "Colorato", + "Cleaned": "Pulito" + }, + "FictionDetailsTab": + { + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Publisher": "Editore", + "Edition": "Edizione", + "Year": "Anno", + "Language": "Lingua", + "Format": "Formato", + "Pages": "Pagine", + "FileSize": "Dimensioni", + "Added": "Aggiunto", + "LastModified": "Ultima modifica", + "Md5Hash": "MD5 hash", + "Comments": "Commenti", + "Identifiers": "Identificatori", + "LibgenId": "Libgen ID", + "Isbn": "ISBN", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN" + }, + "SciMagDetailsTab": + { + "Title": "Titolo", + "Authors": "Autori", + "Magazine": "Rivista", + "Year": "Anno", + "Month": "Mese", + "Day": "Giorno", + "Volume": "Volume", + "Issue": "Numero", + "Pages": "Pagine", + "FileSize": "Dimensioni", + "AddedDateTime": "Aggiunto", + "Md5Hash": "MD5 hash", + "AbstractUrl": "Abstract URL", + "Identifiers": "Identificatori", + "LibgenId": "Libgen ID", + "Doi": "DOI", + "Isbn": "ISBN", + "MagazineId": "Magazine ID", + "Issnp": "ISSN (p)", + "Issne": "ISSN (e)", + "PubmedId": "Pubmed ID", + "Pmc": "PMC", + "Pii": "PII", + "AdditionalAttributes": "Attributi aggiuntivi", + "Attribute1": "Attributo 1", + "Attribute2": "Attributo 2", + "Attribute3": "Attributo 3", + "Attribute4": "Attributo 4", + "Attribute5": "Attributo 5", + "Attribute6": "Attributo 6" + }, + "Import": + { + "WindowTitle": "Importa da dump SQL", + "BrowseImportFileDialogTitle": "Posizione del dump SQL", + "AllSupportedFiles": "Tutti i file supportati", + "SqlDumps": "Dump SQL", + "Archives": "Archivi", + "AllFiles": "Tutti i file", + "Elapsed": "Tempo trascorso: {elapsed}", + "FreeSpace": "Spazio libero sul dispositivo: {freeSpace}", + "Unknown": "Sconosciuto", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE IN CORSO...", + "Close": "CHIUDI", + "StatusMessages": + { + "Step": "Passaggio {current} di {total}.", + "DataLookup": "Creazione struttura dati", + "CreatingIndexes": "Creazione indici", + "LoadingIds": "Caricamento identificatori", + "ImportingData": "Importazione dati", + "ImportComplete": "Importazione completa", + "ImportCancelled": "Importazione cancellata", + "DataNotFound": "Dati non trovati", + "ImportError": "Importazione fallita" + }, + "LogMessages": + { + "Step": "Passaggio {step}", + "DataLookup": "Ricerca definizioni della table", + "Scanning": "Scansione...", + "ScannedProgress": "{percent}% dei file sono stati scansionati...", + "NonFictionTableFound": "Trovata tabella libri.", + "FictionTableFound": "Trovata tabella romanzi.", + "SciMagTableFound": "Trovata tabella articoli scinetifici.", + "CreatingIndexes": "Creazione indici mancanti", + "CreatingIndexForColumn": "Creazione indici per la colonna {column} ...", + "LoadingIds": "Caricamento identificatori dei dati noti", + "LoadingColumnValues": "Caricamento dati della colonna {column} ...", + "ImportingData": "Importazione dati", + "ImportBooksProgressNoUpdate": "Libri aggiunti: {added}.", + "ImportBooksProgressWithUpdate": "Libri aggiunti: {added}, Aggiornati: {updated}.", + "ImportArticlesProgressNoUpdate": "Articoli aggiunti: {added}.", + "ImportArticlesProgressWithUpdate": "Articoli aggiunti: {added}, Aggiornati: {updated}.", + "ImportSuccessful": "Importazione completata con successo.", + "ImportCancelled": "Importtazione annullata da utente.", + "DataNotFound": "Impossibile trovare i dati da importare.", + "InsufficientDiskSpace": "Spazio su disco insufficiente.", + "ImportError": "Eddore durante l'importazione." + } + }, + "ExportPanel": + { + "Header": "Esporta i risultati di ricerca in un file", + "Format": "Formato file", + "Excel": "Microsoft Excel 2007-2016 (XLSX)", + "Csv": "Comma-separated values (CSV)", + "Separator": "Separatore", + "Comma": "Comma", + "Semicolon": "Semicolon", + "Tab": "Tab character", + "SaveAs": "Salva come", + "Browse": "Naviga...", + "BrowseDialogTitle": "Esporta risultati della ricerca", + "ExcelFiles": "Microsoft Excel files", + "CsvFiles": "CSV files", + "TsvFiles": "TSV files", + "AllFiles": "All files", + "ExportRange": "Intervallo di esportazione", + "NoLimit": "Tutto", + "Limit": "Solo i primi {count} risultati", + "Export": "ESPORTA", + "Cancel": "ANNULLA", + "SavingFile": "Salvataggio file.", + "RowCountSingleFile": "Righe esportate: {rows}.", + "RowCountMultipleFiles": "Riche esportate: {rows}, file creati: {files}.", + "ErrorWarningTitle": "Errore", + "InvalidExportPath": "Percorso file di esportazione non valido.", + "DirectoryNotFound": "La cartella {directory} non esiste.", + "InvalidExportFileName": "Nome del file di esportazione non valido.", + "OverwritePromptTitle": "sovrascrivere questo file?", + "OverwritePromptText": "File {file} already exists. Do you want to overwrite it?", + "RowLimitWarningTitle": "Row limit", + "RowLimitWarningText": "Il limite massimo di Microsoft Excel è stato raggiunto.L'esportazione è stata interrotta. Per esportare grandi file abilita \"Dividi in file multipli\" nelle impostazioni.", + "ExportError": "Errore durante l'importazione.", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE...", + "ExportInterrupted": "L'esportazione è stata interrotta.", + "Results": "Apri risultati", + "Close": "CHIUDI" + }, + "Exporter": + { + "Yes": "sì", + "No": "no", + "Unknown": "sconosciuto", + "Portrait": "verticale", + "Landscape": "orizzontale", + "NonFictionColumns": + { + "Id": "ID", + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Publisher": "Editore", + "Year": "Anno", + "Language": "Lingua", + "Format": "Formato", + "Isbn": "ISBN", + "Added": "Aggiunto", + "LastModified": "Ultima modifica", + "Library": "Biblioteca", + "FileSize": "Dimensioni", + "Topics": "Argomenti", + "Volume": "Volume", + "Magazine": "Rivista", + "City": "Città", + "Edition": "Edizione", + "BodyMatterPages": "Pagine (Contenuti)", + "TotalPages": "Pagine (Totali)", + "Tags": "Tags", + "Md5Hash": "MD5 hash", + "Comments": "Commenti", + "LibgenId": "Libgen ID", + "Issn": "ISSN", + "Udc": "UDC", + "Lbc": "LBC", + "Lcc": "LCC", + "Ddc": "DDC", + "Doi": "DOI", + "OpenLibraryId": "Open Library ID", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN", + "Dpi": "DPI", + "Ocr": "OCR", + "TableOfContents": "Tabella dei contenuti", + "Scanned": "Scansione", + "Orientation": "Orientamento", + "Paginated": "Impaginazione", + "Colored": "Colorato", + "Cleaned": "Pulito" + }, + "FictionColumns": + { + "Id": "ID", + "Title": "Titolo", + "Authors": "Autori", + "Series": "Serie", + "Publisher": "Editore", + "Edition": "Edizione", + "Year": "Anno", + "Language": "Lingua", + "Format": "Formato", + "Pages": "Pagine", + "FileSize": "Dimensioni", + "Added": "Aggiunto", + "LastModified": "Ultima modifica", + "Md5Hash": "MD5 hash", + "Comments": "Commenti", + "LibgenId": "Libgen ID", + "Isbn": "ISBN", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN" + }, + "SciMagColumns": + { + "Id": "ID", + "Title": "Titolo", + "Authors": "Autori", + "Magazine": "Rivista", + "Year": "Anno", + "Month": "Mese", + "Day": "Giorno", + "Volume": "Volume", + "Issue": "Numero", + "Pages": "Pagine", + "FileSize": "Dimensioni", + "AddedDateTime": "Aggiunti", + "Md5Hash": "MD5 hash", + "AbstractUrl": "Abstract URL", + "LibgenId": "Libgen ID", + "Doi1": "DOI 1", + "Doi2": "DOI 2", + "Isbn": "ISBN", + "MagazineId": "Magazine ID", + "Issnp": "ISSN (p)", + "Issne": "ISSN (e)", + "PubmedId": "Pubmed ID", + "Pmc": "PMC", + "Pii": "PII", + "Attribute1": "Attributo 1", + "Attribute2": "Attributo 2", + "Attribute3": "Attributo 3", + "Attribute4": "Attributo 4", + "Attribute5": "Attributo 5", + "Attribute6": "Attributo 6" + } + }, + "Synchronization": + { + "WindowTitle": "Sincronizzazione lista libri", + "ErrorMessageTitle": "Errore", + "ImportRequired": "Il dump del database dei libri deve essere completato per poter avviare la sincronizzazione", + "NoSynchronizationMirror": "Non è stato selezionato un mirror per la sincronizzazione dei libri", + "OfflineModePromptTitle": "Modalità offline", + "OfflineModePromptText": "Non è possibile avviare la sincronizzazione se è attiva la modalità offline. Disattivarla?", + "Elapsed": "Tempo trascorso: {elapsed}", + "FreeSpace": "Spazio libero sul dispositivo: {freeSpace}", + "Unknown": "Sconosciuto", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE...", + "Close": "CHIUDI", + "StatusMessages": + { + "Step": "Passaggio {current} di {total}.", + "Preparation": "Preparazione alla sincronizzazione", + "CreatingIndexes": "Creazione indici", + "LoadingIds": "Caricamento identificatori", + "SynchronizingData": "Sincronizzazione dati", + "SynchronizationComplete": "Sincronizzazione completa", + "SynchronizationCancelled": "Sincronizzazione annullata", + "SynchronizationError": "Sincronizzazione fallita" + }, + "LogMessages": + { + "Step": "Passaggio {step}", + "CreatingIndexes": "Creazione indici mancanti", + "CreatingIndexForColumn": "Creazione indice per la colonna {column} ...", + "LoadingIds": "Caricamento identificatori dati esistenti", + "LoadingColumnValues": "Caricamento dati colonna {column} ...", + "SynchronizingBookList": "Sincronizzazione lista libri", + "DownloadingNewBooks": "Scaricamento metadati nuovi libri", + "SynchronizationProgressNoAddedNoUpdated": "Libri scaricati: {downloaded}.", + "SynchronizationProgressAdded": "Libri scaricati: {downloaded}, aggiunti: {added}.", + "SynchronizationProgressUpdated": "Libri scaricati: {downloaded}, aggiornati: {updated}.", + "SynchronizationProgressAddedAndUpdated": "Libri scaricati: {downloaded}, aggiunti: {added}, aggiornati: {updated}.", + "SynchronizationSuccessful": "Sincronizzazione completata con successo.", + "SynchronizationCancelled": "Sincronizzazione cancellata da utente.", + "InsufficientDiskSpace": "Spazio su disco insufficiente.", + "SynchronizationError": "Errore durante la sincronizzazione: {error}" + } + }, + "Library": + { + "TabTitle": "Biblioteca", + "ScanNonFiction": "SCANSIONA IN ROMANZI...", + "ScanFiction": "SCANSIONA IN LIBRI...", + "ScanSciMag": "SCANSIONA IN ARICOLI SCIENTIFICI...", + "BrowseDirectoryDialogTitle": "Scansiona in...", + "ScanStarted": "Scansione iniziata nella cartella {directory}", + "CreatingIndexes": "Attendere. Creazione indici mancanti...", + "Found": "Trovati ({count})", + "AddAll": "AGGIUNGI TUTTI ALLA BIBLIOTECA", + "Adding": "AGGIUNTA FILE ALLA BIBLIOTECA...", + "Added": "FILE AGGIUNTI ALLA BIBLIOTECA", + "NotFound": "Mancanti ({count})", + "ScanLog": "Scan log", + "Error": "errore", + "ScanComplete": "Scansione completa. Trovati: {found}, mancanti: {notFound}, errori: {errors}.", + "Columns": + { + "File": "File", + "Authors": "Autori", + "Title": "Titolo" + } + }, + "Database": + { + "WindowTitle": "Informazioni database", + "CurrentDatabase": "Database corrente:", + "NonFiction": "Libri", + "Fiction": "Romanzi", + "SciMagArticles": "Articoli scientifici", + "TotalBooks": "Libri totali", + "TotalArticles": "Articoli totali", + "LastUpdate": "Ultimi aggiornamenti", + "Never": "mai", + "IndexesRequiredTitle": "Indici del database", + "IndexesRequiredText": "Libgen Desktop necessita degli indici mancanti e può crearli. questa operazine può richiedere molto tempo (1 ora) e non può essere interrotta. Proseguire?", + "CreatingIndexes": "Per favore attendere. Creazione indici mancanti del database...{new-line}Questa operazione non può essere interrotta.", + "ChangeDatabase": "CAMBIA DATABASE...", + "BrowseDatabaseDialogTitle": "PErcordo file del database", + "Databases": "Database", + "AllFiles": "Tutti i file", + "Error": "Errore", + "CannotOpenDatabase": "Errore durante l'apertura del database: {file}", + "Close": "CHIUDI" + }, + "SqlDebugger": + { + "WindowTitle": "SQL debugger", + "SqlQueryTextBoxHeader": "Inserisci query SQL", + "Copy": "COPIA NEGLI APPUNTI", + "Close": "CHIUDI" + }, + "DownloadManager": + { + "TabTitle": "Downloads", + "Start": "AVVIA", + "Stop": "STOP", + "Remove": "RIMUOVI", + "StartAll": "AVVIA TUTTI", + "StopAll": "FERMA TUTTI", + "RemoveCompleted": "RIMUOVI COMPLETATI", + "QueuedStatus": "In coda", + "DownloadingStatus": "In download", + "StoppedStatus": "Fermati", + "RetryDelayStatus": "Ritardo nuovo tentativo", + "ErrorStatus": "Errore", + "DownloadProgressKnownFileSize": "Scaricati {downloaded} di {total} bytes ({percent}%)", + "DownloadProgressUnknownFileSize": "Scaricati {downloaded} bytes sconosciuti", + "Log": "Log", + "TechnicalDetails": "Dettagli tecnici", + "Copy": "Copia negli appunti", + "FileNotFoundErrorTitle": "Errore", + "FileNotFoundErrorText": "File {file} mancante.", + "LogMessages": + { + "Queued": "Aggiunto alla coda di download.", + "Started": "Avviato.", + "Stopped": "Fermato.", + "RetryDelay": "Ritardo {count} secondi...", + "Completed": "Download completo.", + "OfflineModeIsOn": "Modalità offline attiva.", + "TransformationError": "Trasformazione {transformation} fallita.", + "TransformationReturnedIncorrectUrl": "Transformazine {transformation} ha restituito un URL non valido.", + "Attempt": "Tentativo {current} di {total}.", + "MaximumDownloadAttempts": "E' stato raggiunto il limite massimo di tentativi di download.", + "DownloadingPage": "Download della pagina: {url}", + "DownloadingFile": "Download del file: {url}", + "StartingFileDownloadKnownFileSize": "Download del file avviato, dimensione file: {size} bytes.", + "StartingFileDownloadUnknownFileSize": "Download del file avviato, dimensione file: sconosciuta.", + "ResumingFileDownloadKnownFileSize": "Ripreso download del file, dimensione parte rimanente: {remaining} bytes.", + "ResumingFileDownloadUnknownFileSize": "Ripreso download del file, dimensione parte rimanente; sconosciuta.", + "Request": "Richiesta", + "Response": "Risposta del server", + "Redirect": "Reindirizza a {url}", + "TooManyRedirects": "Ricevute troppe richieste di reindirizzamento dal server.", + "NonSuccessfulStatusCode": "Server ha restituito: {status}.", + "CannotCreateDownloadDirectory": "Impossibile creare la cartella {directory}", + "CannotCreateOrOpenFile": "Impossibile aprire o creare il file {file}", + "CannotRenamePartFile": "Impossibile rinominare il file {source} in {destination}.", + "HtmlPageReturned": "Server ha restituito una pagina HTML invece del file.", + "NoPartialDownloadSupport": "Server Non supporta download parziali.", + "NoContentLengthWarning": "Attenzione: server non ha fornito la dimensione del file.", + "ServerResponseTimeout": "Timeout risposta del server.", + "DownloadIncompleteError": "Server indica il download come completato, ma non è così.", + "FileWriteError": "Errore di scrittura.", + "LogLineRequestError": "Impossibile inviare richieste a {url}", + "IncorrectRedirectUrl": "Server ha restituito un redirect URL errato: {url}", + "UnexpectedError": "Errore: {error}" + } + }, + "ApplicationUpdate": + { + "WindowTitle": "Aggiorna applicazione", + "UpdateAvailable": "Una nuova versione di Libgen Desktop è disponibile", + "NewVersion": "Nuova versione: {version} rilasciata il {date}", + "Download": "DOWNLOAD", + "DownloadAndInstall": "DOWNLOAD E INSTALLA", + "SkipThisVersion": "SALTA QUESTA VERSIONE", + "Cancel": "ANNULLA", + "Interrupt": "INTERROMPI", + "Interrupting": "INTERRUZIONE...", + "InterruptPromptTitle": "Annullare il download?", + "InterruptPromptText": "Vuoi davvero annullare il download dell'aggiornamento?", + "Error": "Errore", + "IncompleteDownload": "Download dell'aggiornamento non completo.", + "Close": "CHIUDI" + }, + "Settings": + { + "WindowTitle": "Impostazioni", + "Ok": "OK", + "Cancel": "ANNULLA", + "DiscardChangesPromptTitle": "Annullare modifiche?", + "DiscardChangesPromptText": "Le impostazioni sono state modificate. Annullare le modifiche?", + "General": + { + "TabHeader": "Generali", + "Language": "Lingua", + "CheckUpdates": "Controlla disponibilità aggiornamenti", + "UpdateCheckIntervals": + { + "Never": "mai", + "Daily": "giornalmente", + "Weekly": "settimanalmente", + "Monthly": "mensilmente" + } + }, + "Network": + { + "TabHeader": "Rete", + "OfflineMode": "Modalità offline", + "UseHttpProxy": "Usa proxy HTTP", + "ProxyAddress": "Indirizzi", + "ProxyAddressRequired": "Campo richiesto", + "ProxyPort": "Porta", + "ProxyPortValidation": "da {min} a {max}", + "ProxyUserName": "User name", + "ProxyPassword": "Password", + "ProxyPasswordWarning": "Salvare la password qui non è sicuro." + }, + "Download": + { + "TabHeader": "Downloads", + "DownloadMode": "Modalità download", + "OpenInBrowser": "apri URL di download nel browser", + "UseDownloadManager": "usa il gestore di download interno", + "DownloadDirectory": "Download in", + "BrowseDirectoryDialogTitle": "Cartella download", + "DownloadDirectoryNotFound": "La cartella non esiste", + "Timeout": "Download scaduto", + "TimeoutValidation": "Numeri: {min} — {max}", + "Seconds": "secondi", + "DownloadAttempts": "Tentativi di download", + "DownloadAttemptsValidation": "Numeri: {min} — {max}", + "Times": "volte", + "RetryDelay": "Ritardo nuovo tentativo download", + "RetryDelayValidation": "Numeri: {min} — {max}" + }, + "Mirrors": + { + "TabHeader": "Mirrors", + "NonFiction": "Libri", + "Fiction": "Romanzi", + "SciMagArticles": "Articoli scinetifici", + "Books": "Libri", + "Articles": "Articoli", + "Covers": "Copertine", + "Synchronization": "Sincronizzazione", + "NoMirror": "nessun mirror" + }, + "Search": + { + "TabHeader": "Ricerca", + "LimitResults": "Limite risultati ricerca", + "MaximumResults": "Numero massimo risultati", + "PositiveNumbersOnly": "Solo numeri positivi", + "OpenDetails": "Apri dettagli libro / articolo:", + "InModalWindow": "in finestra modale", + "InNonModalWindow": "in finestra non modale", + "InNewTab": "in nuova finestra" + }, + "Export": + { + "TabHeader": "Esporta", + "OpenResults": "Apri rislutati dopo l'esportazione", + "SplitIntoMultipleFiles": "Dividi in file multipli", + "MaximumRowsPerFile": "Righe massime per file", + "MaximumRowsPerFileValidation": "Numeri da {min} a {max}", + "ExcelLimitNote": "Note: Microsoft Excel Non supporta file con più di {count} righe." + }, + "Advanced": + { + "TabHeader": "Avanzate", + "UseLogging": "Scrivi dati diagnostici in un file", + "EnableSqlDebugger": "Abilita SQL debugger" + } + }, + "About": + { + "WindowTitle": "Info Libgen Desktop", + "ApplicationName": "Libgen Desktop", + "Version": "Versione attuale: {version} rilasciata il {date}", + "CheckForUpdates": "CONTROLLA PER AGGIORNAMENTI", + "CheckingUpdates": "CONTROLLO PER AGGIORNAMENTI...", + "OfflineModeIsOnTooltip": "Modalità offline attiva", + "LatestVersion": "Stai usando la versione più recente.", + "NewVersionAvailable": "Nuova versione disponibile: {version} rilasciata il {date}", + "Update": "AGGIORNA", + "Translators": "Traduttori:" + }, + "MessageBox": + { + "Ok": "OK", + "Yes": "SI'", + "No": "NO" + }, + "ErrorWindow": + { + "WindowTitle": "Errore", + "UnexpectedError": "ERRORE NON PREVISTO", + "Copy": "COPIA NEGLI APPUNTI", + "Close": "CHIUDI" + } +} diff --git a/LibgenDesktop/Resources/Languages/Portuguse_BR.lng b/LibgenDesktop/Resources/Languages/Portuguse_BR.lng new file mode 100644 index 0000000..f0378f9 --- /dev/null +++ b/LibgenDesktop/Resources/Languages/Portuguse_BR.lng @@ -0,0 +1,745 @@ +{ + "General": + { + "Name": "Portuguese BR", + "LocalizedName": "Português BR", + "CultureCode": "pt-BR", + "TranslatorName": "Scoria" + }, + "Formatting": + { + "DecimalSeparator": ",", + "ThousandsSeparator": ".", + "DateFormat": "dd/MM/yyyy", + "TimeFormat": "hh:mm:ss tt", + "FileSizePostfixes": + { + "Byte": "bytes", + "Kilobyte": "KB", + "Megabyte": "MB", + "Gigabyte": "GB", + "Terabyte": "TB" + } + }, + "MainWindow": + { + "WindowTitle": "Libgen Desktop", + "MainMenu": + { + "DownloadManagerTooltip": "Gerenciador de Download", + "BookmarksTooltip": "Marcadores", + "NoBookmarks": "Sem Marcadores", + "Update": "Atualizar...", + "Import": "Importar...", + "Synchronize": "Sincronizar...", + "Library": "Coleção", + "Database": "Base de dados...", + "SqlDebugger": "Depurador SQL", + "Settings": "Configurações", + "About": "Sobre" + } + }, + "SearchTab": + { + "TabTitle": "Pesquisar", + "SearchPlaceHolder": "Pesquisa", + "NonFictionSelector": "Livros de não-ficção", + "FictionSelector": "Livros de ficção", + "SciMagSelector": "Artigos científicos", + "NonFictionSearchBoxTooltip": "Pesquisar por títulos, autores, séries, editoras, e ISBN sem traços", + "FictionSearchBoxTooltip": " Pesquisar por títulos, autores, séries, editoras, e ISBN sem traços", + "SciMagSearchBoxTooltip": "Pesquisar por títulos, autores, nome da revista, DOI, Pubmed ID, e ISSN (p/e)", + "SearchInProgress": "Pesquisa em progresso...", + "NonFictionSearchProgress": "Livros encontrados: {count}", + "FictionSearchProgress": "Livros encontrados: {count}", + "SciMagSearchProgress": "Artigos encontrados: {count}", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERROMPENDO...", + "DatabaseIsEmpty": "A base de dados está vazia. Faça um download de um dump de base de dados no site da Library Genesis e importe-o aqui.", + "ImportButton": "Importar" + }, + "SearchResultsTabs": + { + "SearchPlaceHolder": "Pesquisar", + "SearchInProgress": "Pesquisa em progresso...", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERRONPENDO...", + "AddToBookmarksTooltip": "Adicionar aos marcadores", + "RemoveFromBookmarksTooltip": "Remover dos marcadores", + "ExportButtonTooltip": "Exportar resultados de pesquisa para um arquivo", + "Details": "Detalhes", + "Open": "Abrir", + "Download": "Download", + "ErrorMessageTitle": "Erro", + "FileNotFoundError": "Arquivo {file} não encontrado.", + "OfflineModeIsOnMessageTitle": "Modo Offline está habilitado", + "OfflineModeIsOnMessageText": "O download é desativado enquanto o modo offline está habilitado. Você pode desligá-lo na janela de configurações.", + "NoDownloadMirrorError": "Nenhum espelho de download foi selecionado. Por favor, escolha um dos espelhos na janela de configurações.", + "LargeNumberOfItemsToDownloadPromptTitle": "Grande número de itens para download", + "LargeNumberOfItemsToDownloadPromptText": "Você está prestes a fazer download de {number} items. Você tem certeza?" + }, + "NonFictionSearchResultsTab": + { + "SearchBoxTooltip": "Pesquisa por título, autores, séries, editoras e ISBN sem traços", + "SearchProgress": "Livros encontrados: {count}", + "StatusBar": "Livros encontrados: {count}", + "Columns": + { + "Title": "Título", + "Authors": "Autores", + "Series": "Série", + "Year": "Ano", + "Publisher": "Editora", + "Format": "Formato", + "FileSize": "Tamanho", + "Ocr": "OCR", + "InLocalLibrary": "Na coleção local" + } + }, + "FictionSearchResultsTab": + { + "SearchBoxTooltip": "Pesquisa por título, autores, séries, editoras e ISBN com traços", + "SearchProgress": "Livros encontrados:{count}", + "StatusBar": "Livros encontrados:{count}", + "Columns": + { + "Title": "Título", + "Authors": "Autores", + "Series": "Série", + "Year": "Ano", + "Publisher": "Editora", + "Format": "Formato", + "FileSize": "Tamanho", + "InLocalLibrary": "Na coleção local" + } + }, + "SciMagSearchResultsTab": + { + "SearchBoxTooltip": "Pesquisa por título, autores, nome da revista, DOI, Pubmed ID e ISSN (p/e)", + "SearchProgress": "Artigos encontrados:{count}", + "StatusBar": "Artigos encontrados: {count}", + "Columns": + { + "Title": "Título", + "Authors": "Autores", + "Magazine": "Revista", + "Year": "Ano", + "FileSize": "Tamanho", + "Doi": "DOI", + "InLocalLibrary": "Na coleção local" + } + }, + "DetailsTabs": + { + "CoverIsLoading": "Carregando capa...", + "NoCover": "Sem capa dispónivel", + "NoCoverMirror": "Nenhum espelho foi selecionado{new-line}para carregar esta capa", + "NoCoverDueToOfflineMode": "Modo Offline está habilitado.{new-line}Capa não carregada.", + "CoverLoadingError": "Não foi possível carregar a capa", + "Yes": "sim", + "No": "não", + "Unknown": "desconhecido", + "Portrait": "retrato", + "Landscape": "paisagem", + "CopyContextMenu": "copiar \"{text}\"", + "Download": "DOWNLOAD", + "DownloadFromMirror": "DOWNLOAD a partir de {mirror}", + "Queued": "ENFILEIRADO", + "Downloading": "DOWNLOADING", + "Stopped": "INTERROMPIDO", + "Error": "ERRO DE DOWNLOAD", + "Open": "ABRIR ARQUIVO", + "ErrorMessageTitle": "Erro", + "FileNotFoundError": "Arquivo {file} não encontrado.", + "NoDownloadMirrorTooltip": "Nenhum espelho foi selecionado", + "OfflineModeIsOnTooltip": "O modo offline está habilitado", + "Close": "FECHAR" + }, + "NonFictionDetailsTab": + { + "Title": "Título", + "Authors": "Autores", + "Series": "Série", + "Publisher": "Editora", + "Year": "Ano", + "Language": "Idioma", + "Format": "Formato", + "Isbn": "ISBN", + "Added": "Adicionado", + "LastModified": "Última modificação", + "Library": "Coleção", + "FileSize": "Tamanho", + "Topics": "Tópicos", + "Volume": "Volume", + "Magazine": "Revista", + "City": "Cidade", + "Edition": "Edição", + "Pages": "Páginas", + "BodyMatterPages": "matéria corporal", + "TotalPages": "Total de páginas", + "Tags": "Tags", + "Md5Hash": "MD5 hash", + "Comments": "Comentários", + "Identifiers": "Identificadores", + "LibgenId": "Libgen ID", + "Issn": "ISSN", + "Udc": "UDC", + "Lbc": "LBC", + "Lcc": "LCC", + "Ddc": "DDC", + "Doi": "DOI", + "OpenLibraryId": "Open Library ID", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN", + "AdditionalAttributes": "Atributos adicionais", + "Dpi": "DPI", + "Ocr": "OCR", + "TableOfContents": "Tabela de Conteúdo", + "Scanned": "Escaneado", + "Orientation": "Orientação", + "Paginated": "Paginado", + "Colored": "Colorido", + "Cleaned": "Limpo" + }, + "FictionDetailsTab": + { + "Title": "Título", + "Authors": "Autores", + "Series": "Série", + "Publisher": "Editora", + "Edition": "Edição", + "Year": "Ano", + "Language": "Idioma", + "Format": "Formato", + "Pages": "Péginas", + "FileSize": "Tamanho", + "Added": "Adicionado", + "LastModified": "Última Modificação", + "Md5Hash": "MD5 hash", + "Comments": "Comentários", + "Identifiers": "Identificadores", + "LibgenId": "Libgen ID", + "Isbn": "ISBN", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN" + }, + "SciMagDetailsTab": + { + "Title": "Título", + "Authors": "Autores", + "Magazine": "Revista", + "Year": "Ano", + "Month": "Mês", + "Day": "Dia", + "Volume": "Volume", + "Issue": "Emissão", + "Pages": "Páginas", + "FileSize": "Tamanho", + "AddedDateTime": "Adicionado", + "Md5Hash": "MD5 hash", + "AbstractUrl": "Abstract URL", + "Identifiers": "Identificadores", + "LibgenId": "Libgen ID", + "Doi": "DOI", + "Isbn": "ISBN", + "MagazineId": "Revista ID", + "Issnp": "ISSN (p)", + "Issne": "ISSN (e)", + "PubmedId": "Pubmed ID", + "Pmc": "PMC", + "Pii": "PII", + "AdditionalAttributes": "Atributos adicionais", + "Attribute1": "Attribute 1", + "Attribute2": "Attribute 2", + "Attribute3": "Attribute 3", + "Attribute4": "Attribute 4", + "Attribute5": "Attribute 5", + "Attribute6": "Attribute 6" + }, + "Import": + { + "WindowTitle": "Importação de um dump SQL", + "BrowseImportFileDialogTitle": "Localização do dump SQL", + "AllSupportedFiles": "Todos os arquivos suportados", + "SqlDumps": "SQL dumps", + "Archives": "Arquivos", + "AllFiles": "Todos os arquivos", + "Elapsed": "Tempo decorrido:{elapsed}", + "FreeSpace": "Espaço livre no dispositivo: {freeSpace}", + "Unknown": "Desconhecido", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERROMPENDO...", + "Close": "FECHAR", + "StatusMessages": + { + "Step": "Passo{current} de {total}.", + "DataLookup": "Lookup de definição de tabela", + "CreatingIndexes": "Criando índices", + "LoadingIds": "Carregando identificadores", + "ImportingData": "Importando dados", + "ImportComplete": "Importação completa", + "ImportCancelled": "Importação foi cancelada", + "DataNotFound": "Dados não encontrados", + "ImportError": "Falha na importação" + }, + "LogMessages": + { + "Step": "Passo {step}", + "DataLookup": "Buscando as definições da tabela", + "Scanning": "Escane...", + "ScannedProgress": "{percent}% dos arquivos foi concluída...", + "NonFictionTableFound": "Tabela de livros de não-ficção encontrada.", + "FictionTableFound": "Tabela de livro de ficção encontrada.", + "SciMagTableFound": "Tabela de artigos científicos encontrada.", + "CreatingIndexes": "Criando índices faltando", + "CreatingIndexForColumn": " Criando índice para a coluna {column}...", + "LoadingIds": "Carregando identificadores de dados existentes", + "LoadingColumnValues": "Carregando dados para a coluna {column}...", + "ImportingData": "Importando Dados", + "ImportBooksProgressNoUpdate": "Livros adicionados:{added}.", + "ImportBooksProgressWithUpdate": "Livros adicionados:{added}, updated: {updated}.", + "ImportArticlesProgressNoUpdate": "Artigos adicionados: {added}.", + "ImportArticlesProgressWithUpdate": "Artigos adicionados: {added}, Atualizado: {updated}.", + "ImportSuccessful": "Importação concluída com sucesso.", + "ImportCancelled": "Importação foi cancelada pelo usuário.", + "DataNotFound": "Não foi possível encontrar os dados para importação.", + "InsufficientDiskSpace": "Espaço de disco insuficiente.", + "ImportError": "Um erro ocorreu durante a importação." + } + }, + "ExportPanel": + { + "Header": "Exportar resultados de pesquisa para um arquivo", + "Format": "Formato", + "Excel": "Microsoft Excel 2007-2016 (XLSX)", + "Csv": "Comma-separated values (CSV)", + "Separator": "Separador", + "Comma": "Vírgula", + "Semicolon": "Ponto", + "Tab": "Tab character", + "SaveAs": "Salve como", + "Browse": "Navegar...", + "BrowseDialogTitle": "Exportar resultados de pesquisa", + "ExcelFiles": "Arquivos Microsoft Excel", + "CsvFiles": "Arquivos CSV ", + "TsvFiles": "Arquivos TSV ", + "AllFiles": "Todos os arquivos", + "ExportRange": "Abrangência de exportação", + "NoLimit": "Tudo", + "Limit": "Primeiros {count} resultados apenas", + "Export": "EXPORTAR", + "Cancel": "CANCELAR", + "SavingFile": "Salvando o arquivo.", + "RowCountSingleFile": "Linhas exportadas: {rows}.", + "RowCountMultipleFiles": "Linhas exportadas: {rows}, arquivos criados: {files}.", + "ErrorWarningTitle": "Erro", + "InvalidExportPath": "Caminho inválido de arquivo de exportação.", + "DirectoryNotFound": "Diretório{directory} não existe.", + "InvalidExportFileName": "Nome de arquivo de exportação inválido.", + "OverwritePromptTitle": "Sobrescrever o arquivo?", + "OverwritePromptText": "Arquivo {file} já existe. Você quer sobrescrevê-lo?", + "RowLimitWarningTitle": "Limite de linhas", + "RowLimitWarningText": "Contagem máxima de linha foi alcançada para o Microsoft Excel. Exportação não pode ser continuada. Para exportar mais linhas, por favor, habilite a opção \"Dividir em vários arquivos\" nas configurações do aplicativo.", + "ExportError": "Um erro ocorreu durante a exportação.", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERROMPENDO...", + "ExportInterrupted": "Exportação foi interrompida.", + "Results": "ABRIR RESULTADOS", + "Close": "FECHAR" + }, + "Exporter": + { + "Yes": "SIM", + "No": "NÃO", + "Unknown": "desconhecido", + "Portrait": "retrato", + "Landscape": "paisagem", + "NonFictionColumns": + { + "Id": "ID", + "Title": "Título", + "Authors": "Autores", + "Series": "Série", + "Publisher": "Editora", + "Year": "Ano", + "Language": "Idioma", + "Format": "Formato", + "Isbn": "ISBN", + "Added": "Adicionado", + "LastModified": "Última Modificação", + "Library": "Coleção", + "FileSize": "Tamanho", + "Topics": "Tópicos", + "Volume": "Volume", + "Magazine": "Revista", + "City": "Cidade", + "Edition": "Edição", + "BodyMatterPages": "Páginas (Body Matter)", + "TotalPages": "Páginas (Total)", + "Tags": "Tags", + "Md5Hash": "MD5 hash", + "Comments": "Comentários", + "LibgenId": "Libgen ID", + "Issn": "ISSN", + "Udc": "UDC", + "Lbc": "LBC", + "Lcc": "LCC", + "Ddc": "DDC", + "Doi": "DOI", + "OpenLibraryId": "Open Library ID", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN", + "Dpi": "DPI", + "Ocr": "OCR", + "TableOfContents": "Tabela de Conteúdo", + "Scanned": "Escaneado", + "Orientation": "Orientação", + "Paginated": "Paginado", + "Colored": "Colorido", + "Cleaned": "Limpo" + }, + "FictionColumns": + { + "Id": "ID", + "Title": "Title", + "Authors": "Autores", + "Series": "Series", + "Publisher": "Publisher", + "Edition": "Edition", + "Year": "Year", + "Language": "Language", + "Format": "Format", + "Pages": "Pages", + "FileSize": "File Size", + "Added": "Added", + "LastModified": "Last Modified", + "Md5Hash": "MD5 hash", + "Comments": "Comments", + "LibgenId": "Libgen ID", + "Isbn": "ISBN", + "GoogleBookId": "Google Books ID", + "Asin": "ASIN" + }, + "SciMagColumns": + { + "Id": "ID", + "Title": "Título", + "Authors": "Autores", + "Magazine": "Revista", + "Year": "Ano", + "Month": "Mês", + "Day": "Dia", + "Volume": "Volume", + "Issue": "Emissão", + "Pages": "Páginas", + "FileSize": "Tamanho", + "AddedDateTime": "Adicionado", + "Md5Hash": "MD5 hash", + "AbstractUrl": "Abstract URL", + "LibgenId": "Libgen ID", + "Doi1": "DOI 1", + "Doi2": "DOI 2", + "Isbn": "ISBN", + "MagazineId": "Magazine ID", + "Issnp": "ISSN (p)", + "Issne": "ISSN (e)", + "PubmedId": "Pubmed ID", + "Pmc": "PMC", + "Pii": "PII", + "Attribute1": "Attribute 1", + "Attribute2": "Attribute 2", + "Attribute3": "Attribute 3", + "Attribute4": "Attribute 4", + "Attribute5": "Attribute 5", + "Attribute6": "Attribute 6" + } + }, + "Synchronization": + { + "WindowTitle": "Sincronização da lista de livros de não-ficção", + "ErrorMessageTitle": "Erro", + "ImportRequired": "A importação da base de dados de não-ficção precisa ser concluída para iniciar a sincronização.", + "NoSynchronizationMirror": "Nenhum espelho de sincronização de livros de não-ficção foi selecionado.", + "OfflineModePromptTitle": "Offline modo", + "OfflineModePromptText": "A sincronização não pode ser iniciada enquanto o modo offline está ligado. Você quer desligá-lo?", + "Elapsed": "Tempo decorrido: {elapsed}", + "FreeSpace": "Espaço livre no dispositivo: {freeSpace}", + "Unknown": "desconhecido", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERROMPENDO...", + "Close": "FECHAR", + "StatusMessages": + { + "Step": "Passo {current} de {total}.", + "Preparation": "Preparando-se para sincronização", + "CreatingIndexes": "Criando índices", + "LoadingIds": "Carregando identificadores ", + "SynchronizingData": "Sincronizando os dados", + "SynchronizationComplete": "Sincronização completa", + "SynchronizationCancelled": "A sincronização foi cancelada", + "SynchronizationError": "Sincronização falhou" + }, + "LogMessages": + { + "Step": "Passo {step}", + "CreatingIndexes": "Criando índices faltando", + "CreatingIndexForColumn": "Criando índice para a coluna {column}...", + "LoadingIds": "Carregando indentificadores de dados existentes", + "LoadingColumnValues": "Carregando dados para a coluna {column}...", + "SynchronizingBookList": "Sincronizando a lista de livros", + "DownloadingNewBooks": "Realizando download dos metadados dos novos livros...", + "SynchronizationProgressNoAddedNoUpdated": "Livros baixados: {downloaded}.", + "SynchronizationProgressAdded": "Livros baixados: {downloaded}, aicionados: {added}.", + "SynchronizationProgressUpdated": "Livros baixados: {downloaded}, atualizados: {updated}.", + "SynchronizationProgressAddedAndUpdated": "Livros baixados: {downloaded}, Adicionados: {added}, Atualizados: {updated}.", + "SynchronizationSuccessful": "A sincronização foi concluída com sucesso.", + "SynchronizationCancelled": "A sincronização foi cancelada pelo usuário.", + "InsufficientDiskSpace": "Espaço de disco insuficiente.", + "SynchronizationError": "Um erro ocorreu durante a sincronização: {error}" + } + }, + "Library": + { + "TabTitle": "Coleção", + "ScanNonFiction": "ESCANEAMENTO DE LIVROS DE NÃO-FICÇÃO...", + "ScanFiction": "ESCANEAMENTO DE LIVROS DE FICÇÃO...", + "ScanSciMag": "ESCANEAMENTO DE ARTIGOS CIENTÍFICOS...", + "BrowseDirectoryDialogTitle": "Escaneie em...", + "ScanStarted": "Escaneamento começou em {directory}", + "CreatingIndexes": "Aguarde. Criando índices de banco de dados ausentes...", + "Found": "Encontrado ({count})", + "AddAll": "ADICIONE TODOS OS ARQUIVOS ENCONTRADOS À COLEÇÃO", + "Adding": "ADICIONANDO ARQUIVOS À COLEÇÃO...", + "Added": "TODOS OS ARQUIVOS FORAM ADICIONADOS À COLEÇÃO", + "NotFound": "Não encontrado ({count})", + "ScanLog": "Log de varredura", + "Error": "erro", + "ScanComplete": "Escaneamento completo. Encontrado: {found}, não encontrado: {notFound}, erros: {errors}.", + "Columns": + { + "File": "Arquivo", + "Authors": "Autores", + "Title": "Título" + } + }, + "Database": + { + "WindowTitle": "Informação da base de dados", + "CurrentDatabase": "Base de dados atual:", + "NonFiction": "livros de não-ficção", + "Fiction": "Livros de ficção", + "SciMagArticles": "Artigos científicos", + "TotalBooks": "Total de livros", + "TotalArticles": "Total de artigos", + "LastUpdate": "Última atualização", + "Never": "Nunca", + "IndexesRequiredTitle": "Índices da base de dados", + "IndexesRequiredText": "Libgen Desktop precisa criar índices de base de dados ausentes. Esta operação pode levar muito tempo (mais de uma hora) e não pode ser interrompida. Você quer continuar?", + "CreatingIndexes": "Aguarde. Criando índices de base de dados ausentes...{new-line}Esta operação não pode ser interrompida.", + "ChangeDatabase": "MUDAR BASE DE DADOS...", + "BrowseDatabaseDialogTitle": "Localização do arquivo de base de dados", + "Databases": "Base de dados", + "AllFiles": "Todos os arquivos", + "Error": "Erro", + "CannotOpenDatabase": "Um erro ocorreu ao tentar abrir o arquivo de base de dados: {file}", + "Close": "FECHAR" + }, + "SqlDebugger": + { + "WindowTitle": "DEPURADOR SQL", + "SqlQueryTextBoxHeader": "Digite consulta SQL", + "Copy": "Copiar para área de transferência", + "Close": "FECHAR" + }, + "DownloadManager": + { + "TabTitle": "Downloads", + "Start": "INICIAR", + "Stop": "PARAR", + "Remove": "REMOVER", + "StartAll": "INICIAR TODOS", + "StopAll": "PARAR TODOS", + "RemoveCompleted": "REMOVER CONCLUÍDOS", + "QueuedStatus": "Enfileirado", + "DownloadingStatus": "Downloading", + "StoppedStatus": "Parado", + "RetryDelayStatus": "Delay de retentativa", + "ErrorStatus": "Erro", + "DownloadProgressKnownFileSize": "Baixado {downloaded} de {total} bytes ({percent}%)", + "DownloadProgressUnknownFileSize": "Baixado {downloaded} bytes de desconhecido", + "Log": "Log", + "TechnicalDetails": "Detalhes técnicos", + "Copy": "Copiar para área de transferência", + "FileNotFoundErrorTitle": "Erro", + "FileNotFoundErrorText": "Arquivo {file} não encontrado.", + "LogMessages": + { + "Queued": "Adicionado à fila de download.", + "Started": "Iniciado.", + "Stopped": "Parado.", + "RetryDelay": "Delay {count} segundos...", + "Completed": "Download concluído.", + "OfflineModeIsOn": "O modo offline está ligado.", + "TransformationError": "Transformação {transformation} falhou.", + "TransformationReturnedIncorrectUrl": "Transformação {transformation} retornou uma URL inválida.", + "Attempt": "Tentativa {current} de {total}.", + "MaximumDownloadAttempts": "Tentativas máximas de download foram alcançadas.", + "DownloadingPage": "Página de download: {url}", + "DownloadingFile": "Baixando arquivo: {url}", + "StartingFileDownloadKnownFileSize": "O download do arquivo começou, tamanho do arquivo: {size} bytes.", + "StartingFileDownloadUnknownFileSize": "Download de arquivos começou, tamanho do arquivo: desconhecido.", + "ResumingFileDownloadKnownFileSize": "O download do arquivo foi retomado, tamanho restante: {remaining} bytes.", + "ResumingFileDownloadUnknownFileSize": "Download de arquivos retomado, tamanho restante: desconhecido.", + "Request": "Solicitação", + "Response": "Resposta do servidor", + "Redirect": "Redirecionar para {url}", + "TooManyRedirects": "Muitas respostas redirecionadas foram recebidas do servidor.", + "NonSuccessfulStatusCode": "Servidor retornou:{status}.", + "CannotCreateDownloadDirectory": "Não foi possível criar diretório {directory}", + "CannotCreateOrOpenFile": "Não foi possível criar ou abrir o arquivo {file}", + "CannotRenamePartFile": "Não foi possível renomear o arquivo {source} no {destination}.", + "HtmlPageReturned": "Servidor retornou página HTML em vez do arquivo.", + "NoPartialDownloadSupport": "O servidor não suporta downloads parciais.", + "NoContentLengthWarning": "Aviso: o servidor não forneceu o tamanho do arquivo.", + "ServerResponseTimeout": "Tempo de resposta do servidor excedido.", + "DownloadIncompleteError": "Servidor indica que o download de arquivos está completo, mas não está.", + "FileWriteError": "Erro de gravação de arquivo.", + "LogLineRequestError": "Não foi possível enviar requisição para {url}", + "IncorrectRedirectUrl": "Servidor retornou redirecionamento incorreto de URL: {url}", + "UnexpectedError": "Ocorreu um erro inesperado:{error}" + } + }, + "ApplicationUpdate": + { + "WindowTitle": "Atualização do aplicativo", + "UpdateAvailable": "Nova versão do Libgen Desktop está disponível", + "NewVersion": "Nova versão: {version} lançado em {date}", + "Download": "DOWNLOAD", + "DownloadAndInstall": "FAÇA DOWNLOAD E INSTALE", + "SkipThisVersion": "PULE ESTA VERSÃO", + "Cancel": "CANCELAR", + "Interrupt": "INTERROMPER", + "Interrupting": "INTERROMPENDO...", + "InterruptPromptTitle": "Cancelar o download?", + "InterruptPromptText": "Você quer cancelar o download da atualização?", + "Error": "Erro", + "IncompleteDownload": "O download de atualização não está completo.", + "Close": "FECHAR" + }, + "Settings": + { + "WindowTitle": "Configurações", + "Ok": "OK", + "Cancel": "CANCELAR", + "DiscardChangesPromptTitle": "Descartar mudanças?", + "DiscardChangesPromptText": "As configurações foram alteradas. Tem certeza de descartar as mudanças?", + "General": + { + "TabHeader": "Geral", + "Language": "Idioma", + "CheckUpdates": "Verifique as atualizações do aplicativo", + "UpdateCheckIntervals": + { + "Never": "Nunca", + "Daily": "Diáriamente", + "Weekly": "Semanalmente", + "Monthly": "Mensalmente" + } + }, + "Network": + { + "TabHeader": "Rede", + "OfflineMode": "Modo Offline", + "UseHttpProxy": "Usar Proxy HTTP", + "ProxyAddress": "Endereço", + "ProxyAddressRequired": "Campo necessário", + "ProxyPort": "Porta", + "ProxyPortValidation": "Números de{min} a {max}", + "ProxyUserName": "Nome de usuário", + "ProxyPassword": "Senha", + "ProxyPasswordWarning": "Armazenar a senha aqui é inseguro." + }, + "Download": + { + "TabHeader": "Downloads", + "DownloadMode": "Modo de download", + "OpenInBrowser": "abrir URL de download no navegador", + "UseDownloadManager": "usar gerenciador de download interno", + "DownloadDirectory": "Fazer download em", + "BrowseDirectoryDialogTitle": "Diretório de download", + "DownloadDirectoryNotFound": "Diretório não existe", + "Timeout": "Tempo de excedimento de download", + "TimeoutValidation": "Números: {min} — {max}", + "Seconds": "Segundos", + "DownloadAttempts": "Tentativas de download", + "DownloadAttemptsValidation": "Números: {min} — {max}", + "Times": "Tentativas", + "RetryDelay": "Delay de retentativa de Download", + "RetryDelayValidation": "Números: {min} — {max}" + }, + "Mirrors": + { + "TabHeader": "Espelhos", + "NonFiction": "Livros de não-ficção", + "Fiction": "Livros de ficção", + "SciMagArticles": "Artigos científicos", + "Books": "Livros", + "Articles": "Artigos", + "Covers": "Capas", + "Synchronization": "Sincronização", + "NoMirror": "sem espelho" + }, + "Search": + { + "TabHeader": "Pesquisa", + "LimitResults": "Limite de resultados de pesquisa", + "MaximumResults": "Contagem máxima de resultados", + "PositiveNumbersOnly": "Números positivos apenas", + "OpenDetails": "Abrir livro / Detalhes de artigo:", + "InModalWindow": "em uma janela modal", + "InNonModalWindow": "em uma janela não modal", + "InNewTab": "em uma nova guia" + }, + "Export": + { + "TabHeader": "Exportação", + "OpenResults": "Abrir resultados após exportação", + "SplitIntoMultipleFiles": "Dividir em vários arquivos", + "MaximumRowsPerFile": "Linhas máximas por arquivo", + "MaximumRowsPerFileValidation": "Números de {min} até {max}", + "ExcelLimitNote": "Nota: Microsoft Excel não suporta arquivos com mais do que {count} linhas." + }, + "Advanced": + { + "TabHeader": "Avançado", + "UseLogging": "Escrever informações de diagnóstico em um arquivo", + "EnableSqlDebugger": "Habilitar depurador SQL" + } + }, + "About": + { + "WindowTitle": "Sobre Libgen Desktop", + "ApplicationName": "Libgen Desktop", + "Version": "Versão atual: {version} lançado em {date}", + "CheckForUpdates": "VERIFIQUE ATUALIZAÇÕES", + "CheckingUpdates": "VERIFICANDO ATUALIZAÇÕES...", + "OfflineModeIsOnTooltip": "O modo offline está ligado", + "LatestVersion": "Você está usando a versão mais recente.", + "NewVersionAvailable": "Nova versão está disponível: {version} lançado em {date}", + "Update": "ATUALIZAR", + "Translators": "Tradutor: Scoria" + }, + "MessageBox": + { + "Ok": "OK", + "Yes": "SIM", + "No": "NÃO" + }, + "ErrorWindow": + { + "WindowTitle": "Erro", + "UnexpectedError": "Um erro inesperado ocorreu", + "Copy": "COPIAR PARA ÁREA DE TRANSFERÊNCIA", + "Close": "FECHAR" + } +} diff --git a/LibgenDesktop/Resources/Languages/Romanian.lng b/LibgenDesktop/Resources/Languages/Romanian.lng index 8c34fa8..b4ddaba 100644 --- a/LibgenDesktop/Resources/Languages/Romanian.lng +++ b/LibgenDesktop/Resources/Languages/Romanian.lng @@ -39,25 +39,6 @@ "About": "Despre" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Biblioteca Digitală Libgen", - "FirstRunMessage": "Bine ați venit la Biblioteca Digitală Libgen.", - "DatabaseNotFound": "Baza de date nu a fost gasită.", - "DatabaseCorrupted": "Baza de date este coruptă.", - "LibgenServerDatabase": "Baza de date {database} este o bază de date Libgen Server care nu este compatibilă cu structura bazei de date Libgen Desktop.", - "ChooseOption": "Alege o acțiune", - "CreateNewDatabase": "Creează o nouă Baza de date", - "OpenExistingDatabase": "Deschide o Baza de date deja creată", - "BrowseNewDatabaseDialogTitle": "Noua locație pentru Baza de date", - "BrowseExistingDatabaseDialogTitle": "Locația curentă a Bazei de date", - "Databases": "Baza de date", - "AllFiles": "Toate fișierele", - "Error": "Eroare", - "CannotCreateDatabase": "Nu s-a putut crea baza de date.", - "Ok": "DE ACORD", - "Cancel": "RENUNȚĂ" - }, "SearchTab": { "TabTitle": "Căutare", @@ -224,7 +205,6 @@ { "Title": "Titlul", "Authors": "Autor(i)", - "RussianAuthor": "Autor(i) rus(i)", "Series": "Colecția", "Publisher": "Editura", "Edition": "Ediția", @@ -232,7 +212,6 @@ "Language": "Limba", "Format": "Formatul", "Pages": "Paginile", - "Version": "Versiunea", "FileSize": "Dimensiunea", "Added": "Adăugat la data de", "LastModified": "Ultima modificare", @@ -424,7 +403,6 @@ "Id": "ID", "Title": "Titlul", "Authors": "Autor(i)", - "RussianAuthor": "Autor(i) ruș(i)", "Series": "Colecția", "Publisher": "Editura", "Edition": "Ediția", @@ -432,7 +410,6 @@ "Language": "Limba", "Format": "Formatul", "Pages": "Pagini", - "Version": "Versiunea", "FileSize": "Dimensiunea", "Added": "Adăugat la data de", "LastModified": "Ultima modificare", diff --git a/LibgenDesktop/Resources/Languages/Russian.lng b/LibgenDesktop/Resources/Languages/Russian.lng index 3b8ff13..58bf7ef 100644 --- a/LibgenDesktop/Resources/Languages/Russian.lng +++ b/LibgenDesktop/Resources/Languages/Russian.lng @@ -39,25 +39,157 @@ "About": "О программе" } }, - "CreateDatabaseWindow": + "SetupWizardWindow": { "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Добро пожаловать в Libgen Desktop.", - "DatabaseNotFound": "База данных {database} не найдена.", - "DatabaseCorrupted": "База данных {database} повреждена.", - "LibgenServerDatabase": "Файл {database} является базой данных приложения Libgen Server и не может быть использован в приложении Libgen Desktop.", - "ChooseOption": "Выберите действие", - "CreateNewDatabase": "Создать новую базу данных", - "OpenExistingDatabase": "Открыть существующую базу данных", - "BrowseNewDatabaseDialogTitle": "Сохранение новой базы данных", - "BrowseExistingDatabaseDialogTitle": "Выбор базы данных", - "Databases": "Базы данных", - "AllFiles": "Все файлы", - "Error": "Ошибка", - "CannotCreateDatabase": "Не удалось создать базу данных.", - "Ok": "OK", - "Cancel": "ОТМЕНА" - }, + "LanguageStep": + { + "ChooseLanguage": "Пожалуйста, выберите язык:" + }, + "SetupModeStep": + { + "WelcomeAndChooseOption": "Добро пожаловать в Libgen Desktop. Выберите действие:", + "FirstTimeUser": "Я использую Libgen Desktop впервые", + "ExperiencedUser": "У меня есть опыт работы с Libgen Desktop" + }, + "DatabaseOperationStep": + { + "ChooseAction": "Пожалуйста, выберите нужное действие:", + "CreateNewDatabase": "Создать новую базу данных", + "OpenExistingDatabase": "Открыть существующую базу данных" + }, + "DownloadModeStep": + { + "ChooseDownloadMode": "Выберите способ скачивания дампов баз данных:", + "DownloadManagerMode": "Скачать их при помощи Libgen Desktop", + "UseProxyServer": "Использовать прокси-сервер", + "ProxySettings": "НАСТРОЙКИ...", + "BrowserMode": "Я хочу скачать их вручную" + }, + "StepListStep": + { + "StepListHeader": "Первоначальная настройка Libgen Desktop", + "Step": "Шаг {step}", + "DownloadingDumps": "Скачивание дампов баз данных", + "CreatingDatabase": "Создание базы данных Libgen Desktop", + "ImportingDumps": "Импортирование дампов в базу данных Libgen Desktop", + "ClickNextButton": "Нажмите кнопку \"Далее\" для начала установки." + }, + "ProxySettingsWindow": + { + "WindowTitle": "Настройки прокси-сервера", + "ProxyAddress": "Адрес", + "ProxyAddressRequired": "Обязательное поле", + "ProxyPort": "Порт", + "ProxyPortValidation": "Числа от {min} до {max}", + "ProxyUserName": "Имя пользователя", + "ProxyPassword": "Пароль", + "ProxyPasswordWarning": "Хранить здесь пароль небезопасно.", + "Ok": "OK", + "Cancel": "Отмена" + }, + "DownloadDumpInfoStep": + { + "DownloadingDumpInfo": "Идет загрузка информации о дампах баз данных. Пожалуйста, подождите...", + "CannotDownloadDumpInfo": "Не удалось загрузить информацию о дампах баз данных", + "Interrupt": "ПРЕРВАТЬ", + "Interrupting": "ПРЕРЫВАЕТСЯ...", + "Retry": "ПОВТОРИТЬ" + }, + "CollectionsStep": + { + "ChooseCollections": "Выберите коллекции, которые вы хотите использовать в Libgen Desktop:", + "NonFiction": "Нехудожественная литература", + "Fiction": "Художественная литература", + "SciMagArticles": "Научные статьи", + "DownloadSizeExact": "Размер скачиваемого дампа: {size}", + "DownloadSizeApproximate": "Размер скачиваемого дампа: примерно {size}", + "DatabaseSize": "Размер базы данных: примерно {size}", + "ImportTimeInMinutes": "Продолжительность импорта: {from}–{to} минут", + "ImportTimeInHours": "Продолжительность импорта: {from}–{to} часов", + "DownloadInto": "Скачать в:", + "BrowseDirectoryDialogTitle": "Выберите директорию для хранения скачиваемых дампов", + "ErrorWarningTitle": "Ошибка", + "NoCollectionsSelected": "Нужно выбрать хотя бы одну коллекцию.", + "DirectoryNotFound": "Директория {directory} не существует. Пожалуйста, выберите другую директорию." + }, + "DownloadDumpsStep": + { + "NonFictionDumpName": "Дамп БД для нехудожественной литературы", + "FictionDumpName": "Дамп БД для художественной литературы", + "SciMagArticlesDumpName": "Дамп БД для научных статей", + "QueuedStatus": "В очереди", + "DownloadingStatus": "Загружается", + "StoppedStatus": "Остановлено", + "ErrorStatus": "Ошибка", + "DownloadProgress": "Загружено: {downloaded} из {total} байт ({percent}%)", + "Interrupt": "ПРЕРВАТЬ", + "Interrupting": "ПРЕРЫВАЕТСЯ...", + "Retry": "ПОВТОРИТЬ" + }, + "DownloadDumpLinksStep": + { + "OpenPage": "Откройте страницу со списком дампов в вашем браузере:", + "CopyLink": "Копировать ссылку", + "DownloadFiles": "Затем скачайте следующие файлы:", + "NonFictionDumpName": "Дамп БД для нехудожественной литературы", + "FictionDumpName": "Дамп БД для художественной литературы", + "SciMagArticlesDumpName": "Дамп БД для научных статей", + "FileName": "Имя файла: {file}", + "YYYY": "ГГГГ", + "MM": "ММ", + "DD": "ДД", + "MostRecentDateNote": "где {dateTemplate} — самая поздняя из доступных дат в списке файлов." + }, + "CreateDatabaseStep": + { + "DatabaseFilePathPrompt": "Пожалуйста, выберите место, где вы бы хотели хранить файл базы данных:", + "DatabaseCreated": "База данных Libgen Desktop успешно создана.", + "CannotCreateDatabase": "Не удалось создать базу данных Libgen Desktop.", + "DiskSpaceRequirementsNote": "Вам понадобится примерно {size} свободного места на диске.", + "SelectDatabaseFilePathDialogTitle": "Расположение для новой базы данных Libgen Desktop", + "Databases": "Базы данных", + "AllFiles": "Все файлы", + "CreateDatabase": "СОЗДАТЬ БАЗУ ДАННЫХ", + "CreatingDatabase": "СОЗДАЕТСЯ БАЗА ДАННЫХ...", + "DatabaseFileOverwritePromptTitle": "Перезаписать файл базы данных?", + "DatabaseFileOverwritePromptText": "Файл {file} уже существует. Вы хотите перезаписать его?" + }, + "ImportDumpsStep": + { + "NonFictionDumpName": "Дамп БД для нехудожественной литературы", + "FictionDumpName": "Дамп БД для художественной литературы", + "SciMagArticlesDumpName": "Дамп БД для научных статей", + "Status": "Статус: {status}", + "NotImported": "еще не импортирован", + "Importing": "импортируется...", + "ImportSuccessful": "успешно импортирован", + "ImportCancelled": "импорт отменен", + "ImportError": "ошибка импорта", + "ImportButton": "ИМПОРТ...", + "ImportingButton": "ИМПОРТИРУЕТСЯ...", + "DeleteDumps": "Удалить файлы дампов после успешного импорта" + }, + "ConfirmationStep": + { + "StepHeader": "Установка завершена", + "SettingsHeader": "Прежде чем вы закроете мастер установки, обратите внимание на следующие настройки:", + "AllowInternetConnection": "Разрешить Libgen Desktop подключаться к интернету", + "UseDownloadManager": "Использовать встроенный менеджер загрузок для скачивания книг и статей", + "UseBrowser": "Открывать ссылки на загрузку файлов в браузере", + "YouCanChangeSettings": "Вы всегда можете изменить эти и другие параметры в настройках программы." + }, + "StepHeaderTemplate": "Шаг {current} из {total}: {header}", + "DownloadingDumpsStepHeader": "Загрузка дампов баз данных", + "CreatingDatabaseStepHeader": "Создание базы данных Libgen Desktop", + "ImportingDumpsStepHeader": "Импорт дампов БД в базу данных Libgen Desktop", + "Back": "НАЗАД", + "Next": "ДАЛЕЕ", + "Finish": "ГОТОВО", + "Cancel": "ОТМЕНА", + "ExitSetupTitle": "Отменить настройку", + "ExitSetupText": "Настройка Libgen Desktop еще не завершена. Вы действительно хотите выйти?" + }, "SearchTab": { "TabTitle": "Поиск", @@ -89,6 +221,7 @@ "Details": "Детальная информация", "Open": "Открыть", "Download": "Скачать", + "Copy": "Копировать", "ErrorMessageTitle": "Ошибка", "FileNotFoundError": "Файл {file} не найден.", "OfflineModeIsOnMessageTitle": "Включен автономный режим", @@ -108,6 +241,7 @@ "Authors": "Авторы", "Series": "Серия", "Year": "Год", + "Language": "Язык", "Publisher": "Издатель", "Format": "Формат", "FileSize": "Размер файла", @@ -126,6 +260,7 @@ "Authors": "Авторы", "Series": "Серия", "Year": "Год", + "Language": "Язык", "Publisher": "Издатель", "Format": "Формат", "FileSize": "Размер файла", @@ -224,7 +359,6 @@ { "Title": "Наименование", "Authors": "Авторы", - "RussianAuthor": "Автор (рус.)", "Series": "Серия", "Publisher": "Издатель", "Edition": "Издание", @@ -232,8 +366,9 @@ "Language": "Язык", "Format": "Формат", "Pages": "Страниц", - "Version": "Версия", "FileSize": "Размер файла", + "Library": "Библиотека", + "Issue": "Выпуск", "Added": "Добавлено", "LastModified": "Обновлено", "Md5Hash": "MD5-хэш", @@ -325,6 +460,13 @@ "ImportCancelled": "Импорт был прерван пользователем.", "DataNotFound": "Не найдены данные для импорта.", "InsufficientDiskSpace": "Недостаточно места на диске.", + "WrongTableFound": "Ожидалось найти {expected}, но была найдена {found}.", + "ExpectedNonFictionTable": "таблицу с нехудожественными книгами", + "ExpectedFictionTable": "таблицу с художественными книгами", + "ExpectedSciMagTable": "таблицу с научными статьями", + "FoundNonFictionTable": "таблица с нехудожественными книгами", + "FoundFictionTable": "таблица с художественными книгами", + "FoundSciMagTable": "таблица с научными статьями", "ImportError": "Импорт завершился с ошибками." } }, @@ -424,7 +566,6 @@ "Id": "ID", "Title": "Наименование", "Authors": "Авторы", - "RussianAuthor": "Автор (рус.)", "Series": "Серия", "Publisher": "Издатель", "Edition": "Издание", @@ -432,8 +573,9 @@ "Language": "Язык", "Format": "Формат", "Pages": "Страниц", - "Version": "Версия", "FileSize": "Размер файла", + "Library": "Библиотека", + "Issue": "Выпуск", "Added": "Добавлено", "LastModified": "Обновлено", "Md5Hash": "MD5-хэш", @@ -564,9 +706,29 @@ "Databases": "Базы данных", "AllFiles": "Все файлы", "Error": "Ошибка", - "CannotOpenDatabase": "Произошла ошибка при открытии файла базы данных: {file}", + "DatabaseNotValid": "Файл {file} не является корректной базой данных Libgen Desktop.", + "DatabaseDumpFile": "Похоже, что {file} — это файл дампа, а не база данных Libgen Desktop.", + "LibgenServerDatabase": "Файл {database} является базой данных приложения Libgen Server, структура которой не совместима со структурой базы данных Libgen Desktop.", + "OldFictionSchemaTitle": "Удалить коллекцию художественной литературы?", + "OldFictionSchemaText": "Необходимо обновление структуры базы данных {database}. Начиная с февраля 2020 года основное зеркало библиотеки использует новую структуру базы данных для коллекции художественной литературы. Для продолжения использования этой коллекции в программе Libgen Desktop вам необходимо скачать и импортировать новый дамп базы данных для коллекции художественной литературы. Вы хотите удалить старую коллекцию художественной литературы из этой базы данных?", "Close": "ЗАКРЫТЬ" }, + "DatabaseError": + { + "WindowTitle": "Libgen Desktop", + "DatabaseNotFound": "База данных {database} не найдена.", + "DatabaseNotValid": "Файл {file} не является корректной базой данных Libgen Desktop.", + "DatabaseDumpFile": "Похоже, что {file} — это файл дампа, а не база данных Libgen Desktop. Запустите мастер установки для того, чтобы импортировать его.", + "LibgenServerDatabase": "Файл {database} является базой данных приложения Libgen Server, структура которой не совместима со структурой базы данных Libgen Desktop.", + "OldFictionSchema": "Необходимо обновление структуры базы данных {database}. Начиная с февраля 2020 года основное зеркало библиотеки использует новую структуру базы данных для коллекции художественной литературы. Для продолжения использования этой коллекции в программе Libgen Desktop вам необходимо скачать и импортировать новый дамп базы данных для коллекции художественной литературы.", + "HeaderTemplate": "{error} Выберите действие:", + "OpenAnotherDatabase": "Открыть другую базу данных", + "StartSetupWizard": "Запустить мастер установки", + "DeleteFiction": "Удалить существующую коллекцию художественной литературы и продолжить", + "Exit": "Выйти из Libgen Desktop", + "Ok": "OK", + "Cancel": "ОТМЕНА" + }, "SqlDebugger": { "WindowTitle": "Отладчик SQL", @@ -660,6 +822,7 @@ { "TabHeader": "Общие", "Language": "Язык интерфейса", + "PercentTranslated": "переведено {percent}%", "CheckUpdates": "Проверять обновления программы", "UpdateCheckIntervals": { diff --git a/LibgenDesktop/Resources/Languages/Simplified Chinese.lng b/LibgenDesktop/Resources/Languages/Simplified Chinese.lng index 9daae4f..647e4ca 100644 --- a/LibgenDesktop/Resources/Languages/Simplified Chinese.lng +++ b/LibgenDesktop/Resources/Languages/Simplified Chinese.lng @@ -39,25 +39,6 @@ "About": "关于" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Libgen 桌面版", - "FirstRunMessage": "欢迎使用 Libgen 桌面版", - "DatabaseNotFound": "无法找到数据库“{database}”。", - "DatabaseCorrupted": "数据库“{database}”已损坏。", - "LibgenServerDatabase": "“{database}”是 Libgen 服务器所用数据库,由于格式不同,不能用于 Libgen 桌面版。", - "ChooseOption": "选择操作", - "CreateNewDatabase": "创建新数据库", - "OpenExistingDatabase": "打开现有数据库", - "BrowseNewDatabaseDialogTitle": "新数据库存放位置", - "BrowseExistingDatabaseDialogTitle": "现有数据库位置", - "Databases": "数据库", - "AllFiles": "所有文件", - "Error": "错误", - "CannotCreateDatabase": "无法创建数据库文件。", - "Ok": "确定", - "Cancel": "取消" - }, "SearchTab": { "TabTitle": "搜索", @@ -224,7 +205,6 @@ { "Title": "书名", "Authors": "作者", - "RussianAuthor": "作者(俄语)", "Series": "系列", "Publisher": "出版商", "Edition": "发行版本", @@ -232,7 +212,6 @@ "Language": "语言", "Format": "文件格式", "Pages": "页数", - "Version": "版本", "FileSize": "文件大小", "Added": "添加日期", "LastModified": "修改日期", @@ -424,7 +403,6 @@ "Id": "ID", "Title": "书名", "Authors": "作者", - "RussianAuthor": "作者(俄语)", "Series": "系列", "Publisher": "出版商", "Edition": "发行版本", @@ -432,7 +410,6 @@ "Language": "语言", "Format": "文件格式", "Pages": "页数", - "Version": "版本", "FileSize": "文件大小", "Added": "添加日期", "LastModified": "修改日期", diff --git a/LibgenDesktop/Resources/Languages/Spanish.lng b/LibgenDesktop/Resources/Languages/Spanish.lng index 014b6d6..f3b0645 100644 --- a/LibgenDesktop/Resources/Languages/Spanish.lng +++ b/LibgenDesktop/Resources/Languages/Spanish.lng @@ -38,24 +38,6 @@ "About": "Acerca de" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Bienvenido a Libgen Desktop.", - "DatabaseNotFound": "Base de datos {database} no encontrada.", - "DatabaseCorrupted": "La base de datos {database} está corrupta.", - "ChooseOption": "Escoja una opción", - "CreateNewDatabase": "Crear una base de datos", - "OpenExistingDatabase": "Abrir una base de datos existente", - "BrowseNewDatabaseDialogTitle": "Localización de la nueva base de datos", - "BrowseExistingDatabaseDialogTitle": "Localización de la base de datos existente", - "Databases": "Bases de datos", - "AllFiles": "Todos los archivos", - "Error": "Error", - "CannotCreateDatabase": "No se puede crear la base de datos.", - "Ok": "OK", - "Cancel": "CANCELAR" - }, "SearchTab": { "TabTitle": "Buscar", @@ -212,7 +194,6 @@ { "Title": "Título", "Authors": "Autores", - "RussianAuthor": "Autor en ruso", "Series": "Series", "Publisher": "Editorial", "Edition": "Edición", @@ -220,7 +201,6 @@ "Language": "Idioma", "Format": "Formato", "Pages": "Páginas", - "Version": "Versión", "FileSize": "Tamaño", "Added": "Añadido", "LastModified": "Última modificación", @@ -410,7 +390,6 @@ "Id": "ID", "Title": "Título", "Authors": "Autores", - "RussianAuthor": "Author in Russian", "Series": "Series", "Publisher": "Editorial", "Edition": "Edición", @@ -418,7 +397,6 @@ "Language": "Idioma", "Format": "Formato", "Pages": "Páginas", - "Version": "Versión", "FileSize": "Tamaño", "Added": "Añadido", "LastModified": "Última modificación", diff --git a/LibgenDesktop/Resources/Languages/Turkish.lng b/LibgenDesktop/Resources/Languages/Turkish.lng index aa64658..768d74b 100644 --- a/LibgenDesktop/Resources/Languages/Turkish.lng +++ b/LibgenDesktop/Resources/Languages/Turkish.lng @@ -39,25 +39,6 @@ "About": "Hakkında" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Libgen Desktop'a Hoş Geldiniz.", - "DatabaseNotFound": "{database} veri tabanı bulunamadı.", - "DatabaseCorrupted": "{database} veri tabanı bozuk.", - "LibgenServerDatabase": "{database} veri tabanı Libgen Desktop veri tabanı yapısıyla uyumlu olmayan bir Libgen Sunucu veri tabanı.", - "ChooseOption": "Bir eylem seç", - "CreateNewDatabase": "Yeni bir veri tabanı oluştur", - "OpenExistingDatabase": "Var olan bir veri tabanı aç", - "BrowseNewDatabaseDialogTitle": "Yeni veri tabanı konumu", - "BrowseExistingDatabaseDialogTitle": "Var olan veri tabanı konumu", - "Databases": "Veri tabanları", - "AllFiles": "Tüm dosyalar", - "Error": "Hata", - "CannotCreateDatabase": "Veri tabanı oluşturulamadı.", - "Ok": "TAMAM", - "Cancel": "İPTAL" - }, "SearchTab": { "TabTitle": "Ara", @@ -224,7 +205,6 @@ { "Title": "Başlık", "Authors": "Yazar", - "RussianAuthor": "Yazar (Rusça)", "Series": "Dizi", "Publisher": "Yayıncı", "Edition": "Basım", @@ -232,7 +212,6 @@ "Language": "Dil", "Format": "Tür", "Pages": "Sayfa", - "Version": "Sürüm", "FileSize": "Dosya Boyutu", "Added": "Eklenme Tarihi", "LastModified": "Son Değiştirilme Tarihi", @@ -424,7 +403,6 @@ "Id": "ID", "Title": "Başlık", "Authors": "Yazar", - "RussianAuthor": "Yazar (Rusça)", "Series": "Dizi", "Publisher": "Yayıncı", "Edition": "Basım", @@ -432,7 +410,6 @@ "Language": "Dil", "Format": "Tür", "Pages": "Sayfa", - "Version": "Sürüm", "FileSize": "Dosya Boyutu", "Added": "Eklenme Tarihi", "LastModified": "Son Değiştirilme Tarihi", diff --git a/LibgenDesktop/Resources/Languages/Ukrainian.lng b/LibgenDesktop/Resources/Languages/Ukrainian.lng index db355c9..0244c96 100644 --- a/LibgenDesktop/Resources/Languages/Ukrainian.lng +++ b/LibgenDesktop/Resources/Languages/Ukrainian.lng @@ -35,24 +35,6 @@ "About": "Про програму" } }, - "CreateDatabaseWindow": - { - "WindowTitle": "Libgen Desktop", - "FirstRunMessage": "Ласкаво просимо до Libgen Desktop.", - "DatabaseNotFound": "База даних {database} не знайдена.", - "DatabaseCorrupted": "База даних {database} пошкоджена.", - "ChooseOption": "Оберіть дію", - "CreateNewDatabase": "Створити нову базу даних", - "OpenExistingDatabase": "Відкрити існуючу базу даних", - "BrowseNewDatabaseDialogTitle": "Збереження нової бази даних", - "BrowseExistingDatabaseDialogTitle": "Вибір бази даних", - "Databases": "Бази даних", - "AllFiles": "Усі файли", - "Error": "Помилка", - "CannotCreateDatabase": "Не вдалося створити базу даних.", - "Ok": "OK", - "Cancel": "СКАСУВАТИ" - }, "SearchTab": { "TabTitle": "Пошук", @@ -207,7 +189,6 @@ { "Title": "Найменування", "Authors": "Автори", - "RussianAuthor": "Автор (рос.)", "Series": "Серія", "Publisher": "Видавець", "Edition": "Видання", @@ -215,7 +196,6 @@ "Language": "Мова", "Format": "Формат", "Pages": "Сторінок", - "Version": "Версія", "FileSize": "Розмір файлу", "Added": "Додано", "LastModified": "Оновлено", @@ -405,7 +385,6 @@ "Id": "ID", "Title": "Найменування", "Authors": "Автори", - "RussianAuthor": "Автор (рос.)", "Series": "Серія", "Publisher": "Видавець", "Edition": "Видання", @@ -413,7 +392,6 @@ "Language": "Мова", "Format": "Формат", "Pages": "Сторінок", - "Version": "Версія", "FileSize": "Розмір файлу", "Added": "Додано", "LastModified": "Оновлено", diff --git a/LibgenDesktop/Resources/Mirrors/genlibrusec_dbdumps.xslt b/LibgenDesktop/Resources/Mirrors/genlibrusec_dbdumps.xslt new file mode 100644 index 0000000..ee8ea70 --- /dev/null +++ b/LibgenDesktop/Resources/Mirrors/genlibrusec_dbdumps.xslt @@ -0,0 +1,25 @@ + + + + + libgen_compact_ + + + + fiction_ + + + + scimag_ + + + + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Resources/Mirrors/mirrors.config b/LibgenDesktop/Resources/Mirrors/mirrors.config index 2dde856..ba5b4be 100644 --- a/LibgenDesktop/Resources/Mirrors/mirrors.config +++ b/LibgenDesktop/Resources/Mirrors/mirrors.config @@ -2,10 +2,19 @@ "gen.lib.rus.ec": { "NonFictionDownloadUrl": "http://93.174.95.29/main/{thousand-bucket}/{md5:l}/", - "NonFictionCoverUrl": "http://93.174.95.29/covers/{cover-url}", + "NonFictionCoverUrl": "http://gen.lib.rus.ec/covers/{cover-url}", "NonFictionSynchronizationUrl": "http://gen.lib.rus.ec/json.php", - "FictionDownloadUrl": "http://93.174.95.29/fiction/{thousand-bucket}/{md5}.{ext}/", - "FictionCoverUrl": "http://93.174.95.29/fictioncovers/{thousand-bucket}/{md5}.jpg" + "FictionDownloadUrl": "http://93.174.95.29/fiction/{thousand-bucket}/{md5:l}.{ext}/", + "FictionCoverUrl": "http://gen.lib.rus.ec/fictioncovers/{thousand-bucket}/{md5:l}.jpg", + "DatabaseDumpPageUrl": "http://gen.lib.rus.ec/dbdumps/", + "DatabaseDumpPageTransformation": "genlibrusec_dbdumps", + "DatabaseDumpManualDownload": + { + "NonFictionFileNameTemplate": "libgen_compact_{date}.rar", + "FictionFileNameTemplate": "fiction_{date}.rar", + "SciMagFileNameTemplate": "scimag_{date}.sql.gz", + "DateTemplate": "YYYY-MM-DD" + } }, "libgen.lc": { diff --git a/LibgenDesktop/Styles/Common.xaml b/LibgenDesktop/Styles/Common.xaml new file mode 100644 index 0000000..b075244 --- /dev/null +++ b/LibgenDesktop/Styles/Common.xaml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/Confirmation.xaml b/LibgenDesktop/Styles/SetupSteps/Confirmation.xaml new file mode 100644 index 0000000..000884d --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/Confirmation.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/CreateDatabase.xaml b/LibgenDesktop/Styles/SetupSteps/CreateDatabase.xaml new file mode 100644 index 0000000..9a4fc94 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/CreateDatabase.xaml @@ -0,0 +1,27 @@ + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/DatabaseOperation.xaml b/LibgenDesktop/Styles/SetupSteps/DatabaseOperation.xaml new file mode 100644 index 0000000..48f2271 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/DatabaseOperation.xaml @@ -0,0 +1,14 @@ + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/DownloadDumpInfo.xaml b/LibgenDesktop/Styles/SetupSteps/DownloadDumpInfo.xaml new file mode 100644 index 0000000..10a39cb --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/DownloadDumpInfo.xaml @@ -0,0 +1,32 @@ + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/DownloadDumpLinks.xaml b/LibgenDesktop/Styles/SetupSteps/DownloadDumpLinks.xaml new file mode 100644 index 0000000..8eeae45 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/DownloadDumpLinks.xaml @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/DownloadDumps.xaml b/LibgenDesktop/Styles/SetupSteps/DownloadDumps.xaml new file mode 100644 index 0000000..cdbd645 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/DownloadDumps.xaml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/ImportDumps.xaml b/LibgenDesktop/Styles/SetupSteps/ImportDumps.xaml new file mode 100644 index 0000000..fe3c261 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/ImportDumps.xaml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/Language.xaml b/LibgenDesktop/Styles/SetupSteps/Language.xaml new file mode 100644 index 0000000..2f4ccee --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/Language.xaml @@ -0,0 +1,16 @@ + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/SetupMode.xaml b/LibgenDesktop/Styles/SetupSteps/SetupMode.xaml new file mode 100644 index 0000000..cca3ab5 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/SetupMode.xaml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/SetupSteps/StepList.xaml b/LibgenDesktop/Styles/SetupSteps/StepList.xaml new file mode 100644 index 0000000..1b1b456 --- /dev/null +++ b/LibgenDesktop/Styles/SetupSteps/StepList.xaml @@ -0,0 +1,21 @@ + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Views/Styles/DownloadManagerTabStyles.xaml b/LibgenDesktop/Styles/Tabs/DownloadManager.xaml similarity index 95% rename from LibgenDesktop/Views/Styles/DownloadManagerTabStyles.xaml rename to LibgenDesktop/Styles/Tabs/DownloadManager.xaml index 057d3c7..47382d8 100644 --- a/LibgenDesktop/Views/Styles/DownloadManagerTabStyles.xaml +++ b/LibgenDesktop/Styles/Tabs/DownloadManager.xaml @@ -3,7 +3,7 @@ xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:mw="clr-namespace:Lada.Windows.Input;assembly=WpfMouseWheelLib"> - + - - + + - diff --git a/LibgenDesktop/Views/Styles/ErrorWindowStyles.xaml b/LibgenDesktop/Styles/Windows/Error.xaml similarity index 100% rename from LibgenDesktop/Views/Styles/ErrorWindowStyles.xaml rename to LibgenDesktop/Styles/Windows/Error.xaml diff --git a/LibgenDesktop/Views/Styles/ImportWindowStyles.xaml b/LibgenDesktop/Styles/Windows/Import.xaml similarity index 100% rename from LibgenDesktop/Views/Styles/ImportWindowStyles.xaml rename to LibgenDesktop/Styles/Windows/Import.xaml diff --git a/LibgenDesktop/Views/Styles/MainWindowStyles.xaml b/LibgenDesktop/Styles/Windows/Main.xaml similarity index 88% rename from LibgenDesktop/Views/Styles/MainWindowStyles.xaml rename to LibgenDesktop/Styles/Windows/Main.xaml index 66606e2..e1452ba 100644 --- a/LibgenDesktop/Views/Styles/MainWindowStyles.xaml +++ b/LibgenDesktop/Styles/Windows/Main.xaml @@ -1,9 +1,6 @@  - - - @@ -26,51 +27,13 @@ - - - - - + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Styles/Windows/SetupWizardProxySettings.xaml b/LibgenDesktop/Styles/Windows/SetupWizardProxySettings.xaml new file mode 100644 index 0000000..68acb6b --- /dev/null +++ b/LibgenDesktop/Styles/Windows/SetupWizardProxySettings.xaml @@ -0,0 +1,35 @@ + + + + + + + + \ No newline at end of file diff --git a/LibgenDesktop/Views/Styles/SqlDebuggerWindowStyles.xaml b/LibgenDesktop/Styles/Windows/SqlDebugger.xaml similarity index 100% rename from LibgenDesktop/Views/Styles/SqlDebuggerWindowStyles.xaml rename to LibgenDesktop/Styles/Windows/SqlDebugger.xaml diff --git a/LibgenDesktop/Views/Styles/SynchronizationWindowStyles.xaml b/LibgenDesktop/Styles/Windows/Synchronization.xaml similarity index 100% rename from LibgenDesktop/Views/Styles/SynchronizationWindowStyles.xaml rename to LibgenDesktop/Styles/Windows/Synchronization.xaml diff --git a/LibgenDesktop/Views/Styles/WindowStyles.xaml b/LibgenDesktop/Styles/Windows/Windows.xaml similarity index 85% rename from LibgenDesktop/Views/Styles/WindowStyles.xaml rename to LibgenDesktop/Styles/Windows/Windows.xaml index 0c9ba90..21309d8 100644 --- a/LibgenDesktop/Views/Styles/WindowStyles.xaml +++ b/LibgenDesktop/Styles/Windows/Windows.xaml @@ -6,14 +6,29 @@ - + + + + - + + + diff --git a/LibgenDesktop/Views/Controls/ControlExtensions.cs b/LibgenDesktop/Views/Controls/ControlExtensions.cs index 2d94b1b..a078ec0 100644 --- a/LibgenDesktop/Views/Controls/ControlExtensions.cs +++ b/LibgenDesktop/Views/Controls/ControlExtensions.cs @@ -30,8 +30,7 @@ public static T FindChild(this DependencyObject parent, string childName = nu for (int i = 0; i < childrenCount; i++) { DependencyObject child = VisualTreeHelper.GetChild(parent, i); - T childType = child as T; - if (childType == null) + if (!(child is T)) { result = FindChild(child, childName); if (result != null) diff --git a/LibgenDesktop/Views/Controls/DownloaderListBox.cs b/LibgenDesktop/Views/Controls/DownloadManagerListBox.cs similarity index 91% rename from LibgenDesktop/Views/Controls/DownloaderListBox.cs rename to LibgenDesktop/Views/Controls/DownloadManagerListBox.cs index c934588..62c881b 100644 --- a/LibgenDesktop/Views/Controls/DownloaderListBox.cs +++ b/LibgenDesktop/Views/Controls/DownloadManagerListBox.cs @@ -7,11 +7,16 @@ namespace LibgenDesktop.Views.Controls { - internal class DownloaderListBox : ListBox + internal class DownloadManagerListBox : ListBox { - public static readonly DependencyProperty SelectionChangedCommandProperty = DependencyProperty.Register("SelectionChangedCommand", typeof(ICommand), typeof(DownloaderListBox)); - public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), typeof(DownloaderListBox)); - public static readonly DependencyProperty SelectedRowsProperty = DependencyProperty.Register("SelectedRows", typeof(IList), typeof(DownloaderListBox)); + public static readonly DependencyProperty SelectionChangedCommandProperty = DependencyProperty.Register("SelectionChangedCommand", typeof(ICommand), + typeof(DownloadManagerListBox)); + + public static readonly DependencyProperty DoubleClickCommandProperty = DependencyProperty.Register("DoubleClickCommand", typeof(ICommand), + typeof(DownloadManagerListBox)); + + public static readonly DependencyProperty SelectedRowsProperty = DependencyProperty.Register("SelectedRows", typeof(IList), + typeof(DownloadManagerListBox)); public ICommand SelectionChangedCommand { diff --git a/LibgenDesktop/Views/Controls/ExportPanel.xaml b/LibgenDesktop/Views/Controls/ExportPanel.xaml index d95e1ca..a35428f 100644 --- a/LibgenDesktop/Views/Controls/ExportPanel.xaml +++ b/LibgenDesktop/Views/Controls/ExportPanel.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + diff --git a/LibgenDesktop/Views/Controls/ImportLogPanel.xaml b/LibgenDesktop/Views/Controls/ImportLogPanel.xaml index 12331a5..486181f 100644 --- a/LibgenDesktop/Views/Controls/ImportLogPanel.xaml +++ b/LibgenDesktop/Views/Controls/ImportLogPanel.xaml @@ -2,7 +2,7 @@ xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> - + diff --git a/LibgenDesktop/Views/Controls/LanguageComboBox.xaml b/LibgenDesktop/Views/Controls/LanguageComboBox.xaml new file mode 100644 index 0000000..930a095 --- /dev/null +++ b/LibgenDesktop/Views/Controls/LanguageComboBox.xaml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + diff --git a/LibgenDesktop/Views/Controls/LanguageComboBox.xaml.cs b/LibgenDesktop/Views/Controls/LanguageComboBox.xaml.cs new file mode 100644 index 0000000..33c1831 --- /dev/null +++ b/LibgenDesktop/Views/Controls/LanguageComboBox.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows; +using static LibgenDesktop.Common.Constants; + +namespace LibgenDesktop.Views.Controls +{ + public partial class LanguageComboBox + { + public static readonly DependencyProperty PercentTranslatedFontSizeProperty = + DependencyProperty.Register("PercentTranslatedFontSize", typeof(double), typeof(LanguageComboBox), new PropertyMetadata(DEFAULT_FONT_SIZE)); + + public LanguageComboBox() + { + InitializeComponent(); + } + + public double PercentTranslatedFontSize + { + get + { + return (double)GetValue(PercentTranslatedFontSizeProperty); + } + set + { + SetValue(PercentTranslatedFontSizeProperty, value); + } + } + } +} diff --git a/LibgenDesktop/Views/Controls/LibgenDesktopWindow.cs b/LibgenDesktop/Views/Controls/LibgenDesktopWindow.cs index 960616e..14aba3c 100644 --- a/LibgenDesktop/Views/Controls/LibgenDesktopWindow.cs +++ b/LibgenDesktop/Views/Controls/LibgenDesktopWindow.cs @@ -8,12 +8,23 @@ namespace LibgenDesktop.Views.Controls { public class LibgenDesktopWindow : Window { - public static readonly DependencyProperty ShowIconProperty = DependencyProperty.Register("ShowIcon", typeof(bool), typeof(LibgenDesktopWindow), new PropertyMetadata(true)); - public static readonly DependencyProperty ShowMinimizeButtonProperty = DependencyProperty.Register("ShowMinimizeButton", typeof(bool), typeof(LibgenDesktopWindow), new PropertyMetadata(true)); - public static readonly DependencyProperty ShowMaximizeButtonProperty = DependencyProperty.Register("ShowMaximizeButton", typeof(bool), typeof(LibgenDesktopWindow), new PropertyMetadata(true)); - public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), typeof(LibgenDesktopWindow), new PropertyMetadata(true)); - public static readonly DependencyProperty ClosingCommandProperty = DependencyProperty.Register("ClosingCommand", typeof(FuncCommand), typeof(LibgenDesktopWindow)); - public static readonly DependencyProperty ClosedCommandProperty = DependencyProperty.Register("ClosedCommand", typeof(ICommand), typeof(LibgenDesktopWindow)); + public static readonly DependencyProperty ShowIconProperty = DependencyProperty.Register("ShowIcon", typeof(bool), typeof(LibgenDesktopWindow), + new PropertyMetadata(true)); + + public static readonly DependencyProperty ShowMinimizeButtonProperty = DependencyProperty.Register("ShowMinimizeButton", typeof(bool), + typeof(LibgenDesktopWindow), new PropertyMetadata(true)); + + public static readonly DependencyProperty ShowMaximizeButtonProperty = DependencyProperty.Register("ShowMaximizeButton", typeof(bool), + typeof(LibgenDesktopWindow), new PropertyMetadata(true)); + + public static readonly DependencyProperty ShowCloseButtonProperty = DependencyProperty.Register("ShowCloseButton", typeof(bool), + typeof(LibgenDesktopWindow), new PropertyMetadata(true)); + + public static readonly DependencyProperty ClosingCommandProperty = DependencyProperty.Register("ClosingCommand", typeof(FuncCommand), + typeof(LibgenDesktopWindow)); + + public static readonly DependencyProperty ClosedCommandProperty = DependencyProperty.Register("ClosedCommand", typeof(ICommand), + typeof(LibgenDesktopWindow)); public bool ShowIcon { @@ -63,11 +74,11 @@ public bool ShowCloseButton } } - public FuncCommand ClosingCommand + public FuncCommand ClosingCommand { get { - return (FuncCommand)GetValue(ClosingCommandProperty); + return (FuncCommand)GetValue(ClosingCommandProperty); } set { @@ -92,28 +103,28 @@ protected override void OnSourceInitialized(EventArgs e) base.OnSourceInitialized(e); if (!ShowIcon) { - WindowManager.RemoveWindowIcon(this); + this.RemoveWindowIcon(); } if (!ShowMinimizeButton) { - WindowManager.RemoveWindowMinimizeButton(this); + this.RemoveWindowMinimizeButton(); } if (!ShowMaximizeButton) { - WindowManager.RemoveWindowMaximizeButton(this); + this.RemoveWindowMaximizeButton(); } if (!ShowCloseButton) { - WindowManager.RemoveWindowCloseButton(this); + this.RemoveWindowCloseButton(); } } protected override void OnClosing(CancelEventArgs e) { - FuncCommand closingCommand = ClosingCommand; + FuncCommand closingCommand = ClosingCommand; if (closingCommand != null) { - e.Cancel = !closingCommand.Execute(); + e.Cancel = !closingCommand.ExecuteWithTypedParameter(DialogResult); } if (!e.Cancel) { diff --git a/LibgenDesktop/Views/Controls/Link.xaml b/LibgenDesktop/Views/Controls/Link.xaml new file mode 100644 index 0000000..7a20684 --- /dev/null +++ b/LibgenDesktop/Views/Controls/Link.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + diff --git a/LibgenDesktop/Views/Controls/Link.xaml.cs b/LibgenDesktop/Views/Controls/Link.xaml.cs new file mode 100644 index 0000000..ac83405 --- /dev/null +++ b/LibgenDesktop/Views/Controls/Link.xaml.cs @@ -0,0 +1,76 @@ +using System; +using System.Diagnostics; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using LibgenDesktop.Infrastructure; + +namespace LibgenDesktop.Views.Controls +{ + public partial class Link + { + public static readonly DependencyProperty UrlProperty = DependencyProperty.Register("Url", typeof(string), typeof(Link)); + + public static readonly DependencyProperty CopyContextMenuItemTextProperty = DependencyProperty.Register("CopyContextMenuItemText", typeof(string), + typeof(Link), new PropertyMetadata(OnCopyContextMenuItemTextChanged)); + + public Link() + { + InitializeComponent(); + } + + public string Url + { + get + { + return (string)GetValue(UrlProperty); + } + set + { + SetValue(UrlProperty, value); + } + } + + public string CopyContextMenuItemText + { + get + { + return (string)GetValue(CopyContextMenuItemTextProperty); + } + set + { + SetValue(CopyContextMenuItemTextProperty, value); + } + } + + protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) + { + base.OnMouseLeftButtonUp(e); + if (!String.IsNullOrWhiteSpace(Url)) + { + Process.Start(Url); + } + } + + private void CopyMenuItemClick(object sender, RoutedEventArgs e) + { + WindowManager.SetClipboardText(Url); + } + + private void CreateContextMenu() + { + ContextMenu linkContextMenu = Resources["linkContextMenu"] as ContextMenu; + MenuItem copyMenuItem = linkContextMenu.Items[0] as MenuItem; + copyMenuItem.Header = CopyContextMenuItemText; + ContextMenu = linkContextMenu; + } + + private static void OnCopyContextMenuItemTextChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) + { + if (dependencyObject is Link link) + { + link.CreateContextMenu(); + } + } + } +} diff --git a/LibgenDesktop/Views/Controls/Toolbar.xaml b/LibgenDesktop/Views/Controls/Toolbar.xaml index 4971f47..a607cfb 100644 --- a/LibgenDesktop/Views/Controls/Toolbar.xaml +++ b/LibgenDesktop/Views/Controls/Toolbar.xaml @@ -4,7 +4,7 @@ xmlns:md="http://materialdesigninxaml.net/winfx/xaml/themes" xmlns:c="clr-namespace:LibgenDesktop.Views.Controls"> - + @@ -21,7 +21,7 @@ -