Warning, file /utilities/krusader/app/DiskUsage/radialMap/segmentTip.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2003-2004 Max Howell <max.howell@methylblue.com>
0003     SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "segmentTip.h"
0009 
0010 // QtCore
0011 #include <QEvent>
0012 // QtGui
0013 #include <QPainter>
0014 // QtWidgets
0015 #include <QApplication> //installing eventFilters
0016 #include <QDesktopWidget>
0017 #include <QToolTip> //for its palette
0018 
0019 #include <KI18n/KLocalizedString>
0020 
0021 #include "../compat.h"
0022 #include "fileTree.h"
0023 
0024 namespace RadialMap
0025 {
0026 
0027 SegmentTip::SegmentTip(uint h)
0028     : QWidget(nullptr, Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint)
0029     , m_cursorHeight(-h)
0030 {
0031     setAttribute(Qt::WA_NoSystemBackground, true);
0032 }
0033 
0034 void SegmentTip::moveto(QPoint p, QWidget &canvas, bool placeAbove)
0035 {
0036     //**** this function is very slow and seems to be visibly influenced by operations like mapFromGlobal() (who knows why!)
0037     //  ** so any improvements are much desired
0038 
0039     // TODO uints could improve the class
0040     p.rx() -= rect().center().x();
0041     p.ry() -= (placeAbove ? 8 + height() : m_cursorHeight - 8);
0042 
0043     const QRect screen = QApplication::desktop()->screenGeometry(parentWidget());
0044 
0045     const int x = p.x();
0046     const int y = p.y();
0047     const int x2 = x + width();
0048     const int y2 = y + height(); // how's it ever gunna get below screen height?! (well you never know I spose)
0049     const int sw = screen.width();
0050     const int sh = screen.height();
0051 
0052     if (x < 0)
0053         p.setX(0);
0054     if (y < 0)
0055         p.setY(0);
0056     if (x2 > sw)
0057         p.rx() -= x2 - sw;
0058     if (y2 > sh)
0059         p.ry() -= y2 - sh;
0060 
0061     // I'm using this QPoint to determine where to offset the bitBlt in m_pixmap
0062     QPoint offset = canvas.mapToGlobal(QPoint()) - p;
0063     if (offset.x() < 0)
0064         offset.setX(0);
0065     if (offset.y() < 0)
0066         offset.setY(0);
0067 
0068     const QRect alphaMaskRect(canvas.mapFromGlobal(p), size());
0069     const QRect intersection(alphaMaskRect.intersected(canvas.rect()));
0070 
0071     m_pixmap = QPixmap(size()); // move to updateTip once you are sure it can never be null
0072     // bitBlt( &m_pixmap, offset, &canvas, intersection, Qt::CopyROP );
0073     QPainter(&m_pixmap).drawPixmap(offset, canvas.grab(intersection));
0074 
0075     QColor col = QToolTip::palette().color(QPalette::Active, QPalette::Window);
0076     col.setAlpha(153); // 0.6
0077 
0078     QRect rct = rect();
0079     if (rct.width())
0080         rct.setWidth(rct.width() - 1);
0081     if (rct.height())
0082         rct.setHeight(rct.height() - 1);
0083 
0084     QPainter paint(&m_pixmap);
0085     paint.setPen(Qt::black);
0086     paint.setBrush(col);
0087     paint.drawRect(rct);
0088     paint.end();
0089 
0090     paint.begin(&m_pixmap);
0091     paint.drawText(rect(), Qt::AlignCenter, m_text);
0092     paint.end();
0093 
0094     p += screen.topLeft(); // for Xinerama users
0095 
0096     move(x, y);
0097     show();
0098     repaint();
0099 }
0100 
0101 void SegmentTip::updateTip(const File *const file, const Directory *const root)
0102 {
0103     const QString s1 = file->fullPath(root);
0104     QString s2 = file->humanReadableSize();
0105     QLocale loc;
0106     const uint MARGIN = 3;
0107     const FileSize pc = 100 * file->size() / root->size();
0108     uint maxw = 0;
0109     uint h = fontMetrics().height() * 2 + 2 * MARGIN;
0110 
0111     if (pc > 0)
0112         s2 += QString(" (%1%)").arg(loc.toString(pc));
0113 
0114     m_text = s1;
0115     m_text += '\n';
0116     m_text += s2;
0117 
0118     if (file->isDir()) {
0119         double files = dynamic_cast<const Directory *>(file)->fileCount();
0120         const auto pc = uint((100 * files) / (double)root->fileCount());
0121         QString s3 = i18n("Files: %1", loc.toString(files, 'f', 0));
0122 
0123         if (pc > 0)
0124             s3 += QString(" (%1%)").arg(loc.toString(pc));
0125 
0126         maxw = fontMetrics().horizontalAdvance(s3);
0127         h += fontMetrics().height();
0128         m_text += '\n';
0129         m_text += s3;
0130     }
0131 
0132     uint w = fontMetrics().horizontalAdvance(s1);
0133     if (w > maxw)
0134         maxw = w;
0135     w = fontMetrics().horizontalAdvance(s2);
0136     if (w > maxw)
0137         maxw = w;
0138 
0139     resize(maxw + 2 * MARGIN, h);
0140 }
0141 
0142 bool SegmentTip::event(QEvent *e)
0143 {
0144     switch (e->type()) {
0145     case QEvent::Show:
0146         qApp->installEventFilter(this);
0147         break;
0148     case QEvent::Hide:
0149         qApp->removeEventFilter(this);
0150         break;
0151     case QEvent::Paint: {
0152         // bitBlt( this, 0, 0, &m_pixmap );
0153         QPainter(this).drawPixmap(0, 0, m_pixmap);
0154         return true;
0155     }
0156     default:;
0157     }
0158 
0159     return false /*QWidget::event( e )*/;
0160 }
0161 
0162 bool SegmentTip::eventFilter(QObject *, QEvent *e)
0163 {
0164     switch (e->type()) {
0165     case QEvent::Leave:
0166         //    case QEvent::MouseButtonPress:
0167         //    case QEvent::MouseButtonRelease:
0168     case QEvent::KeyPress:
0169     case QEvent::KeyRelease:
0170     case QEvent::FocusIn:
0171     case QEvent::FocusOut:
0172     case QEvent::Wheel:
0173         hide(); // FALL THROUGH
0174     default:
0175         return false; // allow this event to passed to target
0176     }
0177 }
0178 
0179 } // namespace RadialMap