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