File indexing completed on 2025-02-09 07:11:33
0001 /* 0002 This file is part of the Kasten Framework, made within the KDE community. 0003 0004 SPDX-FileCopyrightText: 2007, 2009 Friedrich W. H. Kossebau <kossebau@kde.org> 0005 0006 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0007 */ 0008 0009 #include "tabbedviews_p.hpp" 0010 0011 // lib 0012 #include "toolinlineviewwidget.hpp" 0013 #include <abstracttoolinlineview.hpp> 0014 #include <logging.hpp> 0015 // Kasten core 0016 #include <Kasten/AbstractDocument> 0017 // Qt 0018 #include <QDragMoveEvent> 0019 #include <QDropEvent> 0020 #include <QTabBar> 0021 #include <QApplication> 0022 #include <QClipboard> 0023 0024 namespace Kasten { 0025 0026 TabbedViewsPrivate::TabbedViewsPrivate(TabbedViews* parent) 0027 : AbstractGroupedViewsPrivate(parent) 0028 { 0029 } 0030 0031 TabbedViewsPrivate::~TabbedViewsPrivate() 0032 { 0033 delete mViewAreaBox; 0034 } 0035 0036 void TabbedViewsPrivate::init() 0037 { 0038 Q_Q(TabbedViews); 0039 0040 mTabWidget = new TabWidget(); 0041 mTabWidget->setMovable(true); 0042 mTabWidget->setContextMenuPolicy(Qt::CustomContextMenu); 0043 0044 mViewAreaBox = new ViewAreaBox(mTabWidget); 0045 0046 QObject::connect(mTabWidget, &QTabWidget::tabCloseRequested, 0047 q, [&](int index) { onTabCloseRequest(index); }); 0048 QObject::connect(mTabWidget, &QTabWidget::currentChanged, 0049 q, [&](int index) { onCurrentChanged(index); }); 0050 0051 QObject::connect(mTabWidget, &QWidget::customContextMenuRequested, 0052 q, [&](const QPoint& pos) { onContextMenuRequested(pos); }); 0053 0054 QObject::connect(mTabWidget, &TabWidget::testCanDecode, 0055 q, [&](const QDragMoveEvent* event, bool& accept) { onDragMoveEvent(event, accept); }); 0056 QObject::connect(mTabWidget, &TabWidget::receivedDropEvent, 0057 q, [&](QDropEvent* event) { onDropEvent(event); }); 0058 QObject::connect(mTabWidget, &TabWidget::mouseMiddleClick, 0059 q, [&]() { onMouseMiddleClick(); }); 0060 QObject::connect(mTabWidget, &TabWidget::emptySpaceMouseDoubleClicked, 0061 q, [&]() { onEmptySpaceMouseDoubleClicked(); }); 0062 } 0063 0064 QVector<AbstractView*> TabbedViewsPrivate::viewList() const 0065 { 0066 QVector<AbstractView*> result; 0067 0068 const int count = mTabWidget->count(); 0069 result.reserve(count); 0070 for (int i = 0; i < count; ++i) { 0071 const auto* viewBox = static_cast<const ViewBox*>(mTabWidget->widget(i)); 0072 AbstractView* view = viewBox->view(); 0073 result.append(view); 0074 } 0075 0076 return result; 0077 } 0078 0079 int TabbedViewsPrivate::indexOf(AbstractView* view) const 0080 { 0081 int result = -1; 0082 0083 const int tabCount = mTabWidget->count(); 0084 for (int i = 0; i < tabCount; ++i) { 0085 const auto* viewBox = static_cast<const ViewBox*>(mTabWidget->widget(i)); 0086 if (view == viewBox->view()) { 0087 result = i; 0088 break; 0089 } 0090 } 0091 0092 return result; 0093 } 0094 0095 void TabbedViewsPrivate::addViews(const QVector<AbstractView*>& views) 0096 { 0097 Q_Q(TabbedViews); 0098 0099 if (views.size() == 0) { 0100 return; 0101 } 0102 0103 int insertIndex = mTabWidget->currentIndex() + 1; 0104 for (AbstractView* view : views) { 0105 QObject::connect(view, &AbstractModel::titleChanged, 0106 q, [&](const QString& title) { onTitleChanged(title); }); 0107 0108 auto* viewBox = new ViewBox(view, mTabWidget); 0109 mTabWidget->insertTab(insertIndex, viewBox, view->title()); 0110 ++insertIndex; 0111 } 0112 0113 mTabWidget->setCurrentIndex(insertIndex - 1); 0114 0115 // fix for Qt bug: 0116 if (mTabWidget->count() == 1) { 0117 // simulate signal reaction 0118 onCurrentChanged(0); 0119 } 0120 0121 Q_EMIT q->added(views); 0122 } 0123 0124 void TabbedViewsPrivate::removeViews(const QVector<AbstractView*>& views) 0125 { 0126 Q_Q(TabbedViews); 0127 0128 int index = -1; 0129 0130 // TODO: check if contained 0131 for (AbstractView* view : views) { 0132 view->disconnect(q); 0133 0134 index = indexOf(view); 0135 if (index != -1) { 0136 auto* viewBox = static_cast<ViewBox*>(mTabWidget->widget(index)); 0137 0138 mTabWidget->removeTab(index); 0139 delete viewBox; 0140 } 0141 } 0142 0143 // fix for Qt bug: 0144 const int currentIndex = mTabWidget->currentIndex(); 0145 // last removed or no change in index (not bound to widget)? 0146 if (currentIndex == -1 || currentIndex == index) { 0147 // simulate signal reaction 0148 onCurrentChanged(currentIndex); 0149 } 0150 0151 Q_EMIT q->removing(views); 0152 } 0153 0154 void TabbedViewsPrivate::setCurrentToolInlineView(AbstractToolInlineView* view) 0155 { 0156 if (mCurrentToolInlineView != view) { 0157 mCurrentToolInlineView = view; 0158 QWidget* toolInlineViewWidget = mCurrentToolInlineView ? mCurrentToolInlineView->widget() : nullptr; 0159 mViewAreaBox->setBottomToolWidget(toolInlineViewWidget); 0160 } 0161 0162 if (mCurrentToolInlineView) { 0163 mViewAreaBox->showBottomToolWidget(); 0164 } 0165 } 0166 0167 void TabbedViewsPrivate::onCurrentChanged(int index) 0168 { 0169 Q_Q(TabbedViews); 0170 0171 const auto* viewBox = static_cast<const ViewBox*>(mTabWidget->widget(index)); 0172 AbstractView* view = viewBox ? viewBox->view() : nullptr; 0173 0174 if (view == mCurrentView) { 0175 return; 0176 } 0177 0178 setCurrentToolInlineView(nullptr); 0179 0180 if (mCurrentView) { 0181 mCurrentView->disconnect(q); 0182 } 0183 0184 mCurrentView = view; 0185 0186 if (view) { 0187 QObject::connect(view, &AbstractView::focusChanged, 0188 q, [&](bool hasFocus) { onViewFocusChanged(hasFocus); }); 0189 view->widget()->setFocus(); 0190 } 0191 0192 Q_EMIT q->viewFocusChanged(view); 0193 } 0194 0195 void TabbedViewsPrivate::onTabCloseRequest(int tabIndex) 0196 { 0197 Q_Q(TabbedViews); 0198 0199 const QWidget* widget = mTabWidget->widget(tabIndex); 0200 const auto* viewBox = static_cast<const ViewBox*>(widget); 0201 AbstractView* view = viewBox->view(); 0202 0203 const QVector<Kasten::AbstractView*> views { view }; 0204 Q_EMIT q->closeRequest(views); 0205 } 0206 0207 void TabbedViewsPrivate::onTitleChanged(const QString& newTitle) 0208 { 0209 Q_Q(TabbedViews); 0210 0211 auto* view = qobject_cast<AbstractView*>(q->sender()); 0212 if (view) { 0213 const int index = indexOf(view); 0214 if (index != -1) { 0215 mTabWidget->setTabText(index, newTitle); 0216 } 0217 } 0218 } 0219 0220 #if 0 0221 void TabbedViewsPrivate::onModifiedChanged(AbstractDocument::SyncStates newStates) 0222 { 0223 Q_UNUSED(newStates) 0224 AbstractView * view = qobject_cast<AbstractView*>(sender()); 0225 if (view) { 0226 const int index = indexOf(view); 0227 if (index != -1) { 0228 // mViewsTab->setIcon( index, newTitle ); //modificationSymbol 0229 if (index == mViewsTab->currentIndex()) { 0230 setCaption(view->title(), view->document()->hasLocalChanges()); 0231 } 0232 } 0233 } 0234 0235 } 0236 #endif 0237 0238 // TODO: could be just a signal forwarder 0239 void TabbedViewsPrivate::onViewFocusChanged(bool hasFocus) 0240 { 0241 Q_Q(TabbedViews); 0242 0243 // AbstractView* view = qobject_cast<AbstractView *>( q->sender() ); 0244 // qCDebug(LOG_KASTEN_GUI)<<view<<view->title()<<hasFocus; 0245 0246 Q_EMIT q->focusChanged(hasFocus); 0247 } 0248 0249 void TabbedViewsPrivate::onContextMenuRequested(QPoint pos) 0250 { 0251 Q_Q(TabbedViews); 0252 0253 AbstractView* view = nullptr; 0254 QTabBar* tabBar = mTabWidget->tabBar(); 0255 const int tabIndex = tabBar->tabAt(tabBar->mapFrom(mTabWidget, pos)); 0256 if (tabIndex != -1) { 0257 const QWidget* widget = mTabWidget->widget(tabIndex); 0258 const auto* viewBox = static_cast<const ViewBox*>(widget); 0259 view = viewBox->view(); 0260 } 0261 Q_EMIT q->contextMenuRequested(view, mTabWidget->mapTo(mViewAreaBox, pos)); 0262 } 0263 0264 void TabbedViewsPrivate::onMouseMiddleClick() 0265 { 0266 Q_Q(TabbedViews); 0267 0268 const QMimeData* mimeData = QApplication::clipboard()->mimeData(QClipboard::Selection); 0269 0270 Q_EMIT q->dataDropped(mimeData); 0271 } 0272 0273 void TabbedViewsPrivate::onEmptySpaceMouseDoubleClicked() 0274 { 0275 Q_Q(TabbedViews); 0276 0277 Q_EMIT q->newDocumentRequested(); 0278 } 0279 0280 void TabbedViewsPrivate::onDragMoveEvent(const QDragMoveEvent* event, bool& accepted) 0281 { 0282 Q_Q(TabbedViews); 0283 0284 const QMimeData* mimeData = event->mimeData(); 0285 0286 Q_EMIT q->dataOffered(mimeData, accepted); 0287 } 0288 0289 void TabbedViewsPrivate::onDropEvent(QDropEvent* event) 0290 { 0291 Q_Q(TabbedViews); 0292 0293 const QMimeData* mimeData = event->mimeData(); 0294 0295 Q_EMIT q->dataDropped(mimeData); 0296 } 0297 0298 }