File indexing completed on 2024-04-28 08:50:40
0001 /* This file is part of the KDE project 0002 SPDX-FileCopyrightText: 1998, 1999 Michael Reiher <michael.reiher@gmx.de> 0003 SPDX-FileCopyrightText: 2007 David Faure <faure@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "konqframestatusbar.h" 0009 #include "konqdebug.h" 0010 #include "konqframe.h" 0011 #include "konqview.h" 0012 #include <kiconloader.h> 0013 #include <QCheckBox> 0014 #include <QPainter> 0015 #include <QLabel> 0016 #include <QMenu> 0017 #include <QProgressBar> 0018 #include <ksqueezedtextlabel.h> 0019 #include <KLocalizedString> 0020 #include <kactioncollection.h> 0021 #include <QAction> 0022 #include <QIcon> 0023 #include <QMouseEvent> 0024 0025 static QPixmap statusBarIcon(const char *name) 0026 { 0027 return KIconLoader::global()->loadIcon(QLatin1String(name), 0028 KIconLoader::User, 0029 KIconLoader::SizeSmall); 0030 } 0031 0032 /** 0033 * A CheckBox with a special paintEvent(). It looks like the 0034 * unchecked radiobutton in b2k style if unchecked and contains a little 0035 * anchor if checked. 0036 */ 0037 class KonqCheckBox : public QCheckBox 0038 { 0039 //Q_OBJECT // for classname. not used, and needs a moc 0040 public: 0041 explicit KonqCheckBox(QWidget *parent = nullptr) 0042 : QCheckBox(parent) {} 0043 protected: 0044 void paintEvent(QPaintEvent *) override; 0045 0046 QSize sizeHint() const override 0047 { 0048 QSize size = connectPixmap().size(); 0049 // Add some room around the pixmap. Makes it a bit easier to click and 0050 // ensure it does not look crowded with styles which draw a frame 0051 // around statusbar items. 0052 size.rwidth() += 4; 0053 return size; 0054 } 0055 0056 private: 0057 const QPixmap &connectPixmap() const 0058 { 0059 static QPixmap indicator_connect(statusBarIcon("indicator_connect")); 0060 return indicator_connect; 0061 } 0062 0063 const QPixmap &noConnectPixmap() const 0064 { 0065 static QPixmap indicator_noconnect(statusBarIcon("indicator_noconnect")); 0066 return indicator_noconnect; 0067 } 0068 }; 0069 0070 #define DEFAULT_HEADER_HEIGHT 13 0071 0072 void KonqCheckBox::paintEvent(QPaintEvent *) 0073 { 0074 QPainter p(this); 0075 0076 const QPixmap &pixmap = (isChecked() || isDown()) ? connectPixmap() : noConnectPixmap(); 0077 p.drawPixmap( 0078 (width() - pixmap.width()) / 2, 0079 (height() - pixmap.height()) / 2, 0080 pixmap); 0081 } 0082 0083 KonqFrameStatusBar::KonqFrameStatusBar(KonqFrame *_parent) 0084 : QStatusBar(_parent), 0085 m_pParentKonqFrame(_parent), 0086 m_pStatusLabel(nullptr) 0087 { 0088 setSizeGripEnabled(false); 0089 0090 // TODO remove active view indicator and use a different bg color like dolphin does? 0091 // Works nicely for file management, but not so much with other parts... 0092 m_led = new QLabel(this); 0093 m_led->setAlignment(Qt::AlignCenter); 0094 m_led->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); 0095 addWidget(m_led, 0); // led (active view indicator) 0096 m_led->hide(); 0097 0098 // TODO re-enable squeezing 0099 //m_pStatusLabel = new KSqueezedTextLabel( this ); 0100 m_pStatusLabel = new KonqStatusBarMessageLabel(this); 0101 m_pStatusLabel->installEventFilter(this); 0102 addWidget(m_pStatusLabel, 1 /*stretch*/); // status label 0103 0104 m_pLinkedViewCheckBox = new KonqCheckBox(this); 0105 m_pLinkedViewCheckBox->setObjectName(QStringLiteral("m_pLinkedViewCheckBox")); 0106 m_pLinkedViewCheckBox->setFocusPolicy(Qt::NoFocus); 0107 m_pLinkedViewCheckBox->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum)); 0108 m_pLinkedViewCheckBox->setWhatsThis(i18n("Checking this box on at least two views sets those views as 'linked'. " 0109 "Then, when you change directories in one view, the other views " 0110 "linked with it will automatically update to show the current directory. " 0111 "This is especially useful with different types of views, such as a " 0112 "directory tree with an icon view or detailed view, and possibly a " 0113 "terminal emulator window.")); 0114 addPermanentWidget(m_pLinkedViewCheckBox, 0); 0115 connect(m_pLinkedViewCheckBox, SIGNAL(toggled(bool)), 0116 this, SIGNAL(linkedViewClicked(bool))); 0117 0118 m_progressBar = new QProgressBar(this); 0119 m_progressBar->setFormat(i18nc("%p is the percent value, % is the percent sign", "%p%")); 0120 // Minimum width of QProgressBar::sizeHint depends on PM_ProgressBarChunkWidth which doesn't make sense; 0121 // we don't want chunking but we want a reasonably-sized progressbar :) 0122 m_progressBar->setMinimumWidth(150); 0123 m_progressBar->setMaximumHeight(fontMetrics().height()); 0124 m_progressBar->hide(); 0125 addPermanentWidget(m_progressBar, 0); 0126 0127 installEventFilter(this); 0128 } 0129 0130 KonqFrameStatusBar::~KonqFrameStatusBar() 0131 { 0132 } 0133 0134 // I don't think this code _ever_ gets called! 0135 // I don't want to remove it, though. :-) 0136 void KonqFrameStatusBar::mousePressEvent(QMouseEvent *event) 0137 { 0138 QWidget::mousePressEvent(event); 0139 if (!m_pParentKonqFrame->childView()->isPassiveMode()) { 0140 emit clicked(); 0141 update(); 0142 } 0143 0144 //Blocks menu of custom status bar entries 0145 //if (event->button()==RightButton) 0146 // splitFrameMenu(); 0147 } 0148 0149 void KonqFrameStatusBar::splitFrameMenu() 0150 { 0151 KonqMainWindow *mw = m_pParentKonqFrame->childView()->mainWindow(); 0152 0153 // We have to ship the remove view action ourselves, 0154 // since this may not be the active view (passive view) 0155 QAction actRemoveView(QIcon::fromTheme(QStringLiteral("view-close")), i18n("Close View"), nullptr); 0156 actRemoveView.setObjectName(QStringLiteral("removethisview")); 0157 connect(&actRemoveView, &QAction::triggered, m_pParentKonqFrame, &KonqFrame::slotRemoveView, Qt::QueuedConnection); 0158 actRemoveView.setEnabled(mw->mainViewsCount() > 1 || m_pParentKonqFrame->childView()->isToggleView() || m_pParentKonqFrame->childView()->isPassiveMode()); 0159 0160 // For the rest, we borrow them from the main window 0161 // ###### might be not right for passive views ! 0162 KActionCollection *actionColl = mw->actionCollection(); 0163 0164 QMenu menu; 0165 0166 menu.addAction(actionColl->action(QStringLiteral("splitviewh"))); 0167 menu.addAction(actionColl->action(QStringLiteral("splitviewv"))); 0168 menu.addSeparator(); 0169 menu.addAction(actionColl->action(QStringLiteral("lock"))); 0170 menu.addAction(&actRemoveView); 0171 0172 menu.exec(QCursor::pos()); 0173 } 0174 0175 bool KonqFrameStatusBar::eventFilter(QObject *o, QEvent *e) 0176 { 0177 if (o == m_pStatusLabel && e->type() == QEvent::MouseButtonPress) { 0178 emit clicked(); 0179 update(); 0180 if (static_cast<QMouseEvent *>(e)->button() == Qt::RightButton) { 0181 splitFrameMenu(); 0182 } 0183 return true; 0184 } else if (o == this && e->type() == QEvent::ApplicationPaletteChange) { 0185 //unsetPalette(); 0186 setPalette(QPalette()); 0187 updateActiveStatus(); 0188 return true; 0189 } 0190 0191 return QStatusBar::eventFilter(o, e); 0192 } 0193 0194 void KonqFrameStatusBar::message(const QString &msg) 0195 { 0196 // We don't use the message()/clear() mechanism of QStatusBar because 0197 // it really looks ugly (the label border goes away, the active-view indicator 0198 // is hidden...) 0199 QString saveMsg = m_savedMessage; 0200 slotDisplayStatusText(msg); 0201 m_savedMessage = saveMsg; 0202 } 0203 0204 void KonqFrameStatusBar::slotDisplayStatusText(const QString &text) 0205 { 0206 //qCDebug(KONQUEROR_LOG) << text; 0207 m_pStatusLabel->setMessage(text, KonqStatusBarMessageLabel::Default); 0208 m_savedMessage = text; 0209 } 0210 0211 // ### TODO: was also used in kde3 for the signals from kactioncollection... 0212 void KonqFrameStatusBar::slotClear() 0213 { 0214 slotDisplayStatusText(m_savedMessage); 0215 } 0216 0217 void KonqFrameStatusBar::slotLoadingProgress(int percent) 0218 { 0219 if (percent == -1 || percent == 100) { // hide on error and on success 0220 m_progressBar->hide(); 0221 } else { 0222 m_progressBar->show(); 0223 } 0224 0225 m_progressBar->setValue(percent); 0226 } 0227 0228 void KonqFrameStatusBar::slotSpeedProgress(int bytesPerSecond) 0229 { 0230 QString sizeStr; 0231 0232 if (bytesPerSecond > 0) { 0233 sizeStr = i18n("%1/s", KIO::convertSize(bytesPerSecond)); 0234 } else { 0235 sizeStr = i18n("Stalled"); 0236 } 0237 0238 slotDisplayStatusText(sizeStr); // let's share the same label... 0239 } 0240 0241 void KonqFrameStatusBar::slotConnectToNewView(KonqView *, KParts::ReadOnlyPart *, KParts::ReadOnlyPart *newOne) 0242 { 0243 if (newOne) { 0244 connect(newOne, SIGNAL(setStatusBarText(QString)), this, SLOT(slotDisplayStatusText(QString))); 0245 } 0246 slotDisplayStatusText(QString()); 0247 } 0248 0249 void KonqFrameStatusBar::showActiveViewIndicator(bool b) 0250 { 0251 m_led->setVisible(b); 0252 updateActiveStatus(); 0253 } 0254 0255 void KonqFrameStatusBar::showLinkedViewIndicator(bool b) 0256 { 0257 m_pLinkedViewCheckBox->setVisible(b); 0258 } 0259 0260 void KonqFrameStatusBar::setLinkedView(bool b) 0261 { 0262 m_pLinkedViewCheckBox->blockSignals(true); 0263 m_pLinkedViewCheckBox->setChecked(b); 0264 m_pLinkedViewCheckBox->blockSignals(false); 0265 } 0266 0267 void KonqFrameStatusBar::updateActiveStatus() 0268 { 0269 if (m_led->isHidden()) { 0270 //unsetPalette(); 0271 setPalette(QPalette()); 0272 return; 0273 } 0274 0275 bool hasFocus = m_pParentKonqFrame->isActivePart(); 0276 0277 const QColor midLight = palette().midlight().color(); 0278 const QColor Mid = palette().mid().color(); 0279 QPalette palette; 0280 palette.setColor(backgroundRole(), hasFocus ? midLight : Mid); 0281 setPalette(palette); 0282 0283 static QPixmap indicator_viewactive(statusBarIcon("indicator_viewactive")); 0284 static QPixmap indicator_empty(statusBarIcon("indicator_empty")); 0285 m_led->setPixmap(hasFocus ? indicator_viewactive : indicator_empty); 0286 } 0287 0288 void KonqFrameStatusBar::setMessage(const QString &msg, KonqStatusBarMessageLabel::Type type) 0289 { 0290 m_pStatusLabel->setMessage(msg, type); 0291 } 0292