public SettingsWindowViewModel()
        {
            _saveSettingsCommand = new RelayCommand(SaveClicked);
            _browseCommand = new RelayCommand(BrowseClicked);
            _clearCommand = new RelayCommand(ClearClicked);

            MaxParallelDownloads = Properties.Settings.Default.MaxParallelDownloads;
            ReaderPath = Properties.Settings.Default.ReaderPath;
            EnablePreload = Properties.Settings.Default.EnablePreload;
            MaxRecentFolders = Properties.Settings.Default.RecentFolders.MaxItems;
            PreselectDownloadFolder = Properties.Settings.Default.PreselectOutputFolder;
            RecentMangaDaysNum = Properties.Settings.Default.RecentMangaDaysNum;
            ChaptersSelectionMode = Properties.Settings.Default.ChaptersSelectionMode;

            Scrapers = ScraperLoader.Instance.AllScrapers
                .Select(s =>
                    new ScraperInfo(s, !Properties.Settings.Default.DisabledScrapers.Contains(s.ScraperGuid))).ToList();

            try
            {
                using (var reader = new System.IO.StreamReader(System.Windows.Application.GetResourceStream(new System.Uri("/readme.txt", UriKind.Relative)).Stream, Encoding.UTF8))
                {
                    AboutText = reader.ReadToEnd();
                }
            }
            catch (System.IO.IOException ex)
            {
                _log.Error("Unable to load about information from resource.", ex);
                AboutText = "";
            }
        }
        public MainWindowViewModel()
        {
            _searchCommand = new RelayCommand(SearchManga);
            _browseCommand = new RelayCommand(BrowseClicked);
            _saveCommand = new RelayCommand(SaveClicked);

            // load output path from user settings
            _outputPath = Properties.Settings.Default.OutputPath;

            Mangas = new AsyncObservableCollection<IMangaRecord>();
            Chapters = new AsyncObservableCollection<ChapterViewModel>();
            SelectedChapters = new AsyncObservableCollection<IChapterRecord>();

            _requestQueue = new AsyncRequestQueue();
            _requestQueue.TasksCompleted += _requestQueue_TasksCompleted;
            _requestQueue.Initialize();

            _downloadManager = new DownloadManagerViewModel();

            // load all enabled scrapers
            _scrapers = ScraperLoader.Instance.EnabledScrapers;

            if (!string.IsNullOrEmpty(Properties.Settings.Default.SelectedScraper))
                CurrentScraper = _scrapers.FirstOrDefault(s => s.Name == Properties.Settings.Default.SelectedScraper);

            if (CurrentScraper == null)
                CurrentScraper = _scrapers.First();

            _downloadFormatProviders = ScraperLoader.Instance.DownloadFormatProviders;
            CurrentDownloadFormatProvider = ScraperLoader.Instance.GetFirstOrDefaultDownloadFormatProvider(Properties.Settings.Default.DownloadFormatProvider);

            if (Properties.Settings.Default.EnablePreload)
            {
                PreloadMangas();
            }
        }
        public DownloadViewModel(DownloadedChapterInfo downloadInfo, ISemaphore downloadSemaphore)
        {
            if (downloadInfo == null)
                throw new ArgumentNullException("downloadInfo");

            if (downloadSemaphore == null)
                throw new ArgumentNullException("downloadSemaphore");

            if (downloadInfo.ChapterRecord == null)
                throw new ArgumentException("Chapter record is invalid.", "downloadInfo");

            if (String.IsNullOrEmpty(downloadInfo.ChapterRecord.ChapterId))
                throw new ArgumentException("Chapter record id is invalid.", "downloadInfo");

            if (downloadInfo.ChapterRecord.MangaRecord == null)
                throw new ArgumentException("Manga record is invalid.", "downloadInfo");

            if (String.IsNullOrEmpty(downloadInfo.ChapterRecord.MangaRecord.MangaId))
                throw new ArgumentException("Manga record id is invalid.", "downloadInfo");

            _downloadInfo = downloadInfo;
            _downloadSemaphore = downloadSemaphore;

            _scraper = ScraperLoader.Instance.AllScrapers.FirstOrDefault(s => s.ScraperGuid == downloadInfo.ChapterRecord.Scraper);

            if (_scraper != null)
            {
                _downloader = _scraper.GetDownloader();

                // register downloader events
                _downloader.DownloadProgress += _downloader_DownloadProgress;
                _downloader.DownloadCompleted += _downloader_DownloadCompleted;
            }

            if (!String.IsNullOrEmpty(_downloadInfo.Path))
            {
                // file was already downloaded
                State = DownloadState.Unknown;
                Completed = true;
            }
            else
            {
                // we will be downloading the file now
                State = DownloadState.Ok;
                Completed = false;
            }

            CurrentActionText = String.Empty;

            _cancelDownloadCommand = new RelayCommand(Cancel, x => !Completed);
            _removeDownloadCommand = new RelayCommand(Remove);
            _openDownloadCommand = new RelayCommand(Open, x => DownloadExists);
            _retryDownloadCommand = new RelayCommand(RetryDownload, x => _downloader != null
                                                                         && Completed
                                                                         && !DownloadExists
                                                                         && !String.IsNullOrEmpty(_downloadInfo.DownloadFolder));

            CancelText = ButtonCancelText;
        }