/*************************************************************************** sq_converter.cpp - description ------------------- begin : ??? Mar 3 2005 copyright : (C) 2005 by Baryshev Dmitry email : ksquirrel.iv@gmail.com ***************************************************************************/ /*************************************************************************** * * * 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) any later version. * * * ***************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #include #include #include "ksquirrel.h" #include "sq_converter.h" #include "sq_widgetstack.h" #include "sq_diroperator.h" #include "sq_libraryhandler.h" #include "sq_config.h" #include "sq_errorstring.h" #include "sq_imageloader.h" #include "sq_imageconvert.h" SQ_Converter * SQ_Converter::m_sing = 0; SQ_Converter::SQ_Converter(TQObject *parent) : TQObject(parent) { m_sing = this; err_internal = i18n("internal error") + '\n'; err_failed = i18n("failed") + '\n'; special_action = i18n("Converting"); image = 0; } SQ_Converter::~SQ_Converter() { if(image) free(image); } void SQ_Converter::slotStartEdit() { files.clear(); KFileItemList *items = (KFileItemList *)SQ_WidgetStack::instance()->selectedItems(); if(!items || !items->count()) { KMessageBox::information(KSquirrel::app(), i18n("Select files to edit")); return; } else if(!items->first()->url().isLocalFile()) { KMessageBox::information(KSquirrel::app(), i18n("Converter cannot work with remote files.\nSorry")); return; } KFileItem *i = items->first(); for(;i;i = items->next()) { if(i->isFile()) files.append(i->url().path()); } startEditPrivate(); } TQString SQ_Converter::adjustFileName(const TQString &globalprefix, const TQString &name1, int replace, TQString putto, bool paged, int page) { TQFileInfo ff(name1); TQString name = ff.dirPath() + '/' + (replace == 0 ? globalprefix : (replace == 2 ? TQString() : globalprefix)) + ff.fileName(); ff = TQFileInfo(name); TQString result, inner, filter = lw->filter; TQString ext = ff.extension(false); TQString prefix, suffix, name2 = name; TQString spage = TQString::fromLatin1("page_%1.").arg((TQString::fromLatin1("%1").arg(page)).rightJustify(3, '0')); if(!putto.isEmpty()) { if(TQFile::exists(putto)) name2 = putto + '/' + ff.fileName(); } prefix = name2; prefix.truncate(name2.length() - ext.length()); suffix = (SQ_LibraryHandler::instance()->knownExtension(TQString::fromLatin1("*.") + ext)) ? TQString(lw->codec->extension(32)) : ext; if(replace == 0 || replace == 2) result = (!paged) ? (prefix + inner + suffix) : (prefix + spage + inner + suffix); else { result = (!paged) ? (prefix + inner + suffix) : (prefix + spage + inner + suffix); if(TQFile::exists(result)) { inner = TQString::fromLatin1("1."); result = (!paged) ? (prefix + inner + suffix) : (prefix + spage + inner + suffix); } } return result; } void SQ_Converter::errorjmp(jmp_buf jmp, const int code) { error_code = code; longjmp(jmp, 1); } void SQ_Converter::decodingCycle() { int i, j; TQString name; jmp_buf jmp; RGBA *scan; int errors, gerrors = 0, current; TQString putto; int replace = imageopt.where_to_put; bool brk; SQ_Config::instance()->setGroup("Edit tools"); int allpages = SQ_Config::instance()->readNumEntry("load_pages", 0); int pages_num = SQ_Config::instance()->readNumEntry("load_pages_number", 1); if(pages_num < 1) pages_num = 1; altw = SQ_LibraryHandler::instance()->libraryByName(SQ_Config::instance()->readEntry("altlibrary", "Portable Network Graphics")); multi = SQ_Config::instance()->readBoolEntry("multi", true); tempfile = new KTempFile; tempfile->setAutoDelete(true); if(tempfile->status()) { KMessageBox::error(KSquirrel::app(), i18n("Temporary file creation failed")); return; } tempfile->close(); TQStringList::iterator last_it = files.fromLast(); TQStringList::iterator itEnd = files.end(); convert->startConvertion(files.count()); putto = imageopt.putto; for(TQStringList::iterator it = files.begin();it != itEnd;++it) { currentFile = *it; last = (it == last_it); TQFileInfo ff(*it); emit convertText(special_action + ' ' + KStringHandler::rsqueeze(ff.fileName()) + "... ", false); if((lr = SQ_LibraryHandler::instance()->libraryForFile(*it))) { lw = SQ_LibraryHandler::instance()->libraryByName(convopt.libname); if(!lr || !lw) { gerrors++; emit convertText(err_internal, true); emit oneFileProcessed(); continue; } name = TQFile::encodeName(*it); i = lr->codec->read_init(name.ascii()); if(setjmp(jmp)) { gerrors++; lr->codec->read_close(); emit convertText(SQ_ErrorString::instance()->stringSN(error_code), true); emit oneFileProcessed(); continue; } if(i != SQE_OK) errorjmp(jmp, i); errors = 0; current = 0; while(true) { brk = (allpages == 1 && current) || (allpages == 2 && current == pages_num); i = lr->codec->read_next(); im = lr->codec->image(current-1); if(i != SQE_OK || brk) { if(i == SQE_NOTOK || brk) { if(current == 1) name = adjustFileName(prefix, *it, replace, putto); else name = adjustFileName(prefix, *it, replace, putto, true, current); lastFrame = last; i = manipAndWriteDecodedImage(tempfile->name(), im); emit convertText(errors ? (i18n("1 error", "%n errors", errors)+'\n') : SQ_ErrorString::instance()->stringSN(SQE_OK), true); emit oneFileProcessed(); i = SQE_OK; if(replace == 2) { emit convertText(i18n("Removing") + KStringHandler::rsqueeze(ff.fileName()) + TQString("... "), false); bool b = TQFile::remove(*it); emit convertText(b ? SQ_ErrorString::instance()->stringSN(SQE_OK) : err_failed, true); emit oneFileProcessed(); } i = copyFile(tempfile->name(), name); break; } else errorjmp(jmp, i); } if(current) { name = adjustFileName(prefix, *it, replace, putto, true, current); lastFrame = false; manipAndWriteDecodedImage(tempfile->name(), im); i = copyFile(tempfile->name(), name); } im = lr->codec->image(current); image = (RGBA *)realloc(image, im->w * im->h * sizeof(RGBA)); if(!image) { i = SQE_R_NOMEMORY; errorjmp(jmp, i); } for(int pass = 0;pass < im->passes;pass++) { lr->codec->read_next_pass(); for(j = 0;j < im->h;j++) { scan = image + j * im->w; i = lr->codec->read_scanline(scan); errors += (int)(i != SQE_OK); } } if(im->needflip) fmt_utils::flipv((char *)image, im->w * sizeof(RGBA), im->h); convert->fillWriteOptions(&opt, lw->opt); opt.alpha = im->hasalpha; current++; } lr->codec->read_close(); } else { emit convertText(SQ_ErrorString::instance()->stringSN(SQE_R_NOTSUPPORTED), true); emit oneFileProcessed(); } } if(image) { free(image); image = 0; } delete convert; delete tempfile; if(imageopt.close && !gerrors) emit done(true); else emit done(false); } int SQ_Converter::manipAndWriteDecodedImage(const TQString &name, fmt_image *im) { int passes = opt.interlaced ? lw->opt.passes : 1; int s, j, err; RGBA *scan = 0; scan = new RGBA [im->w]; if(!scan) return SQE_W_NOMEMORY; err = lw->codec->write_init(name.ascii(), *im, opt); if(err != SQE_OK) goto error_exit; err = lw->codec->write_next(); if(err != SQE_OK) goto error_exit; for(s = 0;s < passes;s++) { err = lw->codec->write_next_pass(); if(err != SQE_OK) goto error_exit; for(j = 0;j < im->h;j++) { if(lw->opt.needflip) determineNextScan(*im, scan, im->h-j-1); else determineNextScan(*im, scan, j); err = lw->codec->write_scanline(scan); if(err != SQE_OK) goto error_exit; } } err = SQE_OK; error_exit: lw->codec->write_close(); delete scan; return err; } int SQ_Converter::copyFile(const TQString &src, const TQString &dst) const { TQFile f_src(src), f_dst(dst); TQ_LONG read; char data[4096]; if(!f_src.open(IO_ReadOnly)) return SQE_R_NOFILE; if(!f_dst.open(IO_WriteOnly)) { f_src.close(); return SQE_W_NOFILE; } while(!f_src.atEnd()) { read = f_src.readBlock(data, sizeof(data)); f_dst.writeBlock(data, read); if(f_dst.status() != IO_Ok || f_src.status() != IO_Ok) { f_src.close(); f_dst.close(); return SQE_W_ERROR; } } f_src.close(); f_dst.close(); return SQE_OK; } void SQ_Converter::determineNextScan(const fmt_image &im, RGBA *scan, int y) { memcpy(scan, image + y * im.w, im.w * sizeof(RGBA)); } void SQ_Converter::startEditPrivate() { convert = new SQ_ImageConvert(KSquirrel::app()); convert->setCaption(i18n("Convert 1 file", "Convert %n files", files.count())); connect(convert, TQT_SIGNAL(convert(SQ_ImageOptions*, SQ_ImageConvertOptions*)), this, TQT_SLOT(slotStartConvert(SQ_ImageOptions*, SQ_ImageConvertOptions*))); connect(this, TQT_SIGNAL(convertText(const TQString &, bool)), convert, TQT_SLOT(slotDebugText(const TQString &, bool))); connect(this, TQT_SIGNAL(oneFileProcessed()), convert, TQT_SLOT(slotOneProcessed())); connect(this, TQT_SIGNAL(done(bool)), convert, TQT_SLOT(slotDone(bool))); convert->exec(); } void SQ_Converter::slotStartConvert(SQ_ImageOptions *o, SQ_ImageConvertOptions *copt) { imageopt = *o; convopt = *copt; decodingCycle(); } #include "sq_converter.moc"