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