diff --git a/thumbnail/comiccreator.cpp b/thumbnail/comiccreator.cpp index d8f4473e..af25d7d7 100644 --- a/thumbnail/comiccreator.cpp +++ b/thumbnail/comiccreator.cpp @@ -1,314 +1,314 @@ /** * This file is part of the KDE libraries * * Comic Book Thumbnailer for KDE 4 v0.1 * Creates cover page previews for comic-book files (.cbr/z/t). * Copyright (c) 2009 Harsh J * * Some code borrowed from Okular's comicbook generators, * by Tobias Koenig * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // comiccreator.cpp #include "comiccreator.h" #include #include #include #include #include #include #include #include #include #include #include // For KIO-Thumbnail debug outputs // TODO KF5 qCDebug #define KIO_THUMB 11371 extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new ComicCreator; } } ComicCreator::ComicCreator() : m_loop(0) {} bool ComicCreator::create(const QString& path, int width, int height, QImage& img) { Q_UNUSED(width); Q_UNUSED(height); QImage cover; // Detect mime type. QMimeDatabase db; db.mimeTypeForFile(path, QMimeDatabase::MatchContent); const QMimeType mime = db.mimeTypeForFile(path, QMimeDatabase::MatchContent); if (mime.inherits("application/x-cbz") || mime.inherits("application/zip")) { // ZIP archive. cover = extractArchiveImage(path, ZIP); } else if (mime.inherits("application/x-cbt") || mime.inherits("application/x-gzip") || mime.inherits("application/x-tar")) { // TAR archive cover = extractArchiveImage(path, TAR); } else if (mime.inherits("application/x-cbr") || mime.inherits("application/x-rar")) { // RAR archive. cover = extractRARImage(path); } if (cover.isNull()) { qDebug()<<"Error creating the comic book thumbnail."; return false; } // Copy the extracted cover to KIO::ThumbCreator's img reference. img = cover; return true; } void ComicCreator::filterImages(QStringList& entries) { /// Sort case-insensitive, then remove non-image entries. QMap entryMap; Q_FOREACH(const QString& entry, entries) { if (entry.endsWith(QLatin1String(".gif"), Qt::CaseInsensitive) || entry.endsWith(QLatin1String(".jpg"), Qt::CaseInsensitive) || entry.endsWith(QLatin1String(".jpeg"), Qt::CaseInsensitive) || entry.endsWith(QLatin1String(".png"), Qt::CaseInsensitive)) { entryMap.insert(entry.toLower(), entry); } } entries = entryMap.values(); } QImage ComicCreator::extractArchiveImage(const QString& path, const ComicCreator::Type type) { /// Extracts the cover image out of the .cbz or .cbt file. QScopedPointer cArchive; if (type==ZIP) { // Open the ZIP archive. cArchive.reset(new KZip(path)); } else if (type==TAR) { // Open the TAR archive. cArchive.reset(new KTar(path)); } else { // Reject all other types for this method. return QImage(); } // Can our archive be opened? if (!cArchive->open(QIODevice::ReadOnly)) { return QImage(); } // Get the archive's directory. const KArchiveDirectory* cArchiveDir = 0; cArchiveDir = cArchive->directory(); if (!cArchiveDir) { return QImage(); } QStringList entries; // Get and filter the entries from the archive. getArchiveFileList(entries, QString(), cArchiveDir); filterImages(entries); if (entries.isEmpty()) { return QImage(); } // Extract the cover file. const KArchiveFile *coverFile = static_cast (cArchiveDir->entry(entries[0])); if (!coverFile) { return QImage(); } return QImage::fromData(coverFile->data()); } void ComicCreator::getArchiveFileList(QStringList& entries, const QString& prefix, const KArchiveDirectory *dir) { /// Recursively list all files in the ZIP archive into 'entries'. Q_FOREACH (const QString& entry, dir->entries()) { const KArchiveEntry *e = dir->entry(entry); if (e->isDirectory()) { getArchiveFileList(entries, prefix + entry + '/', static_cast(e)); } else if (e->isFile()) { entries.append(prefix + entry); } } } QImage ComicCreator::extractRARImage(const QString& path) { /// Extracts the cover image out of the .cbr file. // Check if unrar is available. Get its path in 'unrarPath'. QString unrar = unrarPath(); if (unrar.isEmpty()) { qDebug()<<"A suitable version of unrar is not available."; return QImage(); } // Get the files and filter the images out. QStringList entries = getRARFileList(path, unrar); filterImages(entries); if (entries.isEmpty()) { return QImage(); } // Clear previously used data arrays. m_stdOut.clear(); m_stdErr.clear(); // Extract the cover file alone. Use verbose paths. // unrar x -n path/to/archive /path/to/temp QTemporaryDir cUnrarTempDir; startProcess(unrar, QStringList() << "x" << "-n" + entries[0] << path << cUnrarTempDir.path()); // Load cover file data into image. QImage cover; cover.load(cUnrarTempDir.path() + QDir::separator() + entries[0]); return cover; } QStringList ComicCreator::getRARFileList(const QString& path, const QString& unrarPath) { /// Get a verbose unrar listing so we can extract a single file later. // CMD: unrar vb /path/to/archive QStringList entries; startProcess(unrarPath, QStringList() << "vb" << path); entries = QString::fromLocal8Bit(m_stdOut).split('\n', QString::SkipEmptyParts); return entries; } QString ComicCreator::unrarPath() const { /// Check the standard paths to see if a suitable unrar is available. QString unrar = QStandardPaths::findExecutable("unrar"); if (unrar.isEmpty()) { unrar = QStandardPaths::findExecutable("unrar-nonfree"); } if (unrar.isEmpty()) { unrar = QStandardPaths::findExecutable("rar"); } if (!unrar.isEmpty()) { QProcess proc; proc.start(unrar, QStringList() << "-version"); proc.waitForFinished(-1); const QStringList lines = QString::fromLocal8Bit(proc.readAllStandardOutput()).split ('\n', QString::SkipEmptyParts); if (!lines.isEmpty()) { if (lines.first().startsWith("RAR ") || lines.first().startsWith("UNRAR ")) { return unrar; } } } return QString(); } void ComicCreator::readProcessOut() { /// Read all std::out data and store to the data array. if (!m_process) return; m_stdOut += m_process->readAllStandardOutput(); } void ComicCreator::readProcessErr() { /// Read available std:err data and kill process if there is any. if (!m_process) return; m_stdErr += m_process->readAllStandardError(); if (!m_stdErr.isEmpty()) { m_process->kill(); return; } } void ComicCreator::finishedProcess(int exitCode, QProcess::ExitStatus exitStatus) { /// Run when process finishes. Q_UNUSED(exitCode) if (m_loop) { m_loop->exit(exitStatus == QProcess::CrashExit ? 1 : 0); } } int ComicCreator::startProcess(const QString& processPath, const QStringList& args) { /// Run a process and store std::out, std::err data in their respective buffers. int ret = 0; #if defined(Q_OS_WIN) m_process.reset(new QProcess(this)); #else m_process.reset(new KPtyProcess(this)); m_process->setOutputChannelMode(KProcess::SeparateChannels); #endif connect(m_process.data(), SIGNAL(readyReadStandardOutput()), SLOT(readProcessOut())); connect(m_process.data(), SIGNAL(readyReadStandardError()), SLOT(readProcessErr())); connect(m_process.data(), SIGNAL(finished(int, QProcess::ExitStatus)), SLOT(finishedProcess(int, QProcess::ExitStatus))); #if defined(Q_OS_WIN) m_process->start(processPath, args, QIODevice::ReadWrite | QIODevice::Unbuffered); ret = m_process->waitForFinished(-1) ? 0 : 1; #else m_process->setProgram(processPath, args); m_process->setNextOpenMode(QIODevice::ReadWrite | QIODevice::Unbuffered); m_process->start(); QEventLoop loop; m_loop = &loop; ret = loop.exec(QEventLoop::WaitForMoreEvents); m_loop = 0; #endif return ret; } ThumbCreator::Flags ComicCreator::flags() const { - return DrawFrame; + return None; } diff --git a/thumbnail/djvucreator.cpp b/thumbnail/djvucreator.cpp index 1547831b..ce53133c 100644 --- a/thumbnail/djvucreator.cpp +++ b/thumbnail/djvucreator.cpp @@ -1,133 +1,133 @@ /* This file is part of the KDE libraries Copyright (C) 2001 Malte Starostik Copyright (C) 2001 Leon Bottou This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "djvucreator.h" #include #include #include #include #include #ifdef HAVE_SYS_SELECT_H #include #endif #include #include #include #include #include #include extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new DjVuCreator; } } bool DjVuCreator::create(const QString &path, int width, int height, QImage &img) { int output[2]; QByteArray data(1024, 'k'); bool ok = false; if (pipe(output) == -1) return false; const char* argv[8]; QByteArray sizearg, fnamearg; sizearg = QByteArray::number(width) + 'x' + QByteArray::number(height); fnamearg = QFile::encodeName( path ); argv[0] = "ddjvu"; argv[1] = "-page"; argv[2] = "1"; // krazy:exclude=doublequote_chars argv[3] = "-size"; argv[4] = sizearg.data(); argv[5] = fnamearg.data(); argv[6] = 0; pid_t pid = fork(); if (pid == 0) { close(output[0]); dup2(output[1], STDOUT_FILENO); execvp(argv[0], const_cast(argv)); exit(1); } else if (pid >= 0) { close(output[1]); int offset = 0; while (!ok) { fd_set fds; FD_ZERO(&fds); FD_SET(output[0], &fds); struct timeval tv; tv.tv_sec = 20; tv.tv_usec = 0; if (select(output[0] + 1, &fds, 0, 0, &tv) <= 0) { if (errno == EINTR || errno == EAGAIN) continue; break; // error or timeout } if (FD_ISSET(output[0], &fds)) { int count = read(output[0], data.data() + offset, 1024); if (count == -1) break; if (count) // prepare for next block { offset += count; data.resize(offset + 1024); } else // got all data { data.resize(offset); ok = true; } } } if (!ok) kill(pid, SIGTERM); int status = 0; if (waitpid(pid, &status, 0) != pid || (status != 0 && status != 256) ) ok = false; } else { close(output[1]); } close(output[0]); int l = img.loadFromData( data ); return ok && l; } ThumbCreator::Flags DjVuCreator::flags() const { - return static_cast(DrawFrame); + return static_cast(None); } diff --git a/thumbnail/htmlcreator.cpp b/thumbnail/htmlcreator.cpp index 29d19027..0083f9c5 100644 --- a/thumbnail/htmlcreator.cpp +++ b/thumbnail/htmlcreator.cpp @@ -1,109 +1,109 @@ /* This file is part of the KDE libraries Copyright (C) 2000 Malte Starostik Copyright (C) 2006 Roberto Cappuccio Copyright (C) 2011 Dawit Alemayehu This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "htmlcreator.h" #include #include #include #include #include extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new HTMLCreator; } } HTMLCreator::HTMLCreator() : m_loadedOk(true), m_page(0) { } HTMLCreator::~HTMLCreator() { delete m_page; } bool HTMLCreator::create(const QString &path, int width, int height, QImage &img) { if (!m_page) { m_page = new QWebEnginePage; connect(m_page, &QWebEnginePage::loadFinished, this, &HTMLCreator::slotFinished); m_page->settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, false); m_page->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false); m_page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessRemoteUrls, false); m_page->settings()->setAttribute(QWebEngineSettings::LocalContentCanAccessFileUrls, true); } QUrl url = QUrl::fromUserInput(path); // the argument should be a QUrl! m_loadedOk = false; m_page->load(url); const int t = startTimer((url.isLocalFile()?5000:30000)); m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); killTimer(t); if (m_page->contentsSize().isEmpty()) { m_loadedOk = false; } if (!m_loadedOk) { return false; } QPixmap pix; if (width > 400 || height > 600) { if (height * 3 > width * 4) { pix = QPixmap(width, width * 4 / 3); } else { pix = QPixmap(height * 3 / 4, height); } } else { pix = QPixmap(400, 600); } pix.fill(Qt::transparent); m_page->view()->render(&pix); img = pix.toImage(); return true; } void HTMLCreator::timerEvent(QTimerEvent *) { m_eventLoop.quit(); } void HTMLCreator::slotFinished(bool ok) { m_loadedOk = ok; m_eventLoop.quit(); } ThumbCreator::Flags HTMLCreator::flags() const { - return DrawFrame; + return None; } #include "htmlcreator.moc" diff --git a/thumbnail/kritacreator.cpp b/thumbnail/kritacreator.cpp index 3b24bc3d..2240010b 100644 --- a/thumbnail/kritacreator.cpp +++ b/thumbnail/kritacreator.cpp @@ -1,108 +1,108 @@ /* This file is part of the Calligra project. Copyright 2015 Friedrich W. H. Kossebau This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kritacreator.h" #include // Qt #include #include #include #include extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new KritaCreator; } } KritaCreator::KritaCreator() { } KritaCreator::~KritaCreator() { } bool KritaCreator::create(const QString &path, int width, int height, QImage &image) { // for now just rely on the rendered data inside the file, // do not load Krita code for rendering ourselves, as that currently (2.9) // means loading all plugins, resources etc. KZip zip(path); if (!zip.open(QIODevice::ReadOnly)) { return false; } QImage thumbnail; bool biggerSizeNeeded = true; // first check if normal thumbnail is good enough // ORA thumbnail? const KArchiveEntry *entry = zip.directory()->entry(QLatin1String("Thumbnails/thumbnail.png")); // KRA thumbnail if (!entry || !entry->isFile()) { entry = zip.directory()->entry(QLatin1String("preview.png")); } if (!entry || !entry->isFile()) { return false; } const KZipFileEntry* fileZipEntry = static_cast(entry); bool thumbLoaded = thumbnail.loadFromData(fileZipEntry->data(), "PNG"); if (thumbLoaded) { biggerSizeNeeded = (thumbnail.width() < width || thumbnail.height() < height); } if (biggerSizeNeeded || !thumbLoaded) { entry = zip.directory()->entry(QLatin1String("mergedimage.png")); } if (entry && entry->isFile()) { fileZipEntry = static_cast(entry); thumbLoaded = thumbnail.loadFromData(fileZipEntry->data(), "PNG"); if (thumbLoaded) { thumbnail = thumbnail.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation); } else { return false; } } if (!thumbnail.isNull()) { // transparent areas put a white background behind the thumbnail // (or better checkerboard?) image = QImage(thumbnail.size(), QImage::Format_RGB32); image.fill(QColor(Qt::white).rgb()); QPainter p(&image); p.drawImage(QPoint(0, 0), thumbnail); return true; } return false; } ThumbCreator::Flags KritaCreator::flags() const { - return DrawFrame; + return None; } diff --git a/thumbnail/textcreator.cpp b/thumbnail/textcreator.cpp index 7c0263c8..c6fd7382 100644 --- a/thumbnail/textcreator.cpp +++ b/thumbnail/textcreator.cpp @@ -1,168 +1,168 @@ /* This file is part of the KDE libraries Copyright (C) 2000,2002 Carsten Pfeiffer 2000 Malte Starostik This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "textcreator.h" #include #include #include #include #include #include #include // TODO Fix or remove kencodingprober code // #include extern "C" { Q_DECL_EXPORT ThumbCreator *new_creator() { return new TextCreator; } } TextCreator::TextCreator() : m_data(0), m_dataSize(0) { } TextCreator::~TextCreator() { delete [] m_data; } static QTextCodec *codecFromContent(const char *data, int dataSize) { #if 0 // ### Use this when KEncodingProber does not return junk encoding for UTF-8 data) KEncodingProber prober; prober.feed(data, dataSize); return QTextCodec::codecForName(prober.encoding()); #else QByteArray ba = QByteArray::fromRawData(data, dataSize); // try to detect UTF text, fall back to locale default (which is usually UTF-8) return QTextCodec::codecForUtfText(ba, QTextCodec::codecForLocale()); #endif } bool TextCreator::create(const QString &path, int width, int height, QImage &img) { bool ok = false; // determine some sizes... // example: width: 60, height: 64 QSize pixmapSize( width, height ); if (height * 3 > width * 4) pixmapSize.setHeight( width * 4 / 3 ); else pixmapSize.setWidth( height * 3 / 4 ); if ( pixmapSize != m_pixmap.size() ) m_pixmap = QPixmap( pixmapSize ); // one pixel for the rectangle, the rest. whitespace int xborder = 1 + pixmapSize.width()/16; // minimum x-border int yborder = 1 + pixmapSize.height()/16; // minimum y-border // this font is supposed to look good at small sizes QFont font = QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont); font.setPixelSize( qMax(7, qMin( 10, ( pixmapSize.height() - 2 * yborder ) / 16 ) ) ); QFontMetrics fm( font ); // calculate a better border so that the text is centered int canvasWidth = pixmapSize.width() - 2*xborder; int canvasHeight = pixmapSize.height() - 2*yborder; int numLines = (int) ( canvasHeight / fm.height() ); // assumes an average line length of <= 120 chars const int bytesToRead = 120 * numLines; // create text-preview QFile file( path ); if ( file.open( QIODevice::ReadOnly )) { if ( !m_data || m_dataSize < bytesToRead + 1 ) { delete [] m_data; m_data = new char[bytesToRead+1]; m_dataSize = bytesToRead + 1; } int read = file.read( m_data, bytesToRead ); if ( read > 0 ) { ok = true; m_data[read] = '\0'; QString text = codecFromContent( m_data, read )->toUnicode( m_data, read ).trimmed(); // FIXME: maybe strip whitespace and read more? // If the text contains tabs or consecutive spaces, it is probably // formatted using white space. Use a fixed pitch font in this case. QStringList textLines = text.split( '\n' ); foreach ( const QString &line, textLines ) { QString trimmedLine = line.trimmed(); if ( trimmedLine.contains( '\t' ) || trimmedLine.contains( " " ) ) { font.setFamily( QFontDatabase::systemFont(QFontDatabase::FixedFont).family()); break; } } #if 0 QPalette palette; QColor bgColor = palette.color( QPalette::Base ); QColor fgColor = palette.color( QPalette::Text ); if ( qGray( bgColor.rgb() ) > qGray( fgColor.rgb() ) ) { bgColor = bgColor.darker( 103 ); } else { bgColor = bgColor.lighter( 103 ); } #else QColor bgColor = QColor ( 245, 245, 245 ); // light-grey background QColor fgColor = Qt::black; #endif m_pixmap.fill( bgColor ); QRect rect; QPainter painter( &m_pixmap ); painter.setFont( font ); painter.setPen( fgColor ); QTextOption textOption( Qt::AlignTop | Qt::AlignLeft ); textOption.setTabStop( 8 * painter.fontMetrics().width( ' ' ) ); textOption.setWrapMode( QTextOption::WrapAtWordBoundaryOrAnywhere ); painter.drawText( QRect( xborder, yborder, canvasWidth, canvasHeight ), text, textOption ); painter.end(); img = m_pixmap.toImage(); } file.close(); } return ok; } ThumbCreator::Flags TextCreator::flags() const { - return (Flags)(DrawFrame | BlendIcon); + return (Flags)BlendIcon; }