00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <qapplication.h>
00024 #include <qdom.h>
00025 #include <qimage.h>
00026 #include <qpainter.h>
00027 #include <qtl.h>
00028 #include <qstringlist.h>
00029 #include <qwidget.h>
00030 #include <qpaintdevicemetrics.h>
00031
00032
00033 #include <dcopobject.h>
00034 #include <kapplication.h>
00035 #include <kcommand.h>
00036 #include <kdebug.h>
00037 #include <kimageio.h>
00038 #include <kfiledialog.h>
00039 #include <kglobal.h>
00040 #include <kmimetype.h>
00041 #include <knotifyclient.h>
00042 #include <klocale.h>
00043 #include <kmessagebox.h>
00044
00045
00046 #include <KoFilterManager.h>
00047 #include <KoMainWindow.h>
00048 #include <KoQueryTrader.h>
00049 #include <KoStore.h>
00050 #include <KoStoreDevice.h>
00051 #include <KoTemplateChooseDia.h>
00052 #include <KoApplication.h>
00053 #include <KoCommandHistory.h>
00054
00055
00056 #include <kis_clipboard.h>
00057 #include <kis_meta_registry.h>
00058 #include "kis_annotation.h"
00059 #include "kis_types.h"
00060 #include "kis_config.h"
00061 #include "kis_debug_areas.h"
00062 #include "kis_doc.h"
00063 #include "kis_factory.h"
00064 #include "kis_image.h"
00065 #include "kis_layer.h"
00066 #include "kis_paint_layer.h"
00067 #include "kis_nameserver.h"
00068 #include "kis_painter.h"
00069 #include "kis_selection.h"
00070 #include "kis_fill_painter.h"
00071 #include "kis_command.h"
00072 #include "kis_view.h"
00073 #include "kis_colorspace.h"
00074 #include "kis_colorspace_factory_registry.h"
00075 #include "kis_profile.h"
00076 #include "kis_id.h"
00077 #include "kis_part_layer.h"
00078 #include "kis_doc_iface.h"
00079 #include "kis_paint_device_action.h"
00080 #include "kis_custom_image_widget.h"
00081 #include "kis_load_visitor.h"
00082 #include "kis_save_visitor.h"
00083 #include "kis_savexml_visitor.h"
00084
00085 static const char *CURRENT_DTD_VERSION = "1.3";
00086
00092 #define APP_MIMETYPE "application/x-krita"
00093
00097 #define NATIVE_MIMETYPE "application/x-kra"
00098
00099 namespace {
00100 class KisCommandImageMv : public KisCommand {
00101 typedef KisCommand super;
00102
00103 public:
00104 KisCommandImageMv(KisDoc *doc,
00105 KisUndoAdapter *adapter,
00106 const QString& name,
00107 const QString& oldName) : super(i18n("Rename Image"), adapter)
00108 {
00109 m_doc = doc;
00110 m_name = name;
00111 m_oldName = oldName;
00112 }
00113
00114 virtual ~KisCommandImageMv()
00115 {
00116 }
00117
00118 virtual void execute()
00119 {
00120 adapter()->setUndo(false);
00121 m_doc->renameImage(m_oldName, m_name);
00122 adapter()->setUndo(true);
00123 }
00124
00125 virtual void unexecute()
00126 {
00127 adapter()->setUndo(false);
00128 m_doc->renameImage(m_name, m_oldName);
00129 adapter()->setUndo(true);
00130 }
00131
00132 private:
00133 KisDoc *m_doc;
00134 QString m_name;
00135 QString m_oldName;
00136 };
00137
00138 }
00139
00140 KisDoc::KisDoc(QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name, bool singleViewMode) :
00141 super(parentWidget, widgetName, parent, name, singleViewMode)
00142 {
00143
00144 m_undo = false;
00145 m_dcop = 0;
00146 m_cmdHistory = 0;
00147 m_nserver = 0;
00148 m_currentImage = 0;
00149 m_currentMacro = 0;
00150 m_macroNestDepth = 0;
00151 m_ioProgressBase = 0;
00152 m_ioProgressTotalSteps = 0;
00153
00154 setInstance( KisFactory::instance(), false );
00155 setTemplateType( "krita_template" );
00156
00157 init();
00158
00159 if (name)
00160 dcopObject();
00161 }
00162
00163 KisDoc::~KisDoc()
00164 {
00165 delete m_cmdHistory;
00166 delete m_nserver;
00167 m_undoListeners.setAutoDelete(false);
00168 delete m_dcop;
00169 }
00170
00171 QCString KisDoc::mimeType() const
00172 {
00173 return APP_MIMETYPE;
00174 }
00175
00176 DCOPObject *KisDoc::dcopObject()
00177 {
00178 if (!m_dcop) {
00179 m_dcop = new KisDocIface(this);
00180 Q_CHECK_PTR(m_dcop);
00181 }
00182 return m_dcop;
00183 }
00184
00185 bool KisDoc::initDoc(InitDocFlags flags, QWidget* parentWidget)
00186 {
00187 if (!init())
00188 return false;
00189
00190 bool ok = false;
00191
00192 QString file;
00193 KoTemplateChooseDia::DialogType dlgtype;
00194
00195 if (flags != KoDocument::InitDocFileNew) {
00196 dlgtype = KoTemplateChooseDia::Everything;
00197 } else {
00198 dlgtype = KoTemplateChooseDia::OnlyTemplates;
00199 }
00200
00201 KoTemplateChooseDia::ReturnType ret =
00202 KoTemplateChooseDia::choose(KisFactory::instance(),
00203 file,
00204 dlgtype,
00205 "krita_template",
00206 parentWidget);
00207 setUndo(false);
00208
00209 if (ret == KoTemplateChooseDia::Template) {
00210 resetURL();
00211 ok = loadNativeFormat( file );
00212 setEmpty();
00213 ok = true;
00214
00215 } else if (ret == KoTemplateChooseDia::File) {
00216 KURL url( file );
00217 ok = openURL(url);
00218 } else if (ret == KoTemplateChooseDia::Empty) {
00219 setEmpty();
00220 ok = true;
00221 }
00222
00223 setModified(false);
00224 KisConfig cfg;
00225 setUndo(cfg.undoEnabled());
00226
00227 return ok;
00228 }
00229
00230 void KisDoc::openExistingFile(const QString& file)
00231 {
00232 setUndo(false);
00233
00234 KoDocument::openExistingFile(file);
00235
00236 setUndo(true);
00237 }
00238
00239 void KisDoc::openTemplate(const QString& file)
00240 {
00241 setUndo(false);
00242
00243 KoDocument::openTemplate(file);
00244
00245 setUndo(true);
00246 }
00247
00248 bool KisDoc::init()
00249 {
00250 if (m_cmdHistory) {
00251 delete m_cmdHistory;
00252 m_cmdHistory = 0;
00253 }
00254
00255 if (m_nserver) {
00256 delete m_nserver;
00257 m_nserver = 0;
00258 }
00259
00260 m_cmdHistory = new KoCommandHistory(actionCollection(), true);
00261 Q_CHECK_PTR(m_cmdHistory);
00262
00263 connect(m_cmdHistory, SIGNAL(documentRestored()), this, SLOT(slotDocumentRestored()));
00264 connect(m_cmdHistory, SIGNAL(commandExecuted(KCommand *)), this, SLOT(slotCommandExecuted(KCommand *)));
00265 setUndo(true);
00266
00267 m_nserver = new KisNameServer(i18n("Image %1"), 1);
00268 Q_CHECK_PTR(m_nserver);
00269
00270 if (!KisMetaRegistry::instance()->csRegistry()->exists(KisID("RGBA",""))) {
00271 KMessageBox::sorry(0, i18n("No colorspace modules loaded: cannot run Krita"));
00272 return false;
00273 }
00274
00275 m_undoListeners.setAutoDelete(false);
00276
00277 return true;
00278 }
00279
00280 QDomDocument KisDoc::saveXML()
00281 {
00282 QDomDocument doc = createDomDocument("DOC", CURRENT_DTD_VERSION);
00283 QDomElement root = doc.documentElement();
00284
00285 root.setAttribute("editor", "Krita");
00286 root.setAttribute("depth", sizeof(Q_UINT8));
00287 root.setAttribute("syntaxVersion", "1");
00288
00289 root.appendChild(saveImage(doc, m_currentImage));
00290
00291 return doc;
00292 }
00293
00294 bool KisDoc::loadOasis( const QDomDocument&, KoOasisStyles&, const QDomDocument&, KoStore* )
00295 {
00296
00297 return false;
00298 }
00299
00300
00301 bool KisDoc::saveOasis( KoStore*, KoXmlWriter* )
00302 {
00303
00304 return false;
00305 }
00306
00307 bool KisDoc::loadXML(QIODevice *, const QDomDocument& doc)
00308 {
00309 QDomElement root;
00310 QString attr;
00311 QDomNode node;
00312 KisImageSP img;
00313
00314 if (!init())
00315 return false;
00316 if (doc.doctype().name() != "DOC")
00317 return false;
00318 root = doc.documentElement();
00319 attr = root.attribute("syntaxVersion");
00320 if (attr.toInt() > 1)
00321 return false;
00322 if ((attr = root.attribute("depth")).isNull())
00323 return false;
00324 m_conversionDepth = attr.toInt();
00325
00326 if (!root.hasChildNodes()) {
00327 return false;
00328 }
00329
00330 setUndo(false);
00331
00332 for (node = root.firstChild(); !node.isNull(); node = node.nextSibling()) {
00333 if (node.isElement()) {
00334 if (node.nodeName() == "IMAGE") {
00335 QDomElement elem = node.toElement();
00336 if (!(img = loadImage(elem)))
00337 return false;
00338 m_currentImage = img;
00339 } else {
00340 return false;
00341 }
00342 }
00343 }
00344
00345 emit loadingFinished();
00346 return true;
00347 }
00348
00349 bool KisDoc::loadChildren(KoStore* store) {
00350 QPtrListIterator<KoDocumentChild> it(children());
00351 for( ; it.current(); ++it ) {
00352 if (!it.current()->loadDocument(store)) {
00353 return false;
00354 }
00355 }
00356 return true;
00357 }
00358
00359 QDomElement KisDoc::saveImage(QDomDocument& doc, KisImageSP img)
00360 {
00361 QDomElement image = doc.createElement("IMAGE");
00362
00363 Q_ASSERT(img);
00364 image.setAttribute("name", img->name());
00365 image.setAttribute("mime", "application/x-kra");
00366 image.setAttribute("width", img->width());
00367 image.setAttribute("height", img->height());
00368 image.setAttribute("colorspacename", img->colorSpace()->id().id());
00369 image.setAttribute("description", img->description());
00370
00371 if (img->getProfile() && img->getProfile()-> valid())
00372 image.setAttribute("profile", img->getProfile()->productName());
00373 image.setAttribute("x-res", img->xRes());
00374 image.setAttribute("y-res", img->yRes());
00375
00376 Q_UINT32 count=0;
00377 KisSaveXmlVisitor visitor(doc, image, count, true);
00378
00379 m_currentImage->rootLayer()->accept(visitor);
00380
00381 return image;
00382 }
00383
00384 KisImageSP KisDoc::loadImage(const QDomElement& element)
00385 {
00386
00387 KisConfig cfg;
00388 QString attr;
00389 QDomNode node;
00390 QDomNode child;
00391 KisImageSP img;
00392 QString name;
00393 Q_INT32 width;
00394 Q_INT32 height;
00395 QString description;
00396 QString profileProductName;
00397 double xres;
00398 double yres;
00399 QString colorspacename;
00400 KisColorSpace * cs;
00401
00402 if ((attr = element.attribute("mime")) == NATIVE_MIMETYPE) {
00403 if ((name = element.attribute("name")).isNull())
00404 return 0;
00405 if ((attr = element.attribute("width")).isNull())
00406 return 0;
00407 width = attr.toInt();
00408 if ((attr = element.attribute("height")).isNull())
00409 return 0;
00410 height = attr.toInt();
00411
00412 description = element.attribute("description");
00413
00414 if ((attr = element.attribute("x-res")).isNull())
00415 xres = 100.0;
00416 xres = attr.toDouble();
00417
00418 if ((attr = element.attribute("y-res")).isNull())
00419 yres = 100.0;
00420 yres = attr.toDouble();
00421
00422 if ((colorspacename = element.attribute("colorspacename")).isNull())
00423 {
00424
00425
00426
00427 colorspacename = "RGBA";
00428 }
00429
00430
00431 if (colorspacename == "Grayscale + Alpha")
00432 colorspacename = "GRAYA";
00433
00434 if ((profileProductName = element.attribute("profile")).isNull()) {
00435
00436 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename,"");
00437 }
00438 else {
00439 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename, profileProductName);
00440 }
00441
00442 if (cs == 0) {
00443 kdWarning(DBG_AREA_FILE) << "Could not open colorspace\n";
00444 return 0;
00445 }
00446
00447 img = new KisImage(this, width, height, cs, name);
00448 img->blockSignals(true);
00449 Q_CHECK_PTR(img);
00450 connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() ));
00451 img->setDescription(description);
00452 img->setResolution(xres, yres);
00453
00454 loadLayers(element, img, img->rootLayer().data());
00455
00456 }
00457
00458 img->notifyImageLoaded();
00459
00460 return img;
00461 }
00462
00463 void KisDoc::loadLayers(const QDomElement& element, KisImageSP img, KisGroupLayerSP parent)
00464 {
00465 QDomNode node = element.firstChild();
00466 QDomNode child;
00467
00468 if(!node.isNull())
00469 {
00470 if (node.isElement()) {
00471 if (node.nodeName() == "LAYERS") {
00472 for (child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
00473 KisLayerSP layer = loadLayer(child.toElement(), img);
00474
00475 if (!layer) {
00476 kdWarning(DBG_AREA_FILE) << "Could not load layer\n";
00477 }
00478 else {
00479 img->nextLayerName();
00480 img->addLayer(layer, parent, 0);
00481 }
00482 }
00483 }
00484 }
00485 }
00486 }
00487
00488 KisLayerSP KisDoc::loadLayer(const QDomElement& element, KisImageSP img)
00489 {
00490
00491
00492
00493
00494 QString attr;
00495 QString name;
00496 Q_INT32 x;
00497 Q_INT32 y;
00498 Q_INT32 opacity;
00499 bool visible;
00500 bool locked;
00501
00502 if ((name = element.attribute("name")).isNull())
00503 return 0;
00504
00505 if ((attr = element.attribute("x")).isNull())
00506 return 0;
00507 x = attr.toInt();
00508
00509 if ((attr = element.attribute("y")).isNull())
00510 return 0;
00511
00512 y = attr.toInt();
00513
00514 if ((attr = element.attribute("opacity")).isNull())
00515 return 0;
00516
00517 if ((opacity = attr.toInt()) < 0 || opacity > Q_UINT8_MAX)
00518 opacity = OPACITY_OPAQUE;
00519
00520
00521 QString compositeOpName = element.attribute("compositeop");
00522 KisCompositeOp compositeOp;
00523
00524 if (compositeOpName.isNull()) {
00525 compositeOp = COMPOSITE_OVER;
00526 } else {
00527 compositeOp = KisCompositeOp(compositeOpName);
00528 }
00529
00530 if (!compositeOp.isValid()) {
00531 return 0;
00532 }
00533
00534 if ((attr = element.attribute("visible")).isNull())
00535 attr = "1";
00536
00537 visible = attr == "0" ? false : true;
00538
00539 if ((attr = element.attribute("locked")).isNull())
00540 attr = "0";
00541
00542 locked = attr == "0" ? false : true;
00543
00544
00545 if ((attr = element.attribute("layertype")).isNull())
00546 return loadPaintLayer(element, img, name, x, y, opacity, visible, locked, compositeOp) ;
00547
00548 if(attr == "paintlayer")
00549 return loadPaintLayer(element, img, name, x, y, opacity, visible, locked, compositeOp);
00550
00551 if(attr == "grouplayer")
00552 return loadGroupLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data();
00553
00554 if(attr == "adjustmentlayer")
00555 return loadAdjustmentLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data();
00556
00557 if(attr == "partlayer")
00558 return loadPartLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data();
00559
00560 kdWarning(DBG_AREA_FILE) << "Specified layertype is not recognised\n";
00561 return 0;
00562 }
00563
00564
00565 KisLayerSP KisDoc::loadPaintLayer(const QDomElement& element, KisImageSP img,
00566 QString name, Q_INT32 x, Q_INT32 y,
00567 Q_INT32 opacity, bool visible, bool locked, KisCompositeOp compositeOp)
00568 {
00569 QString attr;
00570 KisPaintLayerSP layer;
00571 KisColorSpace * cs;
00572
00573 QString colorspacename;
00574 QString profileProductName;
00575
00576 if ((colorspacename = element.attribute("colorspacename")).isNull())
00577 cs = img->colorSpace();
00578 else
00579
00580 cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename,"");
00581
00582 layer = new KisPaintLayer(img, name, opacity, cs);
00583 Q_CHECK_PTR(layer);
00584
00585 layer->setCompositeOp(compositeOp);
00586 layer->setVisible(visible);
00587 layer->setLocked(locked);
00588 layer->setX(x);
00589 layer->setY(y);
00590
00591 if ((element.attribute("filename")).isNull())
00592 m_layerFilenames[layer.data()] = name;
00593 else
00594 m_layerFilenames[layer.data()] = QString(element.attribute("filename"));
00595
00596 if ((attr = element.attribute("hasmask")).isNull())
00597 attr = "0";
00598
00599 if (attr == "1") {
00600
00601 layer->createMask();
00602 }
00603
00604
00605
00606 for( QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling() )
00607 {
00608 QDomElement e = node.toElement();
00609 if ( !e.isNull() && e.tagName() == "ExifInfo" )
00610 {
00611 layer->paintDevice()->exifInfo()->load(e);
00612 }
00613 }
00614 return layer.data();
00615 }
00616
00617 KisGroupLayerSP KisDoc::loadGroupLayer(const QDomElement& element, KisImageSP img,
00618 QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked,
00619 KisCompositeOp compositeOp)
00620 {
00621 QString attr;
00622 KisGroupLayerSP layer;
00623
00624 layer = new KisGroupLayer(img, name, opacity);
00625 Q_CHECK_PTR(layer);
00626
00627 layer->setCompositeOp(compositeOp);
00628 layer->setVisible(visible);
00629 layer->setLocked(locked);
00630 layer->setX(x);
00631 layer->setY(y);
00632
00633 loadLayers(element, img, layer);
00634
00635 return layer;
00636 }
00637
00638 KisAdjustmentLayerSP KisDoc::loadAdjustmentLayer(const QDomElement& element, KisImageSP img,
00639 QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked,
00640 KisCompositeOp compositeOp)
00641 {
00642 QString attr;
00643 KisAdjustmentLayerSP layer;
00644 QString filtername;
00645
00646 if ((filtername = element.attribute("filtername")).isNull()) {
00647
00648 kdWarning(DBG_AREA_FILE) << "No filter in adjustment layer" << endl;
00649 return 0;
00650 }
00651
00652 KisFilter * f = KisFilterRegistry::instance()->get(filtername);
00653 if (!f) {
00654 kdWarning(DBG_AREA_FILE) << "No filter for filtername " << filtername << "\n";
00655 return 0;
00656 }
00657
00658 KisFilterConfiguration * kfc = f->configuration();
00659
00660
00661 layer = new KisAdjustmentLayer(img, name, kfc, 0);
00662 Q_CHECK_PTR(layer);
00663
00664 layer->setCompositeOp(compositeOp);
00665 layer->setVisible(visible);
00666 layer->setLocked(locked);
00667 layer->setX(x);
00668 layer->setY(y);
00669 layer->setOpacity(opacity);
00670
00671 if ((element.attribute("filename")).isNull())
00672 m_layerFilenames[layer.data()] = name;
00673 else
00674 m_layerFilenames[layer.data()] = QString(element.attribute("filename"));
00675
00676 return layer;
00677 }
00678
00679 KisPartLayerSP KisDoc::loadPartLayer(const QDomElement& element, KisImageSP img,
00680 QString name, Q_INT32 , Q_INT32 , Q_INT32 opacity,
00681 bool visible, bool locked,
00682 KisCompositeOp compositeOp) {
00683 KisChildDoc* child = new KisChildDoc(this);
00684 QString filename(element.attribute("filename"));
00685 QDomElement partElement = element.namedItem("object").toElement();
00686
00687 if (partElement.isNull()) {
00688 kdWarning() << "loadPartLayer failed with partElement isNull" << endl;
00689 return 0;
00690 }
00691
00692 child->load(partElement);
00693 insertChild(child);
00694
00695 KisPartLayerSP layer = new KisPartLayerImpl(img, child);
00696 Q_CHECK_PTR(layer);
00697
00698 layer->setCompositeOp(compositeOp);
00699 layer->setVisible(visible);
00700 layer->setLocked(locked);
00701 layer->setOpacity(opacity);
00702 layer->setName(name);
00703
00704 return layer;
00705 }
00706
00707 bool KisDoc::completeSaving(KoStore *store)
00708 {
00709 QString uri = url().url();
00710 QString location;
00711 bool external = isStoredExtern();
00712 Q_INT32 totalSteps = 0;
00713
00714 if (!m_currentImage) return false;
00715
00716 totalSteps = (m_currentImage)->nlayers();
00717
00718
00719 setIOSteps(totalSteps + 1);
00720
00721
00722 Q_UINT32 count=0;
00723 KisSaveVisitor visitor(m_currentImage, store, count);
00724
00725 if(external)
00726 visitor.setExternalUri(uri);
00727
00728 m_currentImage->rootLayer()->accept(visitor);
00729
00730
00731
00732
00733
00734 KisAnnotationSP annotation = (m_currentImage)->annotation("exif");
00735 if (annotation) {
00736 location = external ? QString::null : uri;
00737 location += (m_currentImage)->name() + "/annotations/exif";
00738 if (store->open(location)) {
00739 store->write(annotation->annotation());
00740 store->close();
00741 }
00742 }
00743 if (m_currentImage->getProfile()) {
00744 annotation = m_currentImage->getProfile()->annotation();
00745
00746 if (annotation) {
00747 location = external ? QString::null : uri;
00748 location += m_currentImage->name() + "/annotations/icc";
00749 if (store->open(location)) {
00750 store->write(annotation->annotation());
00751 store->close();
00752 }
00753 }
00754 }
00755
00756 IODone();
00757 return true;
00758 }
00759
00760 bool KisDoc::completeLoading(KoStore *store)
00761 {
00762 QString uri = url().url();
00763 QString location;
00764 bool external = isStoredExtern();
00765 Q_INT32 totalSteps = 0;
00766
00767 totalSteps = (m_currentImage)->nlayers();
00768
00769 setIOSteps(totalSteps);
00770
00771
00772 KisLoadVisitor visitor(m_currentImage, store, m_layerFilenames);
00773
00774 if(external)
00775 visitor.setExternalUri(uri);
00776
00777 m_currentImage->rootLayer()->accept(visitor);
00778
00779
00780
00781 location = external ? QString::null : uri;
00782 location += (m_currentImage)->name() + "/annotations/exif";
00783 if (store->hasFile(location)) {
00784 QByteArray data;
00785 store->open(location);
00786 data = store->read(store->size());
00787 store->close();
00788 (m_currentImage)->addAnnotation(new KisAnnotation("exif", "", data));
00789 }
00790
00791 location = external ? QString::null : uri;
00792 location += (m_currentImage)->name() + "/annotations/icc";
00793 if (store->hasFile(location)) {
00794 QByteArray data;
00795 store->open(location);
00796 data = store->read(store->size());
00797 store->close();
00798 (m_currentImage)->setProfile(new KisProfile(data));
00799 }
00800
00801 IODone();
00802
00803 setModified( false );
00804 setUndo(true);
00805 return true;
00806 }
00807
00808 QWidget* KisDoc::createCustomDocumentWidget(QWidget *parent)
00809 {
00810
00811 KisConfig cfg;
00812
00813 int w = cfg.defImgWidth();
00814 int h = cfg.defImgHeight();
00815
00816 QSize sz = KisClipboard::instance()->clipSize();
00817 if (sz.isValid() && sz.width() != 0 && sz.height() != 0) {
00818 w = sz.width();
00819 h = sz.height();
00820 }
00821 return new KisCustomImageWidget(parent, this, w, h, cfg.defImgResolution(), cfg.workingColorSpace(),"unnamed");
00822 }
00823
00824
00825 KoDocument* KisDoc::hitTest(const QPoint &pos, const QWMatrix& matrix) {
00826 KoDocument* doc = super::hitTest(pos, matrix);
00827 if (doc && doc != this) {
00828
00829
00830 KisPartLayerImpl* partLayer
00831 = dynamic_cast<KisPartLayerImpl*>(currentImage()->activeLayer().data());
00832
00833 if (!partLayer)
00834 return this;
00835
00836 if (doc == partLayer->childDoc()->document()) {
00837 return doc;
00838 }
00839 return this;
00840 }
00841 return doc;
00842 }
00843
00844 void KisDoc::renameImage(const QString& oldName, const QString& newName)
00845 {
00846 (m_currentImage)->setName(newName);
00847
00848 if (undo())
00849 addCommand(new KisCommandImageMv(this, this, newName, oldName));
00850 }
00851
00852
00853 KisImageSP KisDoc::newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * colorstrategy)
00854 {
00855 if (!init())
00856 return 0;
00857
00858 setUndo(false);
00859
00860 KisImageSP img = new KisImage(this, width, height, colorstrategy, name);
00861 Q_CHECK_PTR(img);
00862 connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() ));
00863
00864 KisPaintLayer *layer = new KisPaintLayer(img, img->nextLayerName(), OPACITY_OPAQUE,colorstrategy);
00865 Q_CHECK_PTR(layer);
00866
00867 KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8();
00868 KisFillPainter painter;
00869
00870 painter.begin(layer->paintDevice());
00871 painter.fillRect(0, 0, width, height, KisColor(Qt::white, cs), OPACITY_OPAQUE);
00872 painter.end();
00873
00874 img->addLayer(layer, img->rootLayer(), 0);
00875 img->activate(layer);
00876
00877 m_currentImage = img;
00878
00879 setUndo(true);
00880
00881 return img;
00882 }
00883
00884 bool KisDoc::newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * cs, const KisColor &bgColor, const QString &imgDescription, const double imgResolution)
00885 {
00886 if (!init())
00887 return false;
00888
00889 KisConfig cfg;
00890
00891 Q_UINT8 opacity = OPACITY_OPAQUE;
00892 KisImageSP img;
00893 KisPaintLayer *layer;
00894
00895 if (!cs) return false;
00896
00897 setUndo(false);
00898
00899 img = new KisImage(this, width, height, cs, name);
00900 Q_CHECK_PTR(img);
00901 connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() ));
00902 img->setResolution(imgResolution, imgResolution);
00903 img->setDescription(imgDescription);
00904 img->setProfile(cs->getProfile());
00905
00906 layer = new KisPaintLayer(img, img->nextLayerName(), OPACITY_OPAQUE, cs);
00907 Q_CHECK_PTR(layer);
00908
00909 KisFillPainter painter;
00910 painter.begin(layer->paintDevice());
00911 painter.fillRect(0, 0, width, height, bgColor, opacity);
00912 painter.end();
00913
00914 QValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() ->
00915 csRegistry()->paintDeviceActionsFor(cs);
00916 for (uint i = 0; i < actions.count(); i++)
00917 actions.at(i)->act(layer->paintDevice(), img->width(), img->height());
00918
00919 img->setBackgroundColor(bgColor);
00920 img->addLayer(layer, img->rootLayer(), 0);
00921 img->activate(layer);
00922
00923 m_currentImage = img;
00924
00925 cfg.defImgWidth(width);
00926 cfg.defImgHeight(height);
00927 cfg.defImgResolution(imgResolution);
00928
00929 setUndo(true);
00930
00931 return true;
00932 }
00933
00934 KoView* KisDoc::createViewInstance(QWidget* parent, const char *name)
00935 {
00936 KisView * v = new KisView(this, this, parent, name);
00937 Q_CHECK_PTR(v);
00938
00939 return v;
00940 }
00941
00942 void KisDoc::paintContent(QPainter& painter, const QRect& rc, bool transparent, double zoomX, double zoomY)
00943 {
00944 KisConfig cfg;
00945 QString monitorProfileName = cfg.monitorProfile();
00946 KisProfile * profile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName);
00947 painter.scale(zoomX, zoomY);
00948 QRect rect = rc & m_currentImage->bounds();
00949 KisImage::PaintFlags paintFlags;
00950 if (transparent) {
00951 paintFlags = KisImage::PAINT_SELECTION;
00952 } else {
00953 paintFlags = (KisImage::PaintFlags)(KisImage::PAINT_BACKGROUND|KisImage::PAINT_SELECTION);
00954 }
00955
00956 paintFlags = (KisImage::PaintFlags)(paintFlags | KisImage::PAINT_EMBEDDED_RECT);
00957
00958 m_currentImage->renderToPainter(rect.left(), rect.top(), rect.right(), rect.bottom(), painter, profile, paintFlags);
00959 }
00960
00961 void KisDoc::slotImageUpdated()
00962 {
00963 emit docUpdated();
00964 setModified(true);
00965 }
00966
00967 void KisDoc::slotImageUpdated(const QRect& rect)
00968 {
00969 emit docUpdated(rect);
00970 }
00971
00972 void KisDoc::beginMacro(const QString& macroName)
00973 {
00974 if (m_undo) {
00975 if (m_macroNestDepth == 0) {
00976 Q_ASSERT(m_currentMacro == 0);
00977 m_currentMacro = new KMacroCommand(macroName);
00978 Q_CHECK_PTR(m_currentMacro);
00979 }
00980
00981 m_macroNestDepth++;
00982 }
00983 }
00984
00985 void KisDoc::endMacro()
00986 {
00987 if (m_undo) {
00988 Q_ASSERT(m_macroNestDepth > 0);
00989 if (m_macroNestDepth > 0) {
00990 m_macroNestDepth--;
00991
00992 if (m_macroNestDepth == 0) {
00993 Q_ASSERT(m_currentMacro != 0);
00994
00995 m_cmdHistory->addCommand(m_currentMacro, false);
00996 m_currentMacro = 0;
00997 emit sigCommandExecuted();
00998 }
00999 }
01000 }
01001 }
01002
01003 void KisDoc::setCommandHistoryListener(const KisCommandHistoryListener * l)
01004 {
01005
01006 m_undoListeners.removeRef(l);
01007 m_undoListeners.append(l);
01008 }
01009
01010 void KisDoc::removeCommandHistoryListener(const KisCommandHistoryListener * l)
01011 {
01012 m_undoListeners.removeRef(l);
01013 }
01014
01015 KCommand * KisDoc::presentCommand()
01016 {
01017 return m_cmdHistory->presentCommand();
01018 }
01019
01020 void KisDoc::addCommand(KCommand *cmd)
01021 {
01022 Q_ASSERT(cmd);
01023
01024 KisCommandHistoryListener* l = 0;
01025
01026 for (l = m_undoListeners.first(); l; l = m_undoListeners.next()) {
01027 l->notifyCommandAdded(cmd);
01028 }
01029
01030 setModified(true);
01031
01032 if (m_undo) {
01033 if (m_currentMacro)
01034 m_currentMacro->addCommand(cmd);
01035 else {
01036 m_cmdHistory->addCommand(cmd, false);
01037 emit sigCommandExecuted();
01038 }
01039 } else {
01040 kdDebug() << "Deleting command\n";
01041 delete cmd;
01042 }
01043 }
01044
01045 void KisDoc::setUndo(bool undo)
01046 {
01047 m_undo = undo;
01048 if (m_undo && m_cmdHistory->undoLimit() == 50 ) {
01049 KisConfig cfg;
01050 setUndoLimit( cfg.defUndoLimit() );
01051 }
01052 }
01053
01054 Q_INT32 KisDoc::undoLimit() const
01055 {
01056 return m_cmdHistory->undoLimit();
01057 }
01058
01059 void KisDoc::setUndoLimit(Q_INT32 limit)
01060 {
01061 m_cmdHistory->setUndoLimit(limit);
01062 }
01063
01064 Q_INT32 KisDoc::redoLimit() const
01065 {
01066 return m_cmdHistory->redoLimit();
01067 }
01068
01069 void KisDoc::setRedoLimit(Q_INT32 limit)
01070 {
01071 m_cmdHistory->setRedoLimit(limit);
01072 }
01073
01074 void KisDoc::slotDocumentRestored()
01075 {
01076 setModified(false);
01077 }
01078
01079 void KisDoc::slotCommandExecuted(KCommand *command)
01080 {
01081 setModified(true);
01082 emit sigCommandExecuted();
01083
01084 KisCommandHistoryListener* l = 0;
01085
01086 for (l = m_undoListeners.first(); l; l = m_undoListeners.next()) {
01087 l->notifyCommandExecuted(command);
01088 }
01089
01090 }
01091
01092 void KisDoc::slotUpdate(KisImageSP, Q_UINT32 x, Q_UINT32 y, Q_UINT32 w, Q_UINT32 h)
01093 {
01094 QRect rc(x, y, w, h);
01095
01096 emit docUpdated(rc);
01097 }
01098
01099 bool KisDoc::undo() const
01100 {
01101 return m_undo;
01102 }
01103
01104 void KisDoc::setIOSteps(Q_INT32 nsteps)
01105 {
01106 m_ioProgressTotalSteps = nsteps * 100;
01107 m_ioProgressBase = 0;
01108 emitProgress(0);
01109 }
01110
01111 void KisDoc::IOCompletedStep()
01112 {
01113 m_ioProgressBase += 100;
01114 }
01115
01116 void KisDoc::IODone()
01117 {
01118 emitProgress(-1);
01119 }
01120
01121 void KisDoc::slotIOProgress(Q_INT8 percentage)
01122 {
01123 KApplication *app = KApplication::kApplication();
01124
01125 Q_ASSERT(app);
01126
01127 if (app->hasPendingEvents())
01128 app->processEvents();
01129
01130 int totalPercentage = ((m_ioProgressBase + percentage) * 100) / m_ioProgressTotalSteps;
01131
01132 emitProgress(totalPercentage);
01133 }
01134
01135 KisChildDoc * KisDoc::createChildDoc( const QRect & rect, KoDocument* childDoc )
01136 {
01137 KisChildDoc * ch = new KisChildDoc( this, rect, childDoc );
01138 insertChild( ch );
01139 ch->document()->setStoreInternal(true);
01140 return ch;
01141 }
01142
01143 void KisDoc::prepareForImport()
01144 {
01145 if (m_nserver == 0)
01146 init();
01147 setUndo(false);
01148 }
01149
01150 KisImageSP KisDoc::currentImage()
01151 {
01152 return m_currentImage;
01153 }
01154
01155 void KisDoc::setCurrentImage(KisImageSP image)
01156 {
01157 m_currentImage = image;
01158 setUndo(true);
01159 image->notifyImageLoaded();
01160 emit loadingFinished();
01161 }
01162
01163 void KisDoc::initEmpty()
01164 {
01165 KisConfig cfg;
01166 KisColorSpace * rgb = KisMetaRegistry::instance()->csRegistry()->getRGB8();
01167 newImage("", cfg.defImgWidth(), cfg.defImgHeight(), rgb);
01168 }
01169
01170 #include "kis_doc.moc"
01171