File indexing completed on 2024-04-28 15:35:38

0001 /***************************************************************************
0002                                cmapwidget.cpp
0003                              -------------------
0004     begin                : Sun Mar 18 2001
0005     copyright            : (C) 2001 by Kmud Developer Team
0006     email                : kmud-devel@kmud.de
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "cmapwidget.h"
0019 
0020 #include <QBitmap>
0021 #include <QScrollArea>
0022 #include <QScrollBar>
0023 #include <QToolTip>
0024 
0025 #include <kactioncollection.h>
0026 #include <kxmlguifactory.h>
0027 
0028 #include <KLocalizedString>
0029 
0030 #include "cmapmanager.h"
0031 #include "cmapzone.h"
0032 #include "cmaplevel.h"
0033 #include "cmappath.h"
0034 #include "cmapcmdelementproperties.h"
0035 #include "cmapview.h"
0036 #include "cmaptoolbase.h"
0037 #include "cmappluginbase.h"
0038 
0039 static unsigned char move_bits[] = {
0040    0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0x80, 0x01, 0x80, 0x01, 0x84, 0x21,
0041    0x86, 0x61, 0xff, 0xff, 0xff, 0xff, 0x86, 0x61, 0x84, 0x21, 0x80, 0x01,
0042    0x80, 0x01, 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01};
0043 
0044 CMapWidget::CMapWidget(CMapView *view,CMapManager *manager,QWidget *parent) : QWidget(parent)
0045 {
0046     // Setup vars
0047     viewWidget = view;
0048     bMouseDrag = false;
0049     QBitmap mouseDragCursorShape = QBitmap::fromData (QSize(16,16), move_bits);
0050     mouseDragCursor = new QCursor( mouseDragCursorShape, mouseDragCursorShape, -1,-1);
0051     mapManager = manager;
0052 
0053     initContexMenus();
0054 
0055     // FIXME_jp : set to proper size instead of test size
0056 
0057     // Setup scrollview
0058     setFocusPolicy(Qt::StrongFocus);    
0059     setMouseTracking(true);
0060     setFocus();
0061 }
0062 
0063 CMapWidget::~CMapWidget()
0064 {
0065     viewWidget = nullptr;
0066 }
0067 
0068 /** Used to create the element context menus */
0069 void CMapWidget::initContexMenus(void)
0070 {
0071   room_menu = (QMenu *)getView()->guiFactory()->container("room_popup",getView());
0072   text_menu = (QMenu *)getView()->guiFactory()->container("text_popup",getView());
0073   path_menu = (QMenu *)getView()->guiFactory()->container("path_popup",getView());
0074   empty_menu = (QMenu *)getView()->guiFactory()->container("empty_popup",getView());
0075 }
0076 
0077 /** Used to get the views */
0078 CMapView *CMapWidget::getView(void)
0079 {
0080     return viewWidget;
0081 }
0082 
0083 /** draw the map widget */
0084 void CMapWidget::paintEvent(QPaintEvent *ev)
0085 {
0086   QPainter p(this);
0087   CMapZone *zone = viewWidget->getCurrentlyViewedZone();
0088   QColor color = zone->getUseDefaultBackground() ? mapManager->getMapData()->backgroundColor : zone->getBackgroundColor();
0089   p.fillRect(ev->rect(), color);
0090 
0091   drawGrid(&p);
0092   drawElements(&p);
0093   mapManager->getCurrentTool()->paint(&p);
0094 }
0095 
0096 bool CMapWidget::event(QEvent *e)
0097 {
0098   if (e->type() == QEvent::ToolTip) {
0099     QHelpEvent *helpEvent = static_cast<QHelpEvent *>(e);
0100     QPoint point = helpEvent->pos();
0101 
0102     CMapView *view = getView();
0103     CMapLevel *level = view->getCurrentlyViewedLevel();
0104     CMapElement *element = level ? level->findElementAt(point) : nullptr;
0105     QString s;
0106     if (element)
0107     {
0108       if (element->getElementType() == ROOM)
0109       {
0110         s = ((CMapRoom*)element)->getLabel();
0111       }
0112       else if (element->getElementType() == ZONE)
0113       {
0114         s = ((CMapZone*)element)->getLabel();
0115       }
0116 
0117       if (!s.trimmed().isEmpty())
0118         QToolTip::showText (helpEvent->globalPos(), s, this);
0119       else
0120         QToolTip::hideText ();
0121     }
0122   }
0123   return QWidget::event(e);
0124 }
0125 
0126 
0127 
0128 /** Draw the grid if it's visible */
0129 void CMapWidget::drawGrid(QPainter* p)
0130 {
0131   if (!mapManager->getMapData()->gridVisable) return;
0132 
0133   p->setPen(mapManager->getMapData()->gridColor);
0134 
0135   QSize gridSize = mapManager->getMapData()->gridSize;
0136   int maxx = width();
0137   int maxy = height();
0138 
0139    // Draw the lines going across
0140   for (int y = 0; y <= maxy; y += gridSize.width())
0141     p->drawLine(0, y, maxx, y);
0142   // Draw the lines going down
0143   for (int x = 0; x <= maxx; x += gridSize.height())
0144     p->drawLine(x, 0, x, maxy);
0145 }
0146 
0147 /** Used to draw all the elments */
0148 void CMapWidget::drawElements(QPainter *p)
0149 {
0150   CMapLevel *level = viewWidget->getCurrentlyViewedLevel();
0151   if (!level) return;
0152 
0153   CMapLevel *lowerLevel = level->getPrevLevel();
0154   CMapLevel *upperLevel = level->getNextLevel();
0155 
0156   // Mark all paths as undrawn
0157   foreach (CMapRoom *room, *level->getRoomList())
0158     foreach (CMapPath *path, *room->getPathList())
0159       path->setDone(false);
0160 
0161   if (lowerLevel && mapManager->getMapData()->showLowerLevel)
0162   {
0163     foreach (CMapRoom *room, *lowerLevel->getRoomList())
0164       foreach (CMapPath *path, *room->getPathList())
0165         path->setDone(false);
0166   }
0167 
0168   if (upperLevel && mapManager->getMapData()->showUpperLevel)
0169   {
0170     foreach (CMapRoom *room, *upperLevel->getRoomList())
0171       foreach (CMapPath *path, *room->getPathList())
0172         path->setDone(false);
0173   }
0174 
0175   // Draw the upper map elements
0176   if (lowerLevel && mapManager->getMapData()->showLowerLevel)
0177     foreach (CMapElement *element, lowerLevel->getAllElements())
0178       element->lowerPaint(p, viewWidget->getCurrentlyViewedZone());
0179 
0180   // Paint the map elements of the current map
0181   foreach (CMapElement *element, level->getAllElements())
0182     if (element->getDoPaint())
0183       element->paint(p, viewWidget->getCurrentlyViewedZone());
0184 
0185   // Draw the upper map elements
0186   if (upperLevel && mapManager->getMapData()->showUpperLevel)
0187   {
0188     foreach (CMapElement *element, upperLevel->getAllElements())
0189       element->higherPaint(p, viewWidget->getCurrentlyViewedZone());
0190   }
0191 }
0192 
0193 
0194 /** The mouse release event */
0195 void CMapWidget::mouseReleaseEvent(QMouseEvent *e)
0196 {
0197     QCursor* oldCursor;
0198 
0199     switch (e->button())
0200     {
0201           case Qt::LeftButton:
0202             // Send the mouse event to the current tool
0203             mapManager->getCurrentTool()->mouseReleaseEvent(e->pos(),e,viewWidget->getCurrentlyViewedLevel());
0204             break;
0205 
0206           case Qt::MidButton:
0207             bMouseDrag = false;
0208             oldCursor= new QCursor(cursor());
0209             setCursor(*mouseDragCursor);
0210             delete mouseDragCursor;
0211             mouseDragCursor = oldCursor;
0212             break;
0213 
0214         default:
0215             break;
0216     }
0217 
0218 }
0219 
0220 
0221 void CMapWidget::showRoomContextMenu(void)
0222 {
0223   CMapRoom *room = (CMapRoom *) getView()->getSelectedElement();
0224 
0225   KActionCollection *acol = getView()->actionCollection();
0226   QAction *roomSetCurrentPos = acol->action("roomCurrentPos");
0227   QAction *roomSetLogin = acol->action("roomLoginPoint");   
0228   KSelectAction *labelMenu=(KSelectAction *) acol->action("labelMenu");
0229 
0230   roomSetCurrentPos->setEnabled(!room->getCurrentRoom());
0231   roomSetLogin->setEnabled(!room->getLoginRoom());
0232 
0233   switch(room->getLabelPosition())
0234   {
0235     case CMapRoom::HIDE      : labelMenu->setCurrentItem(0); break;
0236     case CMapRoom::NORTH     : labelMenu->setCurrentItem(1); break;
0237     case CMapRoom::NORTHEAST : labelMenu->setCurrentItem(2); break;
0238     case CMapRoom::EAST      : labelMenu->setCurrentItem(3); break;
0239     case CMapRoom::SOUTHEAST : labelMenu->setCurrentItem(4); break;
0240     case CMapRoom::SOUTH     : labelMenu->setCurrentItem(5); break;
0241     case CMapRoom::SOUTHWEST : labelMenu->setCurrentItem(6); break;
0242     case CMapRoom::WEST      : labelMenu->setCurrentItem(7); break;
0243     case CMapRoom::NORTHWEST : labelMenu->setCurrentItem(8); break;
0244     case CMapRoom::CUSTOM    : labelMenu->setCurrentItem(9); break;
0245   }
0246 
0247 
0248   showContextMenu (room_menu);
0249 }
0250 
0251 void CMapWidget::showPathContextMenu(void)
0252 {
0253   CMapPath *path = (CMapPath *) getView()->getSelectedElement();
0254 
0255   bool twoWay = path->getOpsitePath();
0256 
0257   KActionCollection *acol = getView()->actionCollection();
0258   KToggleAction *pathTwoWay = (KToggleAction *)acol->action("pathTwoWay");
0259   KToggleAction *pathOneWay = (KToggleAction *)acol->action("pathOneWay");
0260   QAction *pathEditBends = acol->action("pathEditBends");
0261   QAction *pathDelBend = acol->action("pathDelBend");
0262   QAction *pathAddBend = acol->action("pathAddBend");
0263 
0264   pathTwoWay->setChecked(twoWay);
0265   pathOneWay->setChecked(!twoWay);
0266 
0267   CMapView *view = (CMapView *) viewWidget;
0268   pathDelBend->setEnabled(path->mouseInPathSeg(selectedPos,view->getCurrentlyViewedZone())!=-1);
0269   pathEditBends->setEnabled(path->getBendCount() > 0);
0270   pathAddBend->setEnabled(path->getSrcRoom()->getZone()==path->getDestRoom()->getZone());
0271 
0272   showContextMenu (path_menu);
0273 }
0274 
0275 
0276 void CMapWidget::showTextContextMenu(void)
0277 {
0278   showContextMenu (text_menu);
0279 }
0280 
0281 void CMapWidget::showOtherContextMenu(void)
0282 {
0283   showContextMenu (empty_menu);
0284 }
0285 
0286 void CMapWidget::showContextMenu(QMenu *menu)
0287 {
0288   CMapView *view = mapManager->getActiveView();
0289   CMapElement *el = view->getSelectedElement();
0290   popupMenu(el, menu, selectedPos);
0291 }
0292 
0293 void CMapWidget::showContexMenu(QMouseEvent *e)
0294 {
0295   CMapLevel *level = viewWidget->getCurrentlyViewedLevel();
0296   if (!level) return;
0297 
0298   CMapView *view = mapManager->getActiveView();
0299   view->setSelectedPos(e->pos());
0300   selectedPos = e->pos();
0301 
0302   view->setSelectedElement(nullptr);
0303   CMapElement *element = level->findElementAt (e->pos());
0304   if (!element) {
0305     showOtherContextMenu();
0306     return;
0307   }
0308 
0309   view->setSelectedElement(element);
0310 
0311   mapManager->unsetEditElement();
0312   switch(element->getElementType())
0313   {
0314     case ROOM : showRoomContextMenu(); break;
0315     case PATH : showPathContextMenu(); break;
0316     case TEXT : showTextContextMenu(); break;
0317     default   : showOtherContextMenu(); break;
0318   }
0319 }
0320 
0321 /** This method is used to tell the plugins a menu is about to open then open the menu */
0322 void CMapWidget::popupMenu(CMapElement *element,QMenu *menu,QPoint pos)
0323 {
0324   if (element) {
0325     for (CMapPluginBase *plugin : mapManager->getPluginList())
0326       plugin->beforeOpenElementMenu(element);
0327   }
0328   menu->popup(mapToGlobal(pos));
0329 }
0330 
0331 /** This is called when the mouse leaves the widget */
0332 void CMapWidget::leaveEvent(QEvent *)
0333 {
0334   // Send the mouse event to the current tool
0335   mapManager->getCurrentTool()->mouseLeaveEvent();
0336 }
0337 
0338 /** This is called when the mouse enters the widget */
0339 void CMapWidget::enterEvent(QEvent *)
0340 {
0341     // Send the mouse event to the current tool
0342     mapManager->getCurrentTool()->mouseEnterEvent();
0343 }
0344 
0345 /** The mouse press event */
0346 void CMapWidget::mousePressEvent(QMouseEvent *e)
0347 {
0348     QCursor* oldCursor;
0349 
0350     switch (e->button())
0351     {
0352           case Qt::RightButton:
0353             showContexMenu(e);
0354             break;
0355 
0356           case Qt::MidButton:
0357             bMouseDrag = true;
0358             nMouseDragPosX = e->globalX();
0359             nMouseDragPosY = e->globalY();
0360             oldCursor = new QCursor(cursor());
0361             setCursor(*mouseDragCursor);
0362             delete mouseDragCursor;
0363             mouseDragCursor = oldCursor;
0364             break;
0365 
0366           case Qt::LeftButton:
0367             // Send the mouse event to the current tool
0368             //p.begin(viewport());
0369             //p.translate(-contentsX(),-contentsY());
0370             mapManager->getCurrentTool()->mousePressEvent(e->pos(),e,viewWidget->getCurrentlyViewedLevel());
0371             //p.end();
0372 
0373         default:
0374             break;
0375 
0376     }
0377 }
0378 
0379 void CMapWidget::mouseDoubleClickEvent(QMouseEvent *e)
0380 {
0381   mapManager->getCurrentTool()->mouseDoubleClickEvent(e->pos(), e, viewWidget->getCurrentlyViewedLevel());
0382 }
0383 
0384 /** Called when the mouse is being moved */
0385 void CMapWidget::mouseMoveEvent(QMouseEvent *e)
0386 {
0387     if (bMouseDrag)
0388     {
0389         int dx, dy;
0390         dx = e->globalX() - nMouseDragPosX;
0391         dy = e->globalY() - nMouseDragPosY;
0392         nMouseDragPosX = e->globalX();
0393         nMouseDragPosY = e->globalY();
0394         QScrollArea *parent = (QScrollArea *) parentWidget();
0395                 QScrollBar *sx = parent->horizontalScrollBar();
0396                 QScrollBar *sy = parent->verticalScrollBar();
0397                 sx->setValue(sx->value() + dx*3);
0398                 sy->setValue(sy->value() + dy*3);
0399     }
0400     else
0401     {
0402         // Send the mouse event to the current tool
0403         mapManager->getCurrentTool()->mouseMoveEvent(e->pos(), e->modifiers(), e->buttons(), viewWidget->getCurrentlyViewedLevel());
0404     }
0405 }
0406 
0407 /** Called when a key is pressed */
0408 void CMapWidget::keyPressEvent(QKeyEvent *e)
0409 {
0410   mapManager->getCurrentTool()->keyPressEvent(e);
0411 }
0412 
0413 /** Called when a key is released */
0414 void CMapWidget::keyReleaseEvent(QKeyEvent *e)
0415 {
0416   mapManager->getCurrentTool()->keyReleaseEvent(e);
0417 }
0418 
0419 #include "moc_cmapwidget.cpp"