diff --git a/App.config b/App.config
index 72a71af..8e15646 100644
--- a/App.config
+++ b/App.config
@@ -1,6 +1,6 @@
-
+
-
-
-
+
+
+
\ No newline at end of file
diff --git a/App.xaml b/App.xaml
new file mode 100644
index 0000000..9afe297
--- /dev/null
+++ b/App.xaml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/App.xaml.cs b/App.xaml.cs
new file mode 100644
index 0000000..06fc145
--- /dev/null
+++ b/App.xaml.cs
@@ -0,0 +1,16 @@
+using System.Windows;
+using LibgenDesktop.Infrastructure;
+
+namespace LibgenDesktop
+{
+ public partial class App : Application
+ {
+ protected override void OnStartup(StartupEventArgs e)
+ {
+ base.OnStartup(e);
+ IWindowContext mainWindowContext = WindowManager.CreateWindow(RegisteredWindows.WindowKey.MAIN_WINDOW);
+ mainWindowContext.Closed += (sender, args) => Shutdown();
+ mainWindowContext.Show();
+ }
+ }
+}
diff --git a/Cache/CachedDataAccessor.cs b/Cache/CachedDataAccessor.cs
deleted file mode 100644
index b1c39db..0000000
--- a/Cache/CachedDataAccessor.cs
+++ /dev/null
@@ -1,85 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Windows.Forms;
-using BrightIdeasSoftware;
-using LibgenDesktop.Database;
-
-namespace LibgenDesktop.Cache
-{
- internal class CachedDataAccessor : IVirtualListDataSource
- {
- private readonly List cachedBooks;
-
- public CachedDataAccessor(List cachedBooks)
- {
- this.cachedBooks = cachedBooks;
- }
-
- public event EventHandler SortingRequested;
-
- public void PrepareCache(int first, int last)
- {
- }
-
- public object GetNthObject(int n)
- {
- if (cachedBooks.Count > n)
- {
- return cachedBooks[n];
- }
- else
- {
- return null;
- }
- }
-
- public int GetObjectCount()
- {
- return cachedBooks.Count;
- }
-
- public int GetObjectIndex(object model)
- {
- return -1;
- }
-
- public void AddObjects(ICollection modelObjects)
- {
- throw new NotImplementedException();
- }
-
- public void InsertObjects(int index, ICollection modelObjects)
- {
- throw new NotImplementedException();
- }
-
- public void RemoveObjects(ICollection modelObjects)
- {
- throw new NotImplementedException();
- }
-
- public int SearchText(string value, int first, int last, OLVColumn column)
- {
- throw new NotImplementedException();
- }
-
- public void SetObjects(IEnumerable collection)
- {
- }
-
- public void Sort(OLVColumn column, SortOrder order)
- {
- }
-
- public void UpdateObject(int index, object modelObject)
- {
- throw new NotImplementedException();
- }
-
- private void RaiseSortingRequested()
- {
-
- }
- }
-}
diff --git a/Cache/DataCache.cs b/Cache/DataCache.cs
deleted file mode 100644
index f11eae3..0000000
--- a/Cache/DataCache.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using System;
-using System.Collections.Generic;
-using LibgenDesktop.Database;
-using LibgenDesktop.Import;
-using LibgenDesktop.Infrastructure;
-
-namespace LibgenDesktop.Cache
-{
- internal class DataCache
- {
- private readonly LocalDatabase localDatabase;
- private List cachedBooks;
- private List searchResults;
- private CachedDataAccessor cachedBooksDataAccessor;
- private CachedDataAccessor searchResultsDataAccessor;
-
- public DataCache(LocalDatabase localDatabase)
- {
- this.localDatabase = localDatabase;
- cachedBooks = new List();
- cachedBooksDataAccessor = new CachedDataAccessor(cachedBooks);
- searchResults = new List();
- searchResultsDataAccessor = new CachedDataAccessor(searchResults);
- DataAccessor = cachedBooksDataAccessor;
- IsInAllBooksMode = true;
- }
-
- public CachedDataAccessor DataAccessor { get; private set; }
- public bool IsInAllBooksMode { get; private set; }
-
- public ProgressOperation CreateLoadBooksOperation()
- {
- searchResults.Clear();
- DataAccessor = cachedBooksDataAccessor;
- return new LoadBooksOperation(localDatabase, cachedBooks);
- }
-
- public ProgressOperation CreateSearchBooksOperation(string searchQuery)
- {
- searchResults.Clear();
- searchQuery = searchQuery.Trim();
- if (searchQuery == String.Empty)
- {
- DataAccessor = cachedBooksDataAccessor;
- IsInAllBooksMode = true;
- return null;
- }
- else
- {
- DataAccessor = searchResultsDataAccessor;
- IsInAllBooksMode = false;
- return new SearchBooksOperation(localDatabase, searchResults, searchQuery);
- }
- }
-
- public ProgressOperation CreateImportSqlDumpOperation(string sqlDumpFilePath)
- {
- cachedBooks.Clear();
- IsInAllBooksMode = true;
- return new ImportSqlDumpOperation(localDatabase, sqlDumpFilePath, cachedBooks);
- }
- }
-}
diff --git a/Cache/LoadBooksOperation.cs b/Cache/LoadBooksOperation.cs
deleted file mode 100644
index 4132e0f..0000000
--- a/Cache/LoadBooksOperation.cs
+++ /dev/null
@@ -1,53 +0,0 @@
-using System.Collections.Generic;
-using System.Threading;
-using LibgenDesktop.Database;
-using LibgenDesktop.Infrastructure;
-using LibgenDesktop.Interface;
-
-namespace LibgenDesktop.Cache
-{
- internal class LoadBooksOperation : ProgressOperation
- {
- private readonly LocalDatabase localDatabase;
- private readonly List targetList;
-
- public LoadBooksOperation(LocalDatabase localDatabase, List targetList)
- {
- this.localDatabase = localDatabase;
- this.targetList = targetList;
- }
-
- protected override void DoWork(CancellationToken token)
- {
- int totalBookCount = localDatabase.CountBooks();
- int currentBatchBookNumber = 0;
- int reportProgressBatchSize = totalBookCount / 1000;
- foreach (Book book in localDatabase.GetAllBooks())
- {
- if (token.IsCancellationRequested)
- {
- return;
- }
- targetList.Add(book);
- currentBatchBookNumber++;
- if (currentBatchBookNumber == reportProgressBatchSize)
- {
- RaiseProgressEvent(new ProgressEventArgs
- {
- ProgressDescription = $"Загрузка книг (загружено {targetList.Count.ToString("N0", Formatters.ThousandsSeparatedNumberFormat)} из {totalBookCount.ToString("N0", Formatters.ThousandsSeparatedNumberFormat)})...",
- PercentCompleted = (double)targetList.Count * 100 / totalBookCount
- });
- currentBatchBookNumber = 0;
- }
- }
- if (currentBatchBookNumber > 0)
- {
- RaiseProgressEvent(new ProgressEventArgs
- {
- PercentCompleted = 100
- });
- }
- RaiseCompletedEvent();
- }
- }
-}
diff --git a/Cache/SearchBooksOperation.cs b/Cache/SearchBooksOperation.cs
deleted file mode 100644
index bc23a27..0000000
--- a/Cache/SearchBooksOperation.cs
+++ /dev/null
@@ -1,51 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Threading;
-using LibgenDesktop.Database;
-using LibgenDesktop.Infrastructure;
-using LibgenDesktop.Interface;
-
-namespace LibgenDesktop.Cache
-{
- internal class SearchBooksOperation : ProgressOperation
- {
- private const int REPORT_PROGRESS_BATCH_SIZE = 2000;
-
- private readonly LocalDatabase localDatabase;
- private readonly List targetList;
- private readonly string searchQuery;
-
- public SearchBooksOperation(LocalDatabase localDatabase, List targetList, string searchQuery)
- {
- this.localDatabase = localDatabase;
- this.targetList = targetList;
- this.searchQuery = searchQuery;
- }
-
- public override bool IsUnbounded => true;
-
- protected override void DoWork(CancellationToken token)
- {
- int currentBatchBookNumber = 0;
- foreach (Book book in localDatabase.SearchBooks(searchQuery))
- {
- if (token.IsCancellationRequested)
- {
- return;
- }
- targetList.Add(book);
- currentBatchBookNumber++;
- if (currentBatchBookNumber == REPORT_PROGRESS_BATCH_SIZE)
- {
- RaiseProgressEvent(new ProgressEventArgs
- {
- ProgressDescription = $"Поиск книг (найдено {targetList.Count.ToString("N0", Formatters.ThousandsSeparatedNumberFormat)})...",
- PercentCompleted = Double.NaN
- });
- currentBatchBookNumber = 0;
- }
- }
- RaiseCompletedEvent();
- }
- }
-}
diff --git a/Common/Constants.cs b/Common/Constants.cs
new file mode 100644
index 0000000..cfe6484
--- /dev/null
+++ b/Common/Constants.cs
@@ -0,0 +1,40 @@
+namespace LibgenDesktop.Common
+{
+ internal static class Constants
+ {
+ public const int MAIN_WINDOW_MIN_WIDTH = 1000;
+ public const int MAIN_WINDOW_MIN_HEIGHT = 500;
+ public const int BOOK_WINDOW_MIN_WIDTH = 1000;
+ public const int BOOK_WINDOW_MIN_HEIGHT = 500;
+ public const int ERROR_WINDOW_MIN_WIDTH = 400;
+ public const int ERROR_WINDOW_MIN_HEIGHT = 300;
+ public const int TITLE_COLUMN_MIN_WIDTH = 150;
+ public const int AUTHORS_COLUMN_MIN_WIDTH = 150;
+ public const int SERIES_COLUMN_MIN_WIDTH = 150;
+ public const int YEAR_COLUMN_MIN_WIDTH = 60;
+ public const int PUBLISHER_COLUMN_MIN_WIDTH = 150;
+ public const int FORMAT_COLUMN_MIN_WIDTH = 80;
+ public const int FILESIZE_COLUMN_MIN_WIDTH = 130;
+ public const int OCR_COLUMN_MIN_WIDTH = 55;
+
+ public const string DEFAULT_DATABASE_FILE_NAME = "libgen.db";
+ public const int DEFAULT_MAIN_WINDOW_WIDTH = 1200;
+ public const int DEFAULT_MAIN_WINDOW_HEIGHT = 650;
+ public const int DEFAULT_BOOK_WINDOW_WIDTH = 1200;
+ public const int DEFAULT_BOOK_WINDOW_HEIGHT = 618;
+ public const int DEFAULT_TITLE_COLUMN_WIDTH = 200;
+ public const int DEFAULT_AUTHORS_COLUMN_WIDTH = 200;
+ public const int DEFAULT_SERIES_COLUMN_WIDTH = 180;
+ public const int DEFAULT_YEAR_COLUMN_WIDTH = 60;
+ public const int DEFAULT_PUBLISHER_COLUMN_WIDTH = 180;
+ public const int DEFAULT_FORMAT_COLUMN_WIDTH = 100;
+ public const int DEFAULT_FILESIZE_COLUMN_WIDTH = 150;
+ public const int DEFAULT_OCR_COLUMN_WIDTH = 55;
+
+ public const int SEARCH_REPORT_PROGRESS_BATCH_SIZE = 2000;
+ public const int INSERT_TRANSACTION_BATCH = 500;
+
+ public const string BOOK_COVER_URL_PREFIX = "http://libgen.io/covers/";
+ public const string BOOK_DOWNLOAD_URL_PREFIX = "http://libgen.io/book/index.php?md5=";
+ }
+}
diff --git a/Import/ImportSqlDumpOperation.cs b/Import/ImportSqlDumpOperation.cs
deleted file mode 100644
index 12be7e5..0000000
--- a/Import/ImportSqlDumpOperation.cs
+++ /dev/null
@@ -1,78 +0,0 @@
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
-using LibgenDesktop.Database;
-using LibgenDesktop.Infrastructure;
-using LibgenDesktop.Interface;
-
-namespace LibgenDesktop.Import
-{
- internal class ImportSqlDumpOperation : ProgressOperation
- {
- private readonly LocalDatabase localDatabase;
- private readonly string sqlDumpFilePath;
- private readonly List targetList;
-
- public ImportSqlDumpOperation(LocalDatabase localDatabase, string sqlDumpFilePath, List targetList)
- {
- this.localDatabase = localDatabase;
- this.sqlDumpFilePath = sqlDumpFilePath;
- this.targetList = targetList;
- }
-
- public override string Title => "Импорт из SQL-дампа";
-
- protected override void DoWork(CancellationToken token)
- {
- RaiseProgressEvent(new ProgressEventArgs
- {
- ProgressDescription = "Импорт из SQL-дампа...",
- PercentCompleted = 0
- });
- using (SqlDumpReader sqlDumpReader = new SqlDumpReader(sqlDumpFilePath))
- {
- sqlDumpReader.ReadRowsProgress += SqlDumpReader_ReadRowsProgress;
- List currentBatchBooks = new List(LocalDatabase.INSERT_TRANSACTION_BATCH);
- foreach (Book book in sqlDumpReader.ReadRows())
- {
- if (token.IsCancellationRequested)
- {
- break;
- }
- currentBatchBooks.Add(book);
- if (currentBatchBooks.Count == LocalDatabase.INSERT_TRANSACTION_BATCH)
- {
- localDatabase.AddBooks(currentBatchBooks);
- foreach (Book currentBatchBook in currentBatchBooks)
- {
- currentBatchBook.ExtendedProperties = null;
- }
- targetList.AddRange(currentBatchBooks);
- currentBatchBooks.Clear();
- }
- }
- if (currentBatchBooks.Any())
- {
- localDatabase.AddBooks(currentBatchBooks);
- foreach (Book currentBatchBook in currentBatchBooks)
- {
- currentBatchBook.ExtendedProperties = null;
- }
- targetList.AddRange(currentBatchBooks);
- }
- sqlDumpReader.ReadRowsProgress -= SqlDumpReader_ReadRowsProgress;
- }
- RaiseCompletedEvent();
- }
-
- private void SqlDumpReader_ReadRowsProgress(object sender, SqlDumpReader.ReadRowsProgressEventArgs e)
- {
- RaiseProgressEvent(new ProgressEventArgs
- {
- ProgressDescription = $"Импорт из SQL-дампа... (импортировано {e.RowsParsed.ToString("N0", Formatters.ThousandsSeparatedNumberFormat)} книг)",
- PercentCompleted = ((double)e.CurrentPosition * 100 / e.TotalLength)
- });
- }
- }
-}
diff --git a/Infrastructure/Command.cs b/Infrastructure/Command.cs
new file mode 100644
index 0000000..87a5f00
--- /dev/null
+++ b/Infrastructure/Command.cs
@@ -0,0 +1,49 @@
+using System;
+using System.Windows.Input;
+
+namespace LibgenDesktop.Infrastructure
+{
+ internal class Command : ICommand
+ {
+ Predicate