umlviewimageexportermodel.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "umlviewimageexportermodel.h"
00014
00015
00016 #include <math.h>
00017
00018
00019 #include <qstringlist.h>
00020 #include <qrect.h>
00021 #include <qimage.h>
00022 #include <qpicture.h>
00023 #include <qpainter.h>
00024 #include <qprinter.h>
00025 #include <qdir.h>
00026 #include <qregexp.h>
00027
00028
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <ktempfile.h>
00032 #include <kapplication.h>
00033 #include <kio/netaccess.h>
00034
00035
00036 #include "uml.h"
00037 #include "umldoc.h"
00038 #include "umlview.h"
00039 #include "umllistview.h"
00040 #include "umllistviewitem.h"
00041
00042 static QStringList supportedImageTypesList;
00043 static QStringList supportedMimeTypesList;
00044
00045 QStringList UMLViewImageExporterModel::supportedImageTypes() {
00046 if (!supportedImageTypesList.size()) {
00047
00048 supportedImageTypesList << "eps";
00049 supportedImageTypesList << "svg";
00050
00051
00052 QStrList qImageFormats = QImage::outputFormats();
00053 for (const char* format = qImageFormats.first(); format; format = qImageFormats.next()) {
00054 supportedImageTypesList << QString(format).lower();
00055 }
00056 }
00057
00058 return supportedImageTypesList;
00059 }
00060
00061 QStringList UMLViewImageExporterModel::supportedMimeTypes() {
00062 if (!supportedMimeTypesList.size()) {
00063 QStringList imageTypes = UMLViewImageExporterModel::supportedImageTypes();
00064 for(QStringList::Iterator it = imageTypes.begin(); it != imageTypes.end(); ++it ) {
00065 QString mimeType = imageTypeToMimeType(*it);
00066 if (!mimeType.isNull())
00067 supportedMimeTypesList.append(mimeType);
00068 }
00069 }
00070
00071 return supportedMimeTypesList;
00072 }
00073
00074 QString UMLViewImageExporterModel::imageTypeToMimeType(const QString& imageType) {
00075 const QString imgType = imageType.lower();
00076 if (QString("bmp") == imgType) return "image/x-bmp";
00077 if (QString("jpeg") == imgType) return "image/jpeg";
00078 if (QString("pbm") == imgType) return "image/x-portable-bitmap";
00079 if (QString("pgm") == imgType) return "image/x-portable-greymap";
00080 if (QString("png") == imgType) return "image/png";
00081 if (QString("ppm") == imgType) return "image/x-portable-pixmap";
00082 if (QString("xbm") == imgType) return "image/x-xbm";
00083 if (QString("xpm") == imgType) return "image/x-xpm";
00084 if (QString("eps") == imgType) return "image/x-eps";
00085 if (QString("svg") == imgType) return "image/svg+xml";
00086 return QString::null;
00087 }
00088
00089 QString UMLViewImageExporterModel::mimeTypeToImageType(const QString& mimeType) {
00090 if (QString("image/x-bmp") == mimeType) return "bmp";
00091 if (QString("image/jpeg") == mimeType) return "jpeg";
00092 if (QString("image/x-portable-bitmap") == mimeType) return "pbm";
00093 if (QString("image/x-portable-greymap") == mimeType) return "pgm";
00094 if (QString("image/png") == mimeType) return "png";
00095 if (QString("image/x-portable-pixmap") == mimeType) return "ppm";
00096 if (QString("image/x-xbm") == mimeType) return "xbm";
00097 if (QString("image/x-xpm") == mimeType) return "xpm";
00098 if (QString("image/x-eps") == mimeType) return "eps";
00099 if (QString("image/svg+xml") == mimeType) return "svg";
00100 return QString::null;
00101 }
00102
00103 QStringList UMLViewImageExporterModel::exportAllViews(const QString &imageType, const KURL &directory, bool useFolders) const {
00104 UMLApp *app = UMLApp::app();
00105
00106
00107 QStringList errors;
00108
00109 UMLViewList views = app->getDocument()->getViewIterator();
00110 for(UMLView *view = views.first(); view; view = views.next()) {
00111 KURL url = directory;
00112 url.addPath(getDiagramFileName(view, imageType, useFolders));
00113
00114 QString returnString = exportView(view, imageType, url);
00115 if (!returnString.isNull()) {
00116 errors.append(view->getName() + ": " + returnString);
00117 }
00118 }
00119
00120 return errors;
00121 }
00122
00123 QString UMLViewImageExporterModel::exportView(UMLView* view, const QString &imageType, const KURL &url) const {
00124
00125 if (!prepareDirectory(url)) {
00126 return i18n("Can not create directory: %1").arg(url.directory());
00127 }
00128
00129
00130
00131
00132 QString fileName;
00133
00134 KTempFile tmpFile;
00135 if (url.isLocalFile()) {
00136 fileName = url.path();
00137 } else {
00138 fileName = tmpFile.name();
00139 }
00140
00141
00142 QRect rect = view->getDiagramRect();
00143 if (rect.isEmpty()) {
00144 tmpFile.unlink();
00145 return i18n("Can not save an empty diagram");
00146 }
00147
00148
00149 if (!exportViewTo(view, imageType, fileName)) {
00150 tmpFile.unlink();
00151 return i18n("A problem occured while saving diagram in %1").arg(fileName);
00152 }
00153
00154
00155 if (!url.isLocalFile()) {
00156 if (!KIO::NetAccess::upload(tmpFile.name(), url, UMLApp::app())) {
00157 tmpFile.unlink();
00158 return i18n("There was a problem saving file: %1").arg(url.path());
00159 }
00160 }
00161
00162 tmpFile.unlink();
00163 return QString::null;
00164 }
00165
00166 QString UMLViewImageExporterModel::getDiagramFileName(UMLView *view, const QString &imageType, bool useFolders ) const {
00167 QString name = view->getName() + '.' + imageType.lower();
00168
00169 if (!useFolders) {
00170 return name;
00171 }
00172
00173 kapp->processEvents();
00174 UMLListView *listView = UMLApp::app()->getListView();
00175 UMLListViewItem* listViewItem = listView->findItem(view->getID());
00176
00177 listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
00178
00179
00180
00181
00182 while (listView->rootView(listViewItem->getType()) == NULL) {
00183 name.insert(0, listViewItem->getText() + '/');
00184 listViewItem = static_cast<UMLListViewItem*>(listViewItem->parent());
00185 if (listViewItem == NULL)
00186 break;
00187 }
00188 return name;
00189 }
00190
00191 bool UMLViewImageExporterModel::prepareDirectory(const KURL &url) const {
00192
00193 KURL directory = url;
00194 directory.setPath("");
00195
00196
00197 QStringList dirs = QStringList::split(QDir::separator(), url.directory());
00198 for (QStringList::ConstIterator it = dirs.begin() ; it != dirs.end(); ++it ) {
00199 directory.addPath(*it);
00200
00201 if (!KIO::NetAccess::exists(directory, true, UMLApp::app())) {
00202
00203 if (!KIO::NetAccess::mkdir(directory, UMLApp::app())) {
00204 return false;
00205 }
00206 }
00207 }
00208
00209 return true;
00210 }
00211
00212 bool UMLViewImageExporterModel::exportViewTo(UMLView* view, const QString &imageType, const QString &fileName) const {
00213
00214 view->clearSelected();
00215
00216 QString imageMimeType = UMLViewImageExporterModel::imageTypeToMimeType(imageType);
00217 if (imageMimeType == "image/x-eps") {
00218 if (!exportViewToEps(view, fileName, true)) {
00219 return false;
00220 }
00221 } else if (imageMimeType == "image/svg+xml") {
00222 if (!exportViewToSvg(view, fileName)) {
00223 return false;
00224 }
00225 } else {
00226 if (!exportViewToPixmap(view, imageType, fileName)) {
00227 return false;
00228 }
00229 }
00230
00231 return true;
00232 }
00233
00234 bool UMLViewImageExporterModel::exportViewToEps(UMLView* view, const QString &fileName, bool isEPS) const {
00235 bool exportSuccessful = true;
00236
00237
00238
00239
00240
00241
00242
00243
00244 QPrinter *printer;
00245
00246 if (isEPS == false) {
00247 printer = new QPrinter(QPrinter::PrinterResolution);
00248 } else {
00249 printer = new QPrinter(QPrinter::ScreenResolution);
00250 }
00251 printer->setOutputToFile(true);
00252 printer->setOutputFileName(fileName);
00253 printer->setColorMode(QPrinter::Color);
00254
00255
00256
00257 QPainter *painter = new QPainter(printer);
00258
00259
00260
00261
00262 view->forceUpdateWidgetFontMetrics(painter);
00263
00264 QRect rect = view->getDiagramRect();
00265 painter->translate(-rect.x(),-rect.y());
00266 view->getDiagram(rect,*painter);
00267
00268 int resolution = printer->resolution();
00269
00270
00271 delete painter;
00272 delete printer;
00273 if (isEPS) {
00274
00275 rect.setWidth( int(ceil(rect.width() * 72.0/resolution)) );
00276 rect.setHeight( int(ceil(rect.height() * 72.0/resolution)) );
00277 exportSuccessful = fixEPS(fileName,rect);
00278 }
00279
00280 view->forceUpdateWidgetFontMetrics(0);
00281
00282 return exportSuccessful;
00283 }
00284
00285 bool UMLViewImageExporterModel::fixEPS(const QString &fileName, QRect rect) const {
00286
00287 QFile epsfile(fileName);
00288 if (! epsfile.open(IO_ReadOnly)) {
00289 return false;
00290 }
00291
00292 QTextStream ts(&epsfile);
00293 QString fileContent = ts.read();
00294 epsfile.close();
00295
00296
00297 QRegExp rx("%%BoundingBox:\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)\\s*(-?[\\d\\.:]+)");
00298 const int pos = rx.search(fileContent);
00299 if (pos < 0) {
00300 kError() << "UMLViewImageExporterModel::fixEPS(" << fileName
00301 << "): cannot find %%BoundingBox" << endl;
00302 return false;
00303 }
00304
00305
00306 if (! epsfile.open(IO_WriteOnly | IO_Truncate)) {
00307 kError() << "UMLViewImageExporterModel::fixEPS(" << fileName
00308 << "): cannot open file for writing" << endl;
00309 return false;
00310 }
00311
00312
00313
00314 const double epsleft = rx.cap(1).toFloat();
00315 const double epstop = rx.cap(4).toFloat();
00316 const int left = int(floor(epsleft));
00317 const int right = int(ceil(epsleft)) + rect.width();
00318 const int top = int(ceil(epstop)) + 1;
00319 const int bottom = int(floor(epstop)) - rect.height() + 1;
00320
00321
00322 fileContent.replace(pos,rx.cap(0).length(),
00323 QString("%%BoundingBox: %1 %2 %3 %4").arg(left).arg(bottom).arg(right).arg(top));
00324
00325 ts << fileContent;
00326 epsfile.close();
00327
00328 return true;
00329 }
00330
00331 bool UMLViewImageExporterModel::exportViewToSvg(UMLView* view, const QString &fileName) const {
00332 bool exportSuccesful;
00333
00334 QPicture* diagram = new QPicture();
00335
00336
00337
00338 QPainter* painter = new QPainter();
00339 painter->begin( diagram );
00340
00341
00342
00343
00344 view->forceUpdateWidgetFontMetrics(painter);
00345
00346 QRect rect = view->getDiagramRect();
00347 painter->translate(-rect.x(),-rect.y());
00348 view->getDiagram(rect,*painter);
00349 painter->end();
00350 exportSuccesful = diagram->save(fileName, QString("SVG").ascii());
00351
00352
00353 delete painter;
00354 delete diagram;
00355
00356 view->forceUpdateWidgetFontMetrics(0);
00357
00358 return exportSuccesful;
00359 }
00360
00361 bool UMLViewImageExporterModel::exportViewToPixmap(UMLView* view, const QString &imageType, const QString &fileName) const {
00362 QRect rect = view->getDiagramRect();
00363 QPixmap diagram(rect.width(), rect.height());
00364 view->getDiagram(rect, diagram);
00365 return diagram.save(fileName, imageType.upper().ascii());
00366 }
This file is part of the documentation for umbrello Version 3.1.0.