From cc71f419ccbf22a78bf8b766d9decbcf1a8225c1 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Wed, 23 May 2018 17:44:32 +0200 Subject: [PATCH 1/3] Revert "Backout changeset c42e71e42d7968ddb6c63fd39011669503b9122c" This reverts commit 040664d3baff905fa9f1b4723b664c1a8d6cf586. --- YACReader/render.cpp | 8 +- common/comic.cpp | 903 ++++++++++++++++++++++--------------------- 2 files changed, 473 insertions(+), 438 deletions(-) diff --git a/YACReader/render.cpp b/YACReader/render.cpp index f89b6932..4d6b1afb 100644 --- a/YACReader/render.cpp +++ b/YACReader/render.cpp @@ -381,8 +381,8 @@ Render::Render() Render::~Render() { - if (comic != nullptr) { - comic->moveToThread(QApplication::instance()->thread()); + if (comic != 0) { + //comic->moveToThread(QApplication::instance()->thread()); comic->deleteLater(); } @@ -607,8 +607,8 @@ void Render::setRotation(int degrees) void Render::setComic(Comic *c) { - if (comic != nullptr) { - comic->moveToThread(QApplication::instance()->thread()); + if (comic != 0) { + //comic->moveToThread(QApplication::instance()->thread()); comic->disconnect(); comic->deleteLater(); } diff --git a/common/comic.cpp b/common/comic.cpp index 5a126701..5b3b5be1 100644 --- a/common/comic.cpp +++ b/common/comic.cpp @@ -234,6 +234,21 @@ void Comic::updateBookmarkImage(int index) emit bookmarksUpdated(); //emit bookmarksLoaded(*bm); } + + if (bm->isBookmark(index)) { + QImage p; + p.loadFromData(_pages[index]); + bm->setBookmark(index, p); + emit bookmarksUpdated(); + //emit bookmarksLoaded(*bm); + } + if (bm->getLastPage() == index) { + QImage p; + p.loadFromData(_pages[index]); + bm->setLastPage(index, p); + emit bookmarksUpdated(); + //emit bookmarksLoaded(*bm); + } } //----------------------------------------------------------------------------- void Comic::setPageLoaded(int page) @@ -378,7 +393,7 @@ bool FileComic::load(const QString &path, const ComicDB &comic) return true; } else { //QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path); - moveToThread(QCoreApplication::instance()->thread()); + //moveToThread(QCoreApplication::instance()->thread()); emit errorOpening(); return false; } @@ -519,154 +534,78 @@ QList> FileComic::getSections(int §ionIndex) sections.append(section2); //out << "SPLIT" << endl; + idx++; + } + + if (sectionIndex == sectionCount) //found + { + if (section.indexOf(realIdx) != 0) { + QVector section1; + QVector section2; + foreach (quint32 si, section) { + if (si < realIdx) { + section1.append(si); + } else { + section2.append(si); + } + } + sectionIndex++; + sections.append(section1); + sections.append(section2); + //out << "SPLIT" << endl; + + } else { + sections.append(section); + } } else { sections.append(section); } - } else { - sections.append(section); + + //out << "se han encontrado : " << sections.count() << " sectionIndex : " << sectionIndex << endl; + return sections; } - //out << "se han encontrado : " << sections.count() << " sectionIndex : " << sectionIndex << endl; - return sections; -} - -void FileComic::process() -{ - CompressedArchive archive(_path); - if (!archive.toolsLoaded()) { - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(tr("7z not found")); - return; - } - - if (!archive.isValid()) { - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(tr("Format not supported")); - return; - } - - //se filtran para obtener s�lo los formatos soportados - _order = archive.getFileNames(); - _fileNames = filter(_order); - - if (_fileNames.size() == 0) { - //QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file")); - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - - //TODO, cambiar por listas - //_order = _fileNames; - - _pages.resize(_fileNames.size()); - _loadedPages = QVector(_fileNames.size(), false); - - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(_pages.size()); - _loaded = true; - - _cfi = 0; - - //TODO, add a setting for choosing the type of page sorting used. - comic_pages_sort(_fileNames, YACReaderHeuristicSorting); - - if (_firstPage == -1) { - _firstPage = bm->getLastPage(); - } - - if (_firstPage >= _pages.length()) { - _firstPage = 0; - } - - _index = _firstPage; - emit(openAt(_index)); - - int sectionIndex; - QList> sections = getSections(sectionIndex); - - for (int i = sectionIndex; i < sections.count(); i++) { - if (_invalidated) { - moveToThread(QCoreApplication::instance()->thread()); + void FileComic::process() + { + CompressedArchive archive(_path); + if (!archive.toolsLoaded()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(tr("7z not found")); return; } - archive.getAllData(sections.at(i), this); - } - for (int i = 0; i < sectionIndex; i++) { - if (_invalidated) { - moveToThread(QCoreApplication::instance()->thread()); + + if (!archive.isValid()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(tr("Format not supported")); return; } - archive.getAllData(sections.at(i), this); - } - //archive.getAllData(QVector(),this); - /* - foreach(QString name,_fileNames) - { - index = _order.indexOf(name); - sortedIndex = _fileNames.indexOf(name); - _pages[sortedIndex] = allData.at(index); - emit imageLoaded(sortedIndex); - emit imageLoaded(sortedIndex,_pages[sortedIndex]); - }*/ - moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); -} -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// + //se filtran para obtener s�lo los formatos soportados + _order = archive.getFileNames(); + _fileNames = filter(_order); -FolderComic::FolderComic() - : Comic() -{ -} + if (_fileNames.size() == 0) { + //QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file")); + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; + } -FolderComic::FolderComic(const QString &path, int atPage) - : Comic(path, atPage) -{ - load(path, atPage); -} + //TODO, cambiar por listas + //_order = _fileNames; -FolderComic::~FolderComic() -{ -} + _pages.resize(_fileNames.size()); + _loadedPages = QVector(_fileNames.size(), false); -bool FolderComic::load(const QString &path, int atPage) -{ - _path = path; - if (atPage == -1) { - bm->newComic(_path); - emit bookmarksUpdated(); - } - _firstPage = atPage; - //emit bookmarksLoaded(*bm); - return true; -} + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(_pages.size()); + _loaded = true; -void FolderComic::process() -{ - QDir d(_path); + _cfi = 0; - d.setNameFilters(getSupportedImageFormats()); - d.setFilter(QDir::Files | QDir::NoDotAndDotDot); - //d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); - QFileInfoList list = d.entryInfoList(); + //TODO, add a setting for choosing the type of page sorting used. + comic_pages_sort(_fileNames, YACReaderHeuristicSorting); - //don't fix double page files sorting, because the user can see how the SO sorts the files in the folder. - std::sort(list.begin(), list.end(), naturalSortLessThanCIFileInfo); - - int nPages = list.size(); - _pages.clear(); - _pages.resize(nPages); - _loadedPages = QVector(nPages, false); - - if (nPages == 0) { - //TODO emitir este mensaje en otro sitio - //QMessageBox::critical(NULL,QObject::tr("No images found"),QObject::tr("There are not images on the selected folder")); - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - } else { if (_firstPage == -1) { _firstPage = bm->getLastPage(); } @@ -676,63 +615,60 @@ void FolderComic::process() } _index = _firstPage; - emit(openAt(_index)); - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(_pages.size()); - _loaded = true; + int sectionIndex; + QList> sections = getSections(sectionIndex); - int count = 0; - int i = _firstPage; - while (count < nPages) { + for (int i = sectionIndex; i < sections.count(); i++) { if (_invalidated) { - moveToThread(QCoreApplication::instance()->thread()); + //moveToThread(QCoreApplication::instance()->thread()); return; } - - QFile f(list.at(i).absoluteFilePath()); - f.open(QIODevice::ReadOnly); - _pages[i] = f.readAll(); - emit imageLoaded(i); - emit imageLoaded(i, _pages[i]); - i++; - if (i == nPages) { - i = 0; - } - count++; + archive.getAllData(sections.at(i), this); } + for (int i = 0; i < sectionIndex; i++) { + if (_invalidated) { + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + archive.getAllData(sections.at(i), this); + } + //archive.getAllData(QVector(),this); + /* + foreach(QString name,_fileNames) + { + index = _order.indexOf(name); + sortedIndex = _fileNames.indexOf(name); + _pages[sortedIndex] = allData.at(index); + emit imageLoaded(sortedIndex); + emit imageLoaded(sortedIndex,_pages[sortedIndex]); + }*/ + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); } - moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); -} -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// -#ifndef NO_PDF + FolderComic::FolderComic() + : Comic() + { + } -PDFComic::PDFComic() - : Comic() -{ -} + FolderComic::FolderComic(const QString &path, int atPage) + : Comic(path, atPage) + { + load(path, atPage); + } -PDFComic::PDFComic(const QString &path, int atPage) - : Comic(path, atPage) -{ - load(path, atPage); -} + FolderComic::~FolderComic() + { + } -PDFComic::~PDFComic() -{ -} - -bool PDFComic::load(const QString &path, int atPage) -{ - QFileInfo fi(path); - - if (fi.exists()) { + bool FolderComic::load(const QString &path, int atPage) + { _path = path; if (atPage == -1) { bm->newComic(_path); @@ -741,319 +677,418 @@ bool PDFComic::load(const QString &path, int atPage) _firstPage = atPage; //emit bookmarksLoaded(*bm); return true; - } else { - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return false; } -} -bool PDFComic::load(const QString &path, const ComicDB &comic) -{ - QFileInfo fi(path); + void FolderComic::process() + { + QDir d(_path); - if (fi.exists()) { - QList bookmarkIndexes; - bookmarkIndexes << comic.info.bookmark1 << comic.info.bookmark2 << comic.info.bookmark3; - if (bm->load(bookmarkIndexes, comic.info.currentPage - 1)) { - emit bookmarksUpdated(); + d.setNameFilters(getSupportedImageFormats()); + d.setFilter(QDir::Files | QDir::NoDotAndDotDot); + //d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); + QFileInfoList list = d.entryInfoList(); + + //don't fix double page files sorting, because the user can see how the SO sorts the files in the folder. + std::sort(list.begin(), list.end(), naturalSortLessThanCIFileInfo); + + int nPages = list.size(); + _pages.clear(); + _pages.resize(nPages); + _loadedPages = QVector(nPages, false); + + if (nPages == 0) { + //TODO emitir este mensaje en otro sitio + //QMessageBox::critical(NULL,QObject::tr("No images found"),QObject::tr("There are not images on the selected folder")); + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + } else { + if (_firstPage == -1) { + _firstPage = bm->getLastPage(); + } + + if (_firstPage >= _pages.length()) { + _firstPage = 0; + } + + _index = _firstPage; + + emit(openAt(_index)); + + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(_pages.size()); + _loaded = true; + + int count = 0; + int i = _firstPage; + while (count < nPages) { + if (_invalidated) { + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + + QFile f(list.at(i).absoluteFilePath()); + f.open(QIODevice::ReadOnly); + _pages[i] = f.readAll(); + emit imageLoaded(i); + emit imageLoaded(i, _pages[i]); + i++; + if (i == nPages) { + i = 0; + } + count++; + } } - _firstPage = comic.info.currentPage - 1; - _path = QDir::cleanPath(path); - return true; - } else { - //QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path); - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return false; + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); } -} -void PDFComic::process() -{ + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////// + +#ifndef NO_PDF + + PDFComic::PDFComic() + : Comic() + { + } + + PDFComic::PDFComic(const QString &path, int atPage) + : Comic(path, atPage) + { + load(path, atPage); + } + + PDFComic::~PDFComic() + { + } + + bool PDFComic::load(const QString &path, int atPage) + { + QFileInfo fi(path); + + if (fi.exists()) { + _path = path; + if (atPage == -1) { + bm->newComic(_path); + emit bookmarksUpdated(); + } + _firstPage = atPage; + //emit bookmarksLoaded(*bm); + return true; + } else { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return false; + } + } + + bool PDFComic::load(const QString &path, const ComicDB &comic) + { + QFileInfo fi(path); + + if (fi.exists()) { + QList bookmarkIndexes; + bookmarkIndexes << comic.info.bookmark1 << comic.info.bookmark2 << comic.info.bookmark3; + if (bm->load(bookmarkIndexes, comic.info.currentPage - 1)) { + emit bookmarksUpdated(); + } + _firstPage = comic.info.currentPage - 1; + _path = QDir::cleanPath(path); + return true; + } else { + //QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path); + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return false; + } + } + + void PDFComic::process() + { #if defined Q_OS_MAC && defined USE_PDFKIT - pdfComic = new MacOSXPDFComic(); - if (!pdfComic->openComic(_path)) { - delete pdfComic; - emit errorOpening(); - return; - } -#elif defined USE_PDFIUM - pdfComic = new PdfiumComic(); - if (!pdfComic->openComic(_path)) { - delete pdfComic; - emit errorOpening(); - return; - } -#else - pdfComic = Poppler::Document::load(_path); - if (!pdfComic) { - //delete pdfComic; - //pdfComic = 0; - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - if (pdfComic->isLocked()) { - moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - - //pdfComic->setRenderHint(Poppler::Document::Antialiasing, true); - pdfComic->setRenderHint(Poppler::Document::TextAntialiasing, true); -#endif - - int nPages = pdfComic->numPages(); - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(nPages); - _loaded = true; - //QMessageBox::critical(NULL,QString("%1").arg(nPages),tr("Invalid PDF file")); - - _pages.clear(); - _pages.resize(nPages); - _loadedPages = QVector(nPages, false); - - if (_firstPage == -1) { - _firstPage = bm->getLastPage(); - } - - if (_firstPage >= _pages.length()) { - _firstPage = 0; - } - - _index = _firstPage; - emit(openAt(_index)); - - //buffer index to avoid race conditions - int buffered_index = _index; - for (int i = buffered_index; i < nPages; i++) { - if (_invalidated) { + pdfComic = new MacOSXPDFComic(); + if (!pdfComic->openComic(_path)) { delete pdfComic; - moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; + } +#elif defined USE_PDFIUM + pdfComic = new PdfiumComic(); + if (!pdfComic->openComic(_path)) { + delete pdfComic; + emit errorOpening(); + return; + } +#else + pdfComic = Poppler::Document::load(_path); + if (!pdfComic) { + //delete pdfComic; + //pdfComic = 0; + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; + } + if (pdfComic->isLocked()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); return; } - renderPage(i); - } - for (int i = 0; i < buffered_index; i++) { - if (_invalidated) { - delete pdfComic; - moveToThread(QCoreApplication::instance()->thread()); - return; - } - renderPage(i); - } - - delete pdfComic; - moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); -} - -void PDFComic::renderPage(int page) -{ -#if defined Q_OS_MAC && defined USE_PDFKIT - QImage img = pdfComic->getPage(page); - if (!img.isNull()) { -#elif defined USE_PDFIUM - QImage img = pdfComic->getPage(page); - if (!img.isNull()) { -#else - Poppler::Page *pdfpage = pdfComic->page(page); - if (pdfpage) { - QImage img = pdfpage->renderToImage(150, 150); - delete pdfpage; + //pdfComic->setRenderHint(Poppler::Document::Antialiasing, true); + pdfComic->setRenderHint(Poppler::Document::TextAntialiasing, true); #endif - QByteArray ba; - QBuffer buf(&ba); - img.save(&buf, "jpg", 96); - _pages[page] = ba; - emit imageLoaded(page); - emit imageLoaded(page, _pages[page]); + + int nPages = pdfComic->numPages(); + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(nPages); + _loaded = true; + //QMessageBox::critical(NULL,QString("%1").arg(nPages),tr("Invalid PDF file")); + + _pages.clear(); + _pages.resize(nPages); + _loadedPages = QVector(nPages, false); + + if (_firstPage == -1) { + _firstPage = bm->getLastPage(); + } + + if (_firstPage >= _pages.length()) { + _firstPage = 0; + } + + _index = _firstPage; + emit(openAt(_index)); + + //buffer index to avoid race conditions + int buffered_index = _index; + for (int i = buffered_index; i < nPages; i++) { + if (_invalidated) { + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + + renderPage(i); + } + for (int i = 0; i < buffered_index; i++) { + if (_invalidated) { + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + renderPage(i); + } + + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); + } + + void PDFComic::renderPage(int page) + { +#if defined Q_OS_MAC && defined USE_PDFKIT + QImage img = pdfComic->getPage(page); + if (!img.isNull()) { +#elif defined USE_PDFIUM + QImage img = pdfComic->getPage(page); + if (!img.isNull()) { +#else + Poppler::Page *pdfpage = pdfComic->page(page); + if (pdfpage) { + QImage img = pdfpage->renderToImage(150, 150); + delete pdfpage; +#endif + QByteArray ba; + QBuffer buf(&ba); + img.save(&buf, "jpg", 96); + _pages[page] = ba; + emit imageLoaded(page); + emit imageLoaded(page, _pages[page]); + } } -} #endif //NO_PDF -Comic *FactoryComic::newComic(const QString &path) -{ + Comic *FactoryComic::newComic(const QString &path) + { - QFileInfo fi(path); - if (fi.exists()) { - if (fi.isFile()) { + QFileInfo fi(path); + if (fi.exists()) { + if (fi.isFile()) { #ifndef NO_PDF - if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { - return new PDFComic(); - } else { - return new FileComic(); - } + if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { + return new PDFComic(); + } else { + return new FileComic(); + } #else - return new FileComic(); + return new FileComic(); #endif - } else { - if (fi.isDir()) { - return new FolderComic(); } else { - return NULL; + if (fi.isDir()) { + return new FolderComic(); + } else { + return NULL; + } + } + } else + return NULL; + } + + bool is_double_page(const QString &pageName, const QString &commonPrefix, const int maxExpectedDoublePagesNumberLenght) + { + if (pageName.startsWith(commonPrefix)) { + QString substringContainingPageNumbers = pageName.mid(commonPrefix.length()); + QString pageNumbersSubString; + for (int i = 0; i < substringContainingPageNumbers.length() && substringContainingPageNumbers.at(i).isDigit(); i++) { + pageNumbersSubString.append(substringContainingPageNumbers.at(i)); + } + if (pageNumbersSubString.length() < 3 || pageNumbersSubString.length() > maxExpectedDoublePagesNumberLenght || pageNumbersSubString.length() % 2 == 1) { + return false; + } + + int leftPageNumber = pageNumbersSubString.left(pageNumbersSubString.length() / 2).toInt(); + int rightPageNumber = pageNumbersSubString.mid(pageNumbersSubString.length() / 2).toInt(); + + if (leftPageNumber == 0 || rightPageNumber == 0) { + return false; + } + if ((rightPageNumber - leftPageNumber) == 1) { + return true; } } - } else - return NULL; -} - -bool is_double_page(const QString &pageName, const QString &commonPrefix, const int maxExpectedDoublePagesNumberLenght) -{ - if (pageName.startsWith(commonPrefix)) { - QString substringContainingPageNumbers = pageName.mid(commonPrefix.length()); - QString pageNumbersSubString; - for (int i = 0; i < substringContainingPageNumbers.length() && substringContainingPageNumbers.at(i).isDigit(); i++) { - pageNumbersSubString.append(substringContainingPageNumbers.at(i)); - } - if (pageNumbersSubString.length() < 3 || pageNumbersSubString.length() > maxExpectedDoublePagesNumberLenght || pageNumbersSubString.length() % 2 == 1) { - return false; - } - - int leftPageNumber = pageNumbersSubString.left(pageNumbersSubString.length() / 2).toInt(); - int rightPageNumber = pageNumbersSubString.mid(pageNumbersSubString.length() / 2).toInt(); - - if (leftPageNumber == 0 || rightPageNumber == 0) { - return false; - } - if ((rightPageNumber - leftPageNumber) == 1) { - return true; - } + return false; } - return false; -} -QString get_most_common_prefix(const QList &pageNames) -{ - if (pageNames.isEmpty()) { - return ""; - } - QMap frequency; - int currentPrefixLenght = pageNames.at(0).split('/').last().length(); - int currentPrefixCount = 1; - - int i; - QString previous; - QString current; - for (i = 1; i < pageNames.length(); i++) { - int pos = 0; - previous = pageNames.at(i - 1).split('/').last(); - current = pageNames.at(i).split('/').last(); - for (; pos < current.length() && previous[pos] == current[pos]; pos++) - ; - - if (pos < currentPrefixLenght && pos > 0) { - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - currentPrefixLenght = pos; - currentPrefixCount++; + QString get_most_common_prefix(const QList &pageNames) + { + if (pageNames.isEmpty()) { + return ""; } - /* + QMap frequency; + int currentPrefixLenght = pageNames.at(0).split('/').last().length(); + int currentPrefixCount = 1; + + int i; + QString previous; + QString current; + for (i = 1; i < pageNames.length(); i++) { + int pos = 0; + previous = pageNames.at(i - 1).split('/').last(); + current = pageNames.at(i).split('/').last(); + for (; pos < current.length() && previous[pos] == current[pos]; pos++) + ; + + if (pos < currentPrefixLenght && pos > 0) { + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); + currentPrefixLenght = pos; + currentPrefixCount++; + } + /* else if(pos > currentPrefixLenght) { frequency.insert(pageNames.at(i-1).left(currentPrefixLenght), currentPrefixCount - 1); currentPrefixLenght = pos; currentPrefixCount = 2; }*/ - else if (pos == 0) { - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - currentPrefixLenght = current.length(); - currentPrefixCount = 1; - } else { - currentPrefixCount++; + else if (pos == 0) { + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); + currentPrefixLenght = current.length(); + currentPrefixCount = 1; + } else { + currentPrefixCount++; + } } - } - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - uint maxFrequency = 0; - QString common_prefix = ""; - foreach (QString key, frequency.keys()) { - if (maxFrequency < frequency.value(key)) { - maxFrequency = frequency.value(key); - common_prefix = key; + uint maxFrequency = 0; + QString common_prefix = ""; + foreach (QString key, frequency.keys()) { + if (maxFrequency < frequency.value(key)) { + maxFrequency = frequency.value(key); + common_prefix = key; + } } + + QRegExp allNumberRegExp("\\d+"); + if (allNumberRegExp.exactMatch(common_prefix)) { + return ""; + } + + if (maxFrequency < pageNames.length() * 0.60) //the most common tipe of image file should a proper page, so we can asume that the common_prefix should be in, at least, the 60% of the pages + { + return ""; + } + + return common_prefix; } - QRegExp allNumberRegExp("\\d+"); - if (allNumberRegExp.exactMatch(common_prefix)) { - return ""; - } - - if (maxFrequency < pageNames.length() * 0.60) //the most common tipe of image file should a proper page, so we can asume that the common_prefix should be in, at least, the 60% of the pages + void get_double_pages(const QList &pageNames, QList &singlePageNames /*out*/, QList &doublePageNames /*out*/) { - return ""; - } + uint maxExpectedDoublePagesNumberLenght = (int)(log10(pageNames.length()) + 1) * 2; - return common_prefix; -} + QString mostCommonPrefix = get_most_common_prefix(pageNames); -void get_double_pages(const QList &pageNames, QList &singlePageNames /*out*/, QList &doublePageNames /*out*/) -{ - uint maxExpectedDoublePagesNumberLenght = (int)(log10(pageNames.length()) + 1) * 2; - - QString mostCommonPrefix = get_most_common_prefix(pageNames); - - foreach (const QString &pageName, pageNames) { - if (is_double_page(pageName.split('/').last(), mostCommonPrefix, maxExpectedDoublePagesNumberLenght)) { - doublePageNames.append(pageName); - } else { - singlePageNames.append(pageName); + foreach (const QString &pageName, pageNames) { + if (is_double_page(pageName.split('/').last(), mostCommonPrefix, maxExpectedDoublePagesNumberLenght)) { + doublePageNames.append(pageName); + } else { + singlePageNames.append(pageName); + } } } -} -QList merge_pages(QList &singlePageNames, QList &doublePageNames) -{ - //NOTE: this implementation doesn't differ from std::merge using a custom comparator, but it can be easily tweaked if merging requeries an additional heuristic behaviour - QList pageNames; + QList merge_pages(QList & singlePageNames, QList & doublePageNames) + { + //NOTE: this implementation doesn't differ from std::merge using a custom comparator, but it can be easily tweaked if merging requeries an additional heuristic behaviour + QList pageNames; - int i = 0; - int j = 0; + int i = 0; + int j = 0; - while (i < singlePageNames.length() && j < doublePageNames.length()) { - if (singlePageNames.at(i).compare(doublePageNames.at(j), Qt::CaseInsensitive) < 0) { + while (i < singlePageNames.length() && j < doublePageNames.length()) { + if (singlePageNames.at(i).compare(doublePageNames.at(j), Qt::CaseInsensitive) < 0) { + pageNames.append(singlePageNames.at(i++)); + } else { + pageNames.append(doublePageNames.at(j++)); + } + } + + while (i < singlePageNames.length()) { pageNames.append(singlePageNames.at(i++)); - } else { + } + + while (j < doublePageNames.length()) { pageNames.append(doublePageNames.at(j++)); } + + return pageNames; } - while (i < singlePageNames.length()) { - pageNames.append(singlePageNames.at(i++)); - } + void comic_pages_sort(QList & pageNames, YACReaderPageSortingMode sortingMode) + { + switch (sortingMode) { + case YACReaderNumericalSorting: + std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); + break; - while (j < doublePageNames.length()) { - pageNames.append(doublePageNames.at(j++)); - } + case YACReaderHeuristicSorting: { + std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); - return pageNames; -} + QList singlePageNames; + QList doublePageNames; -void comic_pages_sort(QList &pageNames, YACReaderPageSortingMode sortingMode) -{ - switch (sortingMode) { - case YACReaderNumericalSorting: - std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); - break; + get_double_pages(pageNames, singlePageNames, doublePageNames); - case YACReaderHeuristicSorting: { - std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); + if (doublePageNames.length() > 0) { + pageNames = merge_pages(singlePageNames, doublePageNames); + } + } break; - QList singlePageNames; - QList doublePageNames; - - get_double_pages(pageNames, singlePageNames, doublePageNames); - - if (doublePageNames.length() > 0) { - pageNames = merge_pages(singlePageNames, doublePageNames); + case YACReaderAlphabeticalSorting: + std::sort(pageNames.begin(), pageNames.end()); + break; } - } break; - - case YACReaderAlphabeticalSorting: - std::sort(pageNames.begin(), pageNames.end()); - break; } -} From be547081f22d7f5c37a6e4705fbf10d3ebd3b108 Mon Sep 17 00:00:00 2001 From: Felix Kauselmann Date: Mon, 30 Apr 2018 18:24:31 +0200 Subject: [PATCH 2/3] Fix huge memleak in server code caused by thread pingpong fix. Stopped QThreads don't process events, so cleanup signals get lost. Prevent this from happening by keeping the threads alive and the comic inside the thread (as we already do in the viewer). Cleanup happens by connecting the comic's destroyed() signal to the thread's quit() slot. --- .../server/controllers/v1/comiccontroller.cpp | 7 ++++--- .../server/controllers/v2/comiccontroller_v2.cpp | 16 +++++++--------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/YACReaderLibrary/server/controllers/v1/comiccontroller.cpp b/YACReaderLibrary/server/controllers/v1/comiccontroller.cpp index a01d510b..c523d689 100644 --- a/YACReaderLibrary/server/controllers/v1/comiccontroller.cpp +++ b/YACReaderLibrary/server/controllers/v1/comiccontroller.cpp @@ -57,9 +57,10 @@ void ComicController::service(HttpRequest &request, HttpResponse &response) comicFile->moveToThread(thread); - connect(comicFile, SIGNAL(errorOpening()), thread, SLOT(quit())); - connect(comicFile, SIGNAL(errorOpening(QString)), thread, SLOT(quit())); - connect(comicFile, SIGNAL(imagesLoaded()), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(errorOpening()), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(errorOpening(QString)), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(imagesLoaded()), thread, SLOT(quit())); + connect(comicFile, SIGNAL(destroyed()), thread, SLOT(quit())); connect(thread, SIGNAL(started()), comicFile, SLOT(process())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); diff --git a/YACReaderLibrary/server/controllers/v2/comiccontroller_v2.cpp b/YACReaderLibrary/server/controllers/v2/comiccontroller_v2.cpp index eca197d6..5e89fbf9 100644 --- a/YACReaderLibrary/server/controllers/v2/comiccontroller_v2.cpp +++ b/YACReaderLibrary/server/controllers/v2/comiccontroller_v2.cpp @@ -53,23 +53,21 @@ void ComicControllerV2::service(HttpRequest &request, HttpResponse &response) Comic *comicFile = FactoryComic::newComic(libraries.getPath(libraryId) + comic.path); - if (comicFile != nullptr) { - QThread *thread = nullptr; - - thread = new QThread(); + if (comicFile != NULL) { + QThread *thread = new QThread(); comicFile->moveToThread(thread); - connect(comicFile, SIGNAL(errorOpening()), thread, SLOT(quit())); - connect(comicFile, SIGNAL(errorOpening(QString)), thread, SLOT(quit())); - connect(comicFile, SIGNAL(imagesLoaded()), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(errorOpening()), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(errorOpening(QString)), thread, SLOT(quit())); + //connect(comicFile, SIGNAL(imagesLoaded()), thread, SLOT(quit())); + connect(comicFile, SIGNAL(destroyed()), thread, SLOT(quit())); connect(thread, SIGNAL(started()), comicFile, SLOT(process())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); comicFile->load(libraries.getPath(libraryId) + comic.path); - if (thread != nullptr) - thread->start(); + thread->start(); if (remoteComic) { QLOG_TRACE() << "remote comic requested"; From 7ed19ddd788de439d14eb0d954609005452aa031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20=C3=81ngel=20San=20Mart=C3=ADn?= Date: Tue, 24 Sep 2019 09:17:39 +0200 Subject: [PATCH 3/3] Fix scope GitKraken has some serious issues when resolving conflicts --- common/comic.cpp | 909 ++++++++++++++++++++++++----------------------- 1 file changed, 455 insertions(+), 454 deletions(-) diff --git a/common/comic.cpp b/common/comic.cpp index 5b3b5be1..e16ed5f3 100644 --- a/common/comic.cpp +++ b/common/comic.cpp @@ -560,82 +560,83 @@ QList> FileComic::getSections(int §ionIndex) } else { sections.append(section); } - - //out << "se han encontrado : " << sections.count() << " sectionIndex : " << sectionIndex << endl; - return sections; } - void FileComic::process() - { - CompressedArchive archive(_path); - if (!archive.toolsLoaded()) { + //out << "se han encontrado : " << sections.count() << " sectionIndex : " << sectionIndex << endl; + return sections; +} + +void FileComic::process() +{ + CompressedArchive archive(_path); + if (!archive.toolsLoaded()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(tr("7z not found")); + return; + } + + if (!archive.isValid()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(tr("Format not supported")); + return; + } + + //se filtran para obtener s�lo los formatos soportados + _order = archive.getFileNames(); + _fileNames = filter(_order); + + if (_fileNames.size() == 0) { + //QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file")); + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; + } + + //TODO, cambiar por listas + //_order = _fileNames; + + _pages.resize(_fileNames.size()); + _loadedPages = QVector(_fileNames.size(), false); + + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(_pages.size()); + _loaded = true; + + _cfi = 0; + + //TODO, add a setting for choosing the type of page sorting used. + comic_pages_sort(_fileNames, YACReaderHeuristicSorting); + + if (_firstPage == -1) { + _firstPage = bm->getLastPage(); + } + + if (_firstPage >= _pages.length()) { + _firstPage = 0; + } + + _index = _firstPage; + emit(openAt(_index)); + + int sectionIndex; + QList> sections = getSections(sectionIndex); + + for (int i = sectionIndex; i < sections.count(); i++) { + if (_invalidated) { //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(tr("7z not found")); return; } - - if (!archive.isValid()) { + archive.getAllData(sections.at(i), this); + } + for (int i = 0; i < sectionIndex; i++) { + if (_invalidated) { //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(tr("Format not supported")); return; } - - //se filtran para obtener s�lo los formatos soportados - _order = archive.getFileNames(); - _fileNames = filter(_order); - - if (_fileNames.size() == 0) { - //QMessageBox::critical(NULL,tr("File error"),tr("File not found or not images in file")); - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - - //TODO, cambiar por listas - //_order = _fileNames; - - _pages.resize(_fileNames.size()); - _loadedPages = QVector(_fileNames.size(), false); - - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(_pages.size()); - _loaded = true; - - _cfi = 0; - - //TODO, add a setting for choosing the type of page sorting used. - comic_pages_sort(_fileNames, YACReaderHeuristicSorting); - - if (_firstPage == -1) { - _firstPage = bm->getLastPage(); - } - - if (_firstPage >= _pages.length()) { - _firstPage = 0; - } - - _index = _firstPage; - emit(openAt(_index)); - - int sectionIndex; - QList> sections = getSections(sectionIndex); - - for (int i = sectionIndex; i < sections.count(); i++) { - if (_invalidated) { - //moveToThread(QCoreApplication::instance()->thread()); - return; - } - archive.getAllData(sections.at(i), this); - } - for (int i = 0; i < sectionIndex; i++) { - if (_invalidated) { - //moveToThread(QCoreApplication::instance()->thread()); - return; - } - archive.getAllData(sections.at(i), this); - } - //archive.getAllData(QVector(),this); - /* + archive.getAllData(sections.at(i), this); + } + //archive.getAllData(QVector(),this); + /* foreach(QString name,_fileNames) { index = _order.indexOf(name); @@ -644,211 +645,64 @@ QList> FileComic::getSections(int §ionIndex) emit imageLoaded(sortedIndex); emit imageLoaded(sortedIndex,_pages[sortedIndex]); }*/ + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); +} + +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +FolderComic::FolderComic() + : Comic() +{ +} + +FolderComic::FolderComic(const QString &path, int atPage) + : Comic(path, atPage) +{ + load(path, atPage); +} + +FolderComic::~FolderComic() +{ +} + +bool FolderComic::load(const QString &path, int atPage) +{ + _path = path; + if (atPage == -1) { + bm->newComic(_path); + emit bookmarksUpdated(); + } + _firstPage = atPage; + //emit bookmarksLoaded(*bm); + return true; +} + +void FolderComic::process() +{ + QDir d(_path); + + d.setNameFilters(getSupportedImageFormats()); + d.setFilter(QDir::Files | QDir::NoDotAndDotDot); + //d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); + QFileInfoList list = d.entryInfoList(); + + //don't fix double page files sorting, because the user can see how the SO sorts the files in the folder. + std::sort(list.begin(), list.end(), naturalSortLessThanCIFileInfo); + + int nPages = list.size(); + _pages.clear(); + _pages.resize(nPages); + _loadedPages = QVector(nPages, false); + + if (nPages == 0) { + //TODO emitir este mensaje en otro sitio + //QMessageBox::critical(NULL,QObject::tr("No images found"),QObject::tr("There are not images on the selected folder")); //moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); - } - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - - FolderComic::FolderComic() - : Comic() - { - } - - FolderComic::FolderComic(const QString &path, int atPage) - : Comic(path, atPage) - { - load(path, atPage); - } - - FolderComic::~FolderComic() - { - } - - bool FolderComic::load(const QString &path, int atPage) - { - _path = path; - if (atPage == -1) { - bm->newComic(_path); - emit bookmarksUpdated(); - } - _firstPage = atPage; - //emit bookmarksLoaded(*bm); - return true; - } - - void FolderComic::process() - { - QDir d(_path); - - d.setNameFilters(getSupportedImageFormats()); - d.setFilter(QDir::Files | QDir::NoDotAndDotDot); - //d.setSorting(QDir::Name|QDir::IgnoreCase|QDir::LocaleAware); - QFileInfoList list = d.entryInfoList(); - - //don't fix double page files sorting, because the user can see how the SO sorts the files in the folder. - std::sort(list.begin(), list.end(), naturalSortLessThanCIFileInfo); - - int nPages = list.size(); - _pages.clear(); - _pages.resize(nPages); - _loadedPages = QVector(nPages, false); - - if (nPages == 0) { - //TODO emitir este mensaje en otro sitio - //QMessageBox::critical(NULL,QObject::tr("No images found"),QObject::tr("There are not images on the selected folder")); - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - } else { - if (_firstPage == -1) { - _firstPage = bm->getLastPage(); - } - - if (_firstPage >= _pages.length()) { - _firstPage = 0; - } - - _index = _firstPage; - - emit(openAt(_index)); - - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(_pages.size()); - _loaded = true; - - int count = 0; - int i = _firstPage; - while (count < nPages) { - if (_invalidated) { - //moveToThread(QCoreApplication::instance()->thread()); - return; - } - - QFile f(list.at(i).absoluteFilePath()); - f.open(QIODevice::ReadOnly); - _pages[i] = f.readAll(); - emit imageLoaded(i); - emit imageLoaded(i, _pages[i]); - i++; - if (i == nPages) { - i = 0; - } - count++; - } - } - //moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); - } - - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// - -#ifndef NO_PDF - - PDFComic::PDFComic() - : Comic() - { - } - - PDFComic::PDFComic(const QString &path, int atPage) - : Comic(path, atPage) - { - load(path, atPage); - } - - PDFComic::~PDFComic() - { - } - - bool PDFComic::load(const QString &path, int atPage) - { - QFileInfo fi(path); - - if (fi.exists()) { - _path = path; - if (atPage == -1) { - bm->newComic(_path); - emit bookmarksUpdated(); - } - _firstPage = atPage; - //emit bookmarksLoaded(*bm); - return true; - } else { - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return false; - } - } - - bool PDFComic::load(const QString &path, const ComicDB &comic) - { - QFileInfo fi(path); - - if (fi.exists()) { - QList bookmarkIndexes; - bookmarkIndexes << comic.info.bookmark1 << comic.info.bookmark2 << comic.info.bookmark3; - if (bm->load(bookmarkIndexes, comic.info.currentPage - 1)) { - emit bookmarksUpdated(); - } - _firstPage = comic.info.currentPage - 1; - _path = QDir::cleanPath(path); - return true; - } else { - //QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path); - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return false; - } - } - - void PDFComic::process() - { -#if defined Q_OS_MAC && defined USE_PDFKIT - pdfComic = new MacOSXPDFComic(); - if (!pdfComic->openComic(_path)) { - delete pdfComic; - emit errorOpening(); - return; - } -#elif defined USE_PDFIUM - pdfComic = new PdfiumComic(); - if (!pdfComic->openComic(_path)) { - delete pdfComic; - emit errorOpening(); - return; - } -#else - pdfComic = Poppler::Document::load(_path); - if (!pdfComic) { - //delete pdfComic; - //pdfComic = 0; - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - if (pdfComic->isLocked()) { - //moveToThread(QCoreApplication::instance()->thread()); - emit errorOpening(); - return; - } - - //pdfComic->setRenderHint(Poppler::Document::Antialiasing, true); - pdfComic->setRenderHint(Poppler::Document::TextAntialiasing, true); -#endif - - int nPages = pdfComic->numPages(); - emit pageChanged(0); // this indicates new comic, index=0 - emit numPages(nPages); - _loaded = true; - //QMessageBox::critical(NULL,QString("%1").arg(nPages),tr("Invalid PDF file")); - - _pages.clear(); - _pages.resize(nPages); - _loadedPages = QVector(nPages, false); - + emit errorOpening(); + } else { if (_firstPage == -1) { _firstPage = bm->getLastPage(); } @@ -858,237 +712,384 @@ QList> FileComic::getSections(int §ionIndex) } _index = _firstPage; + emit(openAt(_index)); - //buffer index to avoid race conditions - int buffered_index = _index; - for (int i = buffered_index; i < nPages; i++) { + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(_pages.size()); + _loaded = true; + + int count = 0; + int i = _firstPage; + while (count < nPages) { if (_invalidated) { - delete pdfComic; //moveToThread(QCoreApplication::instance()->thread()); return; } - renderPage(i); - } - for (int i = 0; i < buffered_index; i++) { - if (_invalidated) { - delete pdfComic; - //moveToThread(QCoreApplication::instance()->thread()); - return; + QFile f(list.at(i).absoluteFilePath()); + f.open(QIODevice::ReadOnly); + _pages[i] = f.readAll(); + emit imageLoaded(i); + emit imageLoaded(i, _pages[i]); + i++; + if (i == nPages) { + i = 0; } - renderPage(i); + count++; } + } + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); +} - delete pdfComic; +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef NO_PDF + +PDFComic::PDFComic() + : Comic() +{ +} + +PDFComic::PDFComic(const QString &path, int atPage) + : Comic(path, atPage) +{ + load(path, atPage); +} + +PDFComic::~PDFComic() +{ +} + +bool PDFComic::load(const QString &path, int atPage) +{ + QFileInfo fi(path); + + if (fi.exists()) { + _path = path; + if (atPage == -1) { + bm->newComic(_path); + emit bookmarksUpdated(); + } + _firstPage = atPage; + //emit bookmarksLoaded(*bm); + return true; + } else { //moveToThread(QCoreApplication::instance()->thread()); - emit imagesLoaded(); + emit errorOpening(); + return false; + } +} + +bool PDFComic::load(const QString &path, const ComicDB &comic) +{ + QFileInfo fi(path); + + if (fi.exists()) { + QList bookmarkIndexes; + bookmarkIndexes << comic.info.bookmark1 << comic.info.bookmark2 << comic.info.bookmark3; + if (bm->load(bookmarkIndexes, comic.info.currentPage - 1)) { + emit bookmarksUpdated(); + } + _firstPage = comic.info.currentPage - 1; + _path = QDir::cleanPath(path); + return true; + } else { + //QMessageBox::critical(NULL,tr("Not found"),tr("Comic not found")+" : " + path); + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return false; + } +} + +void PDFComic::process() +{ +#if defined Q_OS_MAC && defined USE_PDFKIT + pdfComic = new MacOSXPDFComic(); + if (!pdfComic->openComic(_path)) { + delete pdfComic; + emit errorOpening(); + return; + } +#elif defined USE_PDFIUM + pdfComic = new PdfiumComic(); + if (!pdfComic->openComic(_path)) { + delete pdfComic; + emit errorOpening(); + return; + } +#else + pdfComic = Poppler::Document::load(_path); + if (!pdfComic) { + //delete pdfComic; + //pdfComic = 0; + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; + } + if (pdfComic->isLocked()) { + //moveToThread(QCoreApplication::instance()->thread()); + emit errorOpening(); + return; } - void PDFComic::renderPage(int page) - { -#if defined Q_OS_MAC && defined USE_PDFKIT - QImage img = pdfComic->getPage(page); - if (!img.isNull()) { -#elif defined USE_PDFIUM - QImage img = pdfComic->getPage(page); - if (!img.isNull()) { -#else - Poppler::Page *pdfpage = pdfComic->page(page); - if (pdfpage) { - QImage img = pdfpage->renderToImage(150, 150); - delete pdfpage; + //pdfComic->setRenderHint(Poppler::Document::Antialiasing, true); + pdfComic->setRenderHint(Poppler::Document::TextAntialiasing, true); #endif - QByteArray ba; - QBuffer buf(&ba); - img.save(&buf, "jpg", 96); - _pages[page] = ba; - emit imageLoaded(page); - emit imageLoaded(page, _pages[page]); - } + + int nPages = pdfComic->numPages(); + emit pageChanged(0); // this indicates new comic, index=0 + emit numPages(nPages); + _loaded = true; + //QMessageBox::critical(NULL,QString("%1").arg(nPages),tr("Invalid PDF file")); + + _pages.clear(); + _pages.resize(nPages); + _loadedPages = QVector(nPages, false); + + if (_firstPage == -1) { + _firstPage = bm->getLastPage(); } + if (_firstPage >= _pages.length()) { + _firstPage = 0; + } + + _index = _firstPage; + emit(openAt(_index)); + + //buffer index to avoid race conditions + int buffered_index = _index; + for (int i = buffered_index; i < nPages; i++) { + if (_invalidated) { + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + + renderPage(i); + } + for (int i = 0; i < buffered_index; i++) { + if (_invalidated) { + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + return; + } + renderPage(i); + } + + delete pdfComic; + //moveToThread(QCoreApplication::instance()->thread()); + emit imagesLoaded(); +} + +void PDFComic::renderPage(int page) +{ +#if defined Q_OS_MAC && defined USE_PDFKIT + QImage img = pdfComic->getPage(page); + if (!img.isNull()) { +#elif defined USE_PDFIUM + QImage img = pdfComic->getPage(page); + if (!img.isNull()) { +#else + Poppler::Page *pdfpage = pdfComic->page(page); + if (pdfpage) { + QImage img = pdfpage->renderToImage(150, 150); + delete pdfpage; +#endif + QByteArray ba; + QBuffer buf(&ba); + img.save(&buf, "jpg", 96); + _pages[page] = ba; + emit imageLoaded(page); + emit imageLoaded(page, _pages[page]); + } +} + #endif //NO_PDF - Comic *FactoryComic::newComic(const QString &path) - { +Comic *FactoryComic::newComic(const QString &path) +{ - QFileInfo fi(path); - if (fi.exists()) { - if (fi.isFile()) { + QFileInfo fi(path); + if (fi.exists()) { + if (fi.isFile()) { #ifndef NO_PDF - if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { - return new PDFComic(); - } else { - return new FileComic(); - } -#else - return new FileComic(); -#endif + if (fi.suffix().compare("pdf", Qt::CaseInsensitive) == 0) { + return new PDFComic(); } else { - if (fi.isDir()) { - return new FolderComic(); - } else { - return NULL; - } + return new FileComic(); } - } else - return NULL; - } - - bool is_double_page(const QString &pageName, const QString &commonPrefix, const int maxExpectedDoublePagesNumberLenght) - { - if (pageName.startsWith(commonPrefix)) { - QString substringContainingPageNumbers = pageName.mid(commonPrefix.length()); - QString pageNumbersSubString; - for (int i = 0; i < substringContainingPageNumbers.length() && substringContainingPageNumbers.at(i).isDigit(); i++) { - pageNumbersSubString.append(substringContainingPageNumbers.at(i)); - } - if (pageNumbersSubString.length() < 3 || pageNumbersSubString.length() > maxExpectedDoublePagesNumberLenght || pageNumbersSubString.length() % 2 == 1) { - return false; - } - - int leftPageNumber = pageNumbersSubString.left(pageNumbersSubString.length() / 2).toInt(); - int rightPageNumber = pageNumbersSubString.mid(pageNumbersSubString.length() / 2).toInt(); - - if (leftPageNumber == 0 || rightPageNumber == 0) { - return false; - } - if ((rightPageNumber - leftPageNumber) == 1) { - return true; +#else + return new FileComic(); +#endif + } else { + if (fi.isDir()) { + return new FolderComic(); + } else { + return NULL; } } - return false; - } + } else + return NULL; +} - QString get_most_common_prefix(const QList &pageNames) - { - if (pageNames.isEmpty()) { - return ""; +bool is_double_page(const QString &pageName, const QString &commonPrefix, const int maxExpectedDoublePagesNumberLenght) +{ + if (pageName.startsWith(commonPrefix)) { + QString substringContainingPageNumbers = pageName.mid(commonPrefix.length()); + QString pageNumbersSubString; + for (int i = 0; i < substringContainingPageNumbers.length() && substringContainingPageNumbers.at(i).isDigit(); i++) { + pageNumbersSubString.append(substringContainingPageNumbers.at(i)); + } + if (pageNumbersSubString.length() < 3 || pageNumbersSubString.length() > maxExpectedDoublePagesNumberLenght || pageNumbersSubString.length() % 2 == 1) { + return false; } - QMap frequency; - int currentPrefixLenght = pageNames.at(0).split('/').last().length(); - int currentPrefixCount = 1; - int i; - QString previous; - QString current; - for (i = 1; i < pageNames.length(); i++) { - int pos = 0; - previous = pageNames.at(i - 1).split('/').last(); - current = pageNames.at(i).split('/').last(); - for (; pos < current.length() && previous[pos] == current[pos]; pos++) - ; + int leftPageNumber = pageNumbersSubString.left(pageNumbersSubString.length() / 2).toInt(); + int rightPageNumber = pageNumbersSubString.mid(pageNumbersSubString.length() / 2).toInt(); - if (pos < currentPrefixLenght && pos > 0) { - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - currentPrefixLenght = pos; - currentPrefixCount++; - } - /* + if (leftPageNumber == 0 || rightPageNumber == 0) { + return false; + } + if ((rightPageNumber - leftPageNumber) == 1) { + return true; + } + } + return false; +} + +QString get_most_common_prefix(const QList &pageNames) +{ + if (pageNames.isEmpty()) { + return ""; + } + QMap frequency; + int currentPrefixLenght = pageNames.at(0).split('/').last().length(); + int currentPrefixCount = 1; + + int i; + QString previous; + QString current; + for (i = 1; i < pageNames.length(); i++) { + int pos = 0; + previous = pageNames.at(i - 1).split('/').last(); + current = pageNames.at(i).split('/').last(); + for (; pos < current.length() && previous[pos] == current[pos]; pos++) + ; + + if (pos < currentPrefixLenght && pos > 0) { + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); + currentPrefixLenght = pos; + currentPrefixCount++; + } + /* else if(pos > currentPrefixLenght) { frequency.insert(pageNames.at(i-1).left(currentPrefixLenght), currentPrefixCount - 1); currentPrefixLenght = pos; currentPrefixCount = 2; }*/ - else if (pos == 0) { - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - currentPrefixLenght = current.length(); - currentPrefixCount = 1; - } else { - currentPrefixCount++; - } - } - - frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - - uint maxFrequency = 0; - QString common_prefix = ""; - foreach (QString key, frequency.keys()) { - if (maxFrequency < frequency.value(key)) { - maxFrequency = frequency.value(key); - common_prefix = key; - } - } - - QRegExp allNumberRegExp("\\d+"); - if (allNumberRegExp.exactMatch(common_prefix)) { - return ""; - } - - if (maxFrequency < pageNames.length() * 0.60) //the most common tipe of image file should a proper page, so we can asume that the common_prefix should be in, at least, the 60% of the pages - { - return ""; - } - - return common_prefix; - } - - void get_double_pages(const QList &pageNames, QList &singlePageNames /*out*/, QList &doublePageNames /*out*/) - { - uint maxExpectedDoublePagesNumberLenght = (int)(log10(pageNames.length()) + 1) * 2; - - QString mostCommonPrefix = get_most_common_prefix(pageNames); - - foreach (const QString &pageName, pageNames) { - if (is_double_page(pageName.split('/').last(), mostCommonPrefix, maxExpectedDoublePagesNumberLenght)) { - doublePageNames.append(pageName); - } else { - singlePageNames.append(pageName); - } + else if (pos == 0) { + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); + currentPrefixLenght = current.length(); + currentPrefixCount = 1; + } else { + currentPrefixCount++; } } - QList merge_pages(QList & singlePageNames, QList & doublePageNames) - { - //NOTE: this implementation doesn't differ from std::merge using a custom comparator, but it can be easily tweaked if merging requeries an additional heuristic behaviour - QList pageNames; + frequency.insert(previous.left(currentPrefixLenght), currentPrefixCount); - int i = 0; - int j = 0; - - while (i < singlePageNames.length() && j < doublePageNames.length()) { - if (singlePageNames.at(i).compare(doublePageNames.at(j), Qt::CaseInsensitive) < 0) { - pageNames.append(singlePageNames.at(i++)); - } else { - pageNames.append(doublePageNames.at(j++)); - } + uint maxFrequency = 0; + QString common_prefix = ""; + foreach (QString key, frequency.keys()) { + if (maxFrequency < frequency.value(key)) { + maxFrequency = frequency.value(key); + common_prefix = key; } + } - while (i < singlePageNames.length()) { + QRegExp allNumberRegExp("\\d+"); + if (allNumberRegExp.exactMatch(common_prefix)) { + return ""; + } + + if (maxFrequency < pageNames.length() * 0.60) //the most common tipe of image file should a proper page, so we can asume that the common_prefix should be in, at least, the 60% of the pages + { + return ""; + } + + return common_prefix; +} + +void get_double_pages(const QList &pageNames, QList &singlePageNames /*out*/, QList &doublePageNames /*out*/) +{ + uint maxExpectedDoublePagesNumberLenght = (int)(log10(pageNames.length()) + 1) * 2; + + QString mostCommonPrefix = get_most_common_prefix(pageNames); + + foreach (const QString &pageName, pageNames) { + if (is_double_page(pageName.split('/').last(), mostCommonPrefix, maxExpectedDoublePagesNumberLenght)) { + doublePageNames.append(pageName); + } else { + singlePageNames.append(pageName); + } + } +} + +QList merge_pages(QList &singlePageNames, QList &doublePageNames) +{ + //NOTE: this implementation doesn't differ from std::merge using a custom comparator, but it can be easily tweaked if merging requeries an additional heuristic behaviour + QList pageNames; + + int i = 0; + int j = 0; + + while (i < singlePageNames.length() && j < doublePageNames.length()) { + if (singlePageNames.at(i).compare(doublePageNames.at(j), Qt::CaseInsensitive) < 0) { pageNames.append(singlePageNames.at(i++)); - } - - while (j < doublePageNames.length()) { + } else { pageNames.append(doublePageNames.at(j++)); } - - return pageNames; } - void comic_pages_sort(QList & pageNames, YACReaderPageSortingMode sortingMode) - { - switch (sortingMode) { - case YACReaderNumericalSorting: - std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); - break; + while (i < singlePageNames.length()) { + pageNames.append(singlePageNames.at(i++)); + } - case YACReaderHeuristicSorting: { - std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); + while (j < doublePageNames.length()) { + pageNames.append(doublePageNames.at(j++)); + } - QList singlePageNames; - QList doublePageNames; + return pageNames; +} - get_double_pages(pageNames, singlePageNames, doublePageNames); +void comic_pages_sort(QList &pageNames, YACReaderPageSortingMode sortingMode) +{ + switch (sortingMode) { + case YACReaderNumericalSorting: + std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); + break; - if (doublePageNames.length() > 0) { - pageNames = merge_pages(singlePageNames, doublePageNames); - } - } break; + case YACReaderHeuristicSorting: { + std::sort(pageNames.begin(), pageNames.end(), naturalSortLessThanCI); - case YACReaderAlphabeticalSorting: - std::sort(pageNames.begin(), pageNames.end()); - break; + QList singlePageNames; + QList doublePageNames; + + get_double_pages(pageNames, singlePageNames, doublePageNames); + + if (doublePageNames.length() > 0) { + pageNames = merge_pages(singlePageNames, doublePageNames); } + } break; + + case YACReaderAlphabeticalSorting: + std::sort(pageNames.begin(), pageNames.end()); + break; } +}