1/***************************************************************************
2 imagemapeditor.cpp - description
3 -------------------
4 begin : Wed Apr 4 2001
5 copyright : (C) 2001 by Jan Sch�er
6 email : j_schaef@informatik.uni-kl.de
7***************************************************************************/
8
9/***************************************************************************
10* *
11* This program is free software; you can redistribute it and/or modify *
12* it under the terms of the GNU General Public License as published by *
13* the Free Software Foundation; either version 2 of the License, or *
14* (at your option) any later version. *
15* *
16***************************************************************************/
17
18#include <iostream>
19#include <assert.h>
20
21// QT
22#include <QScrollArea>
23
24#include <qlayout.h>
25#include <QListWidget>
26#include <qpushbutton.h>
27#include <qpixmap.h>
28#include <qcombobox.h>
29#include <qsplitter.h>
30#include <qfileinfo.h>
31#include <qtextstream.h>
32#include <QMenu>
33#include <qtooltip.h>
34#include <qpainter.h>
35#include <qtabwidget.h>
36#include <qfontdatabase.h>
37#include <qfile.h>
38#include <QLinkedList>
39
40// KDE
41#include <kundostack.h>
42#include <kdebug.h>
43#include <klocale.h>
44#include <kaction.h>
45#include <kstandardaction.h>
46#include <kiconloader.h>
47#include <kfiledialog.h>
48#include <kmessagebox.h>
49#include <kapplication.h>
50#include <kedittoolbar.h>
51#include <kactioncollection.h>
52#include <kglobal.h>
53#include <kstandarddirs.h>
54#include <kstatusbar.h>
55#include <kxmlguifactory.h>
56#include <kio/job.h>
57#include <kinputdialog.h>
58#include <ktoggleaction.h>
59#include <krecentfilesaction.h>
60#include <kxmlguiwindow.h>
61// local
62#include "kimagemapeditor.h"
63#include "kimagemapeditor.moc"
64#include "drawzone.h"
65#include "kimedialogs.h"
66#include "kimecommands.h"
67#include <kicon.h>
68#include "areacreator.h"
69#include "arealistview.h"
70#include "imageslistview.h"
71#include "mapslistview.h"
72#include "kimecommon.h"
73#include "imagemapchoosedialog.h"
74
75#include <QTextEdit>
76
77#include <kparts/genericfactory.h>
78#include <kcomponentdata.h>
79
80// Factory code for KDE 3
81typedef KParts::GenericFactory<KImageMapEditor> KimeFactory;
82K_EXPORT_COMPONENT_FACTORY( libkimagemapeditor , KimeFactory )
83
84KImageMapEditor::KImageMapEditor(QWidget *parentWidget,
85 QObject *parent, const QStringList & )
86 : KParts::ReadWritePart(parent)
87{
88 setComponentData( KimeFactory::componentData() );
89
90// KDockMainWindow* mainWidget;
91
92 mainWindow = dynamic_cast<KXmlGuiWindow*>(parent) ;
93 QSplitter * splitter = 0L;
94 tabWidget = 0L;
95
96 if (mainWindow) {
97// kDebug() << "KImageMapEditor: We got a KDockMainWindow !";
98
99// K3DockWidget* parentDock = mainDock->getMainDockWidget();
100 areaDock = new QDockWidget(i18n("Areas"),mainWindow);
101 mapsDock = new QDockWidget(i18n("Maps"),mainWindow);
102 imagesDock = new QDockWidget(i18n("Images"),mainWindow);
103
104 // Needed to save their state
105 areaDock->setObjectName("areaDock");
106 mapsDock->setObjectName("mapsDock");
107 imagesDock->setObjectName("imagesDock");
108
109 mainWindow->addDockWidget( Qt::LeftDockWidgetArea, areaDock);
110 mainWindow->addDockWidget( Qt::LeftDockWidgetArea, mapsDock);
111 mainWindow->addDockWidget( Qt::LeftDockWidgetArea, imagesDock);
112
113 areaListView = new AreaListView(areaDock);
114 mapsListView = new MapsListView(mapsDock);
115 imagesListView = new ImagesListView(imagesDock);
116
117 areaDock->setWidget(areaListView);
118 mapsDock->setWidget(mapsListView);
119 imagesDock->setWidget(imagesListView);
120
121 }
122 else
123 {
124 areaDock = 0L;
125 mapsDock = 0L;
126 imagesDock = 0L;
127 splitter = new QSplitter(parentWidget);
128 tabWidget = new QTabWidget(splitter);
129 areaListView = new AreaListView(tabWidget);
130 mapsListView = new MapsListView(tabWidget);
131 imagesListView = new ImagesListView(tabWidget);
132
133 tabWidget->addTab(areaListView,i18n("Areas"));
134 tabWidget->addTab(mapsListView,i18n("Maps"));
135 tabWidget->addTab(imagesListView,i18n("Images"));
136 }
137
138
139 connect( areaListView->listView, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
140 connect( areaListView->listView,
141 SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
142 this,
143 SLOT(showTagEditor(QTreeWidgetItem*)));
144 connect( areaListView->listView,
145 SIGNAL(customContextMenuRequested(const QPoint&)),
146 this,
147 SLOT(slotShowPopupMenu(const QPoint &)));
148
149 connect( mapsListView, SIGNAL( mapSelected(const QString &)),
150 this, SLOT( setMap(const QString &)));
151
152 connect( mapsListView, SIGNAL( mapRenamed(const QString &)),
153 this, SLOT( setMapName(const QString &)));
154
155 connect( mapsListView->listView(),
156 SIGNAL(customContextMenuRequested(const QPoint &)),
157 this,
158 SLOT(slotShowMapPopupMenu(const QPoint &)));
159
160 connect( imagesListView, SIGNAL( imageSelected(const KUrl &)),
161 this, SLOT( setPicture(const KUrl &)));
162
163 connect( imagesListView,
164 SIGNAL(customContextMenuRequested(const QPoint &)),
165 this,
166 SLOT(slotShowImagePopupMenu(const QPoint &)));
167
168 if (splitter) {
169 drawZone = new DrawZone(splitter,this);
170 splitter->setStretchFactor(splitter->indexOf(tabWidget), 0);
171 splitter->setStretchFactor(splitter->indexOf(drawZone), 1);
172 setWidget(splitter);
173 } else {
174 QScrollArea *sa = new QScrollArea(mainWindow);
175 drawZone = new DrawZone(0L,this);
176 mainWindow->setCentralWidget(sa);
177 sa->setWidget(drawZone);
178 setWidget(mainWindow);
179 // sa->setWidgetResizable(true);
180 }
181
182
183 areas = new AreaList();
184 currentSelected= new AreaSelection();
185 _currentToolType=KImageMapEditor::Selection;
186 copyArea=0L;
187 defaultArea=0L;
188 currentMapElement = 0L;
189
190 setupActions();
191 setupStatusBar();
192
193 setXMLFile("kimagemapeditorpartui.rc");
194
195 setPicture(getBackgroundImage());
196
197 init();
198 readConfig();
199}
200
201KImageMapEditor::~KImageMapEditor() {
202 writeConfig();
203
204 delete areas;
205
206 delete currentSelected;
207 delete copyArea;
208 delete defaultArea;
209
210 // Delete our DockWidgets
211 if (areaDock) {
212 areaDock->hide();
213 mapsDock->hide();
214 imagesDock->hide();
215
216 delete areaDock;
217 delete mapsDock;
218 delete imagesDock;
219 }
220
221}
222
223MapTag::MapTag() {
224 modified = false;
225 name.clear();
226}
227
228void KImageMapEditor::init()
229{
230 _htmlContent.clear();
231 _imageUrl.clear();
232 // closeUrl();
233 HtmlElement* el = new HtmlElement("<html>\n");
234 _htmlContent.append(el);
235 el = new HtmlElement("<head>\n");
236 _htmlContent.append(el);
237 el = new HtmlElement("</head>\n");
238 _htmlContent.append(el);
239 el = new HtmlElement("<body>\n");
240 _htmlContent.append(el);
241
242 addMap(i18n("unnamed"));
243
244 el = new HtmlElement("</body>\n");
245 _htmlContent.append(el);
246 el = new HtmlElement("</html>\n");
247 _htmlContent.append(el);
248
249 setImageActionsEnabled(false);
250}
251
252KAboutData* KImageMapEditor::createAboutData()
253{
254 KAboutData* aboutData =
255 new KAboutData( "kimagemapeditor", 0, ki18n("KImageMapEditor"),
256 "1.0", ki18n( "An HTML imagemap editor" ),
257 KAboutData::License_GPL,
258 ki18n("(c) 2001-2003 Jan Sch&auml;fer <email>janschaefer@users.sourceforge.net</email>"));
259 return aboutData;
260}
261
262
263void KImageMapEditor::setReadWrite(bool)
264{
265
266 // For now it does not matter if it is readwrite or readonly
267 // it is always readwrite, because Quanta only supports ReadOnlyParts
268 // at this moment and in that case it should be readwrite, too.
269 ReadWritePart::setReadWrite(true);
270 /*
271 if (rw)
272 ;
273 else
274 {
275 actionCollection()->remove(arrowAction);
276 actionCollection()->remove(circleAction);
277 actionCollection()->remove(rectangleAction);
278 actionCollection()->remove(polygonAction);
279 actionCollection()->remove(freehandAction);
280 actionCollection()->remove(addPointAction);
281 actionCollection()->remove(removePointAction);
282
283 actionCollection()->remove(cutAction);
284 actionCollection()->remove(deleteAction);
285 actionCollection()->remove(copyAction);
286 actionCollection()->remove(pasteAction);
287
288 actionCollection()->remove(mapNewAction);
289 actionCollection()->remove(mapDeleteAction);
290 actionCollection()->remove(mapNameAction);
291 actionCollection()->remove(mapDefaultAreaAction);
292
293 actionCollection()->remove(areaPropertiesAction);
294
295 actionCollection()->remove(moveLeftAction);
296 actionCollection()->remove(moveRightAction);
297 actionCollection()->remove(moveUpAction);
298 actionCollection()->remove(moveDownAction);
299
300 actionCollection()->remove(increaseWidthAction);
301 actionCollection()->remove(decreaseWidthAction);
302 actionCollection()->remove(increaseHeightAction);
303 actionCollection()->remove(decreaseHeightAction);
304
305 actionCollection()->remove(toFrontAction);
306 actionCollection()->remove(toBackAction);
307 actionCollection()->remove(forwardOneAction);
308 actionCollection()->remove(backOneAction);
309
310 actionCollection()->remove(imageRemoveAction);
311 actionCollection()->remove(imageAddAction);
312 actionCollection()->remove(imageUsemapAction);
313
314 }
315 */
316
317}
318
319void KImageMapEditor::setModified(bool modified)
320{
321 // get a handle on our Save action and make sure it is valid
322 QAction *save = actionCollection()->action(KStandardAction::name(KStandardAction::Save));
323 if (!save)
324 return;
325
326 // if so, we either enable or disable it based on the current
327 // state
328 if (modified)
329 save->setEnabled(true);
330 else
331 save->setEnabled(false);
332
333 // in any event, we want our parent to do it's thing
334 ReadWritePart::setModified(modified);
335}
336
337
338KConfig *KImageMapEditor::config()
339{
340 KSharedConfigPtr tmp = KimeFactory::componentData().config();
341 return tmp.data();
342}
343
344void KImageMapEditor::readConfig(const KConfigGroup &config) {
345 KConfigGroup data = config.parent().group( "Data" );
346 recentFilesAction->loadEntries( data );
347}
348
349void KImageMapEditor::writeConfig(KConfigGroup& config) {
350 config.writeEntry("highlightareas",highlightAreasAction->isChecked());
351 config.writeEntry("showalt",showAltAction->isChecked());
352 KConfigGroup data = config.parent().group( "Data" );
353 recentFilesAction->saveEntries( data );
354 saveLastURL(config);
355
356}
357
358void KImageMapEditor::readConfig() {
359 readConfig(config()->group("General Options" ) );
360 slotConfigChanged();
361}
362
363void KImageMapEditor::writeConfig() {
364 KConfigGroup cg( config(), "General Options");
365 writeConfig( cg );
366 config()->sync();
367}
368
369
370void KImageMapEditor::saveProperties(KConfigGroup &config)
371{
372 saveLastURL(config);
373}
374
375void KImageMapEditor::readProperties(const KConfigGroup& config)
376{
377 openLastURL(config);
378}
379
380void KImageMapEditor::slotConfigChanged()
381{
382 KConfigGroup group = config()->group("Appearance");
383 int newHeight=group.readEntry("maximum-preview-height",50);
384 group = config()->group("General Options");
385 _commandHistory->setUndoLimit(group.readEntry("undo-level",100));
386#if 0
387 _commandHistory->setRedoLimit(group.readEntry("redo-level",100));
388#endif
389 Area::highlightArea = group.readEntry("highlightareas",true);
390 highlightAreasAction->setChecked(Area::highlightArea);
391 Area::showAlt = group.readEntry("showalt",true);
392 showAltAction->setChecked(Area::showAlt);
393
394 // if the image preview size changed update all images
395 if (maxAreaPreviewHeight!=newHeight) {
396 maxAreaPreviewHeight=newHeight;
397 areaListView->listView->setIconSize(QSize(newHeight,newHeight));
398 }
399
400 updateAllAreas();
401 drawZone->repaint();
402}
403
404void KImageMapEditor::openLastURL(const KConfigGroup & config) {
405 KUrl lastURL ( config.readPathEntry("lastopenurl", QString()) );
406 QString lastMap = config.readEntry("lastactivemap");
407 QString lastImage = config.readPathEntry("lastactiveimage", QString());
408
409
410// kDebug() << "loading from group : " << config.group();
411
412// kDebug() << "loading entry lastopenurl : " << lastURL.path();
413// KMessageBox::information(0L, config.group()+" "+lastURL.path());
414 if (!lastURL.isEmpty()) {
415 openUrl(lastURL);
416 if (!lastMap.isEmpty())
417 mapsListView->selectMap(lastMap);
418 if (!lastImage.isEmpty())
419 setPicture(lastImage);
420// kDebug() << "opening HTML file with map " << lastMap << " and image " << lastImage;
421// if (! openHTMLFile(lastURL, lastMap, lastImage) )
422// closeUrl();
423 //openUrl(lastURL);
424 // else
425 //closeUrl();
426 }
427}
428
429void KImageMapEditor::saveLastURL(KConfigGroup & config) {
430 kDebug() << "saveLastURL: " << url().path();
431 config.writePathEntry("lastopenurl",url().path());
432 config.writeEntry("lastactivemap",mapName());
433 config.writePathEntry("lastactiveimage",_imageUrl.path());
434// kDebug() << "writing entry lastopenurl : " << url().path();
435// kDebug() << "writing entry lastactivemap : " << mapName();
436// kDebug() << "writing entry lastactiveimage : " << _imageUrl.path();
437 //KMessageBox::information(0L, QString("Group: %1 Saving ... %2").arg(config.group()).arg(url().path()));
438}
439
440void KImageMapEditor::setupActions()
441{
442 // File Open
443 QAction *temp =
444 KStandardAction::open(this, SLOT(fileOpen()),
445 actionCollection());
446 temp->setWhatsThis(i18n("<h3>Open File</h3>Click this to <em>open</em> a new picture or HTML file."));
447 temp->setToolTip(i18n("Open new picture or HTML file"));
448
449 // File Open Recent
450 recentFilesAction = KStandardAction::openRecent(this, SLOT(openURL(const KUrl&)),
451 actionCollection());
452 // File Save
453 temp =KStandardAction::save(this, SLOT(fileSave()), actionCollection());
454 temp->setWhatsThis(i18n("<h3>Save File</h3>Click this to <em>save</em> the changes to the HTML file."));
455 temp->setToolTip(i18n("Save HTML file"));
456
457
458 // File Save As
459 (void)KStandardAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
460
461 // File Close
462 temp=KStandardAction::close(this, SLOT(fileClose()), actionCollection());
463 temp->setWhatsThis(i18n("<h3>Close File</h3>Click this to <em>close</em> the currently open HTML file."));
464 temp->setToolTip(i18n("Close HTML file"));
465
466 // Edit Copy
467 copyAction=KStandardAction::copy(this, SLOT(slotCopy()), actionCollection());
468 copyAction->setWhatsThis(i18n("<h3>Copy</h3>"
469 "Click this to <em>copy</em> the selected area."));
470 copyAction->setEnabled(false);
471
472 // Edit Cut
473 cutAction=KStandardAction::cut(this, SLOT(slotCut()), actionCollection());
474 cutAction->setWhatsThis(i18n("<h3>Cut</h3>"
475 "Click this to <em>cut</em> the selected area."));
476 cutAction->setEnabled(false);
477
478 // Edit Paste
479 pasteAction=KStandardAction::paste(this, SLOT(slotPaste()), actionCollection());
480 pasteAction->setWhatsThis(i18n("<h3>Paste</h3>"
481 "Click this to <em>paste</em> the copied area."));
482 pasteAction->setEnabled(false);
483
484
485 // Edit Delete
486 deleteAction = new KAction(KIcon("edit-delete"),
487 i18n("&Delete"), this);
488 actionCollection()->addAction("edit_delete", deleteAction );
489 connect(deleteAction, SIGNAL(triggered(bool) ), SLOT (slotDelete()));
490 deleteAction->setShortcut(QKeySequence(Qt::Key_Delete));
491 deleteAction->setWhatsThis(i18n("<h3>Delete</h3>"
492 "Click this to <em>delete</em> the selected area."));
493 deleteAction->setEnabled(false);
494
495 // Edit Undo/Redo
496 _commandHistory = new KUndoStack(this);
497 _commandHistory->createUndoAction(actionCollection());
498 _commandHistory->createRedoAction(actionCollection());
499
500 // Edit Properties
501 areaPropertiesAction = new KAction(i18n("Pr&operties"), this);
502 actionCollection()->addAction("edit_properties", areaPropertiesAction );
503 connect(areaPropertiesAction, SIGNAL(triggered(bool)), SLOT(showTagEditor()));
504 areaPropertiesAction->setEnabled(false);
505
506 // View Zoom In
507 zoomInAction=KStandardAction::zoomIn(this, SLOT(slotZoomIn()), actionCollection());
508 // View Zoom Out
509 zoomOutAction=KStandardAction::zoomOut(this, SLOT(slotZoomOut()), actionCollection());
510
511 // View Zoom
512 zoomAction = new KSelectAction(i18n("Zoom"), this);
513 actionCollection()->addAction("view_zoom", zoomAction );
514 connect(zoomAction, SIGNAL(triggered(int)), this, SLOT (slotZoom()));
515 zoomAction->setWhatsThis(i18n("<h3>Zoom</h3>"
516 "Choose the desired zoom level."));
517 zoomAction->setItems(QStringList()
518 << i18n("25%")
519 << i18n("50%")
520 << i18n("100%")
521 << i18n("150%")
522 << i18n("200%")
523 << i18n("250%")
524 << i18n("300%")
525 << i18n("500%")
526 << i18n("750%")
527 << i18n("1000%"));
528
529 zoomAction->setCurrentItem(2);
530
531 highlightAreasAction = actionCollection()->add<KToggleAction>("view_highlightareas");
532 highlightAreasAction->setText(i18n("Highlight Areas"));
533
534 connect(highlightAreasAction, SIGNAL(toggled(bool)),
535 this, SLOT(slotHighlightAreas(bool)));
536
537 showAltAction = actionCollection()->add<KToggleAction>("view_showalt");
538 showAltAction->setText(i18n("Show Alt Tag"));
539 connect(showAltAction, SIGNAL(toggled(bool)),this, SLOT (slotShowAltTag(bool)));
540
541 mapNameAction = new KAction(i18n("Map &Name..."), this);
542 actionCollection()->addAction("map_name", mapNameAction );
543 connect(mapNameAction, SIGNAL(triggered(bool)), SLOT(mapEditName()));
544
545 mapNewAction = new KAction(i18n("Ne&w Map..."), this);
546 actionCollection()->addAction("map_new", mapNewAction );
547 connect(mapNewAction, SIGNAL(triggered(bool)), SLOT(mapNew()));
548 mapNewAction->setToolTip(i18n("Create a new map"));
549
550 mapDeleteAction = new KAction(i18n("D&elete Map"), this);
551 actionCollection()->addAction("map_delete", mapDeleteAction );
552 connect(mapDeleteAction, SIGNAL(triggered(bool)), SLOT(mapDelete()));
553 mapDeleteAction->setToolTip(i18n("Delete the current active map"));
554
555 mapDefaultAreaAction = new KAction(i18n("Edit &Default Area..."), this);
556 actionCollection()->addAction("map_defaultarea", mapDefaultAreaAction );
557 connect(mapDefaultAreaAction, SIGNAL(triggered(bool)), SLOT(mapDefaultArea()));
558 mapDefaultAreaAction->setToolTip(i18n("Edit the default area of the current active map"));
559
560 temp = new KAction(i18n("&Preview"), this);
561 actionCollection()->addAction("map_preview", temp );
562 connect(temp, SIGNAL(triggered(bool)), SLOT(mapPreview()));
563 temp->setToolTip(i18n("Show a preview"));
564
565 // IMAGE
566 i18n("&Image");
567
568 imageAddAction = new KAction(i18n("Add Image..."), this);
569 actionCollection()->addAction("image_add", imageAddAction );
570 connect(imageAddAction, SIGNAL(triggered(bool)), SLOT(imageAdd()));
571 imageAddAction->setToolTip(i18n("Add a new image"));
572
573 imageRemoveAction = new KAction(i18n("Remove Image"), this);
574 actionCollection()->addAction("image_remove", imageRemoveAction );
575 connect(imageRemoveAction, SIGNAL(triggered(bool)), SLOT(imageRemove()));
576 imageRemoveAction->setToolTip(i18n("Remove the current visible image"));
577
578 imageUsemapAction = new KAction(i18n("Edit Usemap..."), this);
579 actionCollection()->addAction("image_usemap", imageUsemapAction );
580 connect(imageUsemapAction, SIGNAL(triggered(bool)), SLOT(imageUsemap()));
581 imageUsemapAction->setToolTip(i18n("Edit the usemap tag of the current visible image"));
582
583 temp = new KAction(i18n("Show &HTML"), this);
584 actionCollection()->addAction("map_showhtml", temp );
585 connect(temp, SIGNAL(triggered(bool)), SLOT(mapShowHTML()));
586
587
588 QActionGroup *drawingGroup = new QActionGroup(this);
589 // Selection Tool
590 arrowAction = new KToggleAction(KIcon("arrow"), i18n("&Selection"), this);
591 arrowAction->setShortcut(QKeySequence("s"));
592 actionCollection()->addAction("tool_arrow", arrowAction);
593 connect(arrowAction, SIGNAL(triggered(bool)), SLOT (slotDrawArrow()));
594 arrowAction->setWhatsThis(i18n("<h3>Selection</h3>"
595 "Click this to select areas."));
596 drawingGroup->addAction(arrowAction);
597 arrowAction->setChecked(true);
598
599 // Circle
600 circleAction = new KToggleAction(KIcon( "circle"), i18n("&Circle"), this);
601 circleAction->setShortcut(QKeySequence("c"));
602
603 actionCollection()->addAction("tool_circle", circleAction);
604 connect(circleAction, SIGNAL(triggered(bool)), this, SLOT(slotDrawCircle()));
605 circleAction->setWhatsThis(i18n("<h3>Circle</h3>"
606 "Click this to start drawing a circle."));
607 drawingGroup->addAction(circleAction);
608
609 // Rectangle
610 rectangleAction = new KToggleAction(KIcon("rectangle"), i18n("&Rectangle"), this);
611 rectangleAction->setShortcut(QKeySequence("r"));
612 actionCollection()->addAction("tool_rectangle", rectangleAction);
613 connect(rectangleAction, SIGNAL(triggered(bool)), this, SLOT(slotDrawRectangle()));
614 rectangleAction->setWhatsThis(i18n("<h3>Rectangle</h3>"
615 "Click this to start drawing a rectangle."));
616 drawingGroup->addAction(rectangleAction);
617
618 // Polygon
619 polygonAction = new KToggleAction(KIcon("polygon"), i18n("&Polygon"), this);
620 polygonAction->setShortcut(QKeySequence("p"));
621 actionCollection()->addAction("tool_polygon", polygonAction);
622 connect(polygonAction, SIGNAL(triggered(bool)), SLOT(slotDrawPolygon()));
623 polygonAction->setWhatsThis(i18n("<h3>Polygon</h3>"
624 "Click this to start drawing a polygon."));
625 drawingGroup->addAction(polygonAction);
626
627 // Freehand
628 freehandAction = new KToggleAction(KIcon("freehand"), i18n("&Freehand Polygon"), this);
629 freehandAction->setShortcut(QKeySequence("f"));
630 actionCollection()->addAction("tool_freehand", freehandAction);
631 connect(freehandAction, SIGNAL(triggered(bool)), SLOT(slotDrawFreehand()));
632 freehandAction->setWhatsThis(i18n("<h3>Freehandpolygon</h3>"
633 "Click this to start drawing a freehand polygon."));
634 drawingGroup->addAction(freehandAction);
635
636 // Add Point
637 addPointAction = new KToggleAction(KIcon("addpoint"), i18n("&Add Point"), this);
638 addPointAction->setShortcut(QKeySequence("a"));
639 actionCollection()->addAction("tool_addpoint", addPointAction);
640 connect(addPointAction, SIGNAL(triggered(bool)), SLOT(slotDrawAddPoint()));
641 addPointAction->setWhatsThis(i18n("<h3>Add Point</h3>"
642 "Click this to add points to a polygon."));
643 drawingGroup->addAction(addPointAction);
644
645 // Remove Point
646 removePointAction = new KToggleAction(KIcon("removepoint"), i18n("&Remove Point"), this);
647 removePointAction->setShortcut(QKeySequence("e"));
648 actionCollection()->addAction("tool_removepoint", removePointAction);
649 connect(removePointAction, SIGNAL(triggered(bool)),
650 SLOT(slotDrawRemovePoint()));
651 removePointAction->setWhatsThis(i18n("<h3>Remove Point</h3>"
652 "Click this to remove points from a polygon."));
653 drawingGroup->addAction(removePointAction);
654
655 KAction *action = new KAction(i18n("Cancel Drawing"), this);
656 actionCollection()->addAction("canceldrawing", action );
657 connect(action, SIGNAL(triggered(bool)), SLOT( slotCancelDrawing() ));
658 action->setShortcut(QKeySequence(Qt::Key_Escape));
659
660 moveLeftAction = new KAction(i18n("Move Left"), this);
661 actionCollection()->addAction("moveleft", moveLeftAction );
662 connect(moveLeftAction, SIGNAL(triggered(bool)),
663 SLOT( slotMoveLeft() ));
664 moveLeftAction->setShortcut(KShortcut(QKeySequence(Qt::Key_Left)));
665
666 moveRightAction = new KAction(i18n("Move Right"), this);
667 actionCollection()->addAction("moveright", moveRightAction );
668 connect(moveRightAction, SIGNAL(triggered(bool)), SLOT( slotMoveRight() ));
669 moveRightAction->setShortcut(QKeySequence(Qt::Key_Right));
670
671 moveUpAction = new KAction(i18n("Move Up"), this);
672 actionCollection()->addAction("moveup", moveUpAction );
673 connect(moveUpAction, SIGNAL(triggered(bool)), SLOT( slotMoveUp() ));
674 moveUpAction->setShortcut(QKeySequence(Qt::Key_Up));
675
676 moveDownAction = new KAction(i18n("Move Down"), this);
677 actionCollection()->addAction("movedown", moveDownAction );
678 connect(moveDownAction, SIGNAL(triggered(bool)), SLOT( slotMoveDown() ));
679 moveDownAction->setShortcut(QKeySequence(Qt::Key_Down));
680
681 increaseWidthAction = new KAction(i18n("Increase Width"), this);
682 actionCollection()->addAction("increasewidth", increaseWidthAction );
683 connect(increaseWidthAction, SIGNAL(triggered(bool)), SLOT( slotIncreaseWidth() ));
684 increaseWidthAction->setShortcut(QKeySequence(Qt::Key_Right + Qt::SHIFT));
685
686 decreaseWidthAction = new KAction(i18n("Decrease Width"), this);
687 actionCollection()->addAction("decreasewidth", decreaseWidthAction );
688 connect(decreaseWidthAction, SIGNAL(triggered(bool)), SLOT( slotDecreaseWidth() ));
689 decreaseWidthAction->setShortcut(QKeySequence(Qt::Key_Left + Qt::SHIFT));
690
691 increaseHeightAction = new KAction(i18n("Increase Height"), this);
692 actionCollection()->addAction("increaseheight", increaseHeightAction );
693 connect(increaseHeightAction, SIGNAL(triggered(bool)), SLOT( slotIncreaseHeight() ));
694 increaseHeightAction->setShortcut(QKeySequence(Qt::Key_Up + Qt::SHIFT));
695
696 decreaseHeightAction = new KAction(i18n("Decrease Height"), this);
697 actionCollection()->addAction("decreaseheight", decreaseHeightAction );
698 connect(decreaseHeightAction, SIGNAL(triggered(bool)), SLOT( slotDecreaseHeight() ));
699 decreaseHeightAction->setShortcut(QKeySequence(Qt::Key_Down + Qt::SHIFT));
700
701 toFrontAction = new KAction(i18n("Bring to Front"), this);
702 actionCollection()->addAction("tofront", toFrontAction );
703 connect(toFrontAction, SIGNAL(triggered(bool)), SLOT( slotToFront() ));
704
705 toBackAction = new KAction(i18n("Send to Back"), this);
706 actionCollection()->addAction("toback", toBackAction );
707 connect(toBackAction, SIGNAL(triggered(bool)), SLOT( slotToBack() ));
708
709 forwardOneAction = new KAction(KIcon("raise"), i18n("Bring Forward One"), this);
710 actionCollection()->addAction("forwardone", forwardOneAction );
711 connect(forwardOneAction, SIGNAL(triggered(bool) ), SLOT( slotForwardOne() ));
712 backOneAction = new KAction(KIcon("lower"), i18n("Send Back One"), this);
713 actionCollection()->addAction("backone", backOneAction );
714 connect(backOneAction, SIGNAL(triggered(bool) ), SLOT( slotBackOne() ));
715
716 areaListView->upBtn->addAction(forwardOneAction);
717 areaListView->downBtn->addAction(backOneAction);
718
719 connect( areaListView->upBtn, SIGNAL(pressed()), forwardOneAction, SLOT(trigger()));
720 connect( areaListView->downBtn, SIGNAL(pressed()), backOneAction, SLOT(trigger()));
721
722 action = new KAction(KIcon("configure"), i18n("Configure KImageMapEditor..."), this);
723 actionCollection()->addAction("configure_kimagemapeditor", action );
724 connect(action, SIGNAL(triggered(bool) ), SLOT(slotShowPreferences()));
725
726 kDebug() << "KImageMapEditor: 1";
727
728 if (areaDock) {
729
730 QAction* a = areaDock->toggleViewAction();
731 a->setText(i18n("Show Area List"));
732 actionCollection()->addAction("configure_show_arealist",
733 a);
734
735 a = mapsDock->toggleViewAction();
736 a->setText(i18n("Show Map List"));
737 actionCollection()->addAction("configure_show_maplist", a );
738
739 a = imagesDock->toggleViewAction();
740 a->setText(i18n("Show Image List"));
741 actionCollection()->addAction("configure_show_imagelist", a );
742 }
743
744 kDebug() << "KImageMapEditor: 2";
745 updateActionAccess();
746 kDebug() << "KImageMapEditor: 3";
747}
748
749void KImageMapEditor::setupStatusBar()
750{
751
752// We can't do this with a KPart !
753// widget()->statusBar()->insertItem(i18n(" Cursor")+" : x: 0 ,y: 0",STATUS_CURSOR);
754// widget()->statusBar()->insertItem(i18n(" Selection")+" : - ",STATUS_SELECTION);
755 emit setStatusBarText( i18n(" Selection: - Cursor: x: 0, y: 0 "));
756}
757
758void KImageMapEditor::slotShowPreferences()
759{
760 PreferencesDialog *dialog = new PreferencesDialog(widget(),config());
761 connect(dialog, SIGNAL(preferencesChanged()), this, SLOT(slotConfigChanged()));
762 dialog->exec();
763 delete dialog;
764}
765
766
767void KImageMapEditor::showPopupMenu(const QPoint & pos, const QString & name)
768{
769 QMenu* pop = static_cast<QMenu *>(factory()->container(name, this));
770
771 if (!pop) {
772 kWarning() << QString("KImageMapEditorPart: Missing XML definition for %1\n").arg(name);
773 return;
774 }
775
776 pop->popup(pos);
777}
778
779void KImageMapEditor::slotShowMainPopupMenu(const QPoint & pos)
780{
781 showPopupMenu(pos,"popup_main");
782}
783
784void KImageMapEditor::slotShowMapPopupMenu(const QPoint & pos)
785{
786 kDebug() << "slotShowMapPopupMenu";
787 QTreeWidgetItem* item = mapsListView->listView()->itemAt(pos);
788
789 if (isReadWrite()) {
790 mapDeleteAction->setEnabled(item);
791 mapNameAction->setEnabled(item);
792 mapDefaultAreaAction->setEnabled(item);
793 }
794
795 if (item)
796 mapsListView->selectMap(item);
797
798 showPopupMenu(mapsListView->listView()->viewport()->mapToGlobal(pos),"popup_map");
799}
800
801void KImageMapEditor::slotShowImagePopupMenu(const QPoint & pos)
802{
803 kDebug() << "slotShowImagePopupMenu";
804 QTreeWidgetItem* item = imagesListView->itemAt(pos);
805
806 imageRemoveAction->setEnabled(item);
807 imageUsemapAction->setEnabled(item);
808
809 if (item)
810 imagesListView->setCurrentItem(item);
811
812 showPopupMenu(imagesListView->viewport()->mapToGlobal(pos),"popup_image");
813}
814
815void KImageMapEditor::slotShowPopupMenu(const QPoint & p)
816{
817 QTreeWidgetItem* item = areaListView->listView->itemAt(p);
818
819 if (!item)
820 return;
821
822 if (!item->isSelected())
823 {
824 deselectAll();
825 select(item);
826 }
827
828 slotShowMainPopupMenu(areaListView->listView->viewport()->mapToGlobal(p));
829}
830
831void KImageMapEditor::updateStatusBar()
832{
833 emit setStatusBarText(selectionStatusText+" "+cursorStatusText);
834}
835
836void KImageMapEditor::slotChangeStatusCoords(int x,int y)
837{
838// statusBar()->changeItem(QString(" Cursor : x: %1 ,y: %2 ").arg(x).arg(y),STATUS_CURSOR);
839 cursorStatusText = i18n(" Cursor: x: %1, y: %2 ", x, y);
840 updateStatusBar();
841}
842
843void KImageMapEditor::slotUpdateSelectionCoords() {
844 if (selected()->count()>0) {
845 QRect r=selected()->rect();
846// statusBar()->changeItem(
847 selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ", r.left(), r.top(), r.width(), r.height());
848
849// ,STATUS_SELECTION);
850 kapp->processEvents();
851 } else
852 selectionStatusText = i18n(" Selection: - ");
853 //statusBar()->changeItem(" Selection : - ",STATUS_SELECTION);
854
855 updateStatusBar();
856}
857
858void KImageMapEditor::slotUpdateSelectionCoords( const QRect & r )
859{
860 selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ", r.left(), r.top(), r.width(), r.height());
861 updateStatusBar();
862 kapp->processEvents();
863}
864
865KApplication* KImageMapEditor::app() const
866{
867 return kapp;
868}
869
870
871void KImageMapEditor::drawToCenter(QPainter* p, const QString & str, int y, int width) {
872 int xmid = width / 2;
873
874 QFontMetrics fm = p->fontMetrics();
875 QRect strBounds = fm.boundingRect(str);
876
877 p->drawText(xmid-(strBounds.width()/2),y,str);
878}
879
880
881QImage KImageMapEditor::getBackgroundImage() {
882
883 // Lazy initialisation
884 if ( _backgroundImage.isNull() ) {
885
886
887// QString filename = QString("dropimage_")+KGlobal::locale()->language()+".png";
888// QString path = QString(); //KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/"+filename ) + "kimagemapeditor/"+filename;
889// kDebug() << "getBackgroundPic : loaded image : " << path;
890
891// if ( ! QFileInfo(path).exists() ) {
892 int width = 400;
893 int height = 400;
894 int border = 20;
895 int fontSize = 58;
896
897 QPixmap pix(width,height);
898 pix.fill(QColor(74,76,74));
899 QPainter p(&pix);
900
901 // QFont font = QFontDatabase().font("Luxi Sans","Bold",fontSize);
902 QFont font;
903 font.setBold(true);
904 font.setPixelSize(fontSize);
905 p.setFont( font );
906 p.setCompositionMode(QPainter::CompositionMode_Source);
907 p.setPen(QPen(QColor(112,114,112),1));
908
909 // The translated string must be divided into
910 // parts with about the same size that fit to the image
911 QString str = i18n("Drop an image or HTML file");
912 const QStringList strList = str.split(" ");
913
914 // Get the string parts
915 QString tmp;
916 QStringList outputStrList;
917 QFontMetrics fm = p.fontMetrics();
918
919 for ( QStringList::ConstIterator it = strList.begin(); it != strList.end(); ++it ) {
920 QString tmp2 = tmp + *it;
921
922 if (fm.boundingRect(tmp2).width() > width-border) {
923 outputStrList.append(tmp);
924 tmp = *it + ' ';
925 }
926 else
927 tmp = tmp2 + ' ';
928 }
929
930 // Last one was forgotten so add it.
931 outputStrList.append(tmp);
932
933 // Try to adjust the text vertically centered
934 int step = myround(float(height) / (outputStrList.size()+1));
935 int y = step;
936
937 for ( QStringList::Iterator it = outputStrList.begin(); it != outputStrList.end(); ++it ) {
938 drawToCenter(&p, *it, y, pix.width());
939 y += step;
940 }
941
942 p.end();
943
944 _backgroundImage = pix.toImage();
945 }
946
947
948 return _backgroundImage;
949
950/*
951 QFontDatabase fdb;
952 QStringList families = fdb.families();
953 for ( QStringList::Iterator f = families.begin(); f != families.end(); ++f ) {
954 QString family = *f;
955 qDebug( family );
956 QStringList styles = fdb.styles( family );
957 for ( QStringList::Iterator s = styles.begin(); s != styles.end(); ++s ) {
958 QString style = *s;
959 QString dstyle = "\t" + style + " (";
960 QValueList<int> smoothies = fdb.smoothSizes( family, style );
961 for ( QValueList<int>::Iterator points = smoothies.begin();
962 points != smoothies.end(); ++points ) {
963 dstyle += QString::number( *points ) + " ";
964 }
965 dstyle = dstyle.left( dstyle.length() - 1 ) + ")";
966 qDebug( dstyle );
967 }
968 }
969
970
971 path = KGlobal::dirs()->saveLocation( "data", "kimagemapeditor/" ) +filename;
972 kDebug() << "getBackgroundPic : save new image to : " << path;
973 pix.save(path,"PNG",100);
974 }
975
976 if ( ! QFileInfo(path).exists() ) {
977 kError() << "Couldn't find needed " << filename << " file in "
978 "the data directory of KImageMapEditor.\n"
979 "Perhaps you have forgotten to do a make install !" << endl;
980 exit(1);
981 }
982*/
983}
984
985
986void KImageMapEditor::addArea(Area* area) {
987 if (!area) return;
988
989 // Perhaps we've got a selection of areas
990 // so test it and add all areas of the selection
991 // nested selections are possible but doesn't exist
992 AreaSelection *selection=0L;
993 if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
994 {
995 AreaListIterator it = selection->getAreaListIterator();
996 while (it.hasNext()) {
997 Area* a = it.next();
998 areas->prepend(a);
999 a->setListViewItem(new QTreeWidgetItem(
1000 areaListView->listView,
1001 QStringList(a->attribute("href"))));
1002 a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1003 }
1004 }
1005 else
1006 {
1007 areas->prepend(area);
1008 area->setListViewItem(new QTreeWidgetItem(
1009 areaListView->listView,
1010 QStringList(area->attribute("href"))));
1011 area->listViewItem()->setIcon(1,QIcon(makeListViewPix(*area)));
1012 }
1013
1014 setModified(true);
1015
1016}
1017
1018void KImageMapEditor::addAreaAndEdit(Area* s)
1019{
1020 areas->prepend(s);
1021 s->setListViewItem(new QTreeWidgetItem(
1022 areaListView->listView,
1023 QStringList(s->attribute("href"))));
1024 s->listViewItem()->setIcon(1,QIcon(makeListViewPix(*s)));
1025 deselectAll();
1026 select(s);
1027 if (!showTagEditor(selected())) {
1028 // If the user has pressed cancel
1029 // he undos the creation
1030 commandHistory()->undo();
1031 }
1032}
1033
1034void KImageMapEditor::deleteArea( Area * area )
1035{
1036 if (!area) return;
1037
1038 // only for repaint reasons
1039 QRect redrawRect = area->selectionRect();
1040
1041 // Perhaps we've got a selection of areas
1042 // so test it and delete the whole selection
1043 // nested selections are possible but doesn't exist
1044 AreaSelection *selection=0L;
1045 if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
1046 {
1047 AreaListIterator it = selection->getAreaListIterator();
1048 while (it.hasNext()) {
1049 Area* a = it.next();
1050 currentSelected->remove(a);
1051 areas->removeAll( a );
1052 a->deleteListViewItem();
1053 }
1054 }
1055 else
1056 {
1057 deselect( area );
1058 areas->removeAll( area );
1059 area->deleteListViewItem();
1060 }
1061
1062 drawZone->repaintRect(redrawRect);
1063
1064
1065 // Only to disable cut and copy actions
1066 if (areas->count()==0)
1067 deselectAll();
1068
1069 setModified(true);
1070}
1071
1072void KImageMapEditor::deleteSelected() {
1073
1074 AreaListIterator it = currentSelected->getAreaListIterator();
1075 while (it.hasNext()) {
1076 Area *a = it.next();
1077 currentSelected->remove( a );
1078 areas->removeAll( a );
1079 delete a->listViewItem();
1080 }
1081
1082
1083 drawZone->repaintArea( *currentSelected );
1084 // Only to disable cut and copy actions
1085 if (areas->count()==0)
1086 deselectAll();
1087
1088 setModified(true);
1089}
1090
1091void KImageMapEditor::deleteAllAreas()
1092{
1093 Area* a;
1094 foreach (a,*areas) {
1095 deselect( a );
1096 areas->removeAll( a );
1097 a->deleteListViewItem();
1098 if (!areas->isEmpty())
1099 a = areas->first(); // because the current is deleted
1100 }
1101
1102 drawZone->repaint();
1103
1104}
1105
1106void KImageMapEditor::updateAllAreas()
1107{
1108// kDebug() << "KImageMapEditor::updateAllAreas";
1109 Area* a;
1110 foreach(a,*areas) {
1111 a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1112 }
1113 drawZone->repaint();
1114}
1115
1116void KImageMapEditor::updateSelection() const {
1117 //FIXME: areaListView->listView->triggerUpdate();
1118}
1119
1120AreaSelection* KImageMapEditor::selected() const {
1121 return currentSelected;
1122}
1123
1124void KImageMapEditor::select(Area* a)
1125{
1126 if (!a) return;
1127
1128 currentSelected->add(a);
1129 updateActionAccess();
1130 slotUpdateSelectionCoords();
1131// drawZone->repaintArea( *a);
1132
1133}
1134
1135void KImageMapEditor::selectWithoutUpdate(Area* a)
1136{
1137 if (!a) return;
1138 currentSelected->add(a);
1139}
1140
1141void KImageMapEditor::slotSelectionChanged()
1142{
1143 AreaListIterator it = areaList();
1144 AreaList list = currentSelected->getAreaList();
1145
1146 while (it.hasNext()) {
1147 Area* a = it.next();
1148 if ( a->listViewItem()->isSelected() != (list.contains(a)) )
1149 {
1150 a->listViewItem()->isSelected()
1151 ? select( a )
1152 : deselect( a );
1153
1154 drawZone->repaintArea( *a);
1155 }
1156 }
1157
1158}
1159
1160void KImageMapEditor::select( QTreeWidgetItem* item)
1161{
1162
1163 AreaListIterator it = areaList();
1164 while (it.hasNext()) {
1165 Area* a = it.next();
1166 if (a->listViewItem() == item )
1167 {
1168 select( a );
1169 drawZone->repaintArea( *a);
1170 }
1171 }
1172
1173
1174}
1175
1176AreaListIterator KImageMapEditor::areaList() const {
1177 AreaListIterator it(*areas);
1178 return it;
1179}
1180
1181
1182void KImageMapEditor::slotAreaChanged(Area *area)
1183{
1184 if (!area)
1185 return;
1186
1187 setModified(true);
1188
1189 AreaSelection *selection=0L;
1190 if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
1191 {
1192 AreaListIterator it = selection->getAreaListIterator();
1193 while (it.hasNext()) {
1194 Area* a = it.next();
1195 if (a->listViewItem()) {
1196 a->listViewItem()->setText(0,a->attribute("href"));
1197 a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1198 }
1199 }
1200
1201 }
1202 else
1203 if (area->listViewItem()) {
1204 area->listViewItem()->setText(0,area->attribute("href"));
1205 area->listViewItem()->setIcon(1,QIcon(makeListViewPix(*area)));
1206 }
1207
1208 drawZone->repaintArea(*area);
1209
1210}
1211
1212void KImageMapEditor::deselect(Area* a)
1213{
1214 if (a) {
1215 currentSelected->remove(a);
1216// drawZone->repaintArea(*a);
1217 updateActionAccess();
1218 slotUpdateSelectionCoords();
1219 }
1220}
1221
1222void KImageMapEditor::deselectWithoutUpdate(Area* a)
1223{
1224 if (a) {
1225 currentSelected->remove(a);
1226 }
1227}
1228
1229
1230/**
1231* Makes sure, that the actions cut, copy, delete and
1232* show properties
1233* can only be executed if sth. is selected.
1234**/
1235void KImageMapEditor::updateActionAccess()
1236{
1237 if (!isReadWrite())
1238 return;
1239
1240 if ( 0 < selected()->count())
1241 {
1242 kDebug() << "actions enabled";
1243 areaPropertiesAction->setEnabled(true);
1244 deleteAction->setEnabled(true);
1245 copyAction->setEnabled(true);
1246 cutAction->setEnabled(true);
1247 moveLeftAction->setEnabled(true);
1248 moveRightAction->setEnabled(true);
1249 moveUpAction->setEnabled(true);
1250 moveDownAction->setEnabled(true);
1251 toFrontAction->setEnabled(true);
1252 toBackAction->setEnabled(true);
1253
1254 if ( (selected()->count() == 1) )
1255 {
1256 if (selected()->type()==Area::Polygon)
1257 {
1258 increaseWidthAction->setEnabled(false);
1259 decreaseWidthAction->setEnabled(false);
1260 increaseHeightAction->setEnabled(false);
1261 decreaseHeightAction->setEnabled(false);
1262 addPointAction->setEnabled(true);
1263 removePointAction->setEnabled(true);
1264 }
1265 else
1266 {
1267 increaseWidthAction->setEnabled(true);
1268 decreaseWidthAction->setEnabled(true);
1269 increaseHeightAction->setEnabled(true);
1270 decreaseHeightAction->setEnabled(true);
1271 addPointAction->setEnabled(false);
1272 removePointAction->setEnabled(false);
1273 }
1274
1275 }
1276 else
1277 {
1278 increaseWidthAction->setEnabled(false);
1279 decreaseWidthAction->setEnabled(false);
1280 increaseHeightAction->setEnabled(false);
1281 decreaseHeightAction->setEnabled(false);
1282 addPointAction->setEnabled(false);
1283 removePointAction->setEnabled(false);
1284 }
1285
1286 }
1287 else
1288 {
1289 kDebug() << "Actions disabled";
1290 areaPropertiesAction->setEnabled(false);
1291 deleteAction->setEnabled(false);
1292 copyAction->setEnabled(false);
1293 cutAction->setEnabled(false);
1294 moveLeftAction->setEnabled(false);
1295 moveRightAction->setEnabled(false);
1296 moveUpAction->setEnabled(false);
1297 moveDownAction->setEnabled(false);
1298 increaseWidthAction->setEnabled(false);
1299 decreaseWidthAction->setEnabled(false);
1300 increaseHeightAction->setEnabled(false);
1301 decreaseHeightAction->setEnabled(false);
1302 toFrontAction->setEnabled(false);
1303 toBackAction->setEnabled(false);
1304 addPointAction->setEnabled(false);
1305 removePointAction->setEnabled(false);
1306
1307 }
1308
1309 updateUpDownBtn();
1310}
1311
1312void KImageMapEditor::updateUpDownBtn()
1313{
1314 if (!isReadWrite())
1315 return;
1316
1317 AreaList list = currentSelected->getAreaList();
1318
1319 if (list.isEmpty() || (areas->count() < 2)) {
1320 forwardOneAction->setEnabled(false);
1321 areaListView->upBtn->setEnabled(false);
1322 backOneAction->setEnabled(false);
1323 areaListView->downBtn->setEnabled(false);
1324 return;
1325 }
1326 // if the first Area is in the selection can't move up
1327 if (list.contains( areas->first() )) {
1328 forwardOneAction->setEnabled(false);
1329 areaListView->upBtn->setEnabled(false);
1330 } else {
1331 forwardOneAction->setEnabled(true);
1332 areaListView->upBtn->setEnabled(true);
1333 }
1334
1335 drawZone->repaintArea(*currentSelected);
1336
1337 // if the last Area is in the selection can't move down
1338 if (list.contains( areas->last() )) {
1339 backOneAction->setEnabled(false);
1340 areaListView->downBtn->setEnabled(false);
1341 }
1342 else {
1343 backOneAction->setEnabled(true);
1344 areaListView->downBtn->setEnabled(true);
1345 }
1346
1347}
1348
1349void KImageMapEditor::deselectAll()
1350{
1351 QRect redrawRect= currentSelected->selectionRect();
1352 currentSelected->reset();
1353 drawZone->repaintRect(redrawRect);
1354 updateActionAccess();
1355}
1356
1357Area* KImageMapEditor::onArea(const QPoint & p) const {
1358 Area* s;
1359 foreach(s,*areas) {
1360 if (s->contains(p))
1361 return s;
1362 }
1363 return 0L;
1364}
1365
1366
1367int KImageMapEditor::showTagEditor(Area *a) {
1368 if (!a) return 0;
1369 drawZone->repaintArea(*a);
1370
1371 AreaDialog *dialog= new AreaDialog(this,a);
1372 connect (dialog, SIGNAL(areaChanged(Area*)), this, SLOT(slotAreaChanged(Area*)));
1373
1374 int result = dialog->exec();
1375
1376 return result;
1377
1378
1379}
1380
1381int KImageMapEditor::showTagEditor(QTreeWidgetItem *item) {
1382 if (!item)
1383 return 0;
1384
1385 Area* a;
1386 foreach(a,*areas) {
1387 if (a->listViewItem()==item) {
1388 return showTagEditor(a);
1389 }
1390 }
1391 return 0;
1392}
1393
1394int KImageMapEditor::showTagEditor() {
1395 return showTagEditor(selected());
1396}
1397
1398
1399QString KImageMapEditor::getHTMLImageMap() const {
1400 QString retStr;
1401 retStr+="<map "+QString("name=\"")+_mapName+"\">\n";
1402
1403 Area* a;
1404 foreach(a,*areas) {
1405 retStr+=" "+a->getHTMLCode()+'\n';
1406 }
1407
1408 if (defaultArea && defaultArea->finished())
1409 retStr+=" "+defaultArea->getHTMLCode()+'\n';
1410
1411 retStr+="</map>";
1412 return retStr;
1413}
1414
1415QPixmap KImageMapEditor::makeListViewPix(Area & a)
1416{
1417 QPixmap pix=a.cutOut(drawZone->picture());
1418
1419 double shrinkFactor=1;
1420
1421 // picture fits into max row height ?
1422 if (maxAreaPreviewHeight < pix.height())
1423 shrinkFactor = ( (double) maxAreaPreviewHeight / pix.height() );
1424
1425 QPixmap pix2((int)(pix.width()*shrinkFactor), (int)(pix.height()*shrinkFactor));
1426
1427 // Give all pixels a defined color
1428 pix2.fill(Qt::white);
1429
1430 QPainter p(&pix2);
1431
1432 p.scale(shrinkFactor,shrinkFactor);
1433 p.drawPixmap(0,0,pix);
1434
1435 return pix2;
1436}
1437
1438void KImageMapEditor::setMapName(const QString & s) {
1439 mapsListView->changeMapName(_mapName, s);
1440 _mapName=s;
1441 currentMapElement->mapTag->name = s;
1442}
1443
1444
1445void KImageMapEditor::setPicture(const KUrl & url) {
1446 _imageUrl=url;
1447 if (QFileInfo(url.path()).exists()) {
1448 QImage img(url.path());
1449
1450 if (!img.isNull()) {
1451 setPicture(img);
1452 imageRemoveAction->setEnabled(true);
1453 imageUsemapAction->setEnabled(true);
1454 }
1455 else
1456 kError() << QString("The image %1 could not be opened.").arg(url.path()) << endl;
1457 }
1458 else
1459 kError() << QString("The image %1 does not exist.").arg(url.path()) << endl;
1460}
1461
1462void KImageMapEditor::setPicture(const QImage & pix) {
1463 drawZone->setPicture(pix);
1464 updateAllAreas();
1465}
1466
1467
1468void KImageMapEditor::slotDrawArrow() {
1469 _currentToolType=KImageMapEditor::Selection;
1470
1471}
1472
1473void KImageMapEditor::slotDrawCircle() {
1474 _currentToolType=KImageMapEditor::Circle;
1475 kDebug() << "slotDrawCircle";
1476
1477}
1478
1479void KImageMapEditor::slotDrawRectangle() {
1480 _currentToolType=KImageMapEditor::Rectangle;
1481 kDebug() << "slotDrawRectangle";
1482
1483}
1484
1485void KImageMapEditor::slotDrawPolygon() {
1486 _currentToolType=KImageMapEditor::Polygon;
1487 kDebug() << "slotDrawPolygon";
1488}
1489
1490void KImageMapEditor::slotDrawFreehand() {
1491 _currentToolType=KImageMapEditor::Freehand;
1492}
1493
1494void KImageMapEditor::slotDrawAddPoint() {
1495 _currentToolType=KImageMapEditor::AddPoint;
1496}
1497
1498void KImageMapEditor::slotDrawRemovePoint() {
1499 _currentToolType=KImageMapEditor::RemovePoint;
1500}
1501
1502
1503void KImageMapEditor::slotZoom() {
1504
1505 int i=zoomAction->currentItem();
1506 switch (i) {
1507 case 0 : drawZone->setZoom(0.25);break;
1508 case 1 : drawZone->setZoom(0.5);break;
1509 case 2 : drawZone->setZoom(1);break;
1510 case 3 : drawZone->setZoom(1.5);break;
1511 case 4 : drawZone->setZoom(2.0);break;
1512 case 5 : drawZone->setZoom(2.5);break;
1513 case 6 : drawZone->setZoom(3);break;
1514 case 7 : drawZone->setZoom(5);break;
1515 case 8 : drawZone->setZoom(7.5);break;
1516 case 9 : drawZone->setZoom(10);break;
1517 }
1518 if (i<10)
1519 zoomInAction->setEnabled(true);
1520 else
1521 zoomInAction->setEnabled(false);
1522
1523 if (i>0)
1524 zoomOutAction->setEnabled(true);
1525 else
1526 zoomOutAction->setEnabled(false);
1527}
1528
1529void KImageMapEditor::slotZoomIn() {
1530 if (zoomAction->currentItem()==(int)(zoomAction->items().count()-1))
1531 return;
1532
1533 zoomAction->setCurrentItem(zoomAction->currentItem()+1);
1534 slotZoom();
1535}
1536
1537void KImageMapEditor::slotZoomOut() {
1538 if (zoomAction->currentItem()==0)
1539 return;
1540
1541 zoomAction->setCurrentItem(zoomAction->currentItem()-1);
1542 slotZoom();
1543}
1544
1545void KImageMapEditor::mapDefaultArea()
1546{
1547 if (defaultArea)
1548 showTagEditor(defaultArea);
1549 else {
1550 defaultArea= new DefaultArea();
1551 showTagEditor(defaultArea);
1552 }
1553
1554}
1555
1556void KImageMapEditor::mapEditName()
1557{
1558 bool ok=false;
1559 QString input = KInputDialog::getText(i18n("Enter Map Name"),
1560 i18n("Enter the name of the map:"),
1561 _mapName,&ok,widget());
1562 if (ok) {
1563 if (input != _mapName) {
1564 if (mapsListView->nameAlreadyExists(input))
1565 KMessageBox::sorry(this->widget(), i18n("The name <em>%1</em> already exists.", input));
1566 else {
1567 setMapName(input);
1568 }
1569 }
1570 }
1571}
1572
1573void KImageMapEditor::mapShowHTML()
1574{
1575 KDialog *dialog= new KDialog(widget());
1576 dialog->setModal(true);
1577 dialog->setCaption(i18n("HTML Code of Map"));
1578 dialog->setButtons(KDialog::Ok);
1579 dialog->setDefaultButton(KDialog::Ok);
1580 QTextEdit *edit = new QTextEdit(dialog);
1581
1582 edit->setPlainText(getHtmlCode());
1583 edit->setReadOnly(true);
1584 edit->setLineWrapMode(QTextEdit::NoWrap);
1585 dialog->setMainWidget(edit);
1586// dialog->resize(dialog->calculateSize(edit->maxLineWidth(),edit->numLines()*));
1587// dialog->adjustSize();
1588 dialog->resize(600,400);
1589 dialog->exec();
1590 delete dialog;
1591}
1592
1593void KImageMapEditor::openFile(const KUrl & url) {
1594 if ( ! url.isEmpty()) {
1595 QString ext=QFileInfo(url.path()).completeSuffix().toLower();
1596
1597 if (ext=="png" || ext=="jpg" || ext=="jpeg" || ext=="gif" ||
1598 ext=="bmp" || ext=="xbm" || ext=="xpm" || ext=="mng" || ext=="pnm")
1599 addImage(url);
1600 else
1601 openURL(url);
1602 }
1603}
1604
1605bool KImageMapEditor::openURL(const KUrl & url) {
1606 // If a local file does not exist
1607 // we start with an empty file, so
1608 // that we can return true here.
1609 // For non local files, we cannot check
1610 // the existence
1611 if (url.isLocalFile() &&
1612 ! QFile::exists(url.path()))
1613 return true;
1614 return KParts::ReadWritePart::openUrl(url);
1615}
1616
1617void KImageMapEditor::fileOpen() {
1618
1619 QString fileName = KFileDialog::getOpenFileName(KUrl(),
1620 i18n("*.png *.jpg *.jpeg *.gif *.htm *.html|Web File\n"
1621 "*.png *.jpg *.jpeg *.gif *.bmp *.xbm *.xpm *.pnm *.mng|Images\n"
1622 "*.htm *.html|HTML Files\n"
1623 "*.png|PNG Images\n*.jpg *.jpeg|JPEG Images\n*.gif|GIF-Images\n*|All Files"),
1624 widget(),i18n("Choose File to Open"));
1625
1626 openFile(KUrl( fileName ));
1627}
1628
1629
1630
1631void KImageMapEditor::fileClose()
1632{
1633 if (! closeUrl())
1634 return;
1635
1636
1637 setPicture(getBackgroundImage());
1638 recentFilesAction->setCurrentItem(-1);
1639 setModified(false);
1640}
1641
1642void KImageMapEditor::fileSave()
1643{
1644 // if we aren't read-write, return immediately
1645 if ( ! isReadWrite() )
1646 return;
1647
1648 if (url().isEmpty()) {
1649 fileSaveAs();
1650 }
1651 else {
1652 saveFile();
1653 setModified(false);
1654 }
1655
1656
1657}
1658
1659void KImageMapEditor::fileSaveAs() {
1660
1661 KUrl url = KFileDialog::getSaveUrl(KUrl(),"*.htm *.html|" + i18n( "HTML File" ) +
1662 "\n*.txt|" + i18n( "Text File" ) + "\n*|" + i18n( "All Files" ),widget());
1663 if (url.isEmpty() || !url.isValid()) {
1664 return;
1665 }
1666
1667
1668 QFileInfo fileInfo(url.path());
1669
1670 if ( fileInfo.exists() )
1671 {
1672 if (KMessageBox::warningContinueCancel(widget(),
1673 i18n("<qt>The file <em>%1</em> already exists.<br />Do you want to overwrite it?</qt>", fileInfo.fileName()),
1674 i18n("Overwrite File?"), KGuiItem(i18n("Overwrite")))==KMessageBox::Cancel)
1675 return;
1676
1677 if(!fileInfo.isWritable()) {
1678 KMessageBox::sorry(widget(), i18n("<qt>You do not have write permission for the file <em>%1</em>.</qt>", fileInfo.fileName()));
1679 return;
1680 }
1681 }
1682
1683
1684 saveAs(url);
1685 recentFilesAction->addUrl(url);
1686
1687}
1688
1689
1690bool KImageMapEditor::openFile()
1691{
1692 KUrl u = url();
1693 QFileInfo fileInfo(u.path());
1694
1695 if ( !fileInfo.exists() )
1696 {
1697 KMessageBox::information(widget(),
1698 i18n("<qt>The file <b>%1</b> does not exist.</qt>", fileInfo.fileName()),
1699 i18n("File Does Not Exist"));
1700 return false;
1701 }
1702
1703 openHTMLFile(u);
1704
1705 drawZone->repaint();
1706 recentFilesAction->addUrl(u);
1707 setModified(false);
1708 backupFileCreated = false;
1709 return true;
1710}
1711
1712/**
1713 * This method supposes that the given QTextStream s has just read
1714 * the &lt; of a tag. It now reads all attributes of the tag until a &gt;
1715 * The tagname itself is also read and stored as a <em>tagname</em>
1716 * attribute. After parsing the whole tag it returns a QDict<QString>
1717 * with all attributes and their values. It stores the whole read text in the
1718 * parameter readText.
1719 */
1720QHash<QString,QString> KImageMapEditor::getTagAttributes(QTextStream & s, QString & readText)
1721{
1722 QHash<QString,QString> dict;
1723 // the "<" is already read
1724 QChar w;
1725 QString attr,value;
1726
1727 readText.clear();
1728
1729 // get the tagname
1730 while (!s.atEnd() && w!=' ') {
1731 s >> w;
1732 readText.append(w);
1733 if (w.isSpace() || w=='>') {
1734 dict.insert("tagname",value);
1735 break;
1736 }
1737 value+=w;
1738 }
1739
1740
1741 // do we have a comment ?
1742 // read the comment and return
1743 if (value.right(3)=="-->")
1744 return dict;
1745
1746 if (value.startsWith("!--")) {
1747 while (!s.atEnd()) {
1748 s >> w;
1749 readText.append(w);
1750
1751 if (w=='-') {
1752 s >> w;
1753 readText.append(w);
1754 if (w=='-') {
1755 s >> w;
1756 readText.append(w);
1757 if (w=='>')
1758 return dict;
1759 }
1760 }
1761 }
1762 }
1763
1764 bool attrRead=true; // currently reading an attribute ?
1765 bool equalSign=false; // an equalsign was read?
1766 bool valueRead=false; // currently reading a value ?
1767 QChar quotation='\0'; // currently reading a value with quotation marks ?
1768 bool php=false; // currently reading a php script
1769 attr.clear();
1770 value.clear();
1771
1772 //get the other attributes
1773 while (!s.atEnd() && w!='>')
1774 {
1775 s >> w;
1776 readText.append(w);
1777
1778 // End of PHP Script ?
1779 if (php && (w=='?') )
1780 {
1781 s >> w;
1782 readText.append(w);
1783
1784 if (valueRead)
1785 value+=w;
1786
1787 if (w=='>')
1788 {
1789 php = false;
1790 s >> w;
1791 readText.append(w);
1792 }
1793 }
1794
1795 // Wrong syntax or PHP-Script !
1796 if (!php && (w=='<'))
1797 {
1798 if (valueRead)
1799 value+=w;
1800 s >> w;
1801 readText.append(w);
1802 if (valueRead)
1803 value+=w;
1804
1805 if (w=='?')
1806 {
1807 php = true;
1808 }
1809 } else
1810 // finished ?
1811 if (w=='>') {
1812 if (valueRead)
1813 dict.insert(attr,value);
1814 return dict;
1815 } else
1816 // currently reading an attribute ?
1817 if (attrRead) {
1818 // if there is a whitespace the attributename has finished
1819 // possibly there isn't any value e.g. noshade
1820 if (w.isSpace())
1821 attrRead=false;
1822 else
1823 // an equal sign signals that the value follows
1824 if (w=='=') {
1825 attrRead=false;
1826 equalSign=true;
1827 } else
1828 attr+=w;
1829 } else
1830 // an equal sign was read ? delete every whitespace
1831 if (equalSign) {
1832 if (!w.isSpace()) {
1833 equalSign=false;
1834 valueRead=true;
1835 if (w=='"' || w=='\'')
1836 quotation=w;
1837 }
1838 } else
1839 // currently reading the value
1840 if (valueRead) {
1841 // if php, read without regarding anything
1842 if (php)
1843 value+=w;
1844 // if value within quotation marks is read
1845 // only stop when another quotationmark is found
1846 else
1847 if (quotation != '\0') {
1848 if (quotation!=w) {
1849 value+=w;
1850 } else {
1851 quotation='\0';
1852 valueRead=false;
1853 dict.insert(attr,value);
1854 attr.clear();
1855 value.clear();
1856 }
1857 } else
1858 // a whitespace indicates that the value has finished
1859 if (w.isSpace()) {
1860 valueRead=false;
1861 dict.insert(attr,value);
1862 attr.clear();
1863 value.clear();
1864 }
1865 } else {
1866 if (!w.isSpace()) {
1867 attrRead=true;
1868 attr+=w;
1869 }
1870 }
1871 }
1872
1873 return dict;
1874
1875}
1876
1877
1878bool KImageMapEditor::openHTMLFile(const KUrl & url)
1879{
1880 QFile f(url.path());
1881 if ( !f.exists () )
1882 return false;
1883 f.open(QIODevice::ReadOnly);
1884 QTextStream s(&f);
1885 QString str;
1886 QChar w;
1887 QHash<QString,QString> *attr=0L;
1888 QList<ImageTag*> images;
1889 MapTag *map=0L;
1890 QList<MapTag*> maps;
1891
1892 _htmlContent.clear();
1893 currentMapElement = 0L;
1894
1895 QString temp;
1896 QString origcode;
1897
1898 bool readMap=false;
1899
1900 while (!s.atEnd()) {
1901
1902 s >> w;
1903 if (w=='<')
1904 {
1905 if (!readMap && !origcode.isEmpty()) {
1906 _htmlContent.append( new HtmlElement(origcode));
1907 origcode.clear();
1908 }
1909
1910 origcode.append("<");
1911 attr=new QHash<QString,QString>(getTagAttributes(s,temp));
1912 origcode.append(temp);
1913
1914 if (attr->contains("tagname")) {
1915 QString tagName = attr->value("tagname").toLower();
1916 if (tagName =="img") {
1917 HtmlImgElement *el = new HtmlImgElement(origcode);
1918 el->imgTag = static_cast<ImageTag*>(attr);
1919 images.append(el->imgTag);
1920 _htmlContent.append(el);
1921
1922 origcode.clear();
1923 } else
1924 if (tagName == "map") {
1925 map = new MapTag();
1926 map->name = attr->value("name");
1927 kDebug() << "KImageMapEditor::openHTMLFile: found map with name:" << map->name;
1928
1929 readMap=true;
1930 } else
1931 if (tagName=="/map") {
1932 readMap=false;
1933 maps.append(map);
1934 HtmlMapElement *el = new HtmlMapElement(origcode);
1935 el->mapTag = map;
1936 _htmlContent.append(el);
1937
1938 origcode.clear();
1939 } else
1940 if (readMap) {
1941 if (tagName=="area") {
1942 map->prepend(*attr);
1943 }
1944 } else {
1945 _htmlContent.append(new HtmlElement(origcode));
1946 origcode.clear();
1947 }
1948
1949 }
1950 } // w != "<"
1951 else {
1952 origcode.append(w);
1953 }
1954 }
1955
1956 if (!origcode.isEmpty()) {
1957 _htmlContent.append(new HtmlElement(origcode));
1958 }
1959
1960 f.close();
1961
1962 KUrl imageUrl;
1963
1964 map = 0L;
1965
1966 // If we have more than on map or more than one image
1967 // Let the user choose, otherwise take the only ones
1968 if (maps.count() > 1) {
1969 map = maps.first();
1970 }
1971
1972 if (images.count() > 1) {
1973 ImageTag* imgTag = images.first();
1974 if (imgTag) {
1975 if (imgTag->contains("src"))
1976 imageUrl = KUrl(url,imgTag->value("src"));
1977 }
1978 }
1979
1980 // If there is more than one map and more than one image
1981 // use the map that has an image with an according usemap tag
1982 if (maps.count() > 1 && images.count() > 1) {
1983 bool found = false;
1984 MapTag *mapTag;
1985 foreach(mapTag, maps) {
1986 ImageTag *imageTag;
1987 foreach(imageTag, images) {
1988 if (imageTag->contains("usemap")) {
1989 QString usemap = imageTag->value("usemap");
1990 // Remove the #
1991 QString usemapName = usemap.right(usemap.length()-1);
1992 if (usemapName == mapTag->name) {
1993 if (imageTag->contains("src")) {
1994 imageUrl = KUrl(url,imageTag->value("src"));
1995 found = true;
1996 }
1997 }
1998 }
1999 if (found)
2000 break;
2001 }
2002 if (found)
2003 break;
2004 }
2005 if (found) {
2006 map = mapTag;
2007 }
2008 }
2009
2010
2011 // If there are more than one map or there wasn't
2012 // found a fitting image and there is something to choose
2013 // let the user choose
2014 /* if (maps.count() >1 || (imageUrl.isEmpty() && images.count() > 1))
2015 {
2016 ImageMapChooseDialog dialog(widget(),maps,images,url);
2017 kDebug() << "KImageMapEditor::openHTMLFile: before dialog->exec()";
2018 dialog.exec();
2019 kDebug() << "KImageMapEditor::openHTMLFile: after dialog->exec()";
2020 map = dialog.currentMap;
2021 imageUrl = dialog.pixUrl;
2022 }*/
2023
2024
2025 imagesListView->clear();
2026 imagesListView->setBaseUrl(url);
2027 imagesListView->addImages(images);
2028
2029 mapsListView->clear();
2030 mapsListView->addMaps(maps);
2031
2032
2033 setMapActionsEnabled(false);
2034
2035 if (map) {
2036 mapsListView->selectMap(map->name);
2037 } else {
2038#ifdef WITH_TABWIDGET
2039 if (tabWidget)
2040 tabWidget->showPage(mapsListView);
2041#endif
2042 }
2043
2044
2045 if (!imageUrl.isEmpty()) {
2046 setPicture(imageUrl);
2047 } else {
2048 setPicture(getBackgroundImage());
2049#ifdef WITH_TABWIDGET
2050 if (tabWidget)
2051 tabWidget->showPage(imagesListView);
2052#endif
2053 }
2054
2055
2056 emit setWindowCaption(url.fileName());
2057 setModified(false);
2058 return true;
2059}
2060
2061/**
2062 * Finds the first html element which contains the given text.
2063 * Returns the first matching element.
2064 * Returns 0L if no element was found.
2065 */
2066HtmlElement* KImageMapEditor::findHtmlElement(const QString & containingText) {
2067 HtmlElement *el;
2068 foreach (el,_htmlContent) {
2069 if (el->htmlCode.contains(containingText,Qt::CaseInsensitive)) {
2070 return el;
2071 }
2072 }
2073 return 0L;
2074}
2075
2076/**
2077 * Finds the first html element which contains the given ImageTag.
2078 * Returns the first matching element.
2079 * Returns 0L if no element was found.
2080 */
2081HtmlImgElement* KImageMapEditor::findHtmlImgElement(ImageTag* tag) {
2082 HtmlElement* el;
2083 foreach(el,_htmlContent) {
2084 HtmlImgElement* imgEl = dynamic_cast<HtmlImgElement*>(el);
2085
2086 if (imgEl && imgEl->imgTag == tag)
2087 return imgEl;
2088 }
2089 return 0L;
2090}
2091
2092void KImageMapEditor::addMap(const QString & name = QString()) {
2093 HtmlMapElement* el = new HtmlMapElement("\n<map></map>");
2094 MapTag* map = new MapTag();
2095 map->name = name;
2096 el->mapTag = map;
2097
2098 // Try to find the body tag
2099 HtmlElement* bodyTag = findHtmlElement("<body");
2100
2101 // if we found one add the new map right after the body tag
2102 if (bodyTag) {
2103 uint index = _htmlContent.indexOf(bodyTag);
2104
2105 // Add a newline before the map
2106 _htmlContent.insert(index+1, new HtmlElement("\n"));
2107
2108 _htmlContent.insert(index+2, el);
2109 } // if there is no body tag we add the map to the end of the file
2110 else {
2111 // Add a newline before the map
2112 _htmlContent.append(new HtmlElement("\n"));
2113
2114 _htmlContent.append(el);
2115 kDebug() << "KImageMapEditor::addMap : No <body found ! Appending new map to the end.";
2116 }
2117
2118 mapsListView->addMap(name);
2119 mapsListView->selectMap(name);
2120}
2121
2122/**
2123 * Finds the HtmlMapElement in the HtmlContent, that corresponds
2124 * to the given map name.<br>
2125 * Returns 0L if there exists no map with the given name
2126 */
2127HtmlMapElement* KImageMapEditor::findHtmlMapElement(const QString & mapName) {
2128 foreach(HtmlElement * el,_htmlContent) {
2129 if (dynamic_cast<HtmlMapElement*>(el)) {
2130 HtmlMapElement *tagEl = static_cast<HtmlMapElement*>(el);
2131 if (tagEl->mapTag->name == mapName) {
2132 return tagEl;
2133 }
2134 }
2135 }
2136
2137 kWarning() << "KImageMapEditor::findHtmlMapElement: couldn't find map '" << mapName << "'";
2138 return 0L;
2139}
2140
2141/**
2142 * Calls setMap with the HtmlMapElement with the given map name
2143 */
2144void KImageMapEditor::setMap(const QString & mapName) {
2145 HtmlMapElement* el = findHtmlMapElement(mapName);
2146 if (!el) {
2147 kWarning() << "KImageMapEditor::setMap : Couldn't set map '" << mapName << "', because it wasn't found !";
2148 return;
2149 }
2150
2151 setMap(el);
2152
2153}
2154
2155void KImageMapEditor::setMap(MapTag* map) {
2156 HtmlElement * el;
2157 foreach(el,_htmlContent) {
2158 HtmlMapElement *tagEl = dynamic_cast<HtmlMapElement*>(el);
2159 if (tagEl) {
2160 if (tagEl->mapTag == map) {
2161 setMap(tagEl);
2162 break;
2163 }
2164 }
2165 }
2166
2167}
2168
2169void KImageMapEditor::saveAreasToMapTag(MapTag* map) {
2170 map->clear();
2171 Area* a;
2172 foreach(a,*areas) {
2173 QString shapeStr;
2174
2175 switch (a->type()) {
2176 case Area::Rectangle : shapeStr = "rect";break;
2177 case Area::Circle : shapeStr = "circle";break;
2178 case Area::Polygon : shapeStr = "poly";break;
2179 default : continue;
2180 }
2181
2182 QHash<QString,QString> dict;
2183 dict.insert("shape",shapeStr);
2184
2185 AttributeIterator it = a->attributeIterator();
2186 while (it.hasNext())
2187 {
2188 it.next();
2189 dict.insert(it.key(),it.value());
2190 }
2191
2192 dict.insert("coords",a->coordsToString());
2193
2194 map->append(dict);
2195
2196 }
2197
2198 if (defaultArea && defaultArea->finished()) {
2199 QHash<QString,QString> dict;
2200 dict.insert("shape","default");
2201
2202 AttributeIterator it = defaultArea->attributeIterator();
2203 while (it.hasNext())
2204 {
2205 it.next();
2206 dict.insert(it.key(),it.value());
2207 }
2208
2209 map->append(dict);
2210 }
2211
2212}
2213
2214static void setAttribute(Area* a, const AreaTag & tag, const QString & s) {
2215 if (tag.contains(s))
2216 a->setAttribute(s,tag.value(s));
2217}
2218
2219void KImageMapEditor::setMap(HtmlMapElement* mapElement) {
2220 if (currentMapElement) {
2221 currentMapElement->mapTag->modified=true;
2222 currentMapElement->htmlCode = getHTMLImageMap();
2223 saveAreasToMapTag(currentMapElement->mapTag);
2224 }
2225
2226 currentMapElement = mapElement;
2227 MapTag* map = currentMapElement->mapTag;
2228
2229 // Remove old areas only if a new map is loaded
2230 deleteAllAreas();
2231 delete defaultArea;
2232 defaultArea = 0L;
2233// kDebug() << "KImageMapEditor::setMap : Setting new map : " << map->name;
2234 _mapName = map->name;
2235 AreaTag tag;
2236
2237 QLinkedListIterator<AreaTag> it(*map);
2238 while (it.hasNext()) {
2239 tag = it.next();
2240 QString shape="rect";
2241 if (tag.contains("shape"))
2242 shape=tag.value("shape");
2243
2244 Area::ShapeType type=Area::Rectangle;
2245 if (shape=="circle")
2246 type=Area::Circle;
2247 else if (shape=="poly")
2248 type=Area::Polygon;
2249 else if (shape=="default")
2250 type=Area::Default;
2251
2252 Area* a=AreaCreator::create(type);
2253
2254 setAttribute(a,tag,"href");
2255 setAttribute(a,tag,"alt");
2256 setAttribute(a,tag,"target");
2257 setAttribute(a,tag,"title");
2258 setAttribute(a,tag,"onclick");
2259 setAttribute(a,tag,"ondblclick");
2260 setAttribute(a,tag,"onmousedown");
2261 setAttribute(a,tag,"onmouseup");
2262 setAttribute(a,tag,"onmouseover");
2263 setAttribute(a,tag,"onmousemove");
2264 setAttribute(a,tag,"onmouseout");
2265
2266 if (type==Area::Default) {
2267 defaultArea=a;
2268 defaultArea->setFinished(true);
2269 continue;
2270 }
2271
2272 if (tag.contains("coords"))
2273 a->setCoords(tag.value("coords"));
2274
2275 a->setMoving(false);
2276 addArea(a);
2277 }
2278
2279 updateAllAreas();
2280
2281 setMapActionsEnabled(true);
2282}
2283
2284/**
2285 * Sets whether actions that depend on an selected map
2286 * are enabled
2287 */
2288void KImageMapEditor::setMapActionsEnabled(bool b) {
2289 mapDeleteAction->setEnabled(b);
2290 mapDefaultAreaAction->setEnabled(b);
2291 mapNameAction->setEnabled(b);
2292
2293 arrowAction->setChecked(true);
2294 slotDrawArrow();
2295
2296 arrowAction->setEnabled(b);
2297 circleAction->setEnabled(b);
2298 rectangleAction->setEnabled(b);
2299 polygonAction->setEnabled(b);
2300 freehandAction->setEnabled(b);
2301 addPointAction->setEnabled(b);
2302 removePointAction->setEnabled(b);
2303
2304}
2305
2306QString KImageMapEditor::getHtmlCode() {
2307 if (currentMapElement) {
2308 currentMapElement->htmlCode = getHTMLImageMap();
2309 }
2310
2311 QString result;
2312
2313 HtmlElement *el;
2314 foreach(el,_htmlContent) {
2315 result += el->htmlCode;
2316 }
2317 return result;
2318}
2319
2320
2321/**
2322 create a relative short url based in baseURL
2323
2324 taken from qextfileinfo.cpp:
2325
2326 From WebMaker - KDE HTML Editor
2327 Copyright (C) 1998, 1999 Alexei Dets <dets@services.ru>
2328
2329 Rewritten for Quanta Plus: (C) 2002 Andras Mantia <amantia@freemail.hu>
2330
2331 This program is free software; you can redistribute it and/or modify
2332 it under the terms of the GNU General Public License as published by
2333 the Free Software Foundation; either version 2 of the License, or
2334 (at your option) any later version.
2335*/
2336static KUrl toRelative(const KUrl& urlToConvert,const KUrl& baseURL)
2337{
2338 KUrl resultURL = urlToConvert;
2339 if (urlToConvert.protocol() == baseURL.protocol())
2340 {
2341 QString path = urlToConvert.path();
2342 QString basePath = baseURL.path(KUrl::AddTrailingSlash);
2343 if (path.startsWith("/"))
2344 {
2345 path.remove(0, 1);
2346 basePath.remove(0, 1);
2347 if ( basePath.right(1) != "/" ) basePath.append("/");
2348
2349 int pos=0;
2350 int pos1=0;
2351 for (;;)
2352 {
2353 pos=path.indexOf("/");
2354 pos1=basePath.indexOf("/");
2355 if ( pos<0 || pos1<0 ) break;
2356 if ( path.left(pos+1 ) == basePath.left(pos1+1) )
2357 {
2358 path.remove(0, pos+1);
2359 basePath.remove(0, pos1+1);
2360 }
2361 else
2362 break;
2363 };
2364
2365 if ( basePath == "/" ) basePath="";
2366 int level = basePath.count("/");
2367 for (int i=0; i<level; i++)
2368 {
2369 path="../"+path;
2370 };
2371 }
2372
2373 resultURL.setPath(QDir::cleanPath(path));
2374 }
2375
2376 if (urlToConvert.path().endsWith('/')) resultURL.adjustPath(KUrl::AddTrailingSlash);
2377 return resultURL;
2378}
2379
2380
2381void KImageMapEditor::saveImageMap(const KUrl & url)
2382{
2383 QFileInfo fileInfo(url.path());
2384
2385 if (!QFileInfo(url.directory()).isWritable()) {
2386 KMessageBox::error(widget(),
2387 i18n("<qt>The file <i>%1</i> could not be saved, because you do not have the required write permissions.</qt>", url.path()));
2388 return;
2389 }
2390
2391 if (!backupFileCreated) {
2392 QString backupFile = url.path()+'~';
2393 KIO::file_copy(url, KUrl(backupFile ), -1, KIO::Overwrite | KIO::HideProgressInfo);
2394 backupFileCreated = true;
2395 }
2396
2397 setModified(false);
2398
2399 if (mapName().isEmpty()) {
2400 mapEditName();
2401 }
2402 QFile file(url.path());
2403 file.open(QIODevice::WriteOnly);
2404
2405 QTextStream t(&file);
2406
2407 if (_htmlContent.isEmpty()) {
2408 t << "<html>\n"
2409 << "<head>\n"
2410 << " <title></title>\n"
2411 << "</head>\n"
2412 << "<body>\n"
2413 << " " << getHTMLImageMap()
2414 << "\n"
2415 << " <img src=\"" << toRelative(_imageUrl,KUrl( url.directory() )).path() << "\""
2416 << " usemap=\"#" << _mapName << "\""
2417 << " width=\"" << drawZone->picture().width() << "\""
2418 << " height=\"" << drawZone->picture().height() << "\">\n"
2419 << "</body>\n"
2420 << "</html>";
2421 } else
2422 {
2423 t << getHtmlCode();
2424 }
2425
2426 file.close();
2427
2428}
2429
2430
2431void KImageMapEditor::slotCut()
2432{
2433 if ( 0 == currentSelected->count() )
2434 return;
2435 delete copyArea;
2436
2437 copyArea= static_cast< AreaSelection* > (currentSelected->clone());
2438 pasteAction->setEnabled(true);
2439 QUndoCommand *command= new CutCommand(this,*currentSelected);
2440 commandHistory()->push(command);
2441}
2442
2443
2444void KImageMapEditor::slotDelete()
2445{
2446 if ( 0 == currentSelected->count() )
2447 return;
2448
2449 QUndoCommand *command= new DeleteCommand(this,*currentSelected);
2450 commandHistory()->push(command);
2451}
2452
2453void KImageMapEditor::slotCopy()
2454{
2455 delete copyArea;
2456
2457 copyArea = static_cast< AreaSelection* > (currentSelected->clone());
2458 pasteAction->setEnabled(true);
2459}
2460
2461void KImageMapEditor::slotPaste()
2462{
2463 if (!copyArea)
2464 return;
2465
2466 copyArea->moveBy(5,5);
2467 if (copyArea->rect().x()>= drawZone->getImageRect().width() ||
2468 copyArea->rect().y()>= drawZone->getImageRect().height())
2469 copyArea->moveTo(0,0);
2470
2471 if (copyArea->rect().width()>drawZone->getImageRect().width() ||
2472 copyArea->rect().height()>drawZone->getImageRect().height())
2473 return;
2474
2475 AreaSelection *a=static_cast< AreaSelection* > (copyArea->clone());
2476 commandHistory()->push(new PasteCommand(this,*a));
2477 delete a;
2478// addAreaAndEdit(a);
2479}
2480
2481
2482
2483void KImageMapEditor::slotBackOne()
2484{
2485 if (currentSelected->isEmpty())
2486 return;
2487
2488 AreaList list = currentSelected->getAreaList();
2489
2490
2491 Area *a = 0L;
2492 // move every selected Area one step lower
2493 for (int i=areas->count()-2; i > -1; i--)
2494 {
2495 if (list.contains( areas->at(i) ))
2496 {
2497 uint j = (uint)i+1;
2498 a = areas->at(i);
2499 areas->removeAll(a);
2500 areas->insert(j,a);
2501 QTreeWidgetItem* root = areaListView->listView->invisibleRootItem();
2502 root->insertChild(j,root->takeChild(i));
2503 }
2504 }
2505 // to update the up and down buttons
2506 updateUpDownBtn();
2507
2508}
2509
2510void KImageMapEditor::slotForwardOne()
2511{
2512 if (currentSelected->isEmpty())
2513 return;
2514
2515 AreaList list = currentSelected->getAreaList();
2516
2517 Area *a = 0L;
2518 // move every selected Area one step higher
2519 for (int i=1; i < (int)areas->count(); i++)
2520 {
2521 if (list.contains( areas->at(i) ))
2522 {
2523 uint j = (uint) i-1;
2524 a = areas->at(i);
2525 areas->removeAll(a);
2526 areas->insert(j,a);
2527 QTreeWidgetItem* root = areaListView->listView->invisibleRootItem();
2528 root->insertChild(j,root->takeChild(i));
2529 }
2530 }
2531 // to update the up and down buttons
2532 updateUpDownBtn();
2533}
2534
2535void KImageMapEditor::slotToBack()
2536{
2537 if (currentSelected->isEmpty())
2538 return;
2539
2540 while (backOneAction->isEnabled())
2541 slotBackOne();
2542}
2543
2544void KImageMapEditor::slotToFront()
2545{
2546 if (currentSelected->isEmpty())
2547 return;
2548
2549 while (forwardOneAction->isEnabled())
2550 slotForwardOne();
2551}
2552
2553
2554void KImageMapEditor::slotMoveUp()
2555{
2556 QRect r=selected()->rect();
2557 selected()->setMoving(true);
2558 selected()->moveBy(0,-1);
2559
2560 commandHistory()->push(
2561 new MoveCommand( this, selected(), r.topLeft() ));
2562 selected()->setMoving(false);
2563 slotAreaChanged(selected());
2564 slotUpdateSelectionCoords();
2565}
2566
2567void KImageMapEditor::slotMoveDown()
2568{
2569 QRect r=selected()->rect();
2570 selected()->setMoving(true);
2571 selected()->moveBy(0,1);
2572
2573 commandHistory()->push(
2574 new MoveCommand( this, selected(), r.topLeft() ));
2575 selected()->setMoving(false);
2576 slotAreaChanged(selected());
2577 slotUpdateSelectionCoords();
2578}
2579
2580void KImageMapEditor::slotMoveLeft()
2581{
2582 kDebug() << "slotMoveLeft";
2583 QRect r=selected()->rect();
2584 selected()->setMoving(true);
2585 selected()->moveBy(-1,0);
2586
2587 commandHistory()->push(
2588 new MoveCommand( this, selected(), r.topLeft() ));
2589 selected()->setMoving(false);
2590 slotAreaChanged(selected());
2591 slotUpdateSelectionCoords();
2592}
2593
2594void KImageMapEditor::slotMoveRight()
2595{
2596 QRect r=selected()->rect();
2597 selected()->setMoving(true);
2598 selected()->moveBy(1,0);
2599
2600 commandHistory()->push(
2601 new MoveCommand( this, selected(), r.topLeft() ));
2602 selected()->setMoving(false);
2603 slotAreaChanged(selected());
2604 slotUpdateSelectionCoords();
2605}
2606
2607void KImageMapEditor::slotCancelDrawing()
2608{
2609 drawZone->cancelDrawing();
2610}
2611
2612void KImageMapEditor::slotIncreaseHeight()
2613{
2614 Area *oldArea=selected()->clone();
2615
2616 QRect r = selected()->rect();
2617 r.setHeight( r.height()+1 );
2618 r.translate(0,-1);
2619
2620 selected()->setRect(r);
2621
2622 commandHistory()->push(
2623 new ResizeCommand( this, selected(), oldArea ));
2624 slotAreaChanged(selected());
2625 slotUpdateSelectionCoords();
2626}
2627
2628void KImageMapEditor::slotDecreaseHeight()
2629{
2630 Area *oldArea=selected()->clone();
2631
2632 QRect r = selected()->rect();
2633 r.setHeight( r.height()-1 );
2634 r.translate(0,1);
2635
2636 selected()->setRect(r);
2637
2638 commandHistory()->push(
2639 new ResizeCommand( this, selected(), oldArea ));
2640 slotAreaChanged(selected());
2641 slotUpdateSelectionCoords();
2642}
2643
2644void KImageMapEditor::slotIncreaseWidth()
2645{
2646 Area *oldArea=selected()->clone();
2647
2648 QRect r = selected()->rect();
2649 r.setWidth( r.width()+1 );
2650
2651 selected()->setRect(r);
2652
2653 commandHistory()->push(
2654 new ResizeCommand( this, selected(), oldArea ));
2655 slotAreaChanged(selected());
2656 slotUpdateSelectionCoords();
2657}
2658
2659void KImageMapEditor::slotDecreaseWidth()
2660{
2661 Area *oldArea=selected()->clone();
2662
2663 QRect r = selected()->rect();
2664 r.setWidth( r.width()-1 );
2665
2666 selected()->setRect(r);
2667
2668 commandHistory()->push(
2669 new ResizeCommand( this, selected(), oldArea ));
2670 slotAreaChanged(selected());
2671 slotUpdateSelectionCoords();
2672}
2673
2674void KImageMapEditor::slotHighlightAreas(bool b)
2675{
2676 Area::highlightArea = b;
2677 updateAllAreas();
2678 drawZone->repaint();
2679}
2680
2681void KImageMapEditor::slotShowAltTag(bool b)
2682{
2683 Area::showAlt = b;
2684 drawZone->repaint();
2685}
2686
2687void KImageMapEditor::mapNew()
2688{
2689 QString mapName = mapsListView->getUnusedMapName();
2690 addMap(mapName);
2691 mapEditName();
2692}
2693
2694void KImageMapEditor::mapDelete()
2695{
2696 if (mapsListView->count() == 0)
2697 return;
2698
2699 QString selectedMap = mapsListView->selectedMap();
2700
2701 int result = KMessageBox::warningContinueCancel(widget(),
2702 i18n("<qt>Are you sure you want to delete the map <i>%1</i>?"
2703 " <br /><b>There is no way to undo this.</b></qt>", selectedMap),
2704 i18n("Delete Map?"),KGuiItem(i18n("&Delete"),"edit-delete"));
2705
2706 if (result == KMessageBox::No)
2707 return;
2708
2709
2710
2711 mapsListView->removeMap(selectedMap);
2712 HtmlMapElement* mapEl = findHtmlMapElement(selectedMap);
2713 _htmlContent.removeAll(mapEl);
2714 if (mapsListView->count() == 0) {
2715
2716 currentMapElement = 0L;
2717 deleteAllAreas();
2718 setMapActionsEnabled(false);
2719 }
2720 else {
2721 // The old one was deleted, so the new one got selected
2722 setMap(mapsListView->selectedMap());
2723 }
2724}
2725
2726void KImageMapEditor::mapPreview() {
2727 HTMLPreviewDialog dialog(widget(), url(), getHtmlCode());
2728 dialog.exec();
2729}
2730
2731void KImageMapEditor::deleteAllMaps()
2732{
2733 deleteAllAreas();
2734 mapsListView->clear();
2735 if (isReadWrite()) {
2736 mapDeleteAction->setEnabled(false);
2737 mapDefaultAreaAction->setEnabled(false);
2738 mapNameAction->setEnabled(false);
2739 }
2740}
2741
2742/**
2743 * Doesn't call the closeUrl method, because
2744 * we need the URL for the session management
2745 */
2746bool KImageMapEditor::queryClose() {
2747 if ( ! isModified() )
2748 return true;
2749
2750 switch ( KMessageBox::warningYesNoCancel(
2751 widget(),
2752 i18n("<qt>The file <i>%1</i> has been modified.<br />Do you want to save it?</qt>",
2753 url().fileName()),
2754 QString(),
2755 KStandardGuiItem::save(),
2756 KStandardGuiItem::discard()) )
2757 {
2758 case KMessageBox::Yes :
2759 saveFile();
2760 return true;
2761 case KMessageBox::No :
2762 return true;
2763 default:
2764 return false;
2765 }
2766}
2767
2768bool KImageMapEditor::closeUrl()
2769{
2770 bool result = KParts::ReadWritePart::closeUrl();
2771 if (!result)
2772 return false;
2773
2774 _htmlContent.clear();
2775 deleteAllMaps();
2776 imagesListView->clear();
2777
2778 delete copyArea;
2779 copyArea=0L;
2780
2781 delete defaultArea;
2782 defaultArea=0L;
2783
2784 currentMapElement = 0L;
2785
2786 init();
2787 emit setWindowCaption("");
2788
2789 return true;
2790
2791}
2792
2793void KImageMapEditor::addImage(const KUrl & imgUrl) {
2794 if (imgUrl.isEmpty())
2795 return;
2796
2797 QString relativePath ( toRelative(imgUrl, KUrl( url().directory() )).path() );
2798
2799 QString imgHtml = QString("<img src=\"")+relativePath+QString("\">");
2800 ImageTag* imgTag = new ImageTag();
2801 imgTag->insert("tagname","img");
2802 imgTag->insert("src", relativePath);
2803
2804 HtmlImgElement* imgEl = new HtmlImgElement(imgHtml);
2805 imgEl->imgTag = imgTag;
2806
2807 HtmlElement* bodyEl = findHtmlElement("<body");
2808 if (bodyEl) {
2809 int bodyIndex = _htmlContent.indexOf(bodyEl);
2810 _htmlContent.insert(bodyIndex+1, new HtmlElement("\n"));
2811 _htmlContent.insert(bodyIndex+2, imgEl);
2812 }
2813 else {
2814 _htmlContent.append(new HtmlElement("\n"));
2815 _htmlContent.append(imgEl);
2816 }
2817
2818 imagesListView->addImage(imgTag);
2819 imagesListView->selectImage(imgTag);
2820 setImageActionsEnabled(true);
2821
2822 setModified(true);
2823}
2824
2825/**
2826 * Sets whether the image actions that depend on an
2827 * selected image are enabled
2828 */
2829void KImageMapEditor::setImageActionsEnabled(bool b) {
2830 imageRemoveAction->setEnabled(b);
2831 imageUsemapAction->setEnabled(b);
2832}
2833
2834
2835void KImageMapEditor::imageAdd() {
2836 KUrl imgUrl = KFileDialog::getImageOpenUrl();
2837 addImage(imgUrl);
2838}
2839
2840void KImageMapEditor::imageRemove() {
2841 ImageTag* imgTag = imagesListView->selectedImage();
2842 HtmlImgElement* imgEl = findHtmlImgElement(imgTag);
2843 imagesListView->removeImage(imgTag);
2844 _htmlContent.removeAt(_htmlContent.indexOf(imgEl));
2845
2846 if (imagesListView->topLevelItemCount() == 0) {
2847 setPicture(getBackgroundImage());
2848 setImageActionsEnabled(false);
2849 }
2850 else {
2851 ImageTag* selected = imagesListView->selectedImage();
2852 if (selected) {
2853 if (selected->contains("src")) {
2854 setPicture(KUrl(selected->value("src")));
2855 }
2856 }
2857 }
2858
2859 setModified(true);
2860}
2861
2862void KImageMapEditor::imageUsemap() {
2863
2864 bool ok=false;
2865 ImageTag* imageTag = imagesListView->selectedImage();
2866 if ( ! imageTag)
2867 return;
2868
2869 QString usemap;
2870
2871 if (imageTag->contains("usemap"))
2872 usemap = imageTag->value("usemap");
2873
2874 QStringList maps = mapsListView->getMaps();
2875 int index = maps.indexOf(usemap);
2876 if (index == -1) {
2877 maps.prepend("");
2878 index = 0;
2879 }
2880
2881 QString input =
2882 KInputDialog::getItem(i18n("Enter Usemap"),
2883 i18n("Enter the usemap value:"),
2884 maps,index,true,&ok,widget());
2885 if (ok) {
2886 imageTag->insert("usemap", input);
2887 imagesListView->updateImage(imageTag);
2888 setModified(true);
2889
2890 // Update the htmlCode of the HtmlElement
2891 HtmlImgElement* imgEl = findHtmlImgElement(imageTag);
2892
2893 imgEl->htmlCode = "<";
2894 QString tagName = imgEl->imgTag->value("tagname");
2895 imgEl->htmlCode += QString(tagName);
2896 QHashIterator<QString, QString> it( *imgEl->imgTag );
2897 while (it.hasNext()) {
2898 it.next();
2899 if (it.key() != "tagname") {
2900 imgEl->htmlCode += " " + it.key() + "=\"";
2901 if (it.key() == "usemap")
2902 imgEl->htmlCode += '#';
2903 imgEl->htmlCode += it.value();
2904 imgEl->htmlCode += '"';
2905 }
2906 }
2907
2908 imgEl->htmlCode += '>';
2909
2910 }
2911}
2912
2913