File indexing completed on 2024-12-01 04:01:57
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 < of a tag. It now reads all attributes of the tag until a > 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"