void MovedFilmsWindow::ShowFounded( QStringList fileNames ) { DebugPrintFunc( "MovedFilmsWindow::ShowFounded", fileNames.size() ); // Flip button bScan->setText( tr("Scan") ); progressBar->hide(); // Show for( FilmItem* film : unavailableFilms ) { QString unavailFilePath = film->GetFileName(); QString unavailFileName = QFileInfo(unavailFilePath).fileName(); for( QString newFilePath : fileNames ) { QString newFileName = QFileInfo( newFilePath ).fileName(); if( newFileName == unavailFileName && newFilePath != unavailFilePath ) // Protection from multiple moving { gbFounded->AddItem( newFilePath, qVariantFromValue( (void*)film ) ); fileNames.removeOne( newFilePath ); break; } } } if( gbFounded->GetItemsCount() == 0 ) { QMessageBox::information( this, tr("Moved films"), tr("Nothing was found.") ); } DebugPrintFuncDone( "MovedFilmsWindow::ShowFounded" ); }
void FilmScannerWindow::ShowFound( QStringList fileNames ) { DebugPrintFunc( "FilmScannerWindow::ShowFound", fileNames.size() ); bScan->setText( tr("Scan") ); progressBar->hide(); if( fileNames.isEmpty() ) { QMessageBox::information( this, tr("Film scanner"), tr("Nothing was found.") ); return; } for( const QString& fileName : fileNames ) { #ifdef PORTABLE_VERSION bool setDisabled = existedFileNames.contains( QDir(qApp->applicationDirPath()).relativeFilePath(fileName) ); #else bool setDisabled = existedFileNames.contains( fileName ); #endif gbFound->AddItem( fileName, setDisabled ); } DebugPrintFuncDone( "FilmScannerWindow::ShowFound" ); }
void FilmInfoView::ShowInformation( const QModelIndex& index ) { if( index.isValid() ) { DebugPrintFunc( "FilmInfoView::ShowInformation", index.row() ); const FilmsListProxyModel* model = static_cast<const FilmsListProxyModel*>( index.model() ); QString pattern = "<b>%1:</b> %2"; lFilmTitle->setText( model->index( index.row(), FilmItem::TitleColumn ).data().toString() ); lFilmTitle->show(); for( QPair<FilmItem::Column,QLabel*>& item : textItems ) { QString title = model->headerData( item.first, Qt::Horizontal, Qt::DisplayRole ).toString(); QString text = model->index( index.row(), item.first ).data().toString(); item.second->setText( pattern.arg( title, text ) ); item.second->setVisible( !text.isEmpty() ); } QString title = model->headerData( FilmItem::RatingColumn, Qt::Horizontal, Qt::DisplayRole ).toString(); QString text = model->index( index.row(), FilmItem::RatingColumn ).data( Qt::ToolTipRole ).toString(); lRating->setText( pattern.arg( title, text ) ); lRating->setVisible( !text.isEmpty() ); QVariant pixmap = model->index( index.row(), FilmItem::RatingColumn ).data( Qt::DecorationRole ); lRatingImg->setPixmap( pixmap.value<QPixmap>() ); lRatingImg->setVisible( !text.isEmpty() ); DebugPrintFuncDone( "FilmInfoView::ShowInformation" ); } }
MovedFilmsWindow::MovedFilmsWindow( QWidget* parent ) : QDialog( parent ), filmScannerWorker( new FilmScannerWorker() ) { DebugPrintFunc( "MovedFilmsWindow::MovedFilmsWindow" ); setupUi( this ); setAttribute( Qt::WA_DeleteOnClose ); eDirectory->setText( QDir::homePath() ); progressBar->hide(); // Worker connect( filmScannerWorker, &FilmScannerWorker::Scanned, this, &MovedFilmsWindow::ShowFounded ); // Buttons and view connect( bSelectDirectory, &QPushButton::clicked, this, &MovedFilmsWindow::SelectDirectory ); connect( bScan, &QPushButton::clicked, this, &MovedFilmsWindow::Scan ); connect( bMove, &QPushButton::clicked, this, &MovedFilmsWindow::MoveSelected ); connect( gbFounded, &FoundedListWidget::ItemsCountChanged, this, [this] (int count) { lTotalFounded->setText( QString::number(count) ); } ); connect( gbFounded, &FoundedListWidget::SelectionChanged, this, [this] (int count) { lSelected->setText( QString::number(count) ); } ); DebugPrintFuncDone( "MovedFilmsWindow::MovedFilmsWindow" ); }
bool FilmsListLoader::Populate( FilmItem* rootItem, QString fileName ) { DebugPrintFunc( "FilmsListLoader::Populate", fileName ); QFile file( fileName ); if( file.open(QIODevice::ReadOnly) ) { QDataStream stream( &file ); stream.setVersion( QDataStream::Qt_5_3 ); QString databaseHeader; quint8 databaseVersion; stream >> databaseHeader >> databaseVersion; QByteArray data; stream >> data; file.close(); if( !data.isEmpty() ) { QJsonDocument rootDocument = QJsonDocument::fromJson(data); QJsonObject rootObject = rootDocument.object(); QJsonArray filmsArray = rootObject["films"].toArray(); for( int i = 0; i < filmsArray.count(); ++i ) { rootItem->AppendChild( FromJsonObjectToFilm( filmsArray.at(i).toObject() ) ); } } DebugPrint( "Success!" ); DebugPrintFuncDone( "FilmsListLoader::Populate" ); return( true ); }
void MovedFilmsWindow::Scan() { DebugPrintFunc( "MovedFilmsWindow::Scan" ); // If scans if( filmScannerWorker->isRunning() ) { filmScannerWorker->Cancel(); return; } gbFounded->Clear(); // Messages if( eDirectory->text().isEmpty() ) { QMessageBox::information( this, tr("Moved films"), tr("Select the directory to scan.") ); return; } // Scan filmScannerWorker->SetIsRecursive( cSearchInSubdirs->isChecked() ); filmScannerWorker->SetDir( eDirectory->text() ); filmScannerWorker->start(); // Flip button bScan->setText( tr("Cancel") ); progressBar->show(); }
void FilmInfoWindow::LoadTechnicalInfo( const QString& fileName ) { DebugPrintFunc( "FilmInfoWindow::LoadTechnicalInfo", fileName ); QMutexLocker locker( &loadInfoMutex ); MediaInfo* mi = new MediaInfo( fileName ); emit FullInfoLoaded( mi->GetCompleteData() ); delete mi; DebugPrintFuncDone( "FilmInfoWindow::LoadTechnicalInfo" ); }
void FilmsViewList::RestoreColumnsOrder() { DebugPrintFunc( "FilmsViewList::RestoreColumnsOrder" ); QHeaderView* header = horizontalHeader(); for( int i = 0; i < model()->columnCount(); ++i ) { header->moveSection( header->visualIndex(i), i ); } DebugPrintFuncDone( "FilmsViewList::RestoreColumnsOrder" ); }
MovedFilmsWindow::~MovedFilmsWindow() { DebugPrintFunc( "MovedFilmsWindow::~MovedFilmsWindow" ); if( filmScannerWorker->isRunning() ) { filmScannerWorker->Terminate(); filmScannerWorker->wait(); } delete filmScannerWorker; DebugPrintFuncDone( "MovedFilmsWindow::~MovedFilmsWindow" ); }
void NetworkRequest::run( const QUrl& url ) { DebugPrintFunc( "NetworkRequest::run", url.toString() ); data.clear(); reply = MakeRequest( url ); connect( reply.data(), &QNetworkReply::downloadProgress, this, [this] (quint64 received, quint64 total) { emit Progress( received, total ); } ); connect( reply.data(), &QNetworkReply::readyRead, this, &NetworkRequest::ReadyRead ); connect( reply.data(), &QNetworkReply::finished, this, &NetworkRequest::Finished ); connect( reply.data(), &QNetworkReply::finished, reply.data(), &QObject::deleteLater ); DebugPrintFuncDone( "NetworkRequest::run" ); }
FilmsListModel::FilmsListModel( QObject* parent ) : QAbstractItemModel( parent ), settings( AlexandraSettings::GetInstance() ), rootItem( nullptr ) { DebugPrintFunc( "FilmsListModel::FilmsListModel" ); QList<QVariant> titles = { tr( "Title" ), tr( "Original title" ), tr( "Tagline" ), tr( "Year" ), tr( "Genre" ), tr( "Country" ), tr( "Director" ), tr( "Producer" ), tr( "Screenwriter" ), tr( "Composer" ), tr( "Budget" ), tr( "Rating" ), tr( "Viewed" ), tr( "Favourite" ), tr( "Views" ), tr( "Starring" ), tr( "Description" ), tr( "Tags" ), tr( "Filename" ), tr( "Poster" ) }; rootItem = new FilmItem( titles ); connect( this, SIGNAL(rowsInserted(QModelIndex,int,int)), this, SIGNAL(DatabaseChanged()) ); connect( this, SIGNAL(rowsRemoved(QModelIndex,int,int)), this, SIGNAL(DatabaseChanged()) ); connect( this, SIGNAL(dataChanged(QModelIndex,QModelIndex)), this, SIGNAL(DatabaseChanged()) ); connect( this, SIGNAL(layoutChanged()), this, SIGNAL(DatabaseChanged()) ); connect( this, SIGNAL(modelReset()), this, SIGNAL(DatabaseChanged()) ); connect( &savingTimer, &QTimer::timeout, this, [this] { SaveToFileAsync( savingFileName ); } ); DebugPrintFuncDone( "FilmsListModel::FilmsListModel" ); }
FilmScannerWindow::FilmScannerWindow( QWidget* parent ) : QDialog( parent ), settings( AlexandraSettings::GetInstance() ), filmScannerWorker( new FilmScannerWorker() ), filmAddWorker( new FilmScannerAddWorker() ) { DebugPrintFunc( "FilmScannerWindow::FilmScannerWindow" ); setupUi( this ); setAttribute( Qt::WA_DeleteOnClose ); eDirectory->setText( settings->GetFilmsScannerLastDir() ); progressBar->hide(); // Scanner worker connect( filmScannerWorker, &FilmScannerWorker::Scanned, this, &FilmScannerWindow::ShowFound ); connect( filmScannerWorker, &FilmScannerWorker::IncFoundTotal, this, &FilmScannerWindow::IncFoundTotal ); // Add worker connect( filmAddWorker, &FilmScannerAddWorker::FilmCreated, this, &FilmScannerWindow::AddFilm ); connect( filmAddWorker, &FilmScannerAddWorker::FilmCreated, this, &FilmScannerWindow::DisableFilm ); // Parsers cbSource->addItems( ParserManager().GetAvailableParsers() ); cbSource->setCurrentIndex( settings->GetDefaultParserIndex() ); cDownloadBigPoster->setChecked( settings->GetParsersLoadBigPoster() ); cDownloadMoreInformation->setChecked( settings->GetParsersLoadAdvancedInfo() ); // Buttons and view connect( bSelectDirectory, &QPushButton::clicked, this, &FilmScannerWindow::SelectDirectory ); connect( bScan, &QPushButton::clicked, this, &FilmScannerWindow::Scan ); connect( bAdd, &QPushButton::clicked, this, &FilmScannerWindow::AddSelected ); connect( this->gbFound, &FoundListWidget::ItemsCountChanged, this, [this] (int count) { this->lTotalFound->setText( QString::number(count) ); } ); connect( this->gbFound, &FoundListWidget::SelectionChanged, this, [this] (int count) { lSelected->setText( QString::number(count) ); } ); DebugPrintFuncDone( "FilmScannerWindow::FilmScannerWindow()" ); }
void FilmsViewList::SetDefaultColumnsView() { DebugPrintFunc( "FilmsViewList::SetDefaultColumnsView" ); // Move to start QHeaderView* header = horizontalHeader(); header->moveSection( FilmItem::IsFavouriteColumn, 0 ); header->moveSection( FilmItem::IsViewedColumn + 1, 0 ); // Hide QList<int> hiddenColumns = { FilmItem::OriginalTitleColumn, FilmItem::CountryColumn, FilmItem::ProducerColumn, FilmItem::ScreenwriterColumn, FilmItem::ComposerColumn, FilmItem::BudgetColumn, FilmItem::ViewsCountColumn, FilmItem::TaglineColumn, FilmItem::StarringColumn, FilmItem::DescriptionColumn, FilmItem::TagsColumn, FilmItem::FileNameColumn, FilmItem::PosterColumn }; for( int column : hiddenColumns ) { header->hideSection( column ); } // Show and resize QList< QPair<int,int> > shownColumns = { { FilmItem::TitleColumn, 150 }, { FilmItem::YearColumn, 50 }, { FilmItem::GenreColumn, 110 }, { FilmItem::DirectorColumn, 110 }, { FilmItem::RatingColumn, 50 }, { FilmItem::IsViewedColumn, 20 }, { FilmItem::IsFavouriteColumn, 20 } }; for( QPair<int,int>& column : shownColumns ) { header->showSection( column.first ); header->resizeSection( column.first, column.second ); } header->setSortIndicator( FilmItem::TitleColumn, Qt::AscendingOrder ); DebugPrintFuncDone( "FilmsViewList::SetDefaultColumnsView" ); }
QByteArray NetworkRequest::runSync( const QUrl& url ) { DebugPrintFunc( "NetworkRequest::runSync", url.toString() ); data.clear(); reply = MakeRequest( url ); QEventLoop loop; connect( reply.data(), &QNetworkReply::downloadProgress, this, [this] (quint64 received, quint64 total) { emit Progress( received, total ); } ); connect( reply.data(), &QNetworkReply::readyRead, this, &NetworkRequest::ReadyRead ); connect( reply.data(), &QNetworkReply::finished, this, &NetworkRequest::CheckForRedirect ); connect( reply.data(), &QNetworkReply::finished, &loop, &QEventLoop::quit ); loop.exec(); DebugPrint( QString( "Loaded: %1 bytes" ).arg( data.size() ) ); DebugPrintFuncDone( "NetworkRequest::runSync" ); reply->deleteLater(); return( data ); }
FilmScannerWindow::~FilmScannerWindow() { DebugPrintFunc( "FilmScannerWindow::~FilmScannerWindow" ); if( filmScannerWorker->isRunning() ) { filmScannerWorker->Terminate(); filmScannerWorker->wait(); } else if( filmAddWorker->isRunning() ) { filmAddWorker->Cancel(); filmAddWorker->wait(); } delete filmScannerWorker; delete filmAddWorker; DebugPrintFuncDone( "FilmScannerWindow::~FilmScannerWindow" ); }
QUrl ImdbParser::Parse( const QByteArray& data ) { DebugPrintFunc( "ImdbParser::Parse", data.size() ); QString foundedPage( data ); RegExpTools::SimplifyText( foundedPage ); QRegExp reRedirect( "class=\"number\">1.</td><td class=\"title\"><a href=\"(.*)\">"); QString redirectUrl( RegExpTools::ParseItem( foundedPage, reRedirect ) ); QUrl posterUrl; if( !redirectUrl.isEmpty() ) { redirectUrl = "http://www.imdb.com" + redirectUrl; QString str( request.runSync( QUrl( redirectUrl ) ) ); RegExpTools::SimplifyText( str ); DebugPrint( QString( "Simpified to: %1 bytes" ).arg( str.size() ) ); // Title QRegExp reTitle( "h1 itemprop=\"name\".*>(.*)<span" ); film.SetColumnData( FilmItem::TitleColumn, RegExpTools::ParseItem( str, reTitle ) ); // Original title QRegExp reOriginalTitle( "div class=\"originalTitle\">(.*)<span" ); film.SetColumnData( FilmItem::OriginalTitleColumn, RegExpTools::ParseItem( str, reOriginalTitle ) ); // Tagline QRegExp reTagline( "Taglines:</h4>(.*)<" ); film.SetColumnData( FilmItem::TaglineColumn, RegExpTools::ParseItem( str, reTagline ) ); // Year QRegExp reYear( "Release Date:</h4>.*([0-9]{4})" ); film.SetColumnData( FilmItem::YearColumn, RegExpTools::ParseItem( str, reYear ).toInt() ); // Budget QRegExp reBudget( "Budget:</h4> \\$(.*)<span" ); film.SetColumnData( FilmItem::BudgetColumn, RegExpTools::ParseItem( str, reBudget ).replace( " ", "" ).toDouble() ); // Rating QRegExp reRating( "itemprop=\"ratingValue\">(.*)</span>" ); film.SetColumnData( FilmItem::RatingColumn, RegExpTools::ParseItem( str, reRating ).replace( ",", "." ).toDouble() ); // Country QRegExp reCountryList( "Countr.*</h4>(.*)</div>" ); QRegExp reCountry( "href=\"/country/.*>(.*)</a>" ); film.SetColumnData( FilmItem::CountryColumn, RegExpTools::ParseList( str, reCountryList, reCountry ) ); // Genre QRegExp reGenreList( "Genres:</h4>(.*)</div>" ); QRegExp reGenre( "href=\"/genre/.*>(.*)</a>" ); film.SetColumnData( FilmItem::GenreColumn, RegExpTools::ParseList( str, reGenreList, reGenre ) ); // Description QRegExp reDescription( "Storyline</h2><.*><p>(.*)<em class=\"nobr\">" ); film.SetColumnData( FilmItem::DescriptionColumn, RegExpTools::ParseItem( str, reDescription ).replace( "<br><br>", "<br>\n" ) ); // Advanced information QRegExp reName( "itemprop=\"name\">(.*)</span>" ); if( AlexandraSettings::GetInstance()->GetParsersLoadAdvancedInfo() ) { QString str( request.runSync( QUrl( redirectUrl + "fullcredits" ) ) ); RegExpTools::SimplifyText( str ); DebugPrint( QString( "Simpified to: %1 bytes" ).arg( str.size() ) ); // Starring QRegExp reStarringList( "Cast <span>(.*)Produced by" ); film.SetColumnData( FilmItem::StarringColumn, RegExpTools::ParseList( str, reStarringList, reName, 20 ) ); // 20 first actors // Director QRegExp reDirectorList( "Directed by(.*)Writing Credits" ); reName = QRegExp( "href=\"/name/.*>(.*)</a>" ); film.SetColumnData( FilmItem::DirectorColumn, RegExpTools::ParseList( str, reDirectorList, reName, 10 ) ); // 10 first directors // Screenwriter QRegExp reScreenwriterList( "Writing Credits(.*)Cast" ); film.SetColumnData( FilmItem::ScreenwriterColumn, RegExpTools::ParseList( str, reScreenwriterList, reName, 10 ) ); // 10 first writers // Producer QRegExp reProducerList( "Produced by(.*)Music by" ); film.SetColumnData( FilmItem::ProducerColumn, RegExpTools::ParseList( str, reProducerList, reName, 10 ) ); // 10 first producers // Composer QRegExp reComposerList( "Music by(.*)Film Editing by" ); film.SetColumnData( FilmItem::ComposerColumn, RegExpTools::ParseList( str, reComposerList, reName ) ); } else { // Starring QRegExp reStarringList( "Cast</h2>(.*)</table>" ); film.SetColumnData( FilmItem::StarringColumn, RegExpTools::ParseList( str, reStarringList, reName ) ); // Director QRegExp reDirectorList( "Director.*</h4>(.*)</div>" ); QRegExp reName( "itemprop=\"name\">(.*)</span>" ); film.SetColumnData( FilmItem::DirectorColumn, RegExpTools::ParseList( str, reDirectorList, reName ) ); // Screenwriter QRegExp reScreenwriterList( "Writer.*</h4>(.*)</div>" ); film.SetColumnData( FilmItem::ScreenwriterColumn, RegExpTools::ParseList( str, reScreenwriterList, reName ) ); } // Poster if( AlexandraSettings::GetInstance()->GetParsersLoadBigPoster() ) { QRegExp rePoster( "div class=\"poster\"><a href=\"(.*)\"" ); QString s = QString( request.runSync( QUrl( "http://www.imdb.com" + RegExpTools::ParseItem( str, rePoster ) ) ) ); RegExpTools::SimplifyText( s ); DebugPrint( QString( "Simpified to: %1 bytes" ).arg( s.size() ) ); rePoster = QRegExp( "id=\"primary-img\".*src=\"(.*)\"" ); posterUrl = RegExpTools::ParseItem( s, rePoster ); } if( posterUrl.isEmpty() ) // Small poster { QRegExp rePoster( "div class=\"poster\"><.*><img.*src=\"(.*)\"" ); posterUrl = RegExpTools::ParseItem( str, rePoster ); } DebugPrint( "Text parsed!" ); emit Loaded( film, posterUrl ); } else { emit Error( "Movie not found!" ); } return( posterUrl ); }
ImdbParser::ImdbParser() : AbstractParser() { DebugPrintFunc( "ImdbParser::ImdbParser" ); searchUrlWithYear = QString( "http://www.imdb.com/search/title?title=%1&release_date=%2&view=simple" ); searchUrl = QString( "http://www.imdb.com/search/title?title=%1&view=simple" ); }
bool FilmsListOldLoader::Populate( FilmItem* rootItem, const QString& fileName ) { DebugPrintFunc( "FilmsListOldLoader::Populate", fileName ); QFile file( fileName ); if( file.open(QIODevice::ReadOnly) ) { AlexandraSettings* settings = AlexandraSettings::GetInstance(); QDataStream stream( &file ); QString header; quint8 version; stream >> header >> version; if( version == OldVersion10 ) { QList<Film010> films; stream >> films; for( Film010& film : films ) { // Views counter int viewsCount = film.GetViewsCounter(); if( film.GetIsViewed() && viewsCount == 0 ) { viewsCount = 1; } bool isViewed = (viewsCount > 0) ? true : false; // Poster files renaming (for very old databases) QString posterFilename = film.GetPosterName(); if( !posterFilename.isEmpty() ) { QString posterFilepath = settings->GetPostersDirPath() + "/" + posterFilename; QFile posterFile( posterFilepath ); if( !posterFile.exists() ) { QString maybeOldPoster = FilesExtensions::SearchForEponymousImage(posterFilepath); if ( !maybeOldPoster.isEmpty() ) { QFileInfo fileinfo( maybeOldPoster ); QDir postersDir( fileinfo.absolutePath() ); postersDir.rename( fileinfo.fileName(), posterFilename ); } } } // Filling data QList<QVariant> data; data << film.GetTitle() << film.GetOriginalTitle() << film.GetTagline() << film.GetYear() << film.GetGenre() << film.GetCountry() << film.GetDirector() << film.GetProducer() << film.GetScreenwriter() << film.GetComposer() << film.GetBudget() << film.GetRating() << isViewed << film.GetIsFavourite() << viewsCount << film.GetStarring() << film.GetDescription() << film.GetTags() << film.GetFileName() << film.GetId(); // PosterName FilmItem* item = new FilmItem( data, rootItem ); rootItem->AppendChild( item ); } DebugPrint( "Success!" ); DebugPrintFuncDone( "FilmsListOldLoader::Populate" ); return( true ); }
void FilmsListModel::LoadFromFile( QString fileName ) { DebugPrintFunc( "FilmsList::LoadFromFile", fileName ); beginResetModel(); rootItem->RemoveChildren(); QFile file( fileName ); if( !file.exists() ) { isDatabaseChanged = true; // Will be created emit DatabaseIsEmpty(); } else if( file.open( QIODevice::ReadOnly ) ) { QDataStream stream( &file ); QString databaseHeader; stream >> databaseHeader; if( databaseHeader == Alexandra::databaseHeader ) { bool isLoaded; quint8 databaseVersion; stream >> databaseVersion; file.close(); if( databaseVersion == Alexandra::databaseVersion ) { isLoaded = FilmsListLoader::Populate( rootItem, fileName ); } else { emit DatabaseConvertOld(); isLoaded = FilmsListOldLoader::Populate( rootItem, fileName ); if( isLoaded ) { FilmsListLoader::Save( rootItem, fileName ); } } if( isLoaded ) { DebugPrint( "Reading done!" ); emit DatabaseLoaded(); isReadonly = false; if( rootItem->GetChildrenCount() == 0 ) { emit DatabaseIsEmpty(); } if( !QFileInfo(fileName).isWritable() ) { emit DatabaseIsReadonly(); isReadonly = true; } } else { emit DatabaseReadError( tr("Can't load database!") ); } }