diff --git a/CMakeLists.txt b/CMakeLists.txt index b537113..ff62ae9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,81 +1,84 @@ ####################################################################### # Copyright 2008-2014 Martin Sandsmark # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License or (at your option) version 3 or any later version # accepted by the membership of KDE e.V. (or its successor approved # by the membership of KDE e.V.), which shall act as a proxy # defined in Section 14 of version 3 of the license. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ####################################################################### # KDE Application Version, managed by release script set(KDE_APPLICATIONS_VERSION_MAJOR "19") set(KDE_APPLICATIONS_VERSION_MINOR "11") set(KDE_APPLICATIONS_VERSION_MICRO "70") set(KDE_APPLICATIONS_VERSION "${KDE_APPLICATIONS_VERSION_MAJOR}.${KDE_APPLICATIONS_VERSION_MINOR}.${KDE_APPLICATIONS_VERSION_MICRO}") set(FILELIGHT_VERSION ${KDE_APPLICATIONS_VERSION}) # minimum requirements cmake_minimum_required (VERSION 3.5 FATAL_ERROR) # Spectacle project project(Filelight VERSION ${FILELIGHT_VERSION}) set(PROJECT_VERSION ${KDE_APPLICATIONS_VERSION}) set(KF5_MIN_VERSION "5.46.0") set(QT_REQUIRED_VERSION "5.11.0") find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(ECMAddAppIcon) include(ECMGenerateHeaders) include(ECMInstallIcons) include(ECMMarkNonGuiExecutable) include(ECMOptionalAddSubdirectory) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED Core Widgets) find_package(KF5 ${KF5_MIN_VERSION} REQUIRED XmlGui # For app KIO # For part I18n ) find_package(KF5DocTools) # Optional, not needed on Windows for example. add_definitions(-DTRANSLATION_DOMAIN=\"filelight\") if (KF5Config_VERSION VERSION_GREATER "5.56.0") add_definitions(-DQT_NO_FOREACH) MESSAGE(STATUS "compile without foreach") endif() +if (EXISTS "${CMAKE_SOURCE_DIR}/.git") + add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) +endif() include_directories(src) add_subdirectory(src) add_subdirectory(misc) if (KF5DocTools_FOUND) add_subdirectory(doc) endif() if (ECM_VERSION VERSION_GREATER "5.58.0") install(FILES filelight.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) else() install(FILES filelight.categories DESTINATION ${KDE_INSTALL_CONFDIR}) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/progressBox.cpp b/src/progressBox.cpp index 0178286..df01e9a 100644 --- a/src/progressBox.cpp +++ b/src/progressBox.cpp @@ -1,131 +1,131 @@ /*********************************************************************** * Copyright 2003-2004 Max Howell * Copyright 2008-2009 Martin Sandsmark * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . ***********************************************************************/ #include "progressBox.h" #include "scan.h" #include "mainWindow.h" #include #include #include #include #include #include ProgressBox::ProgressBox(QWidget *parent, Filelight::MainWindow *mainWindow, Filelight::ScanManager *scanManager) : QWidget(parent) , m_manager(scanManager) , m_colorScheme(QPalette::Active, KColorScheme::Tooltip) { hide(); setObjectName(QStringLiteral( "ProgressBox" )); setFont(QFontDatabase::systemFont(QFontDatabase::FixedFont)); setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); setText(999999); setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); setMinimumSize(300, 300); connect(&m_timer, &QTimer::timeout, this, &ProgressBox::report); connect(mainWindow, &Filelight::MainWindow::started, this, &ProgressBox::start); connect(mainWindow, &Filelight::MainWindow::completed, this, &ProgressBox::stop); connect(mainWindow, &Filelight::MainWindow::canceled, this, &ProgressBox::halt); } void ProgressBox::start() //slot { m_timer.start(50); //20 times per second - very smooth report(); show(); } void ProgressBox::report() //slot { setText(m_manager->files()); update(); //repaint(); } void ProgressBox::stop() { m_timer.stop(); } void ProgressBox::halt() { // canceled by stop button m_timer.stop(); QTimer::singleShot(2000, this, &QWidget::hide); } void ProgressBox::setText(int files) { m_text = i18np("%1 File", "%1 Files", files); - m_textWidth = fontMetrics().width(m_text); + m_textWidth = fontMetrics().boundingRect(m_text).width(); m_textHeight = fontMetrics().height(); } #define PIECES_NUM 4 static const float angleFactor[] = { -0.25, 0.9, -1.0, 0.3 }; static const float length[] = { 1.0, 1.0, 1.0, 1.0 }; static const int aLength[] = { 2000, 2000, 2000, 2000 }; void ProgressBox::paintEvent(QPaintEvent*) { QPainter paint(this); paint.setPen(Qt::transparent); paint.setRenderHint(QPainter::Antialiasing); static int tick = 0; tick+=16; for (int i=0; i * Copyright 2008-2009 Martin Sandsmark * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . ***********************************************************************/ #include #include #include #include #include "Config.h" #include "fileTree.h" #include "radialMap.h" #include "sincos.h" #include "widget.h" namespace RadialMap { class Label { public: Label(const RadialMap::Segment *s, int l) : segment(s), level(l), angle(segment->start() + (segment->length() / 2)) { } bool tooClose(const int otherAngle) const { return (angle > otherAngle - LABEL_ANGLE_MARGIN && angle < otherAngle + LABEL_ANGLE_MARGIN); } const RadialMap::Segment *segment; const unsigned int level; const int angle; int targetX, targetY, middleX, startY, startX; int textX, textY, tw, th; QString qs; }; void RadialMap::Widget::paintExplodedLabels(QPainter &paint) const { //we are a friend of RadialMap::Map QVector list; unsigned int startLevel = 0; //1. Create list of labels sorted in the order they will be rendered if (m_focus && m_focus->file() != m_tree) { //separate behavior for selected vs unselected segments //don't bother with files if (m_focus && m_focus->file() && !m_focus->file()->isFolder()) { return; } //find the range of levels we will be potentially drawing labels for //startLevel is the level above whatever m_focus is in for (const Folder *p = (const Folder*)m_focus->file(); p != m_tree; ++startLevel) { p = p->parent(); } //range=2 means 2 levels to draw labels for const uint start = m_focus->start(); const uint end = m_focus->end(); //boundary angles const uint minAngle = int(m_focus->length() * LABEL_MIN_ANGLE_FACTOR); //**** Levels should be on a scale starting with 0 //**** range is a useless parameter //**** keep a topblock var which is the lowestLevel OR startLevel for indentation purposes for (unsigned int i = startLevel; i <= m_map.m_visibleDepth; ++i) { for (const Segment *segment : m_map.m_signature[i]) { if (segment->start() >= start && segment->end() <= end) { if (segment->length() > minAngle) { list.append(new Label(segment, i)); } } } } } else { for (Segment *segment : *m_map.m_signature) { if (segment->length() > 288) { list.append(new Label(segment, 0)); } } } std::sort(list.begin(), list.end(), [](Label *item1, Label *item2) { //you add 1440 to work round the fact that later you want the circle split vertically //and as it is you start at 3 o' clock. It's to do with rightPrevY, stops annoying bug int angle1 = (item1)->angle + 1440; int angle2 = (item2)->angle + 1440; // Also sort by level if (angle1 == angle2) { return (item1->level > item2->level); } if (angle1 > 5760) angle1 -= 5760; if (angle2 > 5760) angle2 -= 5760; return (angle1 < angle2); }); //2. Check to see if any adjacent labels are too close together // if so, remove it (the least significant labels, since we sort by level too). int pos = 0; while (pos < list.size() - 1) { if (list[pos]->tooClose(list[pos+1]->angle)) { delete list.takeAt(pos+1); } else { ++pos; } } //used in next two steps bool varySizes; //**** should perhaps use doubles int *sizes = new int [ m_map.m_visibleDepth + 1 ]; //**** make sizes an array of floats I think instead (or doubles) // If the minimum is larger than the default it fucks up further down if (paint.font().pointSize() < 0 || paint.font().pointSize() < Config::minFontPitch) { QFont font = paint.font(); font.setPointSize(Config::minFontPitch); paint.setFont(font); } QVector::iterator it; do { //3. Calculate font sizes { //determine current range of levels to draw for uint range = 0; for (Label *label : list) { range = qMax(range, label->level); //**** better way would just be to assign if nothing is range } range -= startLevel; //range 0 means 1 level of labels varySizes = Config::varyLabelFontSizes && (range != 0); if (varySizes) { //create an array of font sizes for various levels //will exceed normal font pitch automatically if necessary, but not minPitch //**** this needs to be checked lots //**** what if this is negative (min size gtr than default size) uint step = (paint.font().pointSize() - Config::minFontPitch) / range; if (step == 0) { step = 1; } for (uint x = range + startLevel, y = Config::minFontPitch; x >= startLevel; y += step, --x) { sizes[x] = y; } } } //4. determine label co-ordinates const int preSpacer = int(m_map.m_ringBreadth * 0.5) + m_map.m_innerRadius; const int fullStrutLength = (m_map.width() - m_map.MAP_2MARGIN) / 2 + LABEL_MAP_SPACER; //full length of a strut from map center int prevLeftY = 0; int prevRightY = height(); QFont font; for (it = list.begin(); it != list.end(); ++it) { Label *label = *it; //** bear in mind that text is drawn with QPoint param as BOTTOM left corner of text box QString string = label->segment->file()->displayName(); if (varySizes) { font.setPointSize(sizes[label->level]); } QFontMetrics fontMetrics(font); - const int minTextWidth = fontMetrics.width(QStringLiteral("M...")) + LABEL_TEXT_HMARGIN; // Fully elided string + const int minTextWidth = fontMetrics.boundingRect(QStringLiteral("M...")).width() + LABEL_TEXT_HMARGIN; // Fully elided string const int fontHeight = fontMetrics.height() + LABEL_TEXT_VMARGIN; //used to ensure label texts don't overlap const int lineSpacing = fontHeight / 4; const bool rightSide = (label->angle < 1440 || label->angle > 4320); double sinra, cosra; const double ra = M_PI/2880 * label->angle; //convert to radians sincos(ra, &sinra, &cosra); const int spacer = preSpacer + m_map.m_ringBreadth * label->level; const int centerX = m_map.width() / 2 + m_offset.x(); //centre relative to canvas const int centerY = m_map.height() / 2 + m_offset.y(); int targetX = centerX + cosra * spacer; int targetY = centerY - sinra * spacer; int startX = targetX + cosra * (fullStrutLength - spacer + m_map.m_ringBreadth / 2); int startY = targetY - sinra * (fullStrutLength - spacer); if (rightSide) { //righthand side, going upwards if (startY > prevRightY /*- fmh*/) { //then it is too low, needs to be drawn higher startY = prevRightY /*- fmh*/; } } else {//lefthand side, going downwards if (startY < prevLeftY/* + fmh*/) { //then we're too high, need to be drawn lower startY = prevLeftY /*+ fmh*/; } } int middleX = targetX - (startY - targetY) / tan(ra); int textY = startY + lineSpacing; int textX; - const int textWidth = fontMetrics.width(string) + LABEL_TEXT_HMARGIN; + const int textWidth = fontMetrics.boundingRect(string).width() + LABEL_TEXT_HMARGIN; if (rightSide) { if (startX + minTextWidth > width() || textY < fontHeight || middleX < targetX) { //skip this strut //**** don't duplicate this code list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr break; } prevRightY = textY - fontHeight - lineSpacing; //must be after above's "continue" if (m_offset.x() + m_map.width() + textWidth < width()) { startX = m_offset.x() + m_map.width(); } else { startX = qMax(width() - textWidth, startX); string = fontMetrics.elidedText(string, Qt::ElideMiddle, width() - startX); } textX = startX + LABEL_TEXT_HMARGIN; } else { // left side if (startX - minTextWidth < 0 || textY > height() || middleX > targetX) { //skip this strut list.erase(it); //will delete the label and set it to list.current() which _should_ be the next ptr break; } prevLeftY = textY + fontHeight - lineSpacing; if (m_offset.x() - textWidth > 0) { startX = m_offset.x(); textX = startX - textWidth - LABEL_TEXT_HMARGIN; } else { textX = 0; string = fontMetrics.elidedText(string, Qt::ElideMiddle, startX); - startX = fontMetrics.width(string) + LABEL_TEXT_HMARGIN; + startX = fontMetrics.boundingRect(string).width() + LABEL_TEXT_HMARGIN; } } label->targetX = targetX; label->targetY = targetY; label->middleX = middleX; label->startY = startY; label->startX = startX; label->textX = textX; label->textY = textY; label->qs = string; } //if an element is deleted at this stage, we need to do this whole //iteration again, thus the following loop //**** in rare case that deleted label was last label in top level // and last in labelList too, this will not work as expected (not critical) } while (it != list.end()); //5. Render labels QFont font; for (Label *label : list) { if (varySizes) { //**** how much overhead in making new QFont each time? // (implicate sharing remember) font.setPointSize(sizes[label->level]); paint.setFont(font); } paint.drawLine(label->targetX, label->targetY, label->middleX, label->startY); paint.drawLine(label->middleX, label->startY, label->startX, label->startY); paint.drawText(label->textX, label->textY, label->qs); } qDeleteAll(list); delete [] sizes; } }