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