// TnzQt includes #include "toonzqt/menubarcommand.h" #include "toonzqt/viewcommandids.h" #include "toonzqt/imageutils.h" #include "toonzqt/dvdialog.h" #include "toonzqt/gutil.h" // TnzLib includes #include "toonz/preferences.h" #include "toonz/namebuilder.h" #include "toonz/toonzscene.h" #include "toonz/tproject.h" #include "toonz/Naa2TlvConverter.h" #ifdef _WIN32 #include "avicodecrestrictions.h" #endif // TnzCore includes #include "tsystem.h" #include "tfilepath_io.h" #include "timage_io.h" #include "tlevel.h" #include "tlevel_io.h" #include "tpalette.h" #include "tropcm.h" #include "trasterimage.h" #include "tvectorrenderdata.h" #include "tofflinegl.h" #include "tconvert.h" #include "trop.h" #include "timageinfo.h" #include "tfiletype.h" #include "tfilepath.h" #include "ttoonzimage.h" #include "trasterimage.h" #include "tvectorimage.h" #include "tstroke.h" // TnzQt includes #include // boost includes #include //********************************************************************************** // Local namespace stuff //********************************************************************************** namespace { void addOverlappedRegions(TRegion *reg, vector ®Inf) { regInf.push_back(TFilledRegionInf(reg->getId(), reg->getStyle())); UINT regNum = reg->getSubregionCount(); for (UINT i = 0; i < regNum; i++) addOverlappedRegions(reg->getSubregion(i), regInf); } //-------------------------------------------------------------------- void addRegionsInArea(TRegion *reg, vector ®s, const TRectD &area) { if (area.contains(reg->getBBox())) regs.push_back(TFilledRegionInf(reg->getId(), reg->getStyle())); if (reg->getBBox().overlaps(area)) { UINT regNum = reg->getSubregionCount(); for (UINT i = 0; i < regNum; i++) addRegionsInArea(reg->getSubregion(i), regs, area); } } //-------------------------------------------------------------------- void getFrameIds(TFrameId from, TFrameId to, const TLevelP &level, std::vector &frames) { struct locals { static inline TFrameId getFrame(const TLevel::Table::value_type &pair) { return pair.first; } }; // locals if (from.isEmptyFrame()) from = TFrameId(-(std::numeric_limits::max)()); if (to.isEmptyFrame()) to = TFrameId((std::numeric_limits::max)()); if (from > to) tswap(from, to); const TLevel::Table &table = *level->getTable(); TLevel::Table::const_iterator lBegin = table.lower_bound(from), lEnd = table.upper_bound(to); assert(frames.empty()); frames.insert(frames.end(), boost::make_transform_iterator(lBegin, locals::getFrame), boost::make_transform_iterator(lEnd, locals::getFrame)); } } // namespace //********************************************************************************** // ImageUtils namespace stuff //********************************************************************************** namespace ImageUtils { // todo: spostare da qualche altra parte. rendere accessibile a tutti. utilizzare // anche nella libreria dovunque si usi direttamente "_files" TFilePath getResourceFolder(const TFilePath &scenePath) { return scenePath.getParentDir() + (scenePath.getName() + "_files"); } //----------------------------------------------------------------------------- void copyScene(const TFilePath &dst, const TFilePath &src) { TSystem::copyFile(dst, src); if (TProjectManager::instance()->isTabModeEnabled()) TSystem::copyDir(getResourceFolder(dst), getResourceFolder(src)); TFilePath srcIcon = ToonzScene::getIconPath(src); if (TFileStatus(srcIcon).doesExist()) { TFilePath dstIcon = ToonzScene::getIconPath(dst); TSystem::copyFile(dstIcon, srcIcon); } } //----------------------------------------------------------------------------- TFilePath duplicate(const TFilePath &levelPath) { if (levelPath == TFilePath()) return TFilePath(); if (!TSystem::doesExistFileOrLevel(levelPath)) { MsgBox(WARNING, QObject::tr("It is not possible to find the %1 level.").arg(QString::fromStdWString(levelPath.getWideString()))); return TFilePath(); } NameBuilder *nameBuilder = NameBuilder::getBuilder(toWideString(levelPath.getName())); wstring levelNameOut; do levelNameOut = nameBuilder->getNext(); while (TSystem::doesExistFileOrLevel(levelPath.withName(levelNameOut))); TFilePath levelPathOut = levelPath.withName(levelNameOut); try { if (levelPath.getType() == "tnz") copyScene(levelPathOut, levelPath); else { TSystem::copyFileOrLevel_throw(levelPathOut, levelPath); if (levelPath.getType() == "tlv") { TFilePath pltPath = levelPath.withType("tpl"); if (TSystem::doesExistFileOrLevel(pltPath)) TSystem::copyFileOrLevel_throw(levelPathOut.withType("tpl"), pltPath); } } } catch (...) { QString msg = QObject::tr("There was an error copying %1").arg(toQString(levelPath)); MsgBox(CRITICAL, msg); return TFilePath(); } // QString msg = QString("Copied ") + // QString::fromStdWString(levelPath.withoutParentDir().getWideString()) + // QString(" to " + // QString::fromStdWString(levelPathOut.withoutParentDir().getWideString())); // MsgBox(INFORMATION,msg); return levelPathOut; } //----------------------------------------------------------------------------- void premultiply(const TFilePath &levelPath) { if (levelPath == TFilePath()) return; if (!TSystem::doesExistFileOrLevel(levelPath)) { MsgBox(WARNING, QObject::tr("It is not possible to find the level %1").arg(QString::fromStdWString(levelPath.getWideString()))); return; } TFileType::Type type = TFileType::getInfo(levelPath); if (type == TFileType::CMAPPED_LEVEL) { MsgBox(WARNING, QObject::tr("Cannot premultiply the selected file.")); return; } if (type == TFileType::VECTOR_LEVEL || type == TFileType::VECTOR_IMAGE) { MsgBox(WARNING, QObject::tr("Cannot premultiply a vector-based level.")); return; } if (type != TFileType::RASTER_LEVEL && type != TFileType::RASTER_IMAGE) { MsgBox(INFORMATION, QObject::tr("Cannot premultiply the selected file.")); return; } try { TLevelReaderP lr = TLevelReaderP(levelPath); if (!lr) return; TLevelP level = lr->loadInfo(); if (!level || level->getFrameCount() == 0) return; bool isMovie = type == TFileType::RASTER_LEVEL; /* if (!isMovie && lr->getImageInfo()->m_samplePerPixel!=4) { QMessageBox::information(0, QString("ERROR"), QString("Only rgbm images can be premultiplied!")); return; } */ TLevelWriterP lw; if (!isMovie) { lw = TLevelWriterP(levelPath); if (!lw) return; } qApp->setOverrideCursor(QCursor(Qt::WaitCursor)); qApp->processEvents(); int count = 0; TLevel::Iterator it = level->begin(); for (; it != level->end(); ++it) { TImageReaderP ir = lr->getFrameReader(it->first); TRasterImageP rimg = (TRasterImageP)ir->load(); if (!rimg) continue; TRop::premultiply(rimg->getRaster()); ir = 0; if (isMovie) level->setFrame(it->first, rimg); else { TImageWriterP iw = lw->getFrameWriter(it->first); iw->save(levelPath.withFrame(it->first), rimg); iw = 0; } } lr = TLevelReaderP(); if (isMovie) { TSystem::deleteFile(levelPath); lw = TLevelWriterP(levelPath); if (!lw) { QApplication::restoreOverrideCursor(); return; } lw->save(level); } } catch (...) { MsgBox(WARNING, QObject::tr("Cannot premultiply the selected file.")); QApplication::restoreOverrideCursor(); return; } QApplication::restoreOverrideCursor(); QString msg = QObject::tr("Level %1 premultiplied.").arg(QString::fromStdString(levelPath.getLevelName())); MsgBox(INFORMATION, msg); } //----------------------------------------------------------------------------- void getFillingInformationOverlappingArea( const TVectorImageP &vi, vector ®Inf, const TRectD &area1, const TRectD &area2) { if (!vi->isComputedRegionAlmostOnce()) return; assert(area1 != TRectD() || area2 != TRectD()); vi->findRegions(); UINT regNum = vi->getRegionCount(); TRegion *reg; for (UINT i = 0; i < regNum; i++) { reg = vi->getRegion(i); if (reg->getBBox().overlaps(area1) || reg->getBBox().overlaps(area2)) addOverlappedRegions(reg, regInf); } } //----------------------------------------------------------------------------- void getFillingInformationInArea( const TVectorImageP &vi, vector ®s, const TRectD &area) { if (!vi->isComputedRegionAlmostOnce()) return; vi->findRegions(); UINT regNum = vi->getRegionCount(); for (UINT i = 0; i < regNum; i++) addRegionsInArea(vi->getRegion(i), regs, area); } //-------------------------------------------------------------------- void assignFillingInformation( TVectorImage &vi, const std::vector ®s) { vi.findRegions(); UINT r, rCount = UINT(regs.size()); for (r = 0; r != rCount; ++r) { const TFilledRegionInf &rInfo = regs[r]; if (TRegion *region = vi.getRegion(rInfo.m_regionId)) region->setStyle(rInfo.m_styleId); } } //-------------------------------------------------------------------- void getStrokeStyleInformationInArea( const TVectorImageP &vi, vector> &strokesInfo, const TRectD &area) { if (!vi->isComputedRegionAlmostOnce()) return; vi->findRegions(); UINT regNum = vi->getStrokeCount(); for (UINT i = 0; i < vi->getStrokeCount(); i++) { if (!vi->inCurrentGroup(i)) continue; if (area.contains(vi->getStroke(i)->getBBox())) strokesInfo.push_back(pair(i, vi->getStroke(i)->getStyle())); } } //-------------------------------------------------------------------- void convertFromCM(const TLevelReaderP &lr, const TPaletteP &plt, const TLevelWriterP &lw, const vector &frames, const TAffine &aff, const TRop::ResampleFilterType &resType, FrameTaskNotifier *frameNotifier, const TPixel &bgColor, bool removeDotBeforeFrameNumber = false) { for (int i = 0; i < (int)frames.size(); i++) { if (frameNotifier->abortTask()) break; try { TImageReaderP ir = lr->getFrameReader(frames[i]); TImageP img = ir->load(); TToonzImageP toonzImage(img); double xdpi, ydpi; toonzImage->getDpi(xdpi, ydpi); assert(toonzImage); if (toonzImage) { TRasterCM32P rasCMImage = toonzImage->getRaster(); TRaster32P ras(convert(aff * convert(rasCMImage->getBounds())).getSize()); if (!aff.isIdentity()) TRop::resample(ras, rasCMImage, plt, aff, resType); else TRop::convert(ras, rasCMImage, plt); if (bgColor != TPixel::Transparent) TRop::addBackground(ras, bgColor); TRasterImageP rasImage(ras); rasImage->setDpi(xdpi, ydpi); /*--- ConvertPopup での指定に合わせて、[レベル名].[フレーム番号].[拡張子] のうち、[レベル名]と[フレーム番号]の間のドットを消す。 例:A.0001.tga → A0001.tga になる。 ---*/ if (removeDotBeforeFrameNumber) { TFilePath outPath = lw->getFilePath().withFrame(frames[i]); /*--- フレーム番号と拡張子の文字数の合計。大抵8 ---*/ int index = 4 + 1 + outPath.getType().length(); wstring renamedStr = outPath.getWideString(); if (renamedStr[renamedStr.length() - index - 1] == L'.') renamedStr = renamedStr.substr(0, renamedStr.length() - index - 1) + renamedStr.substr(renamedStr.length() - index, index); const TFilePath fp(renamedStr); TImageWriterP writer(fp); writer->setProperties(lw->getProperties()); writer->save(rasImage); } else { TImageWriterP iw = lw->getFrameWriter(frames[i]); iw->save(rasImage); } } } catch (...) { //QString msg=QObject::tr("Frame %1 : conversion failed!").arg(QString::number(i+1)); // MsgBox(INFORMATION,msg); } /*-- これはプログレスバーを進めるものなので、動画番号ではなく、完了したフレームの枚数を投げる --*/ frameNotifier->notifyFrameCompleted(100 * (i + 1) / frames.size()); } } //-------------------------------------------------------------------- void convertFromVI(const TLevelReaderP &lr, const TPaletteP &plt, const TLevelWriterP &lw, const vector &frames, const TRop::ResampleFilterType &resType, int width, FrameTaskNotifier *frameNotifier) { QString msg; int i; vector images; TRectD maxBbox; for (i = 0; i < (int)frames.size(); i++) { //trovo la bbox che possa contenere tutte le immagini try { TImageReaderP ir = lr->getFrameReader(frames[i]); TVectorImageP img = ir->load(); images.push_back(img); maxBbox += img->getBBox(); } catch (...) { msg = QObject::tr("Frame %1 : conversion failed!").arg(QString::fromStdString(frames[i].expand())); MsgBox(INFORMATION, msg); ; } } maxBbox = maxBbox.enlarge(2); TAffine aff; if (width) //calcolo l'affine aff = TScale((double)width / maxBbox.getLx()); maxBbox = aff * maxBbox; for (i = 0; i < (int)images.size(); i++) { if (frameNotifier->abortTask()) break; try { TVectorImageP vectorImage = images[i]; assert(vectorImage); if (vectorImage) { //faccio il render dell'immagine vectorImage->transform(aff, true); const TVectorRenderData rd(TTranslation(-maxBbox.getP00()), TRect(), plt.getPointer(), 0, true, true); TOfflineGL *glContext = new TOfflineGL(convert(maxBbox).getSize()); glContext->clear(TPixel32::Transparent); glContext->draw(vectorImage, rd); TRaster32P rasImage = (glContext->getRaster()); TImageWriterP iw = lw->getFrameWriter(TFrameId(i + 1)); iw->save(TRasterImageP(rasImage)); } } catch (...) { msg = QObject::tr("Frame %1 : conversion failed!").arg(QString::fromStdString(frames[i].expand())); MsgBox(INFORMATION, msg); } frameNotifier->notifyFrameCompleted(100 * (i + 1) / frames.size()); } } //----------------------------------------------------------------------- void convertFromFullRaster(const TLevelReaderP &lr, const TLevelWriterP &lw, const vector &_frames, const TAffine &aff, const TRop::ResampleFilterType &resType, FrameTaskNotifier *frameNotifier, const TPixel &bgColor, bool removeDotBeforeFrameNumber = false) { vector frames = _frames; if (frames.empty() && lr->loadInfo()->getFrameCount() == 1) //e' una immagine singola, non un livello frames.push_back(TFrameId()); for (int i = 0; i < (int)frames.size(); i++) { if (frameNotifier->abortTask()) break; try { TRasterImageP img; if (frames[i] == TFrameId()) //immagine singola, non livello { assert(frames.size() == 1); TImageP _img; if (!TImageReader::load(lr->getFilePath(), _img)) continue; img = _img; } else { TImageReaderP ir = lr->getFrameReader(frames[i]); img = ir->load(); } TRaster32P raster(convert(aff * img->getBBox()).getSize()); if (!aff.isIdentity()) TRop::resample(raster, img->getRaster(), aff, resType); else { if ((TRaster32P)img->getRaster()) raster = img->getRaster(); else TRop::convert(raster, img->getRaster()); } if (bgColor != TPixel::Transparent) TRop::addBackground(raster, bgColor); TRasterImageP newImg(raster); double xDpi, yDpi; img->getDpi(xDpi, yDpi); if (xDpi == 0 && yDpi == 0) xDpi = yDpi = Preferences::instance()->getDefLevelDpi(); newImg->setDpi(xDpi, yDpi); if (frames[i] == TFrameId()) TImageWriter::save(lw->getFilePath(), newImg); else { /*--- ConvertPopup での指定に合わせて、[レベル名].[フレーム番号].[拡張子] のうち、[レベル名]と[フレーム番号]の間のドットを消す。 例:A.0001.tga → A0001.tga になる。 ---*/ if (removeDotBeforeFrameNumber) { TFilePath outPath = lw->getFilePath().withFrame(frames[i]); /*--- フレーム番号と拡張子の文字数の合計。大抵8 ---*/ int index = 4 + 1 + outPath.getType().length(); wstring renamedStr = outPath.getWideString(); if (renamedStr[renamedStr.length() - index - 1] == L'.') renamedStr = renamedStr.substr(0, renamedStr.length() - index - 1) + renamedStr.substr(renamedStr.length() - index, index); const TFilePath fp(renamedStr); TImageWriterP writer(fp); writer->setProperties(lw->getProperties()); writer->save(newImg); } else { TImageWriterP iw = lw->getFrameWriter(frames[i]); iw->save(newImg); } } } catch (...) { //QString msg=QObject::tr("Frame %1 : conversion failed!").arg(QString::number(i+1)); //MsgBox(INFORMATION,msg); } /*-- これはプログレスバーを進めるものなので、動画番号ではなく、完了したフレームの枚数を投げる --*/ frameNotifier->notifyFrameCompleted(100 * (i + 1) / frames.size()); } } //----------------------------------------------------------------------- void convertFromVector(const TLevelReaderP &lr, const TLevelWriterP &lw, const vector &_frames, FrameTaskNotifier *frameNotifier) { vector frames = _frames; TLevelP lv = lr->loadInfo(); if (frames.empty() && lv->getFrameCount() == 1) //e' una immagine singola, non un livello frames.push_back(TFrameId()); for (int i = 0; i < (int)frames.size(); i++) { if (frameNotifier->abortTask()) break; try { TVectorImageP img; if (frames[i] == TFrameId()) //immagine singola, non livello { assert(frames.size() == 1); TImageP _img; if (!TImageReader::load(lr->getFilePath(), _img)) continue; img = _img; } else { TImageReaderP ir = lr->getFrameReader(frames[i]); img = ir->load(); } img->setPalette(lv->getPalette()); if (frames[i] == TFrameId()) TImageWriter::save(lw->getFilePath(), img); else { TImageWriterP iw = lw->getFrameWriter(frames[i]); iw->save(img); } } catch (...) { //QString msg=QObject::tr("Frame %1 : conversion failed!").arg(QString::number(i+1)); //MsgBox(INFORMATION,msg); } frameNotifier->notifyFrameCompleted(100 * (i + 1) / frames.size()); } } //----------------------------------------------------------------------- void convert(const TFilePath &source, const TFilePath &dest, const TFrameId &from, const TFrameId &to, double framerate, TPropertyGroup *prop, FrameTaskNotifier *frameNotifier, const TPixel &bgColor, bool removeDotBeforeFrameNumber) { std::string dstExt = dest.getType(), srcExt = source.getType(); // Load source level structure TLevelReaderP lr(source); TLevelP level = lr->loadInfo(); #ifdef _WIN32 if (dstExt == "avi") { TDimension res(0, 0); const TImageInfo *info = lr->getImageInfo(level->begin()->first); res.lx = info->m_lx; res.ly = info->m_ly; string codecName = prop->getProperty(0)->getValueAsString(); if (!AviCodecRestrictions::canWriteMovie(toWideString(codecName), res)) { return; //QString msg=QObject::tr("The image resolution does not fit the chosen output file format."); //MsgBox(WARNING,msg); } } #endif; // Get the frames available in level inside the [from, to] range std::vector frames; getFrameIds(from, to, level, frames); // Write the destination level TLevelWriterP lw(dest, prop); lw->setFrameRate(framerate); if (srcExt == "tlv") convertFromCM(lr, level->getPalette(), lw, frames, TAffine(), TRop::Triangle, frameNotifier, bgColor, removeDotBeforeFrameNumber); else if (srcExt == "pli") //assert(!"Conversion from pli files is currently diabled"); convertFromVector(lr, lw, frames, frameNotifier); else convertFromFullRaster(lr, lw, frames, TAffine(), TRop::Triangle, frameNotifier, bgColor, removeDotBeforeFrameNumber); } //============================================================================= void convertNaa2Tlv( const TFilePath &source, const TFilePath &dest, const TFrameId &from, const TFrameId &to, FrameTaskNotifier *frameNotifier, TPalette *palette) { std::string dstExt = dest.getType(), srcExt = source.getType(); // Load source level structure TLevelReaderP lr(source); TLevelP level = lr->loadInfo(); // Get the frames available in level inside the [from, to] range vector frames; getFrameIds(from, to, level, frames); if (frames.empty()) return; // Write the destination level TLevelWriterP lw; // Initialized just before a sure write Naa2TlvConverter converter; converter.setPalette(palette); int f, fCount = int(frames.size()); for (f = 0; f != fCount; ++f) { if (frameNotifier->abortTask()) break; try { TImageReaderP ir = lr->getFrameReader(frames[f]); TImageP img = ir->load(); if (!img) continue; TRasterImageP ri = img; if (!ri) continue; TRaster32P raster = ri->getRaster(); // Converts only 32-bit images, it seems... if (!raster) // continue; // converter.process(raster); if (TToonzImageP dstImg = converter.makeTlv(false)) // Opaque synthetic inks { if (converter.getPalette() == 0) converter.setPalette(dstImg->getPalette()); if (!lw) // Initialize output file only on a sure write lw = TLevelWriterP(dest); // TImageWriterP iw = lw->getFrameWriter(frames[f]); iw->save(dstImg); } else { MsgBox(DVGui::WARNING, QObject::tr( "The source image seems not suitable for this kind of conversion")); frameNotifier->notifyError(); } } catch (...) { } frameNotifier->notifyFrameCompleted(100 * (f + 1) / frames.size()); } } //============================================================================= #define ZOOMLEVELS 13 #define NOZOOMINDEX 6 double ZoomFactors[ZOOMLEVELS] = {0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64}; double getQuantizedZoomFactor(double zf, bool forward) { if (forward && (zf > ZoomFactors[ZOOMLEVELS - 1] || areAlmostEqual(zf, ZoomFactors[ZOOMLEVELS - 1], 1e-5))) return zf; else if (!forward && (zf < ZoomFactors[0] || areAlmostEqual(zf, ZoomFactors[0], 1e-5))) return zf; assert((!forward && zf > ZoomFactors[0]) || (forward && zf < ZoomFactors[ZOOMLEVELS - 1])); int i = 0; for (i = 0; i <= ZOOMLEVELS - 1; i++) if (areAlmostEqual(zf, ZoomFactors[i], 1e-5)) zf = ZoomFactors[i]; if (forward && zf < ZoomFactors[0]) return ZoomFactors[0]; else if (!forward && zf > ZoomFactors[ZOOMLEVELS - 1]) return ZoomFactors[ZOOMLEVELS - 1]; for (i = 0; i < ZOOMLEVELS - 1; i++) if (ZoomFactors[i + 1] - zf >= 0 && zf - ZoomFactors[i] >= 0) { if (forward && ZoomFactors[i + 1] == zf) return ZoomFactors[i + 2]; else if (!forward && ZoomFactors[i] == zf) return ZoomFactors[i - 1]; else return forward ? ZoomFactors[i + 1] : ZoomFactors[i]; } return ZoomFactors[NOZOOMINDEX]; } } // namespace ImageUtils namespace { void getViewerShortcuts(int &zoomIn, int &zoomOut, int &zoomReset, int &zoomFit, int &showHideFullScreen, int &actualPixelSize) { CommandManager *cManager = CommandManager::instance(); zoomIn = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomIn)); zoomOut = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomOut)); zoomReset = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomReset)); zoomFit = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ZoomFit)); showHideFullScreen = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ShowHideFullScreen)); actualPixelSize = cManager->getKeyFromShortcut(cManager->getShortcutFromId(V_ActualPixelSize)); } } //namespace //-------------------------------------------------------------------------- namespace ImageUtils { ShortcutZoomer::ShortcutZoomer(QWidget *zoomingWidget) : m_widget(zoomingWidget) { } //-------------------------------------------------------------------------- bool ShortcutZoomer::exec(QKeyEvent *event) { int zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, showHideFullScreenKey, actualPixelSize; getViewerShortcuts(zoomInKey, zoomOutKey, zoomResetKey, zoomFitKey, showHideFullScreenKey, actualPixelSize); int key = event->key(); if (key == Qt::Key_Control || key == Qt::Key_Shift || key == Qt::Key_Alt) return false; key = key | event->modifiers() & (~0xf0000000); // Ignore if the key is a numpad key return (key == showHideFullScreenKey) ? toggleFullScreen() : (key == Qt::Key_Escape) ? toggleFullScreen(true) : (key == actualPixelSize) ? setActualPixelSize() : (key == zoomFitKey) ? fit() : (key == zoomInKey || key == zoomOutKey || key == zoomResetKey) ? zoom(key == zoomInKey, key == zoomResetKey) : false; } //********************************************************************************************* // FullScreenWidget implementation //********************************************************************************************* FullScreenWidget::FullScreenWidget(QWidget *parent) : QWidget(parent) { QHBoxLayout *layout = new QHBoxLayout(this); layout->setMargin(0); layout->setSpacing(0); setLayout(layout); } //--------------------------------------------------------------------------------- void FullScreenWidget::setWidget(QWidget *widget) { QLayout *layout = this->layout(); delete layout->takeAt(0); if (m_widget = widget) layout->addWidget(m_widget); } //--------------------------------------------------------------------------------- bool FullScreenWidget::toggleFullScreen(bool quit) { if (windowState() & Qt::WindowFullScreen) { hide(); setWindowFlags(windowFlags() & ~(Qt::Window | Qt::WindowStaysOnTopHint)); showNormal(); setContentsMargins(0, 0, 0, 0); // ... m_widget->setFocus(); return true; } else if (!quit) { setContentsMargins(0, 0, 1, 1); // QTBUG #7556 setWindowFlags(windowFlags() | Qt::Window | Qt::WindowStaysOnTopHint); showFullScreen(); return true; } return false; } } //imageutils