Warning, file /graphics/tikzkit/src/app/ViewManager.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* This file is part of the TikZKit project 0002 * 0003 * Copyright (C) 2014 Dominik Haumann <dhaumann@kde.org> 0004 * Copyright (C) 2001 Christoph Cullmann <cullmann@kde.org> 0005 * 0006 * This program 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 or 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 GNU 0014 * Library 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, see <http://www.gnu.org/licenses/>. 0018 */ 0019 0020 #include "ViewManager.h" 0021 0022 #include "TikzKit.h" 0023 #include "MainWindow.h" 0024 #include "DocumentManager.h" 0025 0026 #include <tikz/ui/Editor.h> 0027 #include <tikz/ui/View.h> 0028 #include <tikz/ui/Document.h> 0029 0030 #include <QUrl> 0031 #include <QTabBar> 0032 #include <QStackedWidget> 0033 #include <QVBoxLayout> 0034 0035 ViewManager::ViewManager(MainWindow * mainWin, QWidget * parent) 0036 : QWidget(parent) 0037 , m_mainWindow(mainWin) 0038 , m_activeView(nullptr) 0039 { 0040 auto vbox = new QVBoxLayout(this); 0041 vbox->setContentsMargins(0, 0, 0, 0); 0042 vbox->setSpacing(0); 0043 0044 m_tabBar = new QTabBar(this); 0045 m_tabBar->setDocumentMode(true); 0046 m_tabBar->setTabsClosable(true); 0047 m_tabBar->setDrawBase(false); 0048 connect(m_tabBar, SIGNAL(currentChanged(int)), this, SLOT(activateTab(int))); 0049 connect(m_tabBar, SIGNAL(tabCloseRequested(int)), this, SLOT(closeRequest(int)), Qt::QueuedConnection); 0050 m_stack = new QStackedWidget(this); 0051 0052 vbox->addWidget(m_tabBar); 0053 vbox->addWidget(m_stack); 0054 0055 connect(this, SIGNAL(viewChanged(tikz::ui::View*)), this, SLOT(slotViewChanged())); 0056 connect(TikzKit::self()->documentManager(), SIGNAL(documentCreated(tikz::ui::Document*)), this, SLOT(slotDocumentCreated(tikz::ui::Document*))); 0057 0058 // a-priori track document deletion 0059 connect(TikzKit::self()->documentManager(), SIGNAL(aboutToDeleteDocument(tikz::ui::Document*)), 0060 this, SLOT(slotAboutToDeleteDocument(tikz::ui::Document*))); 0061 0062 // unregister document 0063 connect(TikzKit::self()->documentManager(), SIGNAL(documentDeleted(tikz::ui::Document*)), 0064 this, SLOT(slotDocumentDeleted(tikz::ui::Document*))); 0065 0066 // register existing documents 0067 for (auto doc : TikzKit::self()->documentManager()->documentList()) { 0068 slotDocumentCreated(doc); 0069 } 0070 } 0071 0072 ViewManager::~ViewManager() 0073 { 0074 } 0075 0076 MainWindow *ViewManager::mainWindow() 0077 { 0078 return m_mainWindow; 0079 } 0080 0081 void ViewManager::slotDocumentCreated(tikz::ui::Document *doc) 0082 { 0083 if (!activeView()) { 0084 activateView(doc); 0085 } 0086 0087 connect(doc, SIGNAL(documentNameChanged(tikz::core::Document*)), this, SLOT(updateDocumentName(tikz::core::Document*))); 0088 0089 // hide tabbar if there are less than 2 tabs 0090 if (m_tabBar->count() <= 1) { 0091 m_tabBar->hide(); 0092 } 0093 } 0094 0095 void ViewManager::slotAboutToDeleteDocument(tikz::ui::Document *doc) 0096 { 0097 // kill all connections (namely, documentNameChanged(), modifiedChanged(), ...) 0098 disconnect(doc, nullptr, this, nullptr); 0099 0100 // collect all views of that document that belong to this manager 0101 QList<tikz::ui::View *> closeList; 0102 for (auto view : doc->views()) { 0103 if (m_views.contains(view)) { 0104 closeList.append(view); 0105 } 0106 } 0107 0108 for (auto view : qAsConst(closeList)) { 0109 deleteView(view); 0110 } 0111 } 0112 0113 void ViewManager::slotDocumentDeleted(tikz::ui::Document * doc) 0114 { 0115 // for now, nothing to do 0116 } 0117 0118 tikz::ui::View * ViewManager::createView(tikz::ui::Document *doc) 0119 { 0120 // require a valid doc 0121 Q_ASSERT(doc); 0122 0123 // pass the view the correct main window 0124 tikz::ui::View *view = doc->createView(m_stack, mainWindow()->wrapper()); 0125 0126 m_views.append(view); 0127 0128 // insert View into stack 0129 m_stack->addWidget(view); 0130 0131 // register tab 0132 addTab(view); 0133 0134 // connect(view, SIGNAL(focusIn(tikz::ui::View*)), this, SLOT(activateSpace(tikz::ui::View*))); 0135 0136 Q_EMIT viewCreated(view); 0137 0138 if (!activeView()) { 0139 activateView(view); 0140 } 0141 0142 return view; 0143 } 0144 0145 bool ViewManager::deleteView(tikz::ui::View *view) 0146 { 0147 Q_ASSERT(view); 0148 0149 // unregister tab 0150 removeTab(view); 0151 0152 // deleting the active view automatically activates another tab, which 0153 // in turn activates another view 0154 Q_ASSERT(m_activeView != view); 0155 0156 // remove view from mapping and memory !! 0157 m_views.remove(m_views.indexOf(view)); 0158 delete view; 0159 return true; 0160 } 0161 0162 tikz::ui::View *ViewManager::activeView() 0163 { 0164 return m_activeView; 0165 } 0166 0167 QVector<tikz::ui::View*> ViewManager::views() const 0168 { 0169 return m_views; 0170 } 0171 0172 void ViewManager::activateView(tikz::ui::View * view) 0173 { 0174 Q_ASSERT(view); 0175 Q_ASSERT(m_views.contains(view)); 0176 0177 if (m_activeView == view) { 0178 Q_ASSERT(m_stack->currentWidget() == view); 0179 return; 0180 } 0181 0182 // make sure the correct tab is activated 0183 int index = -1; 0184 for (int i = 0; i < m_tabBar->count(); ++i) { 0185 if (m_tabBar->tabData(i).value<tikz::ui::View*>() == view) { 0186 index = i; 0187 break; 0188 } 0189 } 0190 Q_ASSERT(index >= 0); 0191 0192 auto wasBlocked = m_tabBar->blockSignals(true); 0193 m_tabBar->setCurrentIndex(index); 0194 m_tabBar->blockSignals(wasBlocked); 0195 0196 // make sure the correct view is visible 0197 m_activeView = view; 0198 m_stack->setCurrentWidget(view); 0199 0200 Q_EMIT viewChanged(view); 0201 } 0202 0203 tikz::ui::View *ViewManager::activateView(tikz::ui::Document * doc) 0204 { 0205 // no doc with this id found 0206 if (!doc) { 0207 return activeView(); 0208 } 0209 0210 // activate existing view if possible 0211 int index = -1; 0212 for (int i = 0; i < m_tabBar->count(); ++i) { 0213 if (m_tabBar->tabData(i).value<tikz::ui::View*>()->document() == doc) { 0214 index = i; 0215 break; 0216 } 0217 } 0218 0219 if (index >= 0) { 0220 auto view = m_tabBar->tabData(index).value<tikz::ui::View*>(); 0221 activateView(view); 0222 return view; 0223 } 0224 0225 // create new view otherwise 0226 auto view = createView(doc); 0227 activateView(view); 0228 Q_ASSERT(view == activeView()); 0229 0230 return view; 0231 } 0232 0233 void ViewManager::slotViewChanged() 0234 { 0235 if (activeView() && !activeView()->hasFocus()) { 0236 activeView()->setFocus(); 0237 } 0238 } 0239 0240 void ViewManager::closeView(tikz::ui::View *view) 0241 { 0242 deleteView(view); 0243 } 0244 0245 void ViewManager::addTab(tikz::ui::View * view) 0246 { 0247 int index = -1; 0248 for (int i = 0; i < m_tabBar->count(); ++i) { 0249 if (m_tabBar->tabData(i).value<tikz::ui::View*>() == view) { 0250 index = i; 0251 break; 0252 } 0253 } 0254 Q_ASSERT(index == -1); 0255 0256 auto wasBlocked = m_tabBar->blockSignals(true); 0257 index = m_tabBar->addTab(view->document()->documentName()); 0258 m_tabBar->setTabData(index, QVariant::fromValue<tikz::ui::View*>(view)); 0259 m_tabBar->blockSignals(wasBlocked); 0260 0261 // show tabbar only if there are at least 2 tabs 0262 if (m_tabBar->count() > 1) { 0263 m_tabBar->show(); 0264 } 0265 } 0266 0267 void ViewManager::removeTab(tikz::ui::View * view) 0268 { 0269 int index = -1; 0270 for (int i = 0; i < m_tabBar->count(); ++i) { 0271 if (m_tabBar->tabData(i).value<tikz::ui::View*>() == view) { 0272 index = i; 0273 break; 0274 } 0275 } 0276 Q_ASSERT(index >= 0); 0277 0278 m_tabBar->removeTab(index); 0279 0280 // hide tabbar if there are less than 2 tabs 0281 if (m_tabBar->count() <= 1) { 0282 m_tabBar->hide(); 0283 } 0284 } 0285 0286 void ViewManager::activateTab(int index) 0287 { 0288 // if there are no tabs, just return 0289 if (index < 0) { 0290 m_activeView = nullptr; 0291 Q_EMIT viewChanged(m_activeView); 0292 return; 0293 } 0294 0295 auto view = m_tabBar->tabData(index).value<tikz::ui::View*>(); 0296 0297 // a View *must* always be registered at the Editor. 0298 // Otherwise, it's a dangling pointer! 0299 Q_ASSERT(tikz::ui::Editor::instance()->views().contains(view)); 0300 0301 // the view *must* be in the widget stack, otherwise something is wrong 0302 Q_ASSERT(m_stack->indexOf(view) >= 0); 0303 0304 // finally raise view 0305 activateView(view); 0306 } 0307 0308 void ViewManager::closeRequest(int index) 0309 { 0310 auto view = m_tabBar->tabData(index).value<tikz::ui::View*>(); 0311 0312 // a View *must* always be registered at the Editor. 0313 // Otherwise, it's a dangling pointer! 0314 Q_ASSERT(tikz::ui::Editor::instance()->views().contains(view)); 0315 0316 Q_EMIT closeDocumentRequested(view->document()); 0317 } 0318 0319 void ViewManager::updateDocumentName(tikz::core::Document * doc) 0320 { 0321 for (int i = 0; i < m_tabBar->count(); ++i) { 0322 if (m_tabBar->tabData(i).value<tikz::ui::View*>()->document() == doc) { 0323 m_tabBar->setTabText(i, doc->documentName()); 0324 } 0325 } 0326 } 0327 0328 // kate: indent-width 4; replace-tabs on;