File indexing completed on 2024-04-21 04:20:15

0001 /***************************************************************************
0002                           imagemapeditor.cpp  -  description
0003                             -------------------
0004     begin                : Wed Apr 4 2001
0005     copyright            : (C) 2001 by Jan Schäfer
0006     email                : j_schaef@informatik.uni-kl.de
0007 ***************************************************************************/
0008 
0009 /***************************************************************************
0010 *                                                                         *
0011 *   This program is free software; you can redistribute it and/or modify  *
0012 *   it under the terms of the GNU General Public License as published by  *
0013 *   the Free Software Foundation; either version 2 of the License, or     *
0014 *   (at your option) any later version.                                   *
0015 *                                                                         *
0016 ***************************************************************************/
0017 
0018 #include "kimagemapeditor.h"
0019 
0020 #include <iostream>
0021 #include <assert.h>
0022 
0023 // Qt
0024 #include <QAction>
0025 #include <QActionGroup>
0026 #include <QApplication>
0027 #include <QComboBox>
0028 #include <QDialogButtonBox>
0029 #include <QFile>
0030 #include <QFileDialog>
0031 #include <QFileInfo>
0032 #include <QFontDatabase>
0033 #include <QIcon>
0034 #include <QInputDialog>
0035 #include <QLayout>
0036 #include <QListWidget>
0037 #include <QMenu>
0038 #include <QMimeDatabase>
0039 #include <QMimeType>
0040 #include <QPainter>
0041 #include <QPixmap>
0042 #include <QPushButton>
0043 #include <QScrollArea>
0044 #include <QSplitter>
0045 #include <QStandardPaths>
0046 #include <QTabWidget>
0047 #include <QTextEdit>
0048 #include <QTextStream>
0049 #include <QToolTip>
0050 #include <QUndoStack>
0051 #include <QVBoxLayout>
0052 
0053 // KDE Frameworks
0054 #include <kwidgetsaddons_version.h>
0055 #include <KPluginMetaData>
0056 #include <KActionCollection>
0057 #include <KConfigGroup>
0058 #include <KIO/FileCopyJob>
0059 #include <KLocalizedString>
0060 #include <KMessageBox>
0061 #include <KPluginFactory>
0062 #include <KSharedConfig>
0063 #include <KUndoActions>
0064 #include <KXMLGUIFactory>
0065 #include <KXmlGuiWindow>
0066 
0067 // local
0068 #include "kimagemapeditor_debug.h"
0069 #include "drawzone.h"
0070 #include "kimedialogs.h"
0071 #include "kimecommands.h"
0072 #include "areacreator.h"
0073 #include "arealistview.h"
0074 #include "imageslistview.h"
0075 #include "mapslistview.h"
0076 #include "kimecommon.h"
0077 #include "imagemapchoosedialog.h"
0078 #include "kimagemapeditor_version.h"
0079 
0080 K_PLUGIN_FACTORY_WITH_JSON(KImageMapEditorFactory, "kimagemapeditorpart.json", registerPlugin<KImageMapEditor>();)
0081 
0082 # if QT_VERSION_MAJOR < 6
0083 KImageMapEditor::KImageMapEditor(QWidget *parentWidget, QObject *parent,
0084                                  const KPluginMetaData &metaData,
0085                                  const QVariantList & )
0086   : KParts::ReadWritePart(parent)
0087 {
0088   setMetaData(metaData);
0089 
0090 #else
0091 KImageMapEditor::KImageMapEditor(QWidget *parentWidget, QObject *parent,
0092                                  const KPluginMetaData &metaData)
0093   : KParts::ReadWritePart(parent, metaData)
0094 {
0095 #endif
0096 //  KDockMainWindow* mainWidget;
0097 
0098   mainWindow = dynamic_cast<KXmlGuiWindow*>(parent) ;
0099   QSplitter * splitter = nullptr;
0100   tabWidget = nullptr;
0101 
0102   if (mainWindow) {
0103 //    qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor: We got a KDockMainWindow !";
0104 
0105 //    K3DockWidget* parentDock = mainDock->getMainDockWidget();
0106     areaDock = new QDockWidget(i18n("Areas"),mainWindow);
0107     mapsDock = new QDockWidget(i18n("Maps"),mainWindow);
0108     imagesDock = new QDockWidget(i18n("Images"),mainWindow);
0109 
0110     // Needed to save their state
0111     areaDock->setObjectName("areaDock");
0112     mapsDock->setObjectName("mapsDock");
0113     imagesDock->setObjectName("imagesDock");
0114 
0115     mainWindow->addDockWidget( Qt::LeftDockWidgetArea, areaDock);
0116     mainWindow->addDockWidget( Qt::LeftDockWidgetArea, mapsDock);
0117     mainWindow->addDockWidget( Qt::LeftDockWidgetArea, imagesDock);
0118 
0119     areaListView = new AreaListView(areaDock);
0120     mapsListView = new MapsListView(mapsDock);
0121     imagesListView = new ImagesListView(imagesDock);
0122 
0123     areaDock->setWidget(areaListView);
0124     mapsDock->setWidget(mapsListView);
0125     imagesDock->setWidget(imagesListView);
0126 
0127   }
0128   else
0129   {
0130     areaDock = nullptr;
0131     mapsDock = nullptr;
0132     imagesDock = nullptr;
0133     splitter = new QSplitter(parentWidget);
0134     tabWidget = new QTabWidget(splitter);
0135     areaListView = new AreaListView(tabWidget);
0136     mapsListView = new MapsListView(tabWidget);
0137     imagesListView = new ImagesListView(tabWidget);
0138 
0139     tabWidget->addTab(areaListView,i18n("Areas"));
0140     tabWidget->addTab(mapsListView,i18n("Maps"));
0141     tabWidget->addTab(imagesListView,i18n("Images"));
0142   }
0143 
0144 
0145   connect( areaListView->listView, SIGNAL(itemSelectionChanged()), this, SLOT(slotSelectionChanged()));
0146   connect( areaListView->listView,
0147            SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),
0148            this,
0149            SLOT(showTagEditor(QTreeWidgetItem*)));
0150   connect( areaListView->listView,
0151            SIGNAL(customContextMenuRequested(QPoint)),
0152            this,
0153            SLOT(slotShowPopupMenu(QPoint)));
0154 
0155   connect( mapsListView, SIGNAL(mapSelected(QString)),
0156            this, SLOT(setMap(QString)));
0157 
0158   connect( mapsListView, SIGNAL(mapRenamed(QString)),
0159            this, SLOT(setMapName(QString)));
0160 
0161   connect( mapsListView->listView(),
0162            SIGNAL(customContextMenuRequested(QPoint)),
0163            this,
0164            SLOT(slotShowMapPopupMenu(QPoint)));
0165 
0166   connect( imagesListView, &ImagesListView::imageSelected,
0167            this, QOverload<const QUrl &>::of(&KImageMapEditor::setPicture));
0168 
0169   connect( imagesListView,
0170            SIGNAL(customContextMenuRequested(QPoint)),
0171            this,
0172            SLOT(slotShowImagePopupMenu(QPoint)));
0173 
0174   if (splitter) {
0175     drawZone = new DrawZone(splitter,this);
0176     splitter->setStretchFactor(splitter->indexOf(tabWidget), 0);
0177     splitter->setStretchFactor(splitter->indexOf(drawZone), 1);
0178     setWidget(splitter);
0179   } else {
0180     QScrollArea *sa = new QScrollArea(mainWindow);
0181     drawZone = new DrawZone(nullptr,this);
0182     mainWindow->setCentralWidget(sa);
0183     sa->setWidget(drawZone);
0184     setWidget(mainWindow);
0185     //    sa->setWidgetResizable(true);
0186   }
0187 
0188 
0189   areas = new AreaList();
0190   currentSelected= new AreaSelection();
0191   _currentToolType=KImageMapEditor::Selection;
0192   copyArea = nullptr;
0193   defaultArea = nullptr;
0194   currentMapElement = nullptr;
0195 
0196   setupActions();
0197   setupStatusBar();
0198 
0199   setXMLFile("kimagemapeditorpartui.rc");
0200 
0201   setPicture(getBackgroundImage());
0202 
0203   init();
0204   readConfig();
0205 }
0206 
0207 KImageMapEditor::~KImageMapEditor() {
0208   writeConfig();
0209 
0210   delete areas;
0211 
0212   delete currentSelected;
0213   delete copyArea;
0214   delete defaultArea;
0215 
0216   // Delete our DockWidgets
0217   if (areaDock) {
0218     areaDock->hide();
0219     mapsDock->hide();
0220     imagesDock->hide();
0221 
0222     delete areaDock;
0223     delete mapsDock;
0224     delete imagesDock;
0225   }
0226 
0227 }
0228 
0229 QString KImageMapEditor::componentName() const
0230 {
0231     // the part ui.rc file is in the program folder, not a separate one
0232     // TODO: change the component name to "kimagemapeditorpart" by removing this method and
0233     // adapting the folder where the file is placed.
0234     // Needs a way to also move any potential custom user ui.rc files
0235     // from kimagemapeditor/ to kimagemapeditorpart/
0236     return QStringLiteral("kimagemapeditor");
0237 }
0238 
0239 MapTag::MapTag() {
0240   modified = false;
0241   name.clear();
0242 }
0243 
0244 void KImageMapEditor::init()
0245 {
0246   _htmlContent.clear();
0247   _imageUrl.clear();
0248   //  closeUrl();
0249   HtmlElement* el = new HtmlElement("<html>\n");
0250   _htmlContent.append(el);
0251   el = new HtmlElement("<head>\n");
0252   _htmlContent.append(el);
0253   el = new HtmlElement("</head>\n");
0254   _htmlContent.append(el);
0255   el = new HtmlElement("<body>\n");
0256   _htmlContent.append(el);
0257 
0258   addMap(i18n("unnamed"));
0259 
0260   el = new HtmlElement("</body>\n");
0261   _htmlContent.append(el);
0262   el = new HtmlElement("</html>\n");
0263   _htmlContent.append(el);
0264 
0265   setImageActionsEnabled(false);
0266 }
0267 
0268 void KImageMapEditor::setReadWrite(bool)
0269 {
0270 
0271   // For now it does not matter if it is readwrite or readonly
0272   // it is always readwrite, because Quanta only supports ReadOnlyParts
0273   // at this moment and in that case it should be readwrite, too.
0274   ReadWritePart::setReadWrite(true);
0275   /*
0276     if (rw)
0277       ;
0278     else
0279     {
0280      actionCollection()->remove(arrowAction);
0281      actionCollection()->remove(circleAction);
0282      actionCollection()->remove(rectangleAction);
0283      actionCollection()->remove(polygonAction);
0284      actionCollection()->remove(freehandAction);
0285      actionCollection()->remove(addPointAction);
0286      actionCollection()->remove(removePointAction);
0287 
0288      actionCollection()->remove(cutAction);
0289      actionCollection()->remove(deleteAction);
0290      actionCollection()->remove(copyAction);
0291      actionCollection()->remove(pasteAction);
0292 
0293      actionCollection()->remove(mapNewAction);
0294      actionCollection()->remove(mapDeleteAction);
0295      actionCollection()->remove(mapNameAction);
0296      actionCollection()->remove(mapDefaultAreaAction);
0297 
0298      actionCollection()->remove(areaPropertiesAction);
0299 
0300      actionCollection()->remove(moveLeftAction);
0301      actionCollection()->remove(moveRightAction);
0302      actionCollection()->remove(moveUpAction);
0303      actionCollection()->remove(moveDownAction);
0304 
0305      actionCollection()->remove(increaseWidthAction);
0306      actionCollection()->remove(decreaseWidthAction);
0307      actionCollection()->remove(increaseHeightAction);
0308      actionCollection()->remove(decreaseHeightAction);
0309 
0310      actionCollection()->remove(toFrontAction);
0311      actionCollection()->remove(toBackAction);
0312      actionCollection()->remove(forwardOneAction);
0313      actionCollection()->remove(backOneAction);
0314 
0315      actionCollection()->remove(imageRemoveAction);
0316      actionCollection()->remove(imageAddAction);
0317      actionCollection()->remove(imageUsemapAction);
0318 
0319     }
0320   */
0321 
0322 }
0323 
0324 void KImageMapEditor::setModified(bool modified)
0325 {
0326     // get a handle on our Save action and make sure it is valid
0327     QAction *save = actionCollection()->action(KStandardAction::name(KStandardAction::Save));
0328     if (!save)
0329         return;
0330 
0331     // if so, we either enable or disable it based on the current
0332     // state
0333     if (modified)
0334         save->setEnabled(true);
0335     else
0336         save->setEnabled(false);
0337 
0338     // in any event, we want our parent to do it's thing
0339     ReadWritePart::setModified(modified);
0340 }
0341 
0342 
0343 KConfig *KImageMapEditor::config()
0344 {
0345     /* TODO KF5
0346     KSharedConfigPtr tmp = KimeFactory::componentData().config();
0347     return tmp.data();
0348     */
0349     return new KConfig();
0350 }
0351 
0352 void KImageMapEditor::readConfig(const KConfigGroup &config) {
0353   KConfigGroup data = config.parent().group( "Data" );
0354   recentFilesAction->loadEntries( data );
0355 }
0356 
0357 void KImageMapEditor::writeConfig(KConfigGroup& config) {
0358   config.writeEntry("highlightareas",highlightAreasAction->isChecked());
0359   config.writeEntry("showalt",showAltAction->isChecked());
0360   KConfigGroup data = config.parent().group( "Data" );
0361   recentFilesAction->saveEntries( data );
0362   saveLastURL(config);
0363 
0364 }
0365 
0366 void KImageMapEditor::readConfig() {
0367   readConfig(config()->group("General Options" ) );
0368   slotConfigChanged();
0369 }
0370 
0371 void KImageMapEditor::writeConfig() {
0372   KConfigGroup cg( config(), "General Options");
0373   writeConfig( cg );
0374   config()->sync();
0375 }
0376 
0377 
0378 void KImageMapEditor::saveProperties(KConfigGroup &config)
0379 {
0380   saveLastURL(config);
0381 }
0382 
0383 void KImageMapEditor::readProperties(const KConfigGroup& config)
0384 {
0385   openLastURL(config);
0386 }
0387 
0388 void KImageMapEditor::slotConfigChanged()
0389 {
0390   KConfigGroup group = config()->group("Appearance");
0391   int newHeight=group.readEntry("maximum-preview-height",50);
0392   group = config()->group("General Options");
0393   _commandHistory->setUndoLimit(group.readEntry("undo-level",100));
0394 #if 0
0395   _commandHistory->setRedoLimit(group.readEntry("redo-level",100));
0396 #endif
0397   Area::highlightArea = group.readEntry("highlightareas",true);
0398   highlightAreasAction->setChecked(Area::highlightArea);
0399   Area::showAlt = group.readEntry("showalt",true);
0400   showAltAction->setChecked(Area::showAlt);
0401 
0402   // if the image preview size changed update all images
0403   if (maxAreaPreviewHeight!=newHeight) {
0404     maxAreaPreviewHeight=newHeight;
0405     areaListView->listView->setIconSize(QSize(newHeight,newHeight));
0406   }
0407 
0408   updateAllAreas();
0409   drawZone->repaint();
0410 }
0411 
0412 void KImageMapEditor::openLastURL(const KConfigGroup & config) {
0413   QUrl lastURL ( config.readPathEntry("lastopenurl", QString()) );
0414   QString lastMap = config.readEntry("lastactivemap");
0415   QString lastImage = config.readPathEntry("lastactiveimage", QString());
0416 
0417 
0418 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "loading from group : " << config.group();
0419 
0420 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "loading entry lastopenurl : " << lastURL.path();
0421 //  KMessageBox::information(0L, config.group()+" "+lastURL.path());
0422   if (!lastURL.isEmpty()) {
0423     openUrl(lastURL);
0424     if (!lastMap.isEmpty())
0425       mapsListView->selectMap(lastMap);
0426     if (!lastImage.isEmpty())
0427       setPicture(QUrl::fromLocalFile(lastImage));
0428 //    qCDebug(KIMAGEMAPEDITOR_LOG) << "opening HTML file with map " << lastMap << " and image " << lastImage;
0429 //    if (! openHTMLFile(lastURL, lastMap, lastImage) )
0430 //      closeUrl();
0431       //openUrl(lastURL);
0432       //    else
0433       //closeUrl();
0434   }
0435 }
0436 
0437 void KImageMapEditor::saveLastURL(KConfigGroup & config) {
0438   qCDebug(KIMAGEMAPEDITOR_LOG) << "saveLastURL: " << url().path();
0439   config.writePathEntry("lastopenurl",url().path());
0440   config.writeEntry("lastactivemap",mapName());
0441   config.writePathEntry("lastactiveimage",_imageUrl.path());
0442 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "writing entry lastopenurl : " << url().path();
0443 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "writing entry lastactivemap : " << mapName();
0444 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "writing entry lastactiveimage : " << _imageUrl.path();
0445   //KMessageBox::information(0L, QString("Group: %1 Saving ... %2").arg(config.group()).arg(url().path()));
0446 }
0447 
0448 void KImageMapEditor::setupActions()
0449 {
0450     // File Open
0451   QAction *temp =
0452     KStandardAction::open(this, SLOT(fileOpen()),
0453               actionCollection());
0454   temp->setWhatsThis(i18n("<h3>Open File</h3>Click this to <em>open</em> a new picture or HTML file."));
0455   temp->setToolTip(i18n("Open new picture or HTML file"));
0456 
0457   // File Open Recent
0458   recentFilesAction = KStandardAction::openRecent(this, SLOT(openURL(QUrl)),
0459                                       actionCollection());
0460     // File Save
0461   temp =KStandardAction::save(this, SLOT(fileSave()), actionCollection());
0462     temp->setWhatsThis(i18n("<h3>Save File</h3>Click this to <em>save</em> the changes to the HTML file."));
0463     temp->setToolTip(i18n("Save HTML file"));
0464 
0465 
0466     // File Save As
0467   (void)KStandardAction::saveAs(this, SLOT(fileSaveAs()), actionCollection());
0468 
0469     // File Close
0470   temp=KStandardAction::close(this, SLOT(fileClose()), actionCollection());
0471     temp->setWhatsThis(i18n("<h3>Close File</h3>Click this to <em>close</em> the currently open HTML file."));
0472     temp->setToolTip(i18n("Close HTML file"));
0473 
0474   // Edit Copy
0475   copyAction=KStandardAction::copy(this, SLOT(slotCopy()), actionCollection());
0476   copyAction->setWhatsThis(i18n("<h3>Copy</h3>"
0477                           "Click this to <em>copy</em> the selected area."));
0478   copyAction->setEnabled(false);
0479 
0480   // Edit Cut
0481   cutAction=KStandardAction::cut(this, SLOT(slotCut()), actionCollection());
0482   cutAction->setWhatsThis(i18n("<h3>Cut</h3>"
0483                           "Click this to <em>cut</em> the selected area."));
0484   cutAction->setEnabled(false);
0485 
0486   // Edit Paste
0487   pasteAction=KStandardAction::paste(this, SLOT(slotPaste()), actionCollection());
0488   pasteAction->setWhatsThis(i18n("<h3>Paste</h3>"
0489                           "Click this to <em>paste</em> the copied area."));
0490   pasteAction->setEnabled(false);
0491 
0492 
0493   // Edit Delete
0494   deleteAction = new QAction(QIcon::fromTheme(QStringLiteral("edit-delete")),
0495       i18n("&Delete"), this);
0496   actionCollection()->addAction("edit_delete", deleteAction );
0497   connect(deleteAction, SIGNAL(triggered(bool)), SLOT (slotDelete()));
0498   actionCollection()->setDefaultShortcut(deleteAction, QKeySequence(Qt::Key_Delete));
0499   deleteAction->setWhatsThis(i18n("<h3>Delete</h3>"
0500                           "Click this to <em>delete</em> the selected area."));
0501   deleteAction->setEnabled(false);
0502 
0503   // Edit Undo/Redo
0504   _commandHistory = new QUndoStack(this);
0505   KUndoActions::createUndoAction(_commandHistory, actionCollection());
0506   KUndoActions::createRedoAction(_commandHistory, actionCollection());
0507 
0508   // Edit Properties
0509     areaPropertiesAction  = new QAction(i18n("Pr&operties"), this);
0510     actionCollection()->addAction("edit_properties", areaPropertiesAction );
0511   connect(areaPropertiesAction, SIGNAL(triggered(bool)), SLOT(showTagEditor()));
0512   areaPropertiesAction->setEnabled(false);
0513 
0514   // View Zoom In
0515   zoomInAction=KStandardAction::zoomIn(this, SLOT(slotZoomIn()), actionCollection());
0516   // View Zoom Out
0517   zoomOutAction=KStandardAction::zoomOut(this, SLOT(slotZoomOut()), actionCollection());
0518 
0519   // View Zoom
0520   zoomAction  = new KSelectAction(i18n("Zoom"), this);
0521   actionCollection()->addAction("view_zoom", zoomAction );
0522   connect(zoomAction, &KSelectAction::indexTriggered, this, &KImageMapEditor::slotZoom);
0523   zoomAction->setWhatsThis(i18n("<h3>Zoom</h3>"
0524                           "Choose the desired zoom level."));
0525   zoomAction->setItems(QStringList()
0526     << i18n("25%")
0527     << i18n("50%")
0528     << i18n("100%")
0529     << i18n("150%")
0530     << i18n("200%")
0531     << i18n("250%")
0532     << i18n("300%")
0533     << i18n("500%")
0534     << i18n("750%")
0535     << i18n("1000%"));
0536 
0537   zoomAction->setCurrentItem(2);
0538 
0539   highlightAreasAction = actionCollection()->add<KToggleAction>("view_highlightareas");
0540   highlightAreasAction->setText(i18n("Highlight Areas"));
0541 
0542   connect(highlightAreasAction, SIGNAL(toggled(bool)),
0543       this, SLOT(slotHighlightAreas(bool)));
0544 
0545   showAltAction =   actionCollection()->add<KToggleAction>("view_showalt");
0546   showAltAction->setText(i18n("Show Alt Tag"));
0547   connect(showAltAction, SIGNAL(toggled(bool)),this, SLOT (slotShowAltTag(bool)));
0548 
0549     mapNameAction  = new QAction(i18n("Map &Name..."), this);
0550     actionCollection()->addAction("map_name", mapNameAction );
0551   connect(mapNameAction, SIGNAL(triggered(bool)), SLOT(mapEditName()));
0552 
0553     mapNewAction  = new QAction(i18n("Ne&w Map..."), this);
0554     actionCollection()->addAction("map_new", mapNewAction );
0555   connect(mapNewAction, SIGNAL(triggered(bool)), SLOT(mapNew()));
0556   mapNewAction->setToolTip(i18n("Create a new map"));
0557 
0558     mapDeleteAction  = new QAction(i18n("D&elete Map"), this);
0559     actionCollection()->addAction("map_delete", mapDeleteAction );
0560   connect(mapDeleteAction, SIGNAL(triggered(bool)), SLOT(mapDelete()));
0561   mapDeleteAction->setToolTip(i18n("Delete the current active map"));
0562 
0563     mapDefaultAreaAction  = new QAction(i18n("Edit &Default Area..."), this);
0564     actionCollection()->addAction("map_defaultarea", mapDefaultAreaAction );
0565   connect(mapDefaultAreaAction, SIGNAL(triggered(bool)), SLOT(mapDefaultArea()));
0566   mapDefaultAreaAction->setToolTip(i18n("Edit the default area of the current active map"));
0567 
0568     temp  = new QAction(i18n("&Preview"), this);
0569     actionCollection()->addAction("map_preview", temp );
0570   connect(temp, SIGNAL(triggered(bool)), SLOT(mapPreview()));
0571   temp->setToolTip(i18n("Show a preview"));
0572 
0573   // IMAGE
0574   i18n("&Image");
0575 
0576   imageAddAction  = new QAction(i18n("Add Image..."), this);
0577   actionCollection()->addAction("image_add", imageAddAction );
0578   connect(imageAddAction, SIGNAL(triggered(bool)), SLOT(imageAdd()));
0579   imageAddAction->setToolTip(i18n("Add a new image"));
0580 
0581     imageRemoveAction  = new QAction(i18n("Remove Image"), this);
0582     actionCollection()->addAction("image_remove", imageRemoveAction );
0583   connect(imageRemoveAction, SIGNAL(triggered(bool)), SLOT(imageRemove()));
0584   imageRemoveAction->setToolTip(i18n("Remove the current visible image"));
0585 
0586     imageUsemapAction  = new QAction(i18n("Edit Usemap..."), this);
0587     actionCollection()->addAction("image_usemap", imageUsemapAction );
0588   connect(imageUsemapAction, SIGNAL(triggered(bool)), SLOT(imageUsemap()));
0589   imageUsemapAction->setToolTip(i18n("Edit the usemap tag of the current visible image"));
0590 
0591     temp  = new QAction(i18n("Show &HTML"), this);
0592     actionCollection()->addAction("map_showhtml", temp );
0593   connect(temp, SIGNAL(triggered(bool)), SLOT(mapShowHTML()));
0594 
0595 
0596   QActionGroup *drawingGroup = new QActionGroup(this);
0597   // Selection Tool
0598   arrowAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("arrow")), i18n("&Selection"), this);
0599   actionCollection()->setDefaultShortcut(arrowAction, QKeySequence("s"));
0600   actionCollection()->addAction("tool_arrow", arrowAction);
0601   connect(arrowAction, SIGNAL(triggered(bool)), SLOT (slotDrawArrow()));
0602   arrowAction->setWhatsThis(i18n("<h3>Selection</h3>"
0603                           "Click this to select areas."));
0604   drawingGroup->addAction(arrowAction);
0605   arrowAction->setChecked(true);
0606 
0607   // Circle
0608   circleAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("circle")), i18n("&Circle"), this);
0609   actionCollection()->setDefaultShortcut(circleAction, QKeySequence("c"));
0610 
0611   actionCollection()->addAction("tool_circle", circleAction);
0612   connect(circleAction, SIGNAL(triggered(bool)), this, SLOT(slotDrawCircle()));
0613   circleAction->setWhatsThis(i18n("<h3>Circle</h3>"
0614                           "Click this to start drawing a circle."));
0615   drawingGroup->addAction(circleAction);
0616 
0617   // Rectangle
0618     rectangleAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("rectangle")), i18n("&Rectangle"), this);
0619   actionCollection()->setDefaultShortcut(rectangleAction, QKeySequence("r"));
0620     actionCollection()->addAction("tool_rectangle", rectangleAction);
0621   connect(rectangleAction, SIGNAL(triggered(bool)), this, SLOT(slotDrawRectangle()));
0622   rectangleAction->setWhatsThis(i18n("<h3>Rectangle</h3>"
0623                           "Click this to start drawing a rectangle."));
0624   drawingGroup->addAction(rectangleAction);
0625 
0626   // Polygon
0627     polygonAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("polygon")), i18n("&Polygon"), this);
0628   actionCollection()->setDefaultShortcut(polygonAction, QKeySequence("p"));
0629     actionCollection()->addAction("tool_polygon", polygonAction);
0630   connect(polygonAction, SIGNAL(triggered(bool)), SLOT(slotDrawPolygon()));
0631   polygonAction->setWhatsThis(i18n("<h3>Polygon</h3>"
0632                           "Click this to start drawing a polygon."));
0633   drawingGroup->addAction(polygonAction);
0634 
0635   // Freehand
0636     freehandAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("freehand")), i18n("&Freehand Polygon"), this);
0637   actionCollection()->setDefaultShortcut(freehandAction, QKeySequence("f"));
0638     actionCollection()->addAction("tool_freehand", freehandAction);
0639   connect(freehandAction, SIGNAL(triggered(bool)), SLOT(slotDrawFreehand()));
0640   freehandAction->setWhatsThis(i18n("<h3>Freehandpolygon</h3>"
0641                           "Click this to start drawing a freehand polygon."));
0642   drawingGroup->addAction(freehandAction);
0643 
0644   // Add Point
0645     addPointAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("addpoint")), i18n("&Add Point"), this);
0646   actionCollection()->setDefaultShortcut(addPointAction, QKeySequence("a"));
0647     actionCollection()->addAction("tool_addpoint", addPointAction);
0648   connect(addPointAction, SIGNAL(triggered(bool)), SLOT(slotDrawAddPoint()));
0649   addPointAction->setWhatsThis(i18n("<h3>Add Point</h3>"
0650                           "Click this to add points to a polygon."));
0651   drawingGroup->addAction(addPointAction);
0652 
0653   // Remove Point
0654   removePointAction = new KToggleAction(QIcon::fromTheme(QStringLiteral("removepoint")), i18n("&Remove Point"), this);
0655   actionCollection()->setDefaultShortcut(removePointAction, QKeySequence("e"));
0656   actionCollection()->addAction("tool_removepoint", removePointAction);
0657   connect(removePointAction, SIGNAL(triggered(bool)), 
0658           SLOT(slotDrawRemovePoint()));
0659   removePointAction->setWhatsThis(i18n("<h3>Remove Point</h3>"
0660                           "Click this to remove points from a polygon."));
0661   drawingGroup->addAction(removePointAction);
0662 
0663     QAction *action  = new QAction(i18n("Cancel Drawing"), this);
0664     actionCollection()->addAction("canceldrawing", action );
0665   connect(action, SIGNAL(triggered(bool)), SLOT(slotCancelDrawing()));
0666   actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::Key_Escape));
0667 
0668   moveLeftAction  = new QAction(i18n("Move Left"), this);
0669   actionCollection()->addAction("moveleft", moveLeftAction );
0670   connect(moveLeftAction, SIGNAL(triggered(bool)),
0671          SLOT(slotMoveLeft()));
0672   actionCollection()->setDefaultShortcut(moveLeftAction, QKeySequence(Qt::Key_Left));
0673 
0674     moveRightAction  = new QAction(i18n("Move Right"), this);
0675     actionCollection()->addAction("moveright", moveRightAction );
0676   connect(moveRightAction, SIGNAL(triggered(bool)), SLOT(slotMoveRight()));
0677   actionCollection()->setDefaultShortcut(moveRightAction, QKeySequence(Qt::Key_Right));
0678 
0679     moveUpAction  = new QAction(i18n("Move Up"), this);
0680     actionCollection()->addAction("moveup", moveUpAction );
0681   connect(moveUpAction, SIGNAL(triggered(bool)), SLOT(slotMoveUp()));
0682   actionCollection()->setDefaultShortcut(moveUpAction, QKeySequence(Qt::Key_Up));
0683 
0684     moveDownAction  = new QAction(i18n("Move Down"), this);
0685     actionCollection()->addAction("movedown", moveDownAction );
0686   connect(moveDownAction, SIGNAL(triggered(bool)), SLOT(slotMoveDown()));
0687   actionCollection()->setDefaultShortcut(moveDownAction, QKeySequence(Qt::Key_Down));
0688 
0689     increaseWidthAction  = new QAction(i18n("Increase Width"), this);
0690     actionCollection()->addAction("increasewidth", increaseWidthAction );
0691   connect(increaseWidthAction, SIGNAL(triggered(bool)), SLOT(slotIncreaseWidth()));
0692   actionCollection()->setDefaultShortcut(increaseWidthAction, QKeySequence(Qt::Key_Right | Qt::SHIFT));
0693 
0694     decreaseWidthAction  = new QAction(i18n("Decrease Width"), this);
0695     actionCollection()->addAction("decreasewidth", decreaseWidthAction );
0696   connect(decreaseWidthAction, SIGNAL(triggered(bool)), SLOT(slotDecreaseWidth()));
0697   actionCollection()->setDefaultShortcut(decreaseWidthAction, QKeySequence(Qt::Key_Left | Qt::SHIFT));
0698 
0699     increaseHeightAction  = new QAction(i18n("Increase Height"), this);
0700     actionCollection()->addAction("increaseheight", increaseHeightAction );
0701   connect(increaseHeightAction, SIGNAL(triggered(bool)), SLOT(slotIncreaseHeight()));
0702   actionCollection()->setDefaultShortcut(increaseHeightAction, QKeySequence(Qt::Key_Up | Qt::SHIFT));
0703 
0704     decreaseHeightAction  = new QAction(i18n("Decrease Height"), this);
0705     actionCollection()->addAction("decreaseheight", decreaseHeightAction );
0706   connect(decreaseHeightAction, SIGNAL(triggered(bool)), SLOT(slotDecreaseHeight()));
0707   actionCollection()->setDefaultShortcut(decreaseHeightAction, QKeySequence(Qt::Key_Down | Qt::SHIFT));
0708 
0709     toFrontAction  = new QAction(i18n("Bring to Front"), this);
0710     actionCollection()->addAction("tofront", toFrontAction );
0711   connect(toFrontAction, SIGNAL(triggered(bool)), SLOT(slotToFront()));
0712 
0713     toBackAction  = new QAction(i18n("Send to Back"), this);
0714     actionCollection()->addAction("toback", toBackAction );
0715   connect(toBackAction, SIGNAL(triggered(bool)), SLOT(slotToBack()));
0716 
0717     forwardOneAction  = new QAction(QIcon::fromTheme(QStringLiteral("raise")), i18n("Bring Forward One"), this);
0718     actionCollection()->addAction("forwardone", forwardOneAction );
0719   connect(forwardOneAction, SIGNAL(triggered(bool)), SLOT(slotForwardOne()));
0720     backOneAction  = new QAction(QIcon::fromTheme(QStringLiteral("lower")), i18n("Send Back One"), this);
0721     actionCollection()->addAction("backone", backOneAction );
0722   connect(backOneAction, SIGNAL(triggered(bool)), SLOT(slotBackOne()));
0723 
0724   areaListView->upBtn->addAction(forwardOneAction);
0725   areaListView->downBtn->addAction(backOneAction);
0726 
0727   connect( areaListView->upBtn, SIGNAL(pressed()), forwardOneAction, SLOT(trigger()));
0728   connect( areaListView->downBtn, SIGNAL(pressed()), backOneAction, SLOT(trigger()));
0729 
0730     action  = new QAction(QIcon::fromTheme(QStringLiteral("configure")), i18n("Configure KImageMapEditor..."), this);
0731     actionCollection()->addAction("configure_kimagemapeditor", action );
0732   connect(action, SIGNAL(triggered(bool)), SLOT(slotShowPreferences()));
0733 
0734   qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor: 1";
0735 
0736   if (areaDock) {
0737 
0738     QAction* a =  areaDock->toggleViewAction();
0739     a->setText(i18n("Show Area List"));
0740     actionCollection()->addAction("configure_show_arealist",
0741                   a);
0742 
0743     a = mapsDock->toggleViewAction();
0744     a->setText(i18n("Show Map List"));
0745     actionCollection()->addAction("configure_show_maplist", a );
0746 
0747     a = imagesDock->toggleViewAction();
0748     a->setText(i18n("Show Image List"));
0749     actionCollection()->addAction("configure_show_imagelist", a );
0750   }
0751 
0752   qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor: 2";
0753   updateActionAccess();
0754   qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor: 3";
0755 }
0756 
0757 void KImageMapEditor::setupStatusBar()
0758 {
0759 
0760 //  We can't do this with a KPart !
0761 //  widget()->statusBar()->insertItem(i18n(" Cursor")+" : x: 0 ,y: 0",STATUS_CURSOR);
0762 //  widget()->statusBar()->insertItem(i18n(" Selection")+" : - ",STATUS_SELECTION);
0763   emit setStatusBarText( i18n(" Selection: -  Cursor: x: 0, y: 0 "));
0764 }
0765 
0766 void KImageMapEditor::slotShowPreferences()
0767 {
0768   PreferencesDialog *dialog = new PreferencesDialog(widget(),config());
0769   connect(dialog, SIGNAL(preferencesChanged()), this, SLOT(slotConfigChanged()));
0770   dialog->exec();
0771   delete dialog;
0772 }
0773 
0774 
0775 void KImageMapEditor::showPopupMenu(const QPoint & pos, const QString & name)
0776 {
0777   QMenu* pop = static_cast<QMenu *>(factory()->container(name, this));
0778 
0779   if (!pop) {
0780       qCWarning(KIMAGEMAPEDITOR_LOG) << QString("KImageMapEditorPart: Missing XML definition for %1\n").arg(name);
0781       return;
0782   }
0783 
0784   pop->popup(pos);
0785 }
0786 
0787 void KImageMapEditor::slotShowMainPopupMenu(const QPoint & pos)
0788 {
0789   showPopupMenu(pos,"popup_main");
0790 }
0791 
0792 void KImageMapEditor::slotShowMapPopupMenu(const QPoint & pos)
0793 {
0794   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotShowMapPopupMenu";
0795   QTreeWidgetItem* item = mapsListView->listView()->itemAt(pos);
0796 
0797   if (isReadWrite()) {
0798     mapDeleteAction->setEnabled(item);
0799     mapNameAction->setEnabled(item);
0800     mapDefaultAreaAction->setEnabled(item);
0801   }
0802 
0803   if (item)
0804      mapsListView->selectMap(item);
0805 
0806   showPopupMenu(mapsListView->listView()->viewport()->mapToGlobal(pos),"popup_map");
0807 }
0808 
0809 void KImageMapEditor::slotShowImagePopupMenu(const QPoint & pos)
0810 {
0811   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotShowImagePopupMenu";
0812   QTreeWidgetItem* item = imagesListView->itemAt(pos);
0813 
0814   imageRemoveAction->setEnabled(item);
0815   imageUsemapAction->setEnabled(item);
0816 
0817   if (item)
0818      imagesListView->setCurrentItem(item);
0819 
0820   showPopupMenu(imagesListView->viewport()->mapToGlobal(pos),"popup_image");
0821 }
0822 
0823 void KImageMapEditor::slotShowPopupMenu(const QPoint & p)
0824 {
0825   QTreeWidgetItem* item = areaListView->listView->itemAt(p);
0826 
0827   if (!item)
0828     return;
0829 
0830   if (!item->isSelected())
0831   {
0832     deselectAll();
0833     select(item);
0834   }
0835 
0836   slotShowMainPopupMenu(areaListView->listView->viewport()->mapToGlobal(p));
0837 }
0838 
0839 void KImageMapEditor::updateStatusBar()
0840 {
0841   emit setStatusBarText(selectionStatusText+"  "+cursorStatusText);
0842 }
0843 
0844 void KImageMapEditor::slotChangeStatusCoords(int x,int y)
0845 {
0846 //  statusBar()->changeItem(QString(" Cursor : x: %1 ,y: %2 ").arg(x).arg(y),STATUS_CURSOR);
0847   cursorStatusText = i18n(" Cursor: x: %1, y: %2 ", x, y);
0848   updateStatusBar();
0849 }
0850 
0851 void KImageMapEditor::slotUpdateSelectionCoords() {
0852   if (selected()->count()>0) {
0853     QRect r=selected()->rect();
0854 //      statusBar()->changeItem(
0855     selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ", r.left(), r.top(), r.width(), r.height());
0856 
0857 //        ,STATUS_SELECTION);
0858     qApp->processEvents();
0859   } else
0860     selectionStatusText = i18n(" Selection: - ");
0861     //statusBar()->changeItem(" Selection : - ",STATUS_SELECTION);
0862 
0863   updateStatusBar();
0864 }
0865 
0866 void KImageMapEditor::slotUpdateSelectionCoords( const QRect & r )
0867 {
0868   selectionStatusText = i18n(" Selection: x: %1, y: %2, w: %3, h: %4 ", r.left(), r.top(), r.width(), r.height());
0869   updateStatusBar();
0870   qApp->processEvents();
0871 }
0872 
0873 void KImageMapEditor::drawToCenter(QPainter* p, const QString & str, int y, int width) {
0874   int xmid = width / 2;
0875 
0876   QFontMetrics fm = p->fontMetrics();
0877   QRect strBounds = fm.boundingRect(str);
0878 
0879   p->drawText(xmid-(strBounds.width()/2),y,str);
0880 }
0881 
0882 
0883 QImage KImageMapEditor::getBackgroundImage() {
0884 
0885   // Lazy initialisation
0886   if ( _backgroundImage.isNull() ) {
0887 
0888 
0889 //  QString filename = QString("dropimage_")+KGlobal::locale()->language()+".png";
0890 //  QString path = QString(); //KGlobal::dirs()->findResourceDir( "data", "kimagemapeditor/"+filename ) + "kimagemapeditor/"+filename;
0891 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "getBackgroundPic : loaded image : " << path;
0892 
0893 //  if ( ! QFileInfo(path).exists() ) {
0894     int width = 400;
0895     int height = 400;
0896     int border = 20;
0897     int fontSize = 58;
0898 
0899     QPixmap pix(width,height);
0900     pix.fill(QColor(74,76,74));
0901     QPainter p(&pix);
0902 
0903     //    QFont font = QFontDatabase().font("Luxi Sans","Bold",fontSize);
0904     QFont font;
0905     font.setBold(true);
0906     font.setPixelSize(fontSize);
0907     p.setFont( font );
0908     p.setCompositionMode(QPainter::CompositionMode_Source);
0909     p.setPen(QPen(QColor(112,114,112),1));
0910 
0911     // The translated string must be divided into
0912     // parts with about the same size that fit to the image
0913     QString str = i18n("Drop an image or HTML file");
0914     const QStringList strList = str.split(' ');
0915 
0916     // Get the string parts
0917     QString tmp;
0918     QStringList outputStrList;
0919     QFontMetrics fm = p.fontMetrics();
0920 
0921     for ( QStringList::ConstIterator it = strList.begin(); it != strList.end(); ++it ) {
0922       QString tmp2 = tmp + *it;
0923 
0924         if (fm.boundingRect(tmp2).width() > width-border) {
0925            outputStrList.append(tmp);
0926            tmp = *it + ' ';
0927         }
0928         else
0929           tmp = tmp2 + ' ';
0930     }
0931 
0932     // Last one was forgotten so add it.
0933     outputStrList.append(tmp);
0934 
0935     // Try to adjust the text vertically centered
0936     int step = myround(float(height) / (outputStrList.size()+1));
0937     int y = step;
0938 
0939     for ( QStringList::Iterator it = outputStrList.begin(); it != outputStrList.end(); ++it ) {
0940         drawToCenter(&p, *it, y, pix.width());
0941         y += step;
0942     }
0943 
0944     p.end();
0945 
0946     _backgroundImage = pix.toImage();
0947   }
0948 
0949 
0950   return _backgroundImage;
0951 
0952 /*
0953         QFontDatabase fdb;
0954     QStringList families = fdb.families();
0955     for ( QStringList::Iterator f = families.begin(); f != families.end(); ++f ) {
0956         QString family = *f;
0957         qDebug( family );
0958         QStringList styles = fdb.styles( family );
0959         for ( QStringList::Iterator s = styles.begin(); s != styles.end(); ++s ) {
0960             QString style = *s;
0961             QString dstyle = "\t" + style + " (";
0962             QValueList<int> smoothies = fdb.smoothSizes( family, style );
0963             for ( QValueList<int>::Iterator points = smoothies.begin();
0964                   points != smoothies.end(); ++points ) {
0965                 dstyle += QString::number( *points ) + " ";
0966             }
0967             dstyle = dstyle.left( dstyle.length() - 1 ) + ")";
0968             qDebug( dstyle );
0969         }
0970     }
0971 
0972 
0973     path = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + QLatin1Char('/') + "kimagemapeditor/" ) +filename;
0974     qCDebug(KIMAGEMAPEDITOR_LOG) << "getBackgroundPic : save new image to : " << path;
0975     pix.save(path,"PNG",100);
0976   }
0977 
0978   if ( ! QFileInfo(path).exists() ) {
0979       qCCritical(KIMAGEMAPEDITOR_LOG) << "Couldn't find needed " << filename << " file in "
0980                    "the data directory of KImageMapEditor.\n"
0981                    "Perhaps you have forgotten to do a make install !";
0982       exit(1);
0983   }
0984 */
0985 }
0986 
0987 
0988 void KImageMapEditor::addArea(Area* area) {
0989   if (!area) return;
0990 
0991   // Perhaps we've got a selection of areas
0992   // so test it and add all areas of the selection
0993   // nested selections are possible but doesn't exist
0994   AreaSelection *selection = nullptr;
0995   if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
0996   {
0997     AreaListIterator it = selection->getAreaListIterator();
0998     while (it.hasNext()) {
0999       Area* a = it.next();
1000       areas->prepend(a);
1001       a->setListViewItem(new QTreeWidgetItem(
1002           areaListView->listView,
1003           QStringList(a->attribute("href"))));
1004       a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1005     }
1006   }
1007   else
1008   {
1009     areas->prepend(area);
1010     area->setListViewItem(new QTreeWidgetItem(
1011       areaListView->listView,
1012       QStringList(area->attribute("href"))));
1013     area->listViewItem()->setIcon(1,QIcon(makeListViewPix(*area)));
1014   }
1015 
1016   setModified(true);
1017 
1018 }
1019 
1020 void KImageMapEditor::addAreaAndEdit(Area* s)
1021 {
1022   areas->prepend(s);
1023   s->setListViewItem(new QTreeWidgetItem(
1024     areaListView->listView,
1025     QStringList(s->attribute("href"))));
1026   s->listViewItem()->setIcon(1,QIcon(makeListViewPix(*s)));
1027   deselectAll();
1028   select(s);
1029   if (!showTagEditor(selected())) {
1030     // If the user has pressed cancel
1031     // he undos the creation
1032     commandHistory()->undo();
1033   }
1034 }
1035 
1036 void KImageMapEditor::deleteArea( Area * area )
1037 {
1038   if (!area) return;
1039 
1040   // only for repaint reasons
1041   QRect redrawRect = area->selectionRect();
1042 
1043   // Perhaps we've got a selection of areas
1044   // so test it and delete the whole selection
1045   // nested selections are possible but doesn't exist
1046   AreaSelection *selection = nullptr;
1047     if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
1048   {
1049     AreaListIterator it = selection->getAreaListIterator();
1050     while (it.hasNext()) {
1051       Area* a = it.next();
1052       currentSelected->remove(a);
1053       areas->removeAll( a );
1054       a->deleteListViewItem();
1055     }
1056   }
1057   else
1058   {
1059     deselect( area );
1060     areas->removeAll( area );
1061     area->deleteListViewItem();
1062   }
1063 
1064   drawZone->repaintRect(redrawRect);
1065 
1066 
1067   // Only to disable cut and copy actions
1068   if (areas->count()==0)
1069     deselectAll();
1070 
1071   setModified(true);
1072 }
1073 
1074 void KImageMapEditor::deleteSelected() {
1075 
1076   AreaListIterator it = currentSelected->getAreaListIterator();
1077   while (it.hasNext()) {
1078     Area *a = it.next();
1079     currentSelected->remove( a );
1080     areas->removeAll( a );
1081     delete a->listViewItem();
1082   }
1083 
1084 
1085   drawZone->repaintArea( *currentSelected );
1086   // Only to disable cut and copy actions
1087   if (areas->count()==0)
1088     deselectAll();
1089 
1090   setModified(true);
1091 }
1092 
1093 void KImageMapEditor::deleteAllAreas()
1094 {
1095   Area* a;
1096   foreach (a,*areas) {
1097     deselect( a );
1098     areas->removeAll( a );
1099     a->deleteListViewItem();
1100     if (!areas->isEmpty())
1101       a = areas->first(); // because the current is deleted
1102   }
1103 
1104   drawZone->repaint();
1105 
1106 }
1107 
1108 void KImageMapEditor::updateAllAreas()
1109 {
1110 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::updateAllAreas";
1111   Area* a;
1112   foreach(a,*areas) {
1113     a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1114   }
1115   drawZone->repaint();
1116 }
1117 
1118 void KImageMapEditor::updateSelection() const {
1119   //FIXME: areaListView->listView->triggerUpdate();
1120 }
1121 
1122 AreaSelection* KImageMapEditor::selected() const {
1123   return currentSelected;
1124 }
1125 
1126 void KImageMapEditor::select(Area* a)
1127 {
1128   if (!a) return;
1129 
1130   currentSelected->add(a);
1131   updateActionAccess();
1132   slotUpdateSelectionCoords();
1133 //  drawZone->repaintArea( *a);
1134 
1135 }
1136 
1137 void KImageMapEditor::selectWithoutUpdate(Area* a)
1138 {
1139   if (!a) return;
1140   currentSelected->add(a);
1141 }
1142 
1143 void KImageMapEditor::slotSelectionChanged()
1144 {
1145   AreaListIterator it = areaList();
1146   AreaList list = currentSelected->getAreaList();
1147 
1148   while (it.hasNext()) {
1149     Area* a = it.next();
1150     if ( a->listViewItem()->isSelected() != (list.contains(a)) )
1151     {
1152       a->listViewItem()->isSelected()
1153         ? select( a )
1154         :   deselect( a );
1155 
1156       drawZone->repaintArea( *a);
1157     }
1158   }
1159 
1160 }
1161 
1162 void KImageMapEditor::select( QTreeWidgetItem* item)
1163 {
1164 
1165   AreaListIterator it = areaList();
1166   while (it.hasNext()) {
1167     Area* a = it.next();
1168     if (a->listViewItem() == item )
1169     {
1170       select( a );
1171       drawZone->repaintArea( *a);
1172     }
1173   }
1174 
1175 
1176 }
1177 
1178 AreaListIterator KImageMapEditor::areaList() const {
1179   AreaListIterator it(*areas);
1180   return it;
1181 }
1182 
1183 
1184 void KImageMapEditor::slotAreaChanged(Area *area)
1185 {
1186   if (!area)
1187     return;
1188 
1189   setModified(true);
1190 
1191   AreaSelection *selection = nullptr;
1192   if ( (selection = dynamic_cast <AreaSelection*> ( area ) ) )
1193   {
1194     AreaListIterator it = selection->getAreaListIterator();
1195     while (it.hasNext()) {
1196       Area* a = it.next();
1197       if (a->listViewItem()) {
1198         a->listViewItem()->setText(0,a->attribute("href"));
1199         a->listViewItem()->setIcon(1,QIcon(makeListViewPix(*a)));
1200       }
1201     }
1202 
1203   }
1204   else
1205   if (area->listViewItem()) {
1206     area->listViewItem()->setText(0,area->attribute("href"));
1207     area->listViewItem()->setIcon(1,QIcon(makeListViewPix(*area)));
1208   }
1209 
1210   drawZone->repaintArea(*area);
1211 
1212 }
1213 
1214 void KImageMapEditor::deselect(Area* a)
1215 {
1216   if (a) {
1217     currentSelected->remove(a);
1218 //      drawZone->repaintArea(*a);
1219     updateActionAccess();
1220     slotUpdateSelectionCoords();
1221   }
1222 }
1223 
1224 void KImageMapEditor::deselectWithoutUpdate(Area* a)
1225 {
1226   if (a) {
1227     currentSelected->remove(a);
1228   }
1229 }
1230 
1231 
1232 /**
1233 * Makes sure, that the actions cut, copy, delete and
1234 * show properties
1235 * can only be executed if sth. is selected.
1236 **/
1237 void KImageMapEditor::updateActionAccess()
1238 {
1239   if (!isReadWrite())
1240      return;
1241 
1242   if ( 0 < selected()->count())
1243   {
1244     qCDebug(KIMAGEMAPEDITOR_LOG) << "actions enabled";
1245     areaPropertiesAction->setEnabled(true);
1246     deleteAction->setEnabled(true);
1247     copyAction->setEnabled(true);
1248     cutAction->setEnabled(true);
1249     moveLeftAction->setEnabled(true);
1250     moveRightAction->setEnabled(true);
1251     moveUpAction->setEnabled(true);
1252     moveDownAction->setEnabled(true);
1253     toFrontAction->setEnabled(true);
1254     toBackAction->setEnabled(true);
1255 
1256     if ( (selected()->count() == 1) )
1257     {
1258       if (selected()->type()==Area::Polygon)
1259       {
1260         increaseWidthAction->setEnabled(false);
1261         decreaseWidthAction->setEnabled(false);
1262         increaseHeightAction->setEnabled(false);
1263         decreaseHeightAction->setEnabled(false);
1264         addPointAction->setEnabled(true);
1265         removePointAction->setEnabled(true);
1266       }
1267       else
1268       {
1269         increaseWidthAction->setEnabled(true);
1270         decreaseWidthAction->setEnabled(true);
1271         increaseHeightAction->setEnabled(true);
1272         decreaseHeightAction->setEnabled(true);
1273         addPointAction->setEnabled(false);
1274         removePointAction->setEnabled(false);
1275       }
1276 
1277     }
1278     else
1279     {
1280       increaseWidthAction->setEnabled(false);
1281       decreaseWidthAction->setEnabled(false);
1282       increaseHeightAction->setEnabled(false);
1283       decreaseHeightAction->setEnabled(false);
1284       addPointAction->setEnabled(false);
1285       removePointAction->setEnabled(false);
1286     }
1287 
1288   }
1289   else
1290   {
1291     qCDebug(KIMAGEMAPEDITOR_LOG) << "Actions disabled";
1292     areaPropertiesAction->setEnabled(false);
1293     deleteAction->setEnabled(false);
1294     copyAction->setEnabled(false);
1295     cutAction->setEnabled(false);
1296     moveLeftAction->setEnabled(false);
1297     moveRightAction->setEnabled(false);
1298     moveUpAction->setEnabled(false);
1299     moveDownAction->setEnabled(false);
1300     increaseWidthAction->setEnabled(false);
1301     decreaseWidthAction->setEnabled(false);
1302     increaseHeightAction->setEnabled(false);
1303     decreaseHeightAction->setEnabled(false);
1304     toFrontAction->setEnabled(false);
1305     toBackAction->setEnabled(false);
1306     addPointAction->setEnabled(false);
1307     removePointAction->setEnabled(false);
1308 
1309   }
1310 
1311   updateUpDownBtn();
1312 }
1313 
1314 void KImageMapEditor::updateUpDownBtn()
1315 {
1316   if (!isReadWrite())
1317      return;
1318 
1319   AreaList list = currentSelected->getAreaList();
1320 
1321   if (list.isEmpty() || (areas->count() < 2)) {
1322     forwardOneAction->setEnabled(false);
1323     areaListView->upBtn->setEnabled(false);
1324     backOneAction->setEnabled(false);
1325     areaListView->downBtn->setEnabled(false);
1326     return;
1327   }
1328   // if the first Area is in the selection can't move up
1329   if (list.contains( areas->first() )) {
1330     forwardOneAction->setEnabled(false);
1331     areaListView->upBtn->setEnabled(false);
1332   } else {
1333     forwardOneAction->setEnabled(true);
1334     areaListView->upBtn->setEnabled(true);
1335   }
1336 
1337   drawZone->repaintArea(*currentSelected);
1338 
1339   // if the last Area is in the selection can't move down
1340   if (list.contains( areas->last() )) {
1341     backOneAction->setEnabled(false);
1342     areaListView->downBtn->setEnabled(false);
1343   }
1344   else {
1345     backOneAction->setEnabled(true);
1346     areaListView->downBtn->setEnabled(true);
1347   }
1348 
1349 }
1350 
1351 void KImageMapEditor::deselectAll()
1352 {
1353   QRect redrawRect= currentSelected->selectionRect();
1354   currentSelected->reset();
1355   drawZone->repaintRect(redrawRect);
1356   updateActionAccess();
1357 }
1358 
1359 Area* KImageMapEditor::onArea(const QPoint & p) const {
1360   Area* s;
1361   foreach(s,*areas) {
1362     if (s->contains(p))
1363       return s;
1364   }
1365   return nullptr;
1366 }
1367 
1368 
1369 int KImageMapEditor::showTagEditor(Area *a) {
1370   if (!a) return 0;
1371   drawZone->repaintArea(*a);
1372 
1373   AreaDialog *dialog= new AreaDialog(this,a);
1374   connect (dialog, SIGNAL(areaChanged(Area*)), this, SLOT(slotAreaChanged(Area*)));
1375 
1376   int result = dialog->exec();
1377 
1378   return result;
1379 
1380 
1381 }
1382 
1383 int KImageMapEditor::showTagEditor(QTreeWidgetItem *item) {
1384   if (!item)
1385     return 0;
1386 
1387   Area* a;
1388   foreach(a,*areas) {
1389     if (a->listViewItem()==item) {
1390       return showTagEditor(a);
1391     }
1392   }
1393   return 0;
1394 }
1395 
1396 int KImageMapEditor::showTagEditor() {
1397   return showTagEditor(selected());
1398 }
1399 
1400 
1401 QString KImageMapEditor::getHTMLImageMap() const {
1402   QString retStr;
1403   retStr+="<map "+QString("name=\"")+_mapName+"\">\n";
1404 
1405   Area* a;
1406   foreach(a,*areas) {
1407     retStr+="  "+a->getHTMLCode()+'\n';
1408   }
1409 
1410   if (defaultArea && defaultArea->finished())
1411     retStr+="  "+defaultArea->getHTMLCode()+'\n';
1412 
1413   retStr+="</map>";
1414   return retStr;
1415 }
1416 
1417 QPixmap KImageMapEditor::makeListViewPix(Area & a)
1418 {
1419   QPixmap pix=a.cutOut(drawZone->picture());
1420 
1421   double shrinkFactor=1;
1422 
1423   // picture fits into max row height ?
1424   if (maxAreaPreviewHeight < pix.height())
1425     shrinkFactor = ( (double) maxAreaPreviewHeight / pix.height() );
1426 
1427   QPixmap pix2((int)(pix.width()*shrinkFactor), (int)(pix.height()*shrinkFactor));
1428 
1429   // Give all pixels a defined color
1430   pix2.fill(Qt::white);
1431 
1432   QPainter p(&pix2);
1433 
1434   p.scale(shrinkFactor,shrinkFactor);
1435   p.drawPixmap(0,0,pix);
1436 
1437   return pix2;
1438 }
1439 
1440 void KImageMapEditor::setMapName(const QString & s) {
1441     mapsListView->changeMapName(_mapName, s);
1442     _mapName=s;
1443     currentMapElement->mapTag->name = s;
1444 }
1445 
1446 
1447 void KImageMapEditor::setPicture(const QUrl & url) {
1448   _imageUrl=url;
1449   if (QFileInfo::exists(url.path())) {
1450      QImage img(url.path());
1451 
1452      if (!img.isNull()) {
1453          setPicture(img);
1454          imageRemoveAction->setEnabled(true);
1455          imageUsemapAction->setEnabled(true);
1456      }
1457      else
1458          qCCritical(KIMAGEMAPEDITOR_LOG) << QString("The image %1 could not be opened.").arg(url.path());
1459   }
1460   else
1461      qCCritical(KIMAGEMAPEDITOR_LOG) << QString("The image %1 does not exist.").arg(url.path());
1462 }
1463 
1464 void KImageMapEditor::setPicture(const QImage & pix) {
1465     drawZone->setPicture(pix);
1466     updateAllAreas();
1467 }
1468 
1469 
1470 void KImageMapEditor::slotDrawArrow() {
1471   _currentToolType=KImageMapEditor::Selection;
1472 
1473 }
1474 
1475 void KImageMapEditor::slotDrawCircle() {
1476   _currentToolType=KImageMapEditor::Circle;
1477   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotDrawCircle";
1478 
1479 }
1480 
1481 void KImageMapEditor::slotDrawRectangle() {
1482   _currentToolType=KImageMapEditor::Rectangle;
1483   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotDrawRectangle";
1484 
1485 }
1486 
1487 void KImageMapEditor::slotDrawPolygon() {
1488   _currentToolType=KImageMapEditor::Polygon;
1489   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotDrawPolygon";
1490 }
1491 
1492 void KImageMapEditor::slotDrawFreehand() {
1493   _currentToolType=KImageMapEditor::Freehand;
1494 }
1495 
1496 void KImageMapEditor::slotDrawAddPoint() {
1497   _currentToolType=KImageMapEditor::AddPoint;
1498 }
1499 
1500 void KImageMapEditor::slotDrawRemovePoint() {
1501   _currentToolType=KImageMapEditor::RemovePoint;
1502 }
1503 
1504 
1505 void KImageMapEditor::slotZoom() {
1506 
1507   int i=zoomAction->currentItem();
1508   switch (i) {
1509     case 0 : drawZone->setZoom(0.25);break;
1510     case 1 : drawZone->setZoom(0.5);break;
1511     case 2 : drawZone->setZoom(1);break;
1512     case 3 : drawZone->setZoom(1.5);break;
1513     case 4 : drawZone->setZoom(2.0);break;
1514     case 5 : drawZone->setZoom(2.5);break;
1515     case 6 : drawZone->setZoom(3);break;
1516     case 7 : drawZone->setZoom(5);break;
1517     case 8 : drawZone->setZoom(7.5);break;
1518     case 9 : drawZone->setZoom(10);break;
1519   }
1520   if (i<10)
1521     zoomInAction->setEnabled(true);
1522   else
1523     zoomInAction->setEnabled(false);
1524 
1525   if (i>0)
1526     zoomOutAction->setEnabled(true);
1527   else
1528     zoomOutAction->setEnabled(false);
1529 }
1530 
1531 void KImageMapEditor::slotZoomIn() {
1532   if (zoomAction->currentItem()==(int)(zoomAction->items().count()-1))
1533     return;
1534 
1535   zoomAction->setCurrentItem(zoomAction->currentItem()+1);
1536   slotZoom();
1537 }
1538 
1539 void KImageMapEditor::slotZoomOut() {
1540   if (zoomAction->currentItem()==0)
1541     return;
1542 
1543   zoomAction->setCurrentItem(zoomAction->currentItem()-1);
1544   slotZoom();
1545 }
1546 
1547 void KImageMapEditor::mapDefaultArea()
1548 {
1549   if (defaultArea)
1550     showTagEditor(defaultArea);
1551   else {
1552     defaultArea= new DefaultArea();
1553     showTagEditor(defaultArea);
1554   }
1555 
1556 }
1557 
1558 void KImageMapEditor::mapEditName()
1559 {
1560   bool ok=false;
1561   QString input = QInputDialog::getText(widget(),
1562     i18n("Enter Map Name"), i18n("Enter the name of the map:"),
1563     QLineEdit::Normal, _mapName, &ok);
1564   if (ok && !input.isEmpty()) {
1565     if (input != _mapName) {
1566         if (mapsListView->nameAlreadyExists(input))
1567             KMessageBox::error(this->widget(), i18n("The name <em>%1</em> already exists.", input));
1568         else {
1569             setMapName(input);
1570         }
1571     }
1572   }
1573 }
1574 
1575 void KImageMapEditor::mapShowHTML()
1576 {
1577   QDialog *dialog = new QDialog(widget());
1578   dialog->setModal(true);
1579   dialog->setWindowTitle(i18n("HTML Code of Map"));
1580   QVBoxLayout *mainLayout = new QVBoxLayout(dialog);
1581 
1582   QTextEdit *edit = new QTextEdit;
1583 
1584   edit->setPlainText(getHtmlCode());
1585   edit->setReadOnly(true);
1586   edit->setLineWrapMode(QTextEdit::NoWrap);
1587   mainLayout->addWidget(edit);
1588 //  dialog->resize(dialog->calculateSize(edit->maxLineWidth(),edit->numLines()*));
1589 //  dialog->adjustSize();
1590 
1591   QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok);
1592   QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
1593   okButton->setDefault(true);
1594   okButton->setShortcut(Qt::CTRL | Qt::Key_Return);
1595   connect(buttonBox, SIGNAL(accepted()), dialog, SLOT(accept()));
1596   mainLayout->addWidget(buttonBox);
1597 
1598   dialog->resize(600,400);
1599   dialog->exec();
1600   delete dialog;
1601 }
1602 
1603 void KImageMapEditor::openFile(const QUrl & url) {
1604   if ( ! url.isEmpty()) {
1605     QMimeDatabase db;
1606     QMimeType openedFileType = db.mimeTypeForUrl(url);
1607     if (openedFileType.name().left(6) == "image/") {
1608         addImage(url);
1609     } else {
1610         openURL(url);
1611     }
1612   }
1613 }
1614 
1615 bool KImageMapEditor::openURL(const QUrl & url) {
1616     // If a local file does not exist
1617     // we start with an empty file, so
1618     // that we can return true here.
1619     // For non local files, we cannot check
1620     // the existence
1621     if (url.isLocalFile() &&
1622         ! QFile::exists(url.path()))
1623         return true;
1624     return KParts::ReadWritePart::openUrl(url);
1625 }
1626 
1627 void KImageMapEditor::fileOpen() {
1628 
1629   QString fileName = QFileDialog::getOpenFileName(widget(), i18n("Choose File to Open"), QString(),
1630                      i18n("Web File (*.png *.jpg *.jpeg *.gif *.htm *.html);;Images (*.png *.jpg *.jpeg *.gif *.bmp *.xbm *.xpm *.pnm *.mng);;"
1631                           "HTML Files (*.htm *.html);;All Files (*)"));
1632 
1633   openFile(QUrl::fromUserInput( fileName ));
1634 }
1635 
1636 
1637 
1638 void KImageMapEditor::fileClose()
1639 {
1640   if (! closeUrl())
1641      return;
1642 
1643 
1644     setPicture(getBackgroundImage());
1645     recentFilesAction->setCurrentItem(-1);
1646     setModified(false);
1647 }
1648 
1649 void KImageMapEditor::fileSave()
1650 {
1651   // if we aren't read-write, return immediately
1652   if ( ! isReadWrite() )
1653       return;
1654 
1655   if (url().isEmpty()) {
1656     fileSaveAs();
1657   }
1658   else {
1659     saveFile();
1660     setModified(false);
1661   }
1662 
1663 
1664 }
1665 
1666 void KImageMapEditor::fileSaveAs() {
1667 
1668   QUrl url = QFileDialog::getSaveFileUrl(widget(), QString(), QUrl(), i18n("HTML File (*.htm *.html);;Text File (*.txt);;All Files (*)" ));
1669   if (url.isEmpty() || !url.isValid()) {
1670     return;
1671   }
1672 
1673 
1674   saveAs(url);
1675   recentFilesAction->addUrl(url);
1676 
1677 }
1678 
1679 
1680 bool KImageMapEditor::openFile()
1681 {
1682   QUrl u = url();
1683   QFileInfo fileInfo(u.path());
1684 
1685   if ( !fileInfo.exists() )
1686   {
1687       KMessageBox::information(widget(),
1688         i18n("<qt>The file <b>%1</b> does not exist.</qt>", fileInfo.fileName()),
1689         i18n("File Does Not Exist"));
1690       return false;
1691   }
1692 
1693   openHTMLFile(u);
1694 
1695   drawZone->repaint();
1696   recentFilesAction->addUrl(u);
1697   setModified(false);
1698   backupFileCreated = false;
1699   return true;
1700 }
1701 
1702 /**
1703  * This method supposes that the given QTextStream s has just read
1704  * the &lt; of a tag. It now reads all attributes of the tag until a &gt;
1705  * The tagname itself is also read and stored as a <em>tagname</em>
1706  * attribute. After parsing the whole tag it returns a QDict<QString>
1707  * with all attributes and their values. It stores the whole read text in the
1708  * parameter readText.
1709  */
1710 QHash<QString,QString> KImageMapEditor::getTagAttributes(QTextStream & s, QString & readText)
1711 {
1712   QHash<QString,QString> dict;
1713   // the "<" is already read
1714   QChar w;
1715   QString attr,value;
1716 
1717   readText.clear();
1718 
1719   // get the tagname
1720   while (!s.atEnd() && w!=' ') {
1721     s >> w;
1722     readText.append(w);
1723     if (w.isSpace() || w=='>') {
1724       dict.insert("tagname",value);
1725       break;
1726     }
1727     value+=w;
1728   }
1729 
1730 
1731   // do we have a comment ?
1732   // read the comment and return
1733   if (value.right(3)=="-->")
1734     return dict;
1735 
1736   if (value.startsWith(QLatin1String("!--"))) {
1737     while (!s.atEnd()) {
1738       s >> w;
1739       readText.append(w);
1740 
1741       if (w=='-') {
1742         s >> w;
1743         readText.append(w);
1744         if (w=='-') {
1745           s >> w;
1746           readText.append(w);
1747           if (w=='>')
1748             return dict;
1749         }
1750       }
1751     }
1752   }
1753 
1754   bool attrRead=true;   // currently reading an attribute ?
1755   bool equalSign=false; // an equalsign was read?
1756   bool valueRead=false; // currently reading a value ?
1757   QChar quotation='\0'; // currently reading a value with quotation marks ?
1758   bool php=false; // currently reading a php script
1759   attr.clear();
1760   value.clear();
1761 
1762   //get the other attributes
1763   while (!s.atEnd() && w!='>')
1764   {
1765     s >> w;
1766     readText.append(w);
1767 
1768     // End of PHP Script ?
1769     if (php && (w=='?') )
1770     {
1771       s >> w;
1772       readText.append(w);
1773 
1774       if (valueRead)
1775           value+=w;
1776 
1777       if (w=='>')
1778       {
1779         php = false;
1780         s >> w;
1781         readText.append(w);
1782       }
1783     }
1784 
1785     // Wrong syntax or PHP-Script !
1786     if (!php && (w=='<'))
1787     {
1788       if (valueRead)
1789         value+=w;
1790       s >> w;
1791       readText.append(w);
1792       if (valueRead)
1793         value+=w;
1794 
1795       if (w=='?')
1796       {
1797         php = true;
1798       }
1799     } else
1800     // finished ?
1801     if (w=='>') {
1802       if (valueRead) {
1803         dict.insert(attr,value);
1804       }
1805       return dict;
1806     } else
1807     // currently reading an attribute ?
1808     if (attrRead) {
1809       // if there is a whitespace the attributename has finished
1810       // possibly there isn't any value e.g. noshade
1811       if (w.isSpace())
1812         attrRead=false;
1813       else
1814       // an equal sign signals that the value follows
1815       if (w=='=') {
1816         attrRead=false;
1817         equalSign=true;
1818       } else
1819         attr+=w;
1820     } else
1821     // an equal sign was read ? delete every whitespace
1822     if (equalSign) {
1823       if (!w.isSpace()) {
1824         equalSign=false;
1825         valueRead=true;
1826         if (w=='"' || w=='\'')
1827           quotation=w;
1828       }
1829     } else
1830     // currently reading the value
1831     if (valueRead) {
1832       // if php, read without regarding anything
1833       if (php)
1834         value+=w;
1835       // if value within quotation marks is read
1836       // only stop when another quotationmark is found
1837       else
1838       if (quotation != '\0') {
1839         if (quotation!=w) {
1840           value+=w;
1841         } else {
1842           quotation='\0';
1843           valueRead=false;
1844           dict.insert(attr,value);
1845           attr.clear();
1846           value.clear();
1847         }
1848       } else
1849       // a whitespace indicates that the value has finished
1850       if (w.isSpace()) {
1851         valueRead=false;
1852         dict.insert(attr,value);
1853         attr.clear();
1854         value.clear();
1855       }
1856     } else {
1857       if (!w.isSpace()) {
1858         attrRead=true;
1859         attr+=w;
1860       }
1861     }
1862   }
1863 
1864   return dict;
1865 
1866 }
1867 
1868 
1869 bool KImageMapEditor::openHTMLFile(const QUrl & url)
1870 {
1871   QFile f(url.path());
1872   if ( !f.exists () )
1873       return false;
1874   f.open(QIODevice::ReadOnly);
1875   QTextStream s(&f);
1876   QChar w;
1877   QHash<QString,QString> *attr = nullptr;
1878   QList<ImageTag*> images;
1879   MapTag *map = nullptr;
1880   QList<MapTag*> maps;
1881 
1882   _htmlContent.clear();
1883   currentMapElement = nullptr;
1884 
1885   QString temp;
1886   QString origcode;
1887 
1888   bool readMap=false;
1889 
1890   while (!s.atEnd()) {
1891 
1892     s >> w;
1893     if (w=='<')
1894     {
1895       if (!readMap && !origcode.isEmpty()) {
1896         _htmlContent.append( new HtmlElement(origcode));
1897         origcode.clear();
1898       }
1899 
1900       origcode.append("<");
1901       attr=new QHash<QString,QString>(getTagAttributes(s,temp));
1902       origcode.append(temp);
1903 
1904       if (attr->contains("tagname")) {
1905         QString tagName = attr->value("tagname").toLower();
1906         if (tagName =="img") {
1907           HtmlImgElement *el = new HtmlImgElement(origcode);
1908           el->imgTag = static_cast<ImageTag*>(attr);
1909           images.append(el->imgTag);
1910           _htmlContent.append(el);
1911 
1912           origcode.clear();
1913         } else
1914         if (tagName == "map") {
1915           map = new MapTag();
1916           map->name = attr->value("name");
1917       qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::openHTMLFile: found map with name:" << map->name;
1918       
1919           readMap=true;
1920         } else
1921         if (tagName=="/map") {
1922           readMap=false;
1923           maps.append(map);
1924           HtmlMapElement *el = new HtmlMapElement(origcode);
1925           el->mapTag = map;
1926           _htmlContent.append(el);
1927 
1928           origcode.clear();
1929         } else
1930         if (readMap) {
1931           if (tagName=="area") {
1932              map->push_front(*attr);
1933           }
1934         } else {
1935           _htmlContent.append(new HtmlElement(origcode));
1936           origcode.clear();
1937         }
1938 
1939       }
1940     } // w != "<"
1941     else {
1942       origcode.append(w);
1943     }
1944   }
1945 
1946   if (!origcode.isEmpty()) {
1947     _htmlContent.append(new HtmlElement(origcode));
1948   }
1949 
1950   f.close();
1951 
1952   QUrl imageUrl;
1953 
1954   map = nullptr;
1955 
1956     // If we have more than on map or more than one image
1957     // Let the user choose, otherwise take the only ones
1958     if (maps.count() > 1) {
1959       map = maps.first();
1960     }
1961 
1962     if (images.count() > 1) {
1963       ImageTag* imgTag = images.first();
1964       if (imgTag) {
1965         if (imgTag->contains("src")) {
1966             if (url.path().isEmpty() | !url.path().endsWith('/')) {
1967                 imageUrl = QUrl(url.path() + '/').resolved(QUrl(imgTag->value("src")));
1968             }
1969             else {
1970                 imageUrl = url.resolved(QUrl(imgTag->value("src")));
1971             }
1972         }
1973       }
1974     }
1975 
1976     // If there is more than one map and more than one image
1977     // use the map that has an image with an according usemap tag
1978     if (maps.count() > 1 && images.count() > 1) {
1979       bool found = false;
1980       MapTag *mapTag;
1981       foreach(mapTag, maps) {
1982         ImageTag *imageTag;
1983         foreach(imageTag, images) {
1984             if (imageTag->contains("usemap")) {
1985                 QString usemap = imageTag->value("usemap");
1986                 // Remove the #
1987                 QString usemapName = usemap.right(usemap.length()-1);
1988                 if (usemapName == mapTag->name) {
1989           if (imageTag->contains("src")) {
1990                       if (url.path().isEmpty() | !url.path().endsWith('/')) {
1991                           imageUrl = QUrl(url.path() + '/').resolved(QUrl(imageTag->value("src")));
1992                       }
1993                       else {
1994                           imageUrl = url.resolved(QUrl(imageTag->value("src")));
1995                       }
1996               found = true;
1997           }
1998                 }
1999             }
2000         if (found)
2001           break;
2002         }
2003     if (found)
2004       break;
2005       }
2006       if (found) {
2007     map = mapTag;
2008       }
2009     }
2010 
2011 
2012     // If there are more than one map or there wasn't
2013     // found a fitting image and there is something to choose
2014     // let the user choose
2015     /*    if (maps.count() >1 || (imageUrl.isEmpty() && images.count() > 1))
2016     {
2017       ImageMapChooseDialog dialog(widget(),maps,images,url);
2018       qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::openHTMLFile: before dialog->exec()";
2019       dialog.exec();
2020       qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::openHTMLFile: after dialog->exec()";
2021       map = dialog.currentMap;
2022       imageUrl = dialog.pixUrl;
2023       }*/
2024   
2025 
2026   imagesListView->clear();
2027   imagesListView->setBaseUrl(url);
2028   imagesListView->addImages(images);
2029 
2030   mapsListView->clear();
2031   mapsListView->addMaps(maps);
2032 
2033 
2034   setMapActionsEnabled(false);
2035 
2036   if (map) {
2037     mapsListView->selectMap(map->name);
2038   } else {
2039 #ifdef WITH_TABWIDGET
2040     if (tabWidget)
2041        tabWidget->showPage(mapsListView);
2042 #endif
2043   }
2044 
2045 
2046   if (!imageUrl.isEmpty()) {
2047     setPicture(imageUrl);
2048   } else {
2049     setPicture(getBackgroundImage());
2050 #ifdef WITH_TABWIDGET
2051     if (tabWidget)
2052        tabWidget->showPage(imagesListView);
2053 #endif
2054   }
2055 
2056 
2057   emit setWindowCaption(url.fileName());
2058   setModified(false);
2059   return true;
2060 }
2061 
2062 /**
2063  * Finds the first html element which contains the given text.
2064  * Returns the first matching element.
2065  * Returns 0L if no element was found.
2066  */
2067 HtmlElement* KImageMapEditor::findHtmlElement(const QString & containingText) {
2068   HtmlElement *el;
2069   foreach (el,_htmlContent) {
2070     if (el->htmlCode.contains(containingText,Qt::CaseInsensitive)) {
2071       return el;
2072     }
2073   }
2074   return nullptr;
2075 }
2076 
2077 /**
2078  * Finds the first html element which contains the given ImageTag.
2079  * Returns the first matching element.
2080  * Returns 0L if no element was found.
2081  */
2082 HtmlImgElement* KImageMapEditor::findHtmlImgElement(ImageTag* tag) {
2083   HtmlElement* el;
2084   foreach(el,_htmlContent) {
2085     HtmlImgElement* imgEl = dynamic_cast<HtmlImgElement*>(el);
2086 
2087     if (imgEl && imgEl->imgTag == tag)
2088        return imgEl;
2089   }
2090   return nullptr;
2091 }
2092 
2093 void KImageMapEditor::addMap(const QString & name = QString()) {
2094   HtmlMapElement* el = new HtmlMapElement("\n<map></map>");
2095   MapTag* map = new MapTag();
2096   map->name = name;
2097   el->mapTag = map;
2098 
2099   // Try to find the body tag
2100   HtmlElement* bodyTag = findHtmlElement("<body");
2101 
2102   // if we found one add the new map right after the body tag
2103   if (bodyTag) {
2104      uint index = _htmlContent.indexOf(bodyTag);
2105 
2106      // Add a newline before the map
2107      _htmlContent.insert(index+1, new HtmlElement("\n"));
2108 
2109      _htmlContent.insert(index+2, el);
2110   } // if there is no body tag we add the map to the end of the file
2111   else {
2112      // Add a newline before the map
2113      _htmlContent.append(new HtmlElement("\n"));
2114 
2115      _htmlContent.append(el);
2116      qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::addMap : No <body found ! Appending new map to the end.";
2117   }
2118 
2119   mapsListView->addMap(name);
2120   mapsListView->selectMap(name);
2121 }
2122 
2123 /**
2124  * Finds the HtmlMapElement in the HtmlContent, that corresponds
2125  * to the given map name.<br>
2126  * Returns 0L if there exists no map with the given name
2127  */
2128 HtmlMapElement* KImageMapEditor::findHtmlMapElement(const QString & mapName) {
2129   foreach(HtmlElement * el,_htmlContent) {
2130     if (dynamic_cast<HtmlMapElement*>(el)) {
2131       HtmlMapElement *tagEl = static_cast<HtmlMapElement*>(el);
2132       if (tagEl->mapTag->name == mapName) {
2133          return tagEl;
2134       }
2135     }
2136   }
2137 
2138   qCWarning(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::findHtmlMapElement: couldn't find map '" << mapName << "'";
2139   return nullptr;
2140 }
2141 
2142 /**
2143  * Calls setMap with the HtmlMapElement with the given map name
2144  */
2145 void KImageMapEditor::setMap(const QString & mapName) {
2146     HtmlMapElement* el = findHtmlMapElement(mapName);
2147     if (!el) {
2148       qCWarning(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::setMap : Couldn't set map '" << mapName << "', because it wasn't found !";
2149       return;
2150     }
2151 
2152     setMap(el);
2153 
2154 }
2155 
2156 void KImageMapEditor::setMap(MapTag* map) {
2157   HtmlElement * el;
2158   foreach(el,_htmlContent) {
2159     HtmlMapElement *tagEl = dynamic_cast<HtmlMapElement*>(el);
2160     if (tagEl) {
2161       if (tagEl->mapTag == map) {
2162          setMap(tagEl);
2163          break;
2164       }
2165     }
2166   }
2167 
2168 }
2169 
2170 void KImageMapEditor::saveAreasToMapTag(MapTag* map) {
2171   map->clear();
2172   Area* a;
2173   foreach(a,*areas) {
2174     QString shapeStr;
2175 
2176     switch (a->type()) {
2177       case Area::Rectangle : shapeStr = "rect";break;
2178       case Area::Circle : shapeStr = "circle";break;
2179       case Area::Polygon : shapeStr = "poly";break;
2180       default : continue;
2181     }
2182 
2183     QHash<QString,QString> dict;
2184     dict.insert("shape",shapeStr);
2185 
2186     AttributeIterator it = a->attributeIterator();
2187     while (it.hasNext())
2188     {
2189       it.next();
2190       dict.insert(it.key(),it.value());
2191     }
2192 
2193     dict.insert("coords",a->coordsToString());
2194 
2195     map->push_back(dict);
2196 
2197   }
2198 
2199   if (defaultArea && defaultArea->finished()) {
2200     QHash<QString,QString> dict;
2201     dict.insert("shape","default");
2202 
2203     AttributeIterator it = defaultArea->attributeIterator();
2204     while (it.hasNext())
2205     {
2206       it.next();
2207       dict.insert(it.key(),it.value());
2208     }
2209 
2210     map->push_back(dict);
2211   }
2212 
2213 }
2214 
2215 static void setAttribute(Area* a, const AreaTag & tag, const QString & s) {
2216   if (tag.contains(s))
2217     a->setAttribute(s,tag.value(s));
2218 }
2219 
2220 void KImageMapEditor::setMap(HtmlMapElement* mapElement) {
2221   if (currentMapElement) {
2222     currentMapElement->mapTag->modified=true;
2223     currentMapElement->htmlCode = getHTMLImageMap();
2224     saveAreasToMapTag(currentMapElement->mapTag);
2225   }
2226 
2227   currentMapElement = mapElement;
2228   MapTag* map = currentMapElement->mapTag;
2229 
2230   // Remove old areas only if a new map is loaded
2231   deleteAllAreas();
2232   delete defaultArea;
2233   defaultArea = nullptr;
2234 //    qCDebug(KIMAGEMAPEDITOR_LOG) << "KImageMapEditor::setMap : Setting new map : " << map->name;
2235     _mapName = map->name;
2236     AreaTag tag;
2237 
2238     for (const AreaTag &tag : *map) {
2239         QString shape="rect";
2240         if (tag.contains("shape"))
2241           shape=tag.value("shape");
2242 
2243         Area::ShapeType type=Area::Rectangle;
2244         if (shape=="circle")
2245           type=Area::Circle;
2246         else if (shape=="poly")
2247           type=Area::Polygon;
2248         else if (shape=="default")
2249           type=Area::Default;
2250 
2251         Area* a=AreaCreator::create(type);
2252 
2253         setAttribute(a,tag,"href");
2254         setAttribute(a,tag,"alt");
2255         setAttribute(a,tag,"target");
2256         setAttribute(a,tag,"title");
2257         setAttribute(a,tag,"onclick");
2258         setAttribute(a,tag,"ondblclick");
2259         setAttribute(a,tag,"onmousedown");
2260         setAttribute(a,tag,"onmouseup"); 
2261         setAttribute(a,tag,"onmouseover");
2262         setAttribute(a,tag,"onmousemove");
2263         setAttribute(a,tag,"onmouseout");
2264 
2265         if (type==Area::Default) {
2266           defaultArea=a;
2267           defaultArea->setFinished(true);
2268           continue;
2269         }
2270 
2271         if (tag.contains("coords"))
2272           a->setCoords(tag.value("coords"));
2273 
2274         a->setMoving(false);
2275         addArea(a);
2276     }
2277 
2278     updateAllAreas();
2279 
2280     setMapActionsEnabled(true);
2281 }
2282 
2283 /**
2284  * Sets whether actions that depend on an selected map
2285  * are enabled
2286  */
2287 void KImageMapEditor::setMapActionsEnabled(bool b) {
2288    mapDeleteAction->setEnabled(b);
2289    mapDefaultAreaAction->setEnabled(b);
2290    mapNameAction->setEnabled(b);
2291 
2292    arrowAction->setChecked(true);
2293    slotDrawArrow();
2294 
2295    arrowAction->setEnabled(b);
2296    circleAction->setEnabled(b);
2297    rectangleAction->setEnabled(b);
2298    polygonAction->setEnabled(b);
2299    freehandAction->setEnabled(b);
2300    addPointAction->setEnabled(b);
2301    removePointAction->setEnabled(b);
2302 
2303 }
2304 
2305 QString KImageMapEditor::getHtmlCode() {
2306   if (currentMapElement) {
2307     currentMapElement->htmlCode = getHTMLImageMap();
2308   }
2309 
2310   QString result;
2311 
2312   HtmlElement *el;
2313   foreach(el,_htmlContent) {
2314         result += el->htmlCode;
2315   }
2316   return result;
2317 }
2318 
2319 
2320 /**
2321  create a relative short url based in baseURL
2322 
2323  taken from qextfileinfo.cpp:
2324 
2325  From WebMaker - KDE HTML Editor
2326  Copyright (C) 1998, 1999 Alexei Dets <dets@services.ru>
2327 
2328  Rewritten for Quanta Plus: (C) 2002 Andras Mantia <amantia@freemail.hu>
2329 
2330  This program is free software; you can redistribute it and/or modify
2331  it under the terms of the GNU General Public License as published by
2332  the Free Software Foundation; either version 2 of the License, or
2333  (at your option) any later version.
2334 */
2335 static QUrl toRelative(const QUrl& urlToConvert,const QUrl& baseURL)
2336 {
2337   QUrl resultURL = urlToConvert;
2338   if (urlToConvert.scheme() == baseURL.scheme())
2339   {
2340     QString path = urlToConvert.path();
2341     QString basePath = baseURL.path().endsWith('/') ? baseURL.path() : baseURL.path() + '/';
2342     if (path.startsWith(QLatin1String("/")) && basePath != "/")
2343     {
2344       path.remove(0, 1);
2345       basePath.remove(0, 1);
2346       if ( basePath.right(1) != "/" ) basePath.append("/");
2347 
2348       int pos=0;
2349       int pos1=0;
2350       for (;;)
2351       {
2352         pos=path.indexOf("/");
2353         pos1=basePath.indexOf("/");
2354         if ( pos<0 || pos1<0 ) break;
2355         if ( path.left(pos+1 ) == basePath.left(pos1+1) )
2356         {
2357           path.remove(0, pos+1);
2358           basePath.remove(0, pos1+1);
2359         }
2360         else
2361           break;
2362       };
2363 
2364       if ( basePath == "/" ) basePath="";
2365       int level = basePath.count("/");
2366       for (int i=0; i<level; i++)
2367       {
2368         path="../"+path;
2369       };
2370     }
2371 
2372     resultURL.setPath(QDir::cleanPath(path));
2373   }
2374 
2375   if (urlToConvert.path().endsWith('/')) resultURL.setPath(resultURL.path() + '/');
2376   return resultURL;
2377 }
2378 
2379 
2380 void KImageMapEditor::saveImageMap(const QUrl & url)
2381 {
2382   if (!QFileInfo(url.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path()).isWritable()) {
2383     KMessageBox::error(widget(),
2384       i18n("<qt>The file <i>%1</i> could not be saved, because you do not have the required write permissions.</qt>", url.path()));
2385     return;
2386   }
2387 
2388   if (!backupFileCreated) {
2389     QString backupFile = url.path()+'~';
2390     KIO::file_copy(url, QUrl::fromUserInput(backupFile ), -1, KIO::Overwrite | KIO::HideProgressInfo);
2391     backupFileCreated = true;
2392   }
2393 
2394   setModified(false);
2395 
2396   if (mapName().isEmpty()) {
2397     mapEditName();
2398   }
2399   QFile file(url.path());
2400   file.open(QIODevice::WriteOnly);
2401 
2402   QTextStream t(&file);
2403 
2404   if (_htmlContent.isEmpty()) {
2405     t << "<html>\n"
2406       << "<head>\n"
2407       << "  <title></title>\n"
2408       << "</head>\n"
2409       << "<body>\n"
2410       << "  " << getHTMLImageMap()
2411       << "\n"
2412       << "  <img src=\"" << toRelative(_imageUrl,QUrl( url.adjusted(QUrl::RemoveFilename|QUrl::StripTrailingSlash).path() )).path() << "\""
2413       << " usemap=\"#" << _mapName << "\""
2414       << " width=\"" << drawZone->picture().width() << "\""
2415       << " height=\"" << drawZone->picture().height() << "\">\n"
2416       << "</body>\n"
2417       << "</html>";
2418   } else
2419   {
2420     t << getHtmlCode();
2421   }
2422 
2423   file.close();
2424 
2425 }
2426 
2427 
2428 void KImageMapEditor::slotCut()
2429 {
2430   if ( 0 == currentSelected->count() )
2431     return;
2432   delete copyArea;
2433 
2434   copyArea= static_cast< AreaSelection* > (currentSelected->clone());
2435   pasteAction->setEnabled(true);
2436   QUndoCommand *command= new CutCommand(this,*currentSelected);
2437   commandHistory()->push(command);
2438 }
2439 
2440 
2441 void KImageMapEditor::slotDelete()
2442 {
2443   if ( 0 == currentSelected->count() )
2444     return;
2445 
2446   QUndoCommand *command= new DeleteCommand(this,*currentSelected);
2447   commandHistory()->push(command);
2448 }
2449 
2450 void KImageMapEditor::slotCopy()
2451 {
2452   delete copyArea;
2453 
2454   copyArea = static_cast< AreaSelection* > (currentSelected->clone());
2455   pasteAction->setEnabled(true);
2456 }
2457 
2458 void KImageMapEditor::slotPaste()
2459 {
2460   if (!copyArea)
2461     return;
2462 
2463   copyArea->moveBy(5,5);
2464   if (copyArea->rect().x()>= drawZone->getImageRect().width() ||
2465       copyArea->rect().y()>= drawZone->getImageRect().height())
2466       copyArea->moveTo(0,0);
2467 
2468   if (copyArea->rect().width()>drawZone->getImageRect().width() ||
2469       copyArea->rect().height()>drawZone->getImageRect().height())
2470       return;
2471 
2472   AreaSelection *a=static_cast< AreaSelection* > (copyArea->clone());
2473   commandHistory()->push(new PasteCommand(this,*a));
2474   delete a;
2475 //  addAreaAndEdit(a);
2476 }
2477 
2478 
2479 
2480 void KImageMapEditor::slotBackOne()
2481 {
2482   if (currentSelected->isEmpty())
2483     return;
2484 
2485   AreaList list = currentSelected->getAreaList();
2486 
2487 
2488   Area *a = nullptr;
2489   // move every selected Area one step lower
2490   for (int i=areas->count()-2; i > -1; i--)
2491   {
2492     if (list.contains( areas->at(i) ))
2493     {
2494       uint j = (uint)i+1;
2495       a = areas->at(i);
2496       areas->removeAll(a);
2497       areas->insert(j,a);
2498       QTreeWidgetItem* root = areaListView->listView->invisibleRootItem();
2499       root->insertChild(j,root->takeChild(i));
2500     }
2501   }
2502   // to update the up and down buttons
2503   updateUpDownBtn();
2504 
2505 }
2506 
2507 void KImageMapEditor::slotForwardOne()
2508 {
2509   if (currentSelected->isEmpty())
2510     return;
2511 
2512   AreaList list = currentSelected->getAreaList();
2513 
2514   Area *a = nullptr;
2515   // move every selected Area one step higher
2516   for (int i=1; i < (int)areas->count(); i++)
2517   {
2518     if (list.contains( areas->at(i) ))
2519     {
2520       uint j = (uint) i-1;
2521       a = areas->at(i);
2522       areas->removeAll(a);
2523       areas->insert(j,a);
2524       QTreeWidgetItem* root = areaListView->listView->invisibleRootItem();
2525       root->insertChild(j,root->takeChild(i));
2526     }
2527   }
2528   // to update the up and down buttons
2529   updateUpDownBtn();
2530 }
2531 
2532 void KImageMapEditor::slotToBack()
2533 {
2534   if (currentSelected->isEmpty())
2535     return;
2536 
2537   while (backOneAction->isEnabled())
2538     slotBackOne();
2539 }
2540 
2541 void KImageMapEditor::slotToFront()
2542 {
2543   if (currentSelected->isEmpty())
2544     return;
2545 
2546   while (forwardOneAction->isEnabled())
2547     slotForwardOne();
2548 }
2549 
2550 
2551 void KImageMapEditor::slotMoveUp()
2552 {
2553   QRect r=selected()->rect();
2554   selected()->setMoving(true);
2555   selected()->moveBy(0,-1);
2556 
2557   commandHistory()->push(
2558     new MoveCommand( this, selected(), r.topLeft() ));
2559   selected()->setMoving(false);
2560   slotAreaChanged(selected());
2561   slotUpdateSelectionCoords();
2562 }
2563 
2564 void KImageMapEditor::slotMoveDown()
2565 {
2566   QRect r=selected()->rect();
2567   selected()->setMoving(true);
2568   selected()->moveBy(0,1);
2569 
2570   commandHistory()->push(
2571     new MoveCommand( this, selected(), r.topLeft() ));
2572   selected()->setMoving(false);
2573   slotAreaChanged(selected());
2574   slotUpdateSelectionCoords();
2575 }
2576 
2577 void KImageMapEditor::slotMoveLeft()
2578 {
2579   qCDebug(KIMAGEMAPEDITOR_LOG) << "slotMoveLeft";
2580   QRect r=selected()->rect();
2581   selected()->setMoving(true);
2582   selected()->moveBy(-1,0);
2583 
2584   commandHistory()->push(
2585     new MoveCommand( this, selected(), r.topLeft() ));
2586   selected()->setMoving(false);
2587   slotAreaChanged(selected());
2588   slotUpdateSelectionCoords();
2589 }
2590 
2591 void KImageMapEditor::slotMoveRight()
2592 {
2593   QRect r=selected()->rect();
2594   selected()->setMoving(true);
2595   selected()->moveBy(1,0);
2596 
2597   commandHistory()->push(
2598     new MoveCommand( this, selected(), r.topLeft() ));
2599   selected()->setMoving(false);
2600   slotAreaChanged(selected());
2601   slotUpdateSelectionCoords();
2602 }
2603 
2604 void KImageMapEditor::slotCancelDrawing()
2605 {
2606   drawZone->cancelDrawing();
2607 }
2608 
2609 void KImageMapEditor::slotIncreaseHeight()
2610 {
2611   Area *oldArea=selected()->clone();
2612 
2613   QRect r = selected()->rect();
2614   r.setHeight( r.height()+1 );
2615   r.translate(0,-1);
2616 
2617   selected()->setRect(r);
2618 
2619   commandHistory()->push(
2620     new ResizeCommand( this, selected(), oldArea ));
2621   slotAreaChanged(selected());
2622   slotUpdateSelectionCoords();
2623 }
2624 
2625 void KImageMapEditor::slotDecreaseHeight()
2626 {
2627   Area *oldArea=selected()->clone();
2628 
2629   QRect r = selected()->rect();
2630   r.setHeight( r.height()-1 );
2631   r.translate(0,1);
2632 
2633   selected()->setRect(r);
2634 
2635   commandHistory()->push(
2636     new ResizeCommand( this, selected(), oldArea ));
2637   slotAreaChanged(selected());
2638   slotUpdateSelectionCoords();
2639 }
2640 
2641 void KImageMapEditor::slotIncreaseWidth()
2642 {
2643   Area *oldArea=selected()->clone();
2644 
2645   QRect r = selected()->rect();
2646   r.setWidth( r.width()+1 );
2647 
2648   selected()->setRect(r);
2649 
2650   commandHistory()->push(
2651     new ResizeCommand( this, selected(), oldArea ));
2652   slotAreaChanged(selected());
2653   slotUpdateSelectionCoords();
2654 }
2655 
2656 void KImageMapEditor::slotDecreaseWidth()
2657 {
2658   Area *oldArea=selected()->clone();
2659 
2660   QRect r = selected()->rect();
2661   r.setWidth( r.width()-1 );
2662 
2663   selected()->setRect(r);
2664 
2665   commandHistory()->push(
2666     new ResizeCommand( this, selected(), oldArea ));
2667   slotAreaChanged(selected());
2668   slotUpdateSelectionCoords();
2669 }
2670 
2671 void KImageMapEditor::slotHighlightAreas(bool b)
2672 {
2673   Area::highlightArea = b;
2674   updateAllAreas();
2675   drawZone->repaint();
2676 }
2677 
2678 void KImageMapEditor::slotShowAltTag(bool b)
2679 {
2680   Area::showAlt = b;
2681   drawZone->repaint();
2682 }
2683 
2684 void KImageMapEditor::mapNew()
2685 {
2686     QString mapName = mapsListView->getUnusedMapName();
2687     addMap(mapName);
2688     mapEditName();
2689 }
2690 
2691 void KImageMapEditor::mapDelete()
2692 {
2693   if (mapsListView->count() == 0)
2694      return;
2695 
2696   QString selectedMap = mapsListView->selectedMap();
2697 
2698   int result = KMessageBox::warningContinueCancel(widget(),
2699     i18n("<qt>Are you sure you want to delete the map <i>%1</i>?"
2700          " <br /><b>There is no way to undo this.</b></qt>", selectedMap),
2701     i18n("Delete Map?"),KGuiItem(i18n("&Delete"),"edit-delete"));
2702 
2703   if (result == KMessageBox::Cancel)
2704      return;
2705 
2706 
2707 
2708   mapsListView->removeMap(selectedMap);
2709   HtmlMapElement* mapEl = findHtmlMapElement(selectedMap);
2710   _htmlContent.removeAll(mapEl);
2711   if (mapsListView->count() == 0) {
2712 
2713       currentMapElement = nullptr;
2714       deleteAllAreas();
2715       setMapActionsEnabled(false);
2716   }
2717   else {
2718       // The old one was deleted, so the new one got selected
2719       setMap(mapsListView->selectedMap());
2720   }
2721 }
2722 
2723 void KImageMapEditor::mapPreview() {
2724   HTMLPreviewDialog dialog(widget(), getHtmlCode());
2725   dialog.exec();
2726 }
2727 
2728 void KImageMapEditor::deleteAllMaps()
2729 {
2730   deleteAllAreas();
2731   mapsListView->clear();
2732   if (isReadWrite()) {
2733     mapDeleteAction->setEnabled(false);
2734     mapDefaultAreaAction->setEnabled(false);
2735     mapNameAction->setEnabled(false);
2736   }
2737 }
2738 
2739 /**
2740  * Doesn't call the closeUrl method, because
2741  * we need the URL for the session management
2742  */
2743 bool KImageMapEditor::queryClose() {
2744   if ( ! isModified() )
2745      return true;
2746 
2747 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
2748   switch ( KMessageBox::warningTwoActionsCancel(
2749 #else
2750   switch ( KMessageBox::warningYesNoCancel(
2751 #endif
2752               widget(),
2753           i18n("<qt>The file <i>%1</i> has been modified.<br />Do you want to save it?</qt>",
2754           url().fileName()),
2755           QString(),
2756           KStandardGuiItem::save(),
2757           KStandardGuiItem::discard()) )
2758     {
2759 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
2760     case KMessageBox::PrimaryAction :
2761 #else
2762     case KMessageBox::Yes :
2763 #endif
2764       saveFile();
2765       return true;
2766 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0)
2767     case KMessageBox::SecondaryAction :
2768 #else
2769     case KMessageBox::No :
2770 #endif
2771       return true;
2772     default:
2773       return false;
2774   }
2775 }
2776 
2777 bool KImageMapEditor::closeUrl()
2778 {
2779   bool result = KParts::ReadWritePart::closeUrl();
2780   if (!result)
2781      return false;
2782 
2783   _htmlContent.clear();
2784   deleteAllMaps();
2785   imagesListView->clear();
2786 
2787   delete copyArea;
2788   copyArea = nullptr;
2789 
2790   delete defaultArea;
2791   defaultArea = nullptr;
2792 
2793   currentMapElement = nullptr;
2794 
2795   init();
2796   emit setWindowCaption("");
2797 
2798   return true;
2799 
2800 }
2801 
2802 void KImageMapEditor::addImage(const QUrl & imgUrl) {
2803     if (imgUrl.isEmpty())
2804         return;
2805 
2806     QString relativePath ( toRelative(imgUrl, QUrl( url().adjusted(QUrl::RemoveFilename).path() )).path() );
2807 
2808     QString imgHtml = QString("<img src=\"")+relativePath+QString("\">");
2809     ImageTag* imgTag = new ImageTag();
2810     imgTag->insert("tagname","img");
2811     imgTag->insert("src", relativePath);
2812 
2813     HtmlImgElement* imgEl = new HtmlImgElement(imgHtml);
2814     imgEl->imgTag = imgTag;
2815 
2816     HtmlElement* bodyEl = findHtmlElement("<body");
2817     if (bodyEl) {
2818         int bodyIndex = _htmlContent.indexOf(bodyEl);
2819         _htmlContent.insert(bodyIndex+1, new HtmlElement("\n"));
2820         _htmlContent.insert(bodyIndex+2, imgEl);
2821     }
2822     else {
2823         _htmlContent.append(new HtmlElement("\n"));
2824         _htmlContent.append(imgEl);
2825     }
2826 
2827     imagesListView->addImage(imgTag);
2828     imagesListView->selectImage(imgTag);
2829     setImageActionsEnabled(true);
2830 
2831     setModified(true);
2832 }
2833 
2834 /**
2835  * Sets whether the image actions that depend on an
2836  * selected image are enabled
2837  */
2838 void KImageMapEditor::setImageActionsEnabled(bool b) {
2839   imageRemoveAction->setEnabled(b);
2840   imageUsemapAction->setEnabled(b);
2841 }
2842 
2843 
2844 void KImageMapEditor::imageAdd() {
2845     QUrl imgUrl = QFileDialog::getOpenFileUrl(widget(), i18n("Select image"),
2846                   QUrl(), i18n("Images (*.png *.jpg *.jpeg *.gif *.bmp *.xbm *.xpm *.pnm *.mng);;All Files (*)"));
2847     addImage(imgUrl);
2848 }
2849 
2850 void KImageMapEditor::imageRemove() {
2851     ImageTag* imgTag = imagesListView->selectedImage();
2852     HtmlImgElement* imgEl = findHtmlImgElement(imgTag);
2853     imagesListView->removeImage(imgTag);
2854     _htmlContent.removeAt(_htmlContent.indexOf(imgEl));
2855 
2856     if (imagesListView->topLevelItemCount() == 0) {
2857         setPicture(getBackgroundImage());
2858         setImageActionsEnabled(false);
2859     }
2860     else {
2861       ImageTag* selected = imagesListView->selectedImage();
2862       if (selected) {
2863     if (selected->contains("src")) {
2864       setPicture(QUrl(selected->value("src")));
2865     }
2866       }
2867     }
2868 
2869     setModified(true);
2870 }
2871 
2872 void KImageMapEditor::imageUsemap() {
2873 
2874   bool ok=false;
2875   ImageTag* imageTag = imagesListView->selectedImage();
2876   if ( ! imageTag)
2877      return;
2878 
2879   QString usemap;
2880 
2881   if (imageTag->contains("usemap"))
2882       usemap = imageTag->value("usemap");
2883 
2884   QStringList maps = mapsListView->getMaps();
2885   int index = maps.indexOf(usemap);
2886   if (index == -1) {
2887     maps.prepend("");
2888     index = 0;
2889   }
2890 
2891   QString input =
2892     QInputDialog::getItem(widget(), i18n("Enter Usemap"),
2893               i18n("Enter the usemap value:"),
2894               maps, index, true, &ok);
2895   if (ok) {
2896      imageTag->insert("usemap", input);
2897      imagesListView->updateImage(imageTag);
2898      setModified(true);
2899 
2900      // Update the htmlCode of the HtmlElement
2901      HtmlImgElement* imgEl = findHtmlImgElement(imageTag);
2902 
2903      imgEl->htmlCode = QLatin1String("<");
2904      QString tagName = imgEl->imgTag->value("tagname");
2905      imgEl->htmlCode += QString(tagName);
2906      QHashIterator<QString, QString> it( *imgEl->imgTag );
2907      while (it.hasNext()) {
2908        it.next();
2909        if (it.key() != "tagname") {
2910            imgEl->htmlCode += " " + it.key() + "=\"";
2911            if (it.key() == "usemap")
2912                imgEl->htmlCode += '#';
2913            imgEl->htmlCode += it.value();
2914            imgEl->htmlCode += '"';
2915        }
2916      }
2917 
2918      imgEl->htmlCode += '>';
2919 
2920   }
2921 }
2922 
2923 #include "kimagemapeditor.moc"