File indexing completed on 2025-02-02 12:46:23
0001 /*************************************************************************** 0002 * Copyright (C) 2005 by David Saxton * 0003 * david@bluehaze.org * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ***************************************************************************/ 0010 0011 #include "view.h" 0012 #include "document.h" 0013 #include "iteminterface.h" 0014 #include "ktechlab.h" 0015 #include "viewcontainer.h" 0016 #include "viewiface.h" 0017 0018 #include <KActionCollection> 0019 #include <KLocalizedString> 0020 #include <KSqueezedTextLabel> 0021 #include <KXMLGUIFactory> 0022 0023 #include <QApplication> 0024 #include <QPaintEvent> 0025 #include <QStyle> 0026 #include <QVBoxLayout> 0027 0028 #include <cassert> 0029 0030 #include <ktechlab_debug.h> 0031 0032 // BEGIN class View 0033 View::View(Document *document, ViewContainer *viewContainer, uint viewAreaId) 0034 : QWidget(viewContainer->viewArea(viewAreaId)) 0035 , KXMLGUIClient() 0036 { 0037 setObjectName("view_" + QString::number(viewAreaId)); 0038 m_pFocusWidget = nullptr; 0039 m_dcopID = 0; 0040 m_viewAreaId = viewAreaId; 0041 m_pDocument = document; 0042 p_viewContainer = viewContainer; 0043 m_pViewIface = nullptr; 0044 0045 setFocusPolicy(Qt::ClickFocus); 0046 0047 if (ViewArea *viewArea = viewContainer->viewArea(viewAreaId)) 0048 viewArea->setView(this); 0049 0050 else 0051 qCDebug(KTL_LOG) << " viewArea = " << viewArea; 0052 0053 m_layout = new QVBoxLayout(this); 0054 //m_layout->setMargin(0); // if we remove this some magic visibility calculation goes wrong 0055 0056 // Don't bother creating statusbar if no ktechlab as we are not a main ktechlab tab 0057 if (KTechlab::self()) { 0058 m_statusBar = new ViewStatusBar(this); 0059 0060 m_layout->addWidget(new KVSSBSep(this)); 0061 m_layout->addWidget(m_statusBar); 0062 0063 // connect(KTechlab::self(), SIGNAL(configurationChanged()), this, SLOT(slotUpdateConfiguration())); 0064 connect(KTechlab::self(), &KTechlab::configurationChanged, this, &View::slotUpdateConfiguration); 0065 } 0066 } 0067 0068 View::~View() 0069 { 0070 // if ( KTechlab::self() ) // 2015.09.13 - remove the XMLGUIClient from the factory, even at program close 0071 // KTechlab::self()->factory()->removeClient(this); 0072 // 2017.01.09: do not crash on document close. factory has its clients removed in TextDocument::~TextDocument() 0073 // if ( factory() ) { 0074 // factory()->removeClient( this ); 0075 //} else { 0076 // qCWarning(KTL_LOG) << "Null factory"; 0077 //} 0078 } 0079 0080 QAction *View::actionByName(const QString &name) const 0081 { 0082 QAction *action = actionCollection()->action(name); 0083 if (!action) 0084 qCCritical(KTL_LOG) << "No such action: " << name; 0085 return action; 0086 } 0087 0088 Document *View::document() const 0089 { 0090 return m_pDocument; 0091 } 0092 0093 DCOPObject *View::dcopObject() const 0094 { 0095 return m_pViewIface; 0096 } 0097 0098 bool View::closeView() 0099 { 0100 return p_viewContainer->closeViewArea(viewAreaId()); 0101 } 0102 0103 void View::setFocusWidget(QWidget *focusWidget) 0104 { 0105 assert(focusWidget); 0106 assert(!m_pFocusWidget); 0107 0108 if (hasFocus()) 0109 focusWidget->setFocus(); 0110 0111 m_pFocusWidget = focusWidget; 0112 setFocusProxy(m_pFocusWidget); 0113 m_pFocusWidget->installEventFilter(this); 0114 m_pFocusWidget->setFocusPolicy(Qt::ClickFocus); 0115 } 0116 0117 bool View::eventFilter(QObject *watched, QEvent *e) 0118 { 0119 // qCDebug(KTL_LOG) << e->type(); 0120 0121 if (watched != m_pFocusWidget) 0122 return false; 0123 0124 switch (e->type()) { 0125 case QEvent::FocusIn: { 0126 p_viewContainer->setActiveViewArea(viewAreaId()); 0127 0128 if (KTechlab *ktl = KTechlab::self()) { 0129 ktl->actionByName("file_save")->setEnabled(true); 0130 ktl->actionByName("file_save_as")->setEnabled(true); 0131 ktl->actionByName("file_close")->setEnabled(true); 0132 ktl->actionByName("file_print")->setEnabled(true); 0133 ktl->actionByName("edit_paste")->setEnabled(true); 0134 ktl->actionByName("view_split_leftright")->setEnabled(true); 0135 ktl->actionByName("view_split_topbottom")->setEnabled(true); 0136 0137 ItemInterface::self()->updateItemActions(); 0138 } 0139 0140 // qCDebug(KTL_LOG) << "Focused In"; 0141 emit focused(this); 0142 break; 0143 } 0144 0145 case QEvent::FocusOut: { 0146 // qCDebug(KTL_LOG) << "Focused Out."; 0147 QFocusEvent *fe = static_cast<QFocusEvent *>(e); 0148 0149 if (QWidget *fw = qApp->focusWidget()) { 0150 QString fwClassName(fw->metaObject()->className()); 0151 // qCDebug(KTL_LOG) << "New focus widget is \""<<fw->name()<<"\" of type " << fwClassName; 0152 0153 if ((fwClassName != "KateViewInternal") && (fwClassName != "QViewportWidget")) { 0154 // qCDebug(KTL_LOG) << "Returning as a non-view widget has focus."; 0155 break; 0156 } 0157 } else { 0158 // qCDebug(KTL_LOG) << "No widget currently has focus."; 0159 } 0160 0161 if (fe->reason() == Qt::PopupFocusReason) { 0162 // qCDebug(KTL_LOG) << "Ignoring focus-out event as was a popup."; 0163 break; 0164 } 0165 0166 if (fe->reason() == Qt::ActiveWindowFocusReason) { 0167 // qCDebug(KTL_LOG) << "Ignoring focus-out event as main window lost focus."; 0168 break; 0169 } 0170 0171 emit unfocused(); 0172 break; 0173 } 0174 0175 default: 0176 break; 0177 } 0178 0179 return false; 0180 } 0181 0182 void View::setDCOPID(unsigned id) 0183 { 0184 if (m_dcopID == id) 0185 return; 0186 0187 m_dcopID = id; 0188 if (m_pViewIface) { 0189 QString docID; 0190 docID.setNum(document()->dcopID()); 0191 0192 QString viewID; 0193 viewID.setNum(dcopID()); 0194 0195 m_pViewIface->setObjId("View#" + docID + "." + viewID); 0196 } 0197 } 0198 // END class View 0199 0200 // BEGIN class ViewStatusBar 0201 ViewStatusBar::ViewStatusBar(View *view) 0202 : QStatusBar(view) 0203 { 0204 p_view = view; 0205 0206 m_modifiedLabel = new QLabel(this); 0207 addWidget(m_modifiedLabel, 0 /*, false */); 0208 m_fileNameLabel = new KSqueezedTextLabel(this); 0209 addWidget(m_fileNameLabel, 1 /*, false */); 0210 m_statusLabel = new QLabel(this); 0211 m_statusLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter); 0212 addPermanentWidget(m_statusLabel, 0); 0213 0214 const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize); 0215 m_modifiedPixmap = QIcon::fromTheme("document-save").pixmap(iconSize); 0216 m_unmodifiedPixmap = QIcon::fromTheme("null").pixmap(iconSize); 0217 0218 connect(view->document(), &Document::modifiedStateChanged, this, &ViewStatusBar::slotModifiedStateChanged); 0219 connect(view->document(), &Document::fileNameChanged, this, &ViewStatusBar::slotFileNameChanged); 0220 0221 connect(view, &View::focused, this, &ViewStatusBar::slotViewFocused); 0222 connect(view, &View::unfocused, this, &ViewStatusBar::slotViewUnfocused); 0223 0224 slotModifiedStateChanged(); 0225 slotFileNameChanged(view->document()->url()); 0226 0227 slotViewUnfocused(); 0228 } 0229 0230 void ViewStatusBar::setStatusText(const QString &statusText) 0231 { 0232 m_statusLabel->setText(statusText); 0233 } 0234 0235 void ViewStatusBar::slotModifiedStateChanged() 0236 { 0237 m_modifiedLabel->setPixmap(p_view->document()->isModified() ? m_modifiedPixmap : m_unmodifiedPixmap); 0238 } 0239 0240 void ViewStatusBar::slotFileNameChanged(const QUrl &url) 0241 { 0242 m_fileNameLabel->setText(url.isEmpty() ? i18n("Untitled") : url.adjusted(QUrl::StripTrailingSlash).fileName()); 0243 } 0244 0245 void ViewStatusBar::slotViewFocused(View *) 0246 { 0247 setPalette(p_view->palette()); 0248 } 0249 0250 void ViewStatusBar::slotViewUnfocused() 0251 { 0252 QPalette pal(p_view->palette()); 0253 pal.setColor(QPalette::Window /*QColorGroup::Background */, pal.mid().color()); 0254 pal.setColor(QPalette::Light, pal.midlight().color()); 0255 setPalette(pal); 0256 } 0257 // END class ViewStatusBar 0258 0259 // BEGIN class KVSSBSep 0260 void KVSSBSep::paintEvent(QPaintEvent *e) 0261 { 0262 // QPainter p( this ); 0263 QPainter p; 0264 const bool beginSuccess = p.begin(this); 0265 if (!beginSuccess) { 0266 qCWarning(KTL_LOG) << " painter is not active"; 0267 } 0268 // p.setPen( colorGroup().shadow() ); 0269 // QColorGroup colorGroup(palette()); // 2018.12.02 0270 p.setPen(palette().shadow().color() /* colorGroup.shadow() */); 0271 p.drawLine(e->rect().left(), 0, e->rect().right(), 0); 0272 // p.setPen( ((View*)parentWidget())->hasFocus() ? colorGroup.light() : colorGroup.midlight() ); 0273 View *parentView = dynamic_cast<View *>(parentWidget()); 0274 if (!parentView) { 0275 qCWarning(KTL_LOG) << "parent not View for this=" << this << ", parent=" << parentWidget(); 0276 return; 0277 } 0278 p.setPen(parentView->hasFocus() ? palette().light().color() : palette().midlight().color()); 0279 p.drawLine(e->rect().left(), 1, e->rect().right(), 1); 0280 } 0281 // END class KVSSBSep 0282 0283 #include "moc_view.cpp"