diff --git a/.gitignore b/.gitignore index a44ae58..217cbd8 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,10 @@ *.so.* *.dll *.dylib +Build +checks.json +.vscode +build # Qt-es object_script.*.Release @@ -20,6 +24,7 @@ object_script.*.Debug *_plugin_import.cpp /.qmake.cache /.qmake.stash +src/*.qmake.stash *.pro.user *.pro.user.* *.qbs.user diff --git a/CMakeLists.txt b/CMakeLists.txt deleted file mode 100644 index e087f6b..0000000 --- a/CMakeLists.txt +++ /dev/null @@ -1,43 +0,0 @@ -cmake_minimum_required(VERSION 3.16) - -project(MediaLibraryBuild VERSION 1.0 LANGUAGES CXX) - -# Qt5: automatizza moc, uic, rcc -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) - -# Raccoglie tutti i file .cpp e .h nella cartella src/ -file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS src/*.cpp src/*.h) - -# Crea l'eseguibile principale -add_executable(${PROJECT_NAME} ${SOURCES}) - -target_include_directories(${PROJECT_NAME} PRIVATE src) - -# Trova e linka le librerie Qt necessarie -find_package(Qt5 REQUIRED COMPONENTS Core Widgets Gui) - -target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Widgets Qt5::Gui) - -# Imposta la cartella output dell'eseguibile -set_target_properties(${PROJECT_NAME} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR} -) - -# Abilita il supporto ai test -enable_testing() - -# Test (facoltativi) -file(GLOB_RECURSE TEST_SOURCES CONFIGURE_DEPENDS src/test*.cpp) - -foreach(test_src ${TEST_SOURCES}) - get_filename_component(test_name ${test_src} NAME_WE) - add_executable(${test_name} ${test_src}) - target_include_directories(${test_name} PRIVATE src) - target_link_libraries(${test_name} PRIVATE Qt5::Core Qt5::Widgets Qt5::Gui) - add_test(NAME ${test_name} COMMAND ${test_name}) -endforeach() diff --git a/src/Media/Album.cpp b/src/Media/Album.cpp index d20ecf3..d19e638 100644 --- a/src/Media/Album.cpp +++ b/src/Media/Album.cpp @@ -16,4 +16,74 @@ const std::vector &Album::getBandMembers() const { return band_members_; } const std::vector &Album::getSongs() const { return songs_; } +bool Album::operator==(const Media &other) const { + const Album *other_album = dynamic_cast(&other); + if (other_album) { + return Media::operator==(*other_album) && band_ == other_album->band_ && + band_members_ == other_album->band_members_ && + songs_ == other_album->songs_; + } + return false; +} + +std::vector> Album::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizzo filtro base di Media + std::vector> baseInput(input.begin(), input.end()); + std::vector> filteredBase = Media::filter(baseInput); + + // Filtro specifico per Album + for (const auto& mediaPtr : filteredBase) { + auto albumPtr = std::dynamic_pointer_cast(mediaPtr); + if (!albumPtr) continue; + + bool match = true; + + // Band + if (!band_.empty() && !stringContainsIgnoreCase(albumPtr->getBand(), band_)) + match = false; + + // Band members (ogni membro richiesto deve matchare almeno uno esistente) + if (!band_members_.empty()) { + for (const auto& memberFilter : band_members_) { + bool found = false; + for (const auto& m : albumPtr->getBandMembers()) { + if (stringContainsIgnoreCase(m, memberFilter)) { + found = true; + break; + } + } + if (!found) { + match = false; + break; + } + } + } + + // Songs (ogni canzone richiesta deve matchare almeno una esistente) + if (!songs_.empty()) { + for (const auto& songFilter : songs_) { + bool found = false; + for (const auto& s : albumPtr->getSongs()) { + if (stringContainsIgnoreCase(s, songFilter)) { + found = true; + break; + } + } + if (!found) { + match = false; + break; + } + } + } + + if (match) + result.push_back(albumPtr); + } + + return result; +} + + } // namespace media diff --git a/src/Media/Album.h b/src/Media/Album.h index 99c802e..da0fd7c 100644 --- a/src/Media/Album.h +++ b/src/Media/Album.h @@ -13,11 +13,15 @@ class Album : public Media { Album(const std::string &title, int release, const std::string &language, bool favourite, const std::vector &genres, const std::string &img_path, const std::string ¬es, - const std::string &band, const std::vector &band_members, - const std::vector &songs); + const std::string &band = "", const std::vector &band_members = {}, + const std::vector &songs = {}); const std::string &getBand() const; const std::vector &getBandMembers() const; const std::vector &getSongs() const; + bool operator==(const Media &other) const override; + + std::vector> filter(const std::vector>& input) const; + }; } // namespace media #endif diff --git a/src/Media/AudioBook.cpp b/src/Media/AudioBook.cpp index b1aa6af..89f43ca 100644 --- a/src/Media/AudioBook.cpp +++ b/src/Media/AudioBook.cpp @@ -12,8 +12,13 @@ AudioBook::AudioBook(const std::string& title, int publicationYear, const std::s narrator_(narrator), streamingService_(streamingService) {} -void AudioBook::accept(IConstMediaVisitor& v) const { - v.visit(*this); +bool AudioBook::operator==(const Media& other) const { + const AudioBook* otherAudioBook = dynamic_cast(&other); + if (otherAudioBook) { + return Novel::operator==(*otherAudioBook) && narrator_ == otherAudioBook->narrator_ && + streamingService_ == otherAudioBook->streamingService_; + } + return false; } std::string AudioBook::getNarrator() const { @@ -32,4 +37,33 @@ void AudioBook::setStreamingService(const std::string& service) { streamingService_ = service; } +std::vector> AudioBook::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizza filtro base di Novel (che include filtro di Media) + std::vector> novels(input.begin(), input.end()); + std::vector> filteredNovels = Novel::filter(novels); + + // Filtro specifico AudioBook + for (const auto& novelPtr : filteredNovels) { + auto audiobookPtr = std::dynamic_pointer_cast(novelPtr); + if (!audiobookPtr) continue; + + bool match = true; + + // File size + if (narrator_ != "" && audiobookPtr->getNarrator()!= narrator_) + match = false; + + // DRM + if (streamingService_ != "" && audiobookPtr->getStreamingService() != streamingService_) + match = false; + + if (match) + result.push_back(audiobookPtr); + } + + return result; +} + } \ No newline at end of file diff --git a/src/Media/AudioBook.h b/src/Media/AudioBook.h index ecb7c60..38d77fa 100644 --- a/src/Media/AudioBook.h +++ b/src/Media/AudioBook.h @@ -1,5 +1,5 @@ -#ifndef AudioBook_H -#define AudioBook_H +#ifndef MEDIA_AUDIOBOOK_H +#define MEDIA_AUDIOBOOK_H #include "Novel.h" @@ -11,21 +11,24 @@ class AudioBook : public Novel { std::string streamingService_; public: + //durata è in minuti e usa il campo dati pagine di Novel AudioBook(const std::string& title, int publicationYear, const std::string& language, bool favorite, const std::vector& genres, const std::string& imagePath, const std::string& notes, const std::string& author, const std::string& publisher, unsigned int duration, const std::string& series, const std::string& isbn, - const std::string& narrator, const std::string& streamingService); + const std::string& narrator = "", const std::string& streamingService = ""); - void accept(IConstMediaVisitor& v) const override; + bool operator==(const Media& other) const override; std::string getNarrator() const; std::string getStreamingService() const; void setNarrator(const std::string& narrator); void setStreamingService(const std::string& service); + + std::vector> filter(const std::vector>& input) const; }; } -#endif // AudioBook_H \ No newline at end of file +#endif // MEDIA_AUDIOBOOK_H \ No newline at end of file diff --git a/src/Media/Ebook.cpp b/src/Media/Ebook.cpp index 9a26700..60a10c4 100644 --- a/src/Media/Ebook.cpp +++ b/src/Media/Ebook.cpp @@ -11,9 +11,14 @@ Ebook::Ebook(const std::string& title, int publicationYear, const std::string& l author, publisher, pages, series, isbn), fileSizeBytes_(fileSizeBytes), drm_(drm) {} -void Ebook::accept(IConstMediaVisitor& v) const { - v.visit(*this); -} +bool Ebook::operator==(const Media& other) const { + const Ebook* otherEbook = dynamic_cast(&other); + if (otherEbook) { + return Novel::operator==(*otherEbook) && fileSizeBytes_ == otherEbook->fileSizeBytes_ && + drm_ == otherEbook->drm_; + } + return false; +} unsigned int Ebook::getFileSizeBytes() const { return fileSizeBytes_; @@ -31,4 +36,34 @@ void Ebook::setDrm(bool drm) { drm_ = drm; } +std::vector> Ebook::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizza filtro base di Novel (che include filtro di Media) + std::vector> novels(input.begin(), input.end()); + std::vector> filteredNovels = Novel::filter(novels); + + // Filtro specifico Ebook + for (const auto& novelPtr : filteredNovels) { + auto ebookPtr = std::dynamic_pointer_cast(novelPtr); + if (!ebookPtr) continue; + + bool match = true; + + // File size + if (fileSizeBytes_ > 0 && ebookPtr->getFileSizeBytes() != fileSizeBytes_) + match = false; + + // DRM + if (drm_ && ebookPtr->hasDrm() != drm_) + match = false; + + if (match) + result.push_back(ebookPtr); + } + + return result; +} + + } \ No newline at end of file diff --git a/src/Media/Ebook.h b/src/Media/Ebook.h index 367f85b..d2ba138 100644 --- a/src/Media/Ebook.h +++ b/src/Media/Ebook.h @@ -1,5 +1,5 @@ -#ifndef EBOOK_H -#define EBOOK_H +#ifndef MEDIA_EBOOK_H +#define MEDIA_EBOOK_H #include "Novel.h" @@ -15,17 +15,20 @@ class Ebook : public Novel { bool favorite, const std::vector& genres, const std::string& imagePath, const std::string& notes, const std::string& author, const std::string& publisher, unsigned int pages, const std::string& series, const std::string& isbn, - unsigned int fileSizeBytes, bool drm); + unsigned int fileSizeBytes = 0, bool drm = false); - void accept(IConstMediaVisitor& v) const override; + bool operator==(const Media& other) const override; unsigned int getFileSizeBytes() const; bool hasDrm() const; void setFileSizeBytes(unsigned int size); void setDrm(bool drm); + + std::vector> filter(const std::vector>& input) const; + }; } -#endif // EBOOK_H \ No newline at end of file +#endif // MEDIA_EBOOK_H \ No newline at end of file diff --git a/src/Media/IMedia.h b/src/Media/IMedia.h index 4f603b7..d2ffa8b 100644 --- a/src/Media/IMedia.h +++ b/src/Media/IMedia.h @@ -1,12 +1,10 @@ -#ifndef IMedia_H -#define IMedia_H +#ifndef MEDIA_IMedia_H +#define MEDIA_IMedia_H #include "IConstMediaVisitor.h" - namespace media { - class IMedia { virtual void accept(IConstMediaVisitor &) const = 0; virtual bool open() = 0; @@ -14,5 +12,4 @@ class IMedia { } - #endif \ No newline at end of file diff --git a/src/Media/Media.cpp b/src/Media/Media.cpp index fbad213..2fcdcae 100644 --- a/src/Media/Media.cpp +++ b/src/Media/Media.cpp @@ -1,4 +1,8 @@ #include "Media.h" +#include +#include +#include +#include namespace media { Media::Media(const std::string &title, int release, const std::string &language, @@ -14,12 +18,71 @@ Media::Media(const std::string &title, int release, const std::string &language, void Media::accept(IConstMediaVisitor &v) const {} +bool Media::operator==(const Media &other) const { + return title_ == other.title_ && release_ == other.release_ && + language_ == other.language_ && favourite_ == other.favourite_ && + genres_ == other.genres_ && img_path_ == other.img_path_ && + notes_ == other.notes_; +} + bool Media::open() { notes_ = ""; std::cout<< "Media::open()" << std::endl; return false; } +std::vector> Media::filter(const std::vector>& input) const { + std::vector> result; + + for (const auto& mediaPtr : input) { + if (!mediaPtr) continue; + + const Media& media = *mediaPtr; + bool match = true; + + // Title (substring, case-insensitive) + if (!getTitle().empty() && !stringContainsIgnoreCase(media.getTitle(), getTitle())) + match = false; + + // Release (confronto stretto) + if (getRelease() != std::numeric_limits::min() && + media.getRelease() != getRelease()) + match = false; + + // Language (substring, case-insensitive) + if (!getLanguage().empty() && media.getLanguage() != getLanguage()) + match = false; + + // Favourite (confronto booleano) + if (isFavourite() && media.isFavourite() != isFavourite()) + match = false; + + // Generi (match parziale case-insensitive su ogni genere richiesto) + if (!getGenres().empty()) { + const auto& mediaGenres = media.getGenres(); + for (const auto& genreFilter : getGenres()) { + bool found = false; + for (const auto& g : mediaGenres) { + if (stringContainsIgnoreCase(g, genreFilter)) { + found = true; + break; + } + } + if (!found) { + match = false; + break; + } + } + } + + if (match) + result.push_back(mediaPtr); + } + + return result; +} + + const std::string &Media::getTitle() const { return title_; } int Media::getRelease() const { return release_; } const std::string &Media::getLanguage() const { return language_; }; diff --git a/src/Media/Media.h b/src/Media/Media.h index 2eb83c4..0d39960 100644 --- a/src/Media/Media.h +++ b/src/Media/Media.h @@ -3,9 +3,12 @@ #include #include #include +#include +#include #include "IMedia.h" #include "IConstMediaVisitor.h" +#include "StringUtils.h" namespace media { class Media : IMedia{ @@ -18,13 +21,15 @@ class Media : IMedia{ std::string img_path_; std::string notes_; - protected: - Media(const std::string &title, int release, const std::string &language, - bool favourite, const std::vector &genres, - const std::string &img_path, const std::string ¬es); - - public: + + public: + + Media(const std::string &title = "", int release = std::numeric_limits::max(), const std::string &language = "", + bool favourite = false, const std::vector &genres = {}, + const std::string &img_path = "", const std::string ¬es = ""); + virtual bool operator==(const Media &other) const; + void accept(IConstMediaVisitor &) const override; bool open() override; @@ -38,6 +43,8 @@ class Media : IMedia{ const std::vector &getGenres() const; const std::string &getImgPath() const; const std::string &getNotes() const; -}; + + std::vector> filter(const std::vector> &media) const; +}; } // namespace media #endif diff --git a/src/Media/Movie.cpp b/src/Media/Movie.cpp index 1e7a3a1..6d83d6b 100644 --- a/src/Media/Movie.cpp +++ b/src/Media/Movie.cpp @@ -10,7 +10,63 @@ Movie::Movie(const std::string &title, int release, const std::string &language, cast_(cast), length_(length), universe_(universe) {} +bool Movie::operator==(const Media &other) const { + const Movie *otherMovie = dynamic_cast(&other); + if (otherMovie) { + return Media::operator==(*otherMovie) && cast_ == otherMovie->cast_ && + length_ == otherMovie->length_ && universe_ == otherMovie->universe_; + } + return false; +} const std::vector &Movie::getCast() const { return cast_; } unsigned int Movie::getLength() const { return length_; } const std::string &Movie::getUniverse() const { return universe_; } + +std::vector> Movie::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizza filtro base di Media (poiché Movie deriva da Media) + std::vector> baseInput(input.begin(), input.end()); + std::vector> filteredBase = Media::filter(baseInput); + + for (const auto& mediaPtr : filteredBase) { + auto moviePtr = std::dynamic_pointer_cast(mediaPtr); + if (!moviePtr) continue; + + bool match = true; + + // Cast (match parziale, case-insensitive) + if (!cast_.empty()) { + const auto& movieCast = moviePtr->getCast(); + for (const auto& filterCast : cast_) { + bool found = false; + for (const auto& member : movieCast) { + if (stringContainsIgnoreCase(member, filterCast)) { + found = true; + break; + } + } + if (!found) { + match = false; + break; + } + } + } + + // Length (confronto stretto) + if (length_ != std::numeric_limits::max() && moviePtr->getLength() != length_) + match = false; + + // Universe (match parziale, case-insensitive) + if (!universe_.empty() && !stringContainsIgnoreCase(moviePtr->getUniverse(), universe_)) + match = false; + + if (match) + result.push_back(moviePtr); + } + + return result; +} + + } // namespace media diff --git a/src/Media/Movie.h b/src/Media/Movie.h index 9f23113..c37d134 100644 --- a/src/Media/Movie.h +++ b/src/Media/Movie.h @@ -17,11 +17,14 @@ class Movie : public Media { Movie(const std::string &title, int release, const std::string &language, bool favourite, const std::vector &genres, const std::string &img_path, const std::string ¬es, - const std::vector &cast, unsigned int length, - const std::string &universe); + const std::vector &cast = {}, unsigned int length = std::numeric_limits::max(), + const std::string &universe = ""); + bool operator==(const Media &other) const override; const std::vector &getCast() const; unsigned int getLength() const; const std::string &getUniverse() const; + + std::vector> filter(const std::vector>& input) const; }; } // namespace media #endif diff --git a/src/Media/Novel.cpp b/src/Media/Novel.cpp index 2f21c7e..88f9195 100644 --- a/src/Media/Novel.cpp +++ b/src/Media/Novel.cpp @@ -9,9 +9,14 @@ Novel::Novel(const std::string& title, int publicationYear, const std::string& l : Media(title, publicationYear, language, favorite, genres, imagePath, notes), author_(author), publisher_(publisher), pages_(pages), series_(series), isbn_(isbn) {} -// Visitor -void Novel::accept(IConstMediaVisitor& v) const { - v.visit(*this); +bool Novel::operator==(const Media& other) const { + const Novel* otherNovel = dynamic_cast(&other); + if (otherNovel) { + return Media::operator==(*otherNovel) && author_ == otherNovel->author_ && + publisher_ == otherNovel->publisher_ && pages_ == otherNovel->pages_ && + series_ == otherNovel->series_ && isbn_ == otherNovel->isbn_; + } + return false; } // Getters @@ -28,4 +33,46 @@ void Novel::setPages(unsigned int pages) { pages_ = pages; } void Novel::setSeries(const std::string& series) { series_ = series; } void Novel::setIsbn(const std::string& isbn) { isbn_ = isbn; } + +std::vector> Novel::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizzo del filtro base di Media + std::vector> baseInput(input.begin(), input.end()); + std::vector> filteredBase = Media::filter(baseInput); + + // Filtro specifico per Novel + for (const auto& mediaPtr : filteredBase) { + auto novelPtr = std::dynamic_pointer_cast(mediaPtr); + if (!novelPtr) continue; + + bool match = true; + + // Autore + if (!author_.empty() && !stringContainsIgnoreCase(novelPtr->getAuthor(), author_)) + match = false; + + // Editore + if (!publisher_.empty() && !stringContainsIgnoreCase(novelPtr->getPublisher(), publisher_)) + match = false; + + // Serie + if (!series_.empty() && !stringContainsIgnoreCase(novelPtr->getSeries(), series_)) + match = false; + + // ISBN + if (!isbn_.empty() && !stringContainsIgnoreCase(novelPtr->getIsbn(), isbn_)) + match = false; + + // Pagine (confronto stretto) + if (pages_ > 0 && novelPtr->getPages() != pages_) + match = false; + + if (match) + result.push_back(novelPtr); + } + + return result; +} + } \ No newline at end of file diff --git a/src/Media/Novel.h b/src/Media/Novel.h index 8462a61..64f91c9 100644 --- a/src/Media/Novel.h +++ b/src/Media/Novel.h @@ -1,5 +1,5 @@ -#ifndef Romanzo_H -#define Romanzo_H +#ifndef MEDIA_ROMANZO_H +#define MEDIA_ROMANZO_H #include "Media.h" @@ -16,10 +16,10 @@ class Novel : public Media { public: Novel(const std::string& title, int publicationYear, const std::string& language, bool favorite, const std::vector& genres, const std::string& imagePath, const std::string& notes, - const std::string& author, const std::string& publisher, - unsigned int pages, const std::string& series, const std::string& isbn); + const std::string& author = "", const std::string& publisher = "", + unsigned int pages = std::numeric_limits::max(), const std::string& series = "", const std::string& isbn = ""); - void accept(IConstMediaVisitor& v) const override; + bool operator==(const Media& other) const override; // Getters std::string getAuthor() const; @@ -34,6 +34,9 @@ class Novel : public Media { void setPages(unsigned int pages); void setSeries(const std::string& series); void setIsbn(const std::string& isbn); + + std::vector> filter(const std::vector> &novel) const; }; + } -#endif // Novel_H \ No newline at end of file +#endif // MEDIA_ROMANZO_H \ No newline at end of file diff --git a/src/Media/Series.cpp b/src/Media/Series.cpp index fb6c2a5..3dd0a1f 100644 --- a/src/Media/Series.cpp +++ b/src/Media/Series.cpp @@ -13,7 +13,48 @@ Series::Series(const std::string &title, int release, episodes_(episodes), seasons_(seasons), ended_(ended) {} +bool Series::operator==(const Media &other) const { + const Series *otherSeries = dynamic_cast(&other); + if (otherSeries) { + return Movie::operator==(*otherSeries) && episodes_ == otherSeries->episodes_ && + seasons_ == otherSeries->seasons_ && ended_ == otherSeries->ended_; + } + return false; +} unsigned int Series::getEpisodes() const { return episodes_; } unsigned int Series::getSeasons() const { return seasons_; } bool Series::isEnded() const { return ended_; } + +std::vector> Series::filter(const std::vector>& input) const { + std::vector> result; + + // Riutilizzo filtro base di Movie (che a sua volta chiama Media::filter) + std::vector> baseInput(input.begin(), input.end()); + std::vector> filteredBase = Movie::filter(baseInput); + + for (const auto& mediaPtr : filteredBase) { + auto seriesPtr = std::dynamic_pointer_cast(mediaPtr); + if (!seriesPtr) continue; + + bool match = true; + + // Episodes (confronto stretto) + if (episodes_ != std::numeric_limits::max() && seriesPtr->getEpisodes() != episodes_) + match = false; + + // Seasons (confronto stretto) + if (seasons_ != std::numeric_limits::max() && seriesPtr->getSeasons() != seasons_) + match = false; + + // Ended (confronto booleano) + if (ended_ && ended_ != seriesPtr->isEnded()) + match = false; + + if (match) + result.push_back(seriesPtr); + } + + return result; +} + } // namespace media diff --git a/src/Media/Series.h b/src/Media/Series.h index 91b96b0..42118bc 100644 --- a/src/Media/Series.h +++ b/src/Media/Series.h @@ -14,11 +14,14 @@ class Series : public Movie { bool favourite, const std::vector &genres, const std::string &img_path, const std::string ¬es, const std::vector &cast, unsigned int length, - const std::string &universe, unsigned int episodes, - unsigned int seasons, bool ended); + const std::string &universe, unsigned int episodes = std::numeric_limits::max(), + unsigned int seasons = std::numeric_limits::max(), bool ended = false); + bool operator==(const Media &other) const override; unsigned int getEpisodes() const; unsigned int getSeasons() const; bool isEnded() const; + + std::vector> filter(const std::vector>& input) const; }; -} // namespace media -#endif +} +#endif // MEDIA_SERIES_H diff --git a/src/Media/StringUtils.h b/src/Media/StringUtils.h new file mode 100644 index 0000000..9d52635 --- /dev/null +++ b/src/Media/StringUtils.h @@ -0,0 +1,20 @@ +#ifndef MEDIA_STRINGUTILS_H +#define MEDIA_STRINGUTILS_H + +#include +#include +#include + +namespace media { +inline std::string toLowerCase(const std::string& str) { + std::string lower = str; + std::transform(lower.begin(), lower.end(), lower.begin(), + [](unsigned char c){ return std::tolower(c); }); + return lower; +} + +inline bool stringContainsIgnoreCase(const std::string& text, const std::string& pattern) { + return toLowerCase(text).find(toLowerCase(pattern)) != std::string::npos; +} +} +#endif // MEDIA_STRINGUTILS_H diff --git a/src/src.pro b/src/MediaLibrary.pro similarity index 98% rename from src/src.pro rename to src/MediaLibrary.pro index fa01e1e..4fd055a 100644 --- a/src/src.pro +++ b/src/MediaLibrary.pro @@ -3,7 +3,7 @@ ###################################################################### TEMPLATE = app -TARGET = src +TARGET = MediaLibrary INCLUDEPATH += . QT += widgets diff --git a/src/Memory/Deserializer.h b/src/Memory/Deserializer.h index c86b172..d44d427 100644 --- a/src/Memory/Deserializer.h +++ b/src/Memory/Deserializer.h @@ -1,16 +1,17 @@ #ifndef MEMORY_DESERIALIZER_H #define MEMORY_DESERIALIZER_H #include + #include "../Media/Media.h" namespace memory { class Deserializer { private: - static int vecToJSON(const std::vector &, QFile &); - static int vecToXML(const std::vector &, QFile &); + static std::vector>& XMLtoVec(const QFile &); + static std::vector>& JSONtoVec(const QFile &); public: - static int deserialize(const std::vector &, QFile &); + static std::vector>& deserialize(const QFile &); }; } // namespace memory #endif diff --git a/src/Memory/MediaContainer.cpp b/src/Memory/MediaContainer.cpp new file mode 100644 index 0000000..7d9c177 --- /dev/null +++ b/src/Memory/MediaContainer.cpp @@ -0,0 +1,156 @@ +#include "MediaContainer.h" + +namespace memory { + +void MediaContainer::addMedia(const std::shared_ptr& media) { + if (!media) return; + + data_[static_cast(MediaType::All)].push_back(media); + + MediaType type = determineType(media); + if (type != MediaType::All) { + data_[static_cast(type)].push_back(media); + } +} + +void MediaContainer::removeMedia(const std::shared_ptr& media) { + if (!media) return; + + for (auto& vec : data_) { + vec.erase(std::remove_if(vec.begin(), vec.end(), + [&](const std::shared_ptr& m) { + return typeid(*m) == typeid(*media) && *m == *media; + }), vec.end()); + } +} + +void MediaContainer::clear() { + for (auto& vec : data_) { + vec.clear(); + } +} + +const std::vector>& MediaContainer::getAll() const { + return data_[static_cast(MediaType::All)]; +} + +const std::vector>& MediaContainer::getByType(MediaType type) const { + return data_[static_cast(type)]; +} + +const std::vector>& MediaContainer::getByTypeAndSubtype(MediaType type) const { + std::vector> result; + + switch (type) { + case MediaType::Novel: + result.insert(result.end(), data_[static_cast(MediaType::Novel)].begin(), data_[static_cast(MediaType::Novel)].end()); + result.insert(result.end(), data_[static_cast(MediaType::EBook)].begin(), data_[static_cast(MediaType::EBook)].end()); + result.insert(result.end(), data_[static_cast(MediaType::AudioBook)].begin(), data_[static_cast(MediaType::AudioBook)].end()); + break; + case MediaType::Movie: + result.insert(result.end(), data_[static_cast(MediaType::Movie)].begin(), data_[static_cast(MediaType::Movie)].end()); + result.insert(result.end(), data_[static_cast(MediaType::Series)].begin(), data_[static_cast(MediaType::Series)].end()); + break; + case MediaType::All: + result = data_[0]; + break; + default: + result = data_[static_cast(type)]; + break; + } + + return result; +} + +MediaType MediaContainer::determineType(const std::shared_ptr& media) const { + if (std::dynamic_pointer_cast(media)) return MediaType::Series; + if (std::dynamic_pointer_cast(media)) return MediaType::Movie; + if (std::dynamic_pointer_cast(media)) return MediaType::AudioBook; + if (std::dynamic_pointer_cast(media)) return MediaType::EBook; + if (std::dynamic_pointer_cast(media)) return MediaType::Novel; + if (std::dynamic_pointer_cast(media)) return MediaType::Album; + return MediaType::All; +} + +std::vector> MediaContainer::filter(const media::Media& media) const { + std::shared_ptr mediaPtr = std::make_shared(media); + + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + if (auto m = std::dynamic_pointer_cast(mediaPtr)) return filters(m); + return filters(mediaPtr); +} + +std::vector> MediaContainer::filters(const std::shared_ptr& media) const { + auto allMedia = getAll(); + return media->filter(allMedia); +} + +std::vector> MediaContainer::filters(const std::shared_ptr& novel) const { + auto media = getByTypeAndSubtype(MediaType::Novel); + std::vector> allNovel; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allNovel.push_back(ptr); + std::vector> result; + for (const auto& m : novel->filter(allNovel)) result.push_back(m); + return result; +} + +std::vector> MediaContainer::filters(const std::shared_ptr& album) const { + auto media = getByType(MediaType::Album); + std::vector> allAlbum; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allAlbum.push_back(ptr); + std::vector> result; + for (const auto& m : album->filter(allAlbum)) result.push_back(m); + return result; +} + +std::vector> MediaContainer::filters(const std::shared_ptr& movie) const { + auto media = getByTypeAndSubtype(MediaType::Movie); + std::vector> allMovie; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allMovie.push_back(ptr); + std::vector> result; + for (const auto& m : movie->filter(allMovie)) result.push_back(m); + return result; +} + +std::vector> MediaContainer::filters(const std::shared_ptr& ebook) const { + auto media = getByType(MediaType::EBook); + std::vector> allEbook; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allEbook.push_back(ptr); + std::vector> result; + for (const auto& m : ebook->filter(allEbook)) result.push_back(m); + return result; +} + +std::vector> MediaContainer::filters(const std::shared_ptr& audiobook) const { + auto media = getByType(MediaType::AudioBook); + std::vector> allAudio; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allAudio.push_back(ptr); + std::vector> result; + for (const auto& m : audiobook->filter(allAudio)) result.push_back(m); + return result; +} + +std::vector> MediaContainer::filters(const std::shared_ptr& series) const { + auto media = getByType(MediaType::Series); + std::vector> allSeries; + for (const auto& m : media) + if (auto ptr = std::dynamic_pointer_cast(m)) allSeries.push_back(ptr); + std::vector> result; + for (const auto& m : series->filter(allSeries)) result.push_back(m); + return result; +} + +int MediaContainer::serialize(QSaveFile& file) const { + return Serializer::Serialize(getAll(), file); +} + +} // namespace memory diff --git a/src/Memory/MediaContainer.h b/src/Memory/MediaContainer.h index fa5e702..c4d5938 100644 --- a/src/Memory/MediaContainer.h +++ b/src/Memory/MediaContainer.h @@ -1,14 +1,64 @@ -#ifndef MEMORY_MEDIA_CONTAINER_H -#define MEMORY_MEDIA_CONTAINER_H -#include "../Media/Media.h" +#ifndef MEMORY_MEDIACONTAINER_H +#define MEMORY_MEDIACONTAINER_H + +#include +#include +#include +#include +#include +#include + +#include "Media.h" +#include "Novel.h" +#include "Album.h" +#include "Movie.h" +#include "Ebook.h" +#include "AudioBook.h" +#include "Series.h" +#include "Serializer.h" namespace memory { + +enum class MediaType { + All = 0, + Novel, + Album, + Movie, + EBook, + AudioBook, + Series, + Count +}; + class MediaContainer { - public: - MediaContainer() = default; - int addMedia(media::Media *); - int removeMedia(media::Media *); - std::vector filter(const media::Media *); +private: + std::array>, static_cast(MediaType::Count)> data_; + + MediaType determineType(const std::shared_ptr& media) const; + + std::vector> filters(const std::shared_ptr& media) const; + std::vector> filters(const std::shared_ptr& novel) const; + std::vector> filters(const std::shared_ptr& album) const; + std::vector> filters(const std::shared_ptr& movie) const; + std::vector> filters(const std::shared_ptr& ebook) const; + std::vector> filters(const std::shared_ptr& audiobook) const; + std::vector> filters(const std::shared_ptr& series) const; + + const std::vector>& getAll() const; + const std::vector>& getByType(MediaType type) const; + const std::vector>& getByTypeAndSubtype(MediaType type) const; + +public: + void addMedia(const std::shared_ptr& media); + void removeMedia(const std::shared_ptr& media); + void clear(); + + // Filtri + std::vector> filter(const media::Media& media) const; + + int serialize(QSaveFile& file) const; }; -} // namespace memory -#endif + +} // namespace memory + +#endif // MEMORY_MEDIACONTAINER_H diff --git a/src/Memory/Serializer.h b/src/Memory/Serializer.h index f34aad0..34b5fa9 100644 --- a/src/Memory/Serializer.h +++ b/src/Memory/Serializer.h @@ -1,17 +1,16 @@ #ifndef MEMORY_SERIALIZER_H #define MEMORY_SERIALIZER_H -#include - +#include #include "../Media/Media.h" namespace memory { class Serializer { private: - static std::vector& XMLtoVec(const QFile &); - static std::vector& JSONtoVec(const QFile &); + static int vecToJSON(const std::vector> &, QSaveFile &); + static int vecToXML(const std::vector> &, QSaveFile &); public: - static std::vector& serialize(const QFile &); + static int Serialize(const std::vector> &, QSaveFile &); }; } // namespace memory #endif diff --git a/src/main.cpp b/src/main.cpp index 76e8197..55a15bc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1 +1,52 @@ -int main() { return 0; } +#include +#include +#include +#include +#include "Media/Media.h" // Include il tuo header + +int main() { + // Crea alcuni media + auto media1 = std::make_shared( + "House of Cards", + 2013, + "English", + true, + std::vector{"Drama", "Politics"} + ); + + auto media2 = std::make_shared( + "The Crown", + 2016, + "English", + false, + std::vector{"History", "Drama"} + ); + + auto media3 = std::make_shared( + "Breaking Bad", + 2008, + "English", + false, + std::vector{"Crime", "Thriller"} + ); + + // Inserisci i media in un vettore + std::vector> inputList = {media1, media2, media3}; + + // Crea un oggetto Media come filtro + auto filterMedia = std::make_shared( + "Ho", + std::numeric_limits::min() + ); + + // Filtra + std::vector> filtered = filterMedia->filter(inputList); + + //Stampa i risultati + std::cout << "Media che passano il filtro:\n"; + for (const auto& m : filtered) { + std::cout << "- " << m->getTitle() << "\n"; + } + + return 0; +}