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