File indexing completed on 2024-05-12 17:12:41

0001 /***************************************************************************
0002  *  Copyright (C) 2007 by Romain Campioni                  *
0003  *  Copyright (C) 2009 by Renaud Guezennec                             *
0004  *   https://rolisteam.org/contact                   *
0005  *                                                                         *
0006  *   rolisteam is free software; you can redistribute it and/or modify  *
0007  *   it under the terms of the GNU General Public License as published by  *
0008  *   the Free Software Foundation; either version 2 of the License, or     *
0009  *   (at your option) any later version.                                   *
0010  *                                                                         *
0011  *   This program is distributed in the hope that it will be useful,       *
0012  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0013  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0014  *   GNU General Public License for more details.                          *
0015  *                                                                         *
0016  *   You should have received a copy of the GNU General Public License     *
0017  *   along with this program; if not, write to the                         *
0018  *   Free Software Foundation, Inc.,                                       *
0019  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0020  ***************************************************************************/
0021 #include "workspace.h"
0022 
0023 #include <QQmlEngine>
0024 #include <QtGui>
0025 
0026 #include "controller/contentcontroller.h"
0027 #include "controller/view_controller/charactersheetcontroller.h"
0028 #include "controller/view_controller/imagecontroller.h"
0029 #include "controller/view_controller/mindmapcontroller.h"
0030 #include "controller/view_controller/notecontroller.h"
0031 #include "controller/view_controller/sharednotecontroller.h"
0032 #include "controller/view_controller/vectorialmapcontroller.h"
0033 #include "controller/view_controller/webpagecontroller.h"
0034 #include "controller/view_controller/pdfcontroller.h"
0035 #include "mediacontainers/pdfviewer.h"
0036 #include "controller/instantmessagingcontroller.h"
0037 #include "mediacontainers/instantmessagingview.h"
0038 #include "editors/noteeditor/src/notecontainer.h"
0039 #include "editors/sharededitor/sharednotecontainer.h"
0040 #include "mediacontainers/charactersheetwindow.h"
0041 #include "mediacontainers/image.h"
0042 #include "mediacontainers/mindmapview.h"
0043 #include "mediacontainers/vmapframe.h"
0044 #include "mediacontainers/webview.h"
0045 
0046 #define GRAY_SCALE 191
0047 
0048 Workspace::Workspace(QToolBar* toolbar, ContentController* ctrl, InstantMessagingController* instantCtrl,
0049                      QWidget* parent)
0050     : QMdiArea(parent), m_ctrl(ctrl), m_variableSizeBackground(size()), m_toolbar(toolbar)
0051 {
0052     connect(m_ctrl, &ContentController::maxLengthTabNameChanged, this, &Workspace::updateTitleTab);
0053     connect(m_ctrl, &ContentController::shortTitleTabChanged, this, &Workspace::updateTitleTab);
0054     connect(m_ctrl, &ContentController::workspaceFilenameChanged, this,
0055             [this]()
0056             {
0057                 m_backgroundPicture= QPixmap(m_ctrl->workspaceFilename());
0058                 updateBackGround();
0059             });
0060     connect(m_ctrl, &ContentController::workspaceColorChanged, this, &Workspace::updateBackGround);
0061     connect(m_ctrl, &ContentController::workspacePositioningChanged, this, &Workspace::updateBackGround);
0062 
0063     connect(m_ctrl, &ContentController::mediaControllerCreated, this, &Workspace::addMedia);
0064     connect(this, &Workspace::subWindowActivated, this, &Workspace::updateActiveMediaContainer);
0065 
0066     if(instantCtrl)
0067     {
0068         m_instantMessageView= addSubWindow(new InstantMessagingView(instantCtrl));
0069         m_instantMessageView->setGeometry(0, 0, 400, 600);
0070         m_instantMessageView->setAttribute(Qt::WA_DeleteOnClose, false);
0071         m_instantMessageView->setWindowIcon(QIcon::fromTheme("chaticon"));
0072         connect(instantCtrl, &InstantMessagingController::visibleChanged, m_instantMessageView,
0073                 &QMdiSubWindow::setVisible);
0074         m_instantMessageView->setVisible(instantCtrl->visible());
0075 
0076         m_prevent.reset(new PreventClosing(m_instantMessageView));
0077         connect(m_prevent.get(), &PreventClosing::visibilityObjectChanged, instantCtrl,
0078                 &InstantMessagingController::setVisible);
0079     }
0080     if(m_ctrl)
0081         m_backgroundPicture= QPixmap(m_ctrl->workspaceFilename());
0082     updateBackGround();
0083 }
0084 
0085 Workspace::~Workspace()
0086 {
0087     /*if(nullptr != m_actionSubWindowMap)
0088     {
0089         delete m_actionSubWindowMap;
0090         m_actionSubWindowMap= nullptr;
0091     }*/
0092 }
0093 
0094 void Workspace::updateBackGround()
0095 {
0096     if(!m_ctrl)
0097         return;
0098     QBrush background;
0099     background.setColor(m_ctrl->workspaceColor());
0100     setBackground(background);
0101 
0102     m_variableSizeBackground= m_variableSizeBackground.scaled(size());
0103     m_variableSizeBackground.fill(m_ctrl->workspaceColor());
0104     QPainter painter(&m_variableSizeBackground);
0105 
0106     int x= 0;
0107     int y= 0;
0108     int w= m_backgroundPicture.width();
0109     int h= m_backgroundPicture.height();
0110     bool repeated= false;
0111     switch(m_ctrl->workspacePositioning())
0112     {
0113     case TopLeft:
0114         break;
0115     case BottomLeft:
0116         y= m_variableSizeBackground.size().height() - h;
0117         break;
0118     case Center:
0119         x= m_variableSizeBackground.width() / 2 - w / 2;
0120         y= m_variableSizeBackground.height() / 2 - h / 2;
0121         break;
0122     case TopRight:
0123         x= m_variableSizeBackground.width() - w;
0124         break;
0125     case BottomRight:
0126         x= m_variableSizeBackground.width() - w;
0127         y= m_variableSizeBackground.height() - h;
0128         break;
0129     case Scaled:
0130     {
0131         qreal rd= static_cast<qreal>(w) / static_cast<qreal>(h);
0132         if(rd > 1)
0133         {
0134             w= m_variableSizeBackground.width();
0135             h= static_cast<int>(w / rd);
0136         }
0137         else
0138         {
0139             h= m_variableSizeBackground.height();
0140             w= static_cast<int>(h / rd);
0141         }
0142         x= m_variableSizeBackground.width() / 2 - w / 2;
0143         y= m_variableSizeBackground.height() / 2 - h / 2;
0144     }
0145     break;
0146     case Filled:
0147         w= m_variableSizeBackground.width();
0148         h= m_variableSizeBackground.height();
0149         break;
0150     case Repeated:
0151         repeated= true;
0152         break;
0153     }
0154     if(!repeated)
0155     {
0156         painter.drawPixmap(x, y, w, h, m_backgroundPicture);
0157         setBackground(QBrush(m_variableSizeBackground));
0158     }
0159     else
0160     {
0161         setBackground(QBrush(m_backgroundPicture));
0162     }
0163     update();
0164 }
0165 
0166 void Workspace::resizeEvent(QResizeEvent* event)
0167 {
0168     Q_UNUSED(event)
0169     if((m_variableSizeBackground.size() == this->size()))
0170     {
0171         return;
0172     }
0173 
0174     updateBackGround();
0175 
0176     QMdiArea::resizeEvent(event);
0177 }
0178 
0179 void Workspace::addContainerMedia(MediaContainer* mediac)
0180 {
0181     if(nullptr == mediac)
0182         return;
0183 
0184     addSubWindow(mediac);
0185     if(viewMode() == QMdiArea::TabbedView)
0186     {
0187         mediac->setVisible(true);
0188     }
0189     mediac->setAttribute(Qt::WA_DeleteOnClose, false);
0190     if(nullptr != mediac->widget())
0191     {
0192         mediac->widget()->setAttribute(Qt::WA_DeleteOnClose, false);
0193     }
0194     mediac->installEventFilter(this);
0195 }
0196 void Workspace::removeMediaContainer(MediaContainer* mediac)
0197 {
0198     removeSubWindow(mediac);
0199     mediac->removeEventFilter(this);
0200 }
0201 
0202 void Workspace::setTabbedMode(bool isTabbed)
0203 {
0204     if(!isTabbed)
0205     {
0206         setViewMode(QMdiArea::SubWindowView);
0207         updateTitleTab();
0208         return;
0209     }
0210 
0211     setViewMode(QMdiArea::TabbedView);
0212     // setTabsClosable ( true );
0213     setTabsMovable(true);
0214     setTabPosition(QTabWidget::North);
0215     /// make all subwindows visible.
0216     /*auto keys= m_actionSubWindowMap->keys();
0217     for(QAction* act : keys)
0218     {
0219         auto tmp= m_actionSubWindowMap->value(act);
0220         if(nullptr == tmp)
0221         {
0222 
0223             tmp->setVisible(true);
0224             if(nullptr != act)
0225             {
0226                 act->setChecked(true);
0227             }
0228             if(nullptr != tmp->widget())
0229             {
0230                 tmp->widget()->setVisible(true);
0231             }
0232         }
0233     }*/
0234     updateTitleTab();
0235 }
0236 bool Workspace::updateTitleTab()
0237 {
0238     bool shortName= m_ctrl->shortTitleTab(); // m_preferences->value("shortNameInTabMode", false).toBool();
0239     int textLength= m_ctrl->maxLengthTabName();
0240     if((viewMode() == QMdiArea::TabbedView) && (shortName))
0241     {
0242         /*auto values= m_actionSubWindowMap->values();
0243         for(auto& subwindow : values)
0244         {
0245             auto title= subwindow->windowTitle();
0246             if(title.size() > textLength)
0247             {
0248                 m_titleBar.insert(subwindow, title);
0249                 title= title.left(textLength);
0250                 subwindow->setWindowTitle(title);
0251             }
0252         }*/
0253     }
0254     else
0255     {
0256         auto keys= m_titleBar.keys();
0257         for(auto& key : keys)
0258         {
0259             auto title= m_titleBar.value(key);
0260             key->setWindowTitle(title);
0261         }
0262         m_titleBar.clear();
0263     }
0264     return true;
0265 }
0266 bool Workspace::eventFilter(QObject* object, QEvent* event)
0267 {
0268     if(event->type() == QEvent::Close)
0269     {
0270         QMdiSubWindow* sub= dynamic_cast<QMdiSubWindow*>(object);
0271         if(nullptr != sub)
0272         {
0273             sub->setVisible(false);
0274             event->accept();
0275             return true;
0276         }
0277     }
0278     return QMdiArea::eventFilter(object, event);
0279 }
0280 
0281 QVector<QMdiSubWindow*> Workspace::getAllSubWindowFromId(const QString& id) const
0282 {
0283     QVector<QMdiSubWindow*> vector;
0284 
0285     for(auto& tmp : subWindowList())
0286     {
0287         if(nullptr != tmp->widget())
0288         {
0289             MediaContainer* tmpWindow= dynamic_cast<MediaContainer*>(tmp);
0290             if(nullptr != tmpWindow)
0291             {
0292                 if(tmpWindow->mediaId() == id)
0293                 {
0294                     vector.append(tmp);
0295                 }
0296             }
0297         }
0298     }
0299     return vector;
0300 }
0301 
0302 bool Workspace::closeAllSubs()
0303 {
0304     std::for_each(m_mediaContainers.begin(), m_mediaContainers.end(),
0305                   [this](const std::unique_ptr<MediaContainer>& media) { closeSub(media.get()); });
0306 
0307     return true;
0308 }
0309 
0310 void Workspace::closeActiveSub()
0311 {
0312     m_ctrl->closeCurrentMedia();
0313 }
0314 
0315 bool Workspace::closeSub(MediaContainer* container)
0316 {
0317     if(!container)
0318         return false;
0319 
0320     auto ctrl= m_activeMediaContainer->ctrl();
0321 
0322     ctrl->askToClose();
0323     return true;
0324 }
0325 
0326 void Workspace::updateActiveMediaContainer(QMdiSubWindow* window)
0327 {
0328     auto activeMediaContainer= dynamic_cast<MediaContainer*>(window);
0329 
0330     if(m_activeMediaContainer == activeMediaContainer)
0331         return;
0332 
0333     if(!m_activeMediaContainer.isNull())
0334     {
0335         auto ctrl= m_activeMediaContainer->ctrl();
0336         if(ctrl)
0337             ctrl->setActive(false);
0338     }
0339 
0340     if(nullptr != activeMediaContainer)
0341     {
0342         auto ctrl= activeMediaContainer->ctrl();
0343         ctrl->setActive(true);
0344         if(activeMediaContainer->getContainerType() == MediaContainer::ContainerType::VMapContainer)
0345             emit vmapActive();
0346     }
0347 
0348     m_activeMediaContainer= activeMediaContainer;
0349 }
0350 
0351 void Workspace::addMedia(MediaControllerBase* ctrl)
0352 {
0353     switch(ctrl->contentType())
0354     {
0355     // case Core::ContentType::ONLINEPICTURE:
0356     case Core::ContentType::PICTURE:
0357         addImage(dynamic_cast<ImageController*>(ctrl));
0358         break;
0359     case Core::ContentType::WEBVIEW:
0360         addWebpage(dynamic_cast<WebpageController*>(ctrl));
0361         break;
0362     case Core::ContentType::PDF:
0363         addPdf(dynamic_cast<PdfController*>(ctrl));
0364         break;
0365     case Core::ContentType::NOTES:
0366         addNote(dynamic_cast<NoteController*>(ctrl));
0367         break;
0368     case Core::ContentType::SHAREDNOTE:
0369         addSharedNote(dynamic_cast<SharedNoteController*>(ctrl));
0370         break;
0371     case Core::ContentType::VECTORIALMAP:
0372         addVectorialMap(dynamic_cast<VectorialMapController*>(ctrl));
0373         break;
0374     case Core::ContentType::CHARACTERSHEET:
0375         addCharacterSheet(dynamic_cast<CharacterSheetController*>(ctrl));
0376         break;
0377     case Core::ContentType::MINDMAP:
0378         addMindMap(dynamic_cast<MindMapController*>(ctrl));
0379         break;
0380     default:
0381         break;
0382     }
0383 }
0384 
0385 void Workspace::addWindowAction(const QString& name, MediaContainer* window)
0386 {
0387     auto act= m_toolbar->addAction(window->windowIcon(), name);
0388     act->setCheckable(true);
0389     act->setChecked(true);
0390 
0391     auto ctrl= window->ctrl();
0392 
0393     connect(act, &QAction::triggered, window, &MediaContainer::setVisible);
0394     connect(window, &MediaContainer::visibleChanged, act, &QAction::setChecked);
0395     connect(ctrl, &MediaControllerBase::nameChanged, act, &QAction::setText);
0396     connect(ctrl, &MediaControllerBase::destroyed, act, &QAction::deleteLater);
0397 }
0398 
0399 void Workspace::addWidgetToMdi(MediaContainer* wid, const QString& title)
0400 {
0401     wid->setParent(this);
0402     QMdiSubWindow* sub= addSubWindow(wid);
0403     addWindowAction(title, wid);
0404     sub->setVisible(true);
0405     wid->setVisible(true);
0406 }
0407 void Workspace::addImage(ImageController* ctrl)
0408 {
0409     if(nullptr == ctrl)
0410         return;
0411     std::unique_ptr<MediaContainer> img(new Image(ctrl));
0412     addWidgetToMdi(img.get(), ctrl->name());
0413     m_mediaContainers.push_back(std::move(img));
0414 }
0415 void Workspace::addVectorialMap(VectorialMapController* ctrl)
0416 {
0417     if(nullptr == ctrl)
0418         return;
0419     std::unique_ptr<MediaContainer> vmapFrame(new VMapFrame(ctrl));
0420     vmapFrame->setGeometry(0, 0, 800, 600);
0421     addWidgetToMdi(vmapFrame.get(), ctrl->name());
0422     m_mediaContainers.push_back(std::move(vmapFrame));
0423 }
0424 void Workspace::addCharacterSheet(CharacterSheetController* ctrl)
0425 {
0426     if(nullptr == ctrl)
0427         return;
0428     std::unique_ptr<CharacterSheetWindow> window(new CharacterSheetWindow(ctrl));
0429     addWidgetToMdi(window.get(), ctrl->name());
0430     m_mediaContainers.push_back(std::move(window));
0431 }
0432 
0433 void Workspace::addWebpage(WebpageController* ctrl)
0434 {
0435     if(nullptr == ctrl)
0436         return;
0437     std::unique_ptr<WebView> window(new WebView(ctrl));
0438     addWidgetToMdi(window.get(), ctrl->name());
0439     m_mediaContainers.push_back(std::move(window));
0440 }
0441 
0442 void Workspace::addNote(NoteController* ctrl)
0443 {
0444     if(nullptr == ctrl)
0445         return;
0446     std::unique_ptr<NoteContainer> SharedNote(new NoteContainer(ctrl));
0447     SharedNote->setGeometry(0, 0, 800, 600);
0448     addWidgetToMdi(SharedNote.get(), ctrl->name());
0449     m_mediaContainers.push_back(std::move(SharedNote));
0450 }
0451 
0452 void Workspace::addMindMap(MindMapController* ctrl)
0453 {
0454     if(nullptr == ctrl)
0455         return;
0456     std::unique_ptr<MindMapView> mindMapView(new MindMapView(ctrl));
0457     mindMapView->setGeometry(0, 0, 800, 600);
0458     addWidgetToMdi(mindMapView.get(), ctrl->name());
0459     m_mediaContainers.push_back(std::move(mindMapView));
0460 }
0461 
0462 void Workspace::addSharedNote(SharedNoteController* ctrl)
0463 {
0464     if(nullptr == ctrl)
0465         return;
0466     std::unique_ptr<SharedNoteContainer> SharedNote(new SharedNoteContainer(ctrl));
0467     SharedNote->setGeometry(0, 0, 800, 600);
0468     addWidgetToMdi(SharedNote.get(), ctrl->name());
0469     m_mediaContainers.push_back(std::move(SharedNote));
0470 }
0471 
0472 void Workspace::addPdf(PdfController* ctrl)
0473 {
0474     if(nullptr == ctrl)
0475         return;
0476     std::unique_ptr<PdfViewer> pdfViewer(new PdfViewer(ctrl));
0477     addWidgetToMdi(pdfViewer.get(), ctrl->name());
0478     m_mediaContainers.push_back(std::move(pdfViewer));
0479 }
0480 
0481 PreventClosing::PreventClosing(QObject* watched, QObject* parent) : QObject(parent), m_watched(watched)
0482 {
0483     if(m_watched)
0484         m_watched->installEventFilter(this);
0485 }
0486 
0487 bool PreventClosing::eventFilter(QObject* obj, QEvent* event)
0488 {
0489     if(obj == m_watched && event->type() == QEvent::Hide)
0490     {
0491         event->accept();
0492         emit visibilityObjectChanged(false);
0493         return true;
0494     }
0495     else
0496         return QObject::eventFilter(obj, event);
0497 }