diff --git a/src/kwatchgnupg/CMakeLists.txt b/src/kwatchgnupg/CMakeLists.txt index b10f40f9a..d35027218 100644 --- a/src/kwatchgnupg/CMakeLists.txt +++ b/src/kwatchgnupg/CMakeLists.txt @@ -1,43 +1,42 @@ set(kwatchgnupg_version 1.0) find_package(KF5Notifications ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version-kwatchgnupg.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/version-kwatchgnupg.h) set(kwatchgnupg_SRCS - kdlogtextwidget.cpp ../utils/gnupg-helper.cpp ../utils/hex.cpp ../utils/kuniqueservice.cpp ../kleopatra_debug.cpp kwatchgnupgmainwin.cpp kwatchgnupgconfig.cpp aboutdata.cpp tray.cpp main.cpp ) ecm_qt_declare_logging_category(kwatchgnupg_SRCS HEADER kwatchgnupg_debug.h IDENTIFIER KWATCHGNUPG_LOG CATEGORY_NAME org.kde.pim.kwatchgnupg) qt5_add_resources(kwatchgnupg_SRCS kwatchgnupg.qrc) if(WIN32) set(kwatchgnupg_SRCS ${kwatchgnupg_SRCS} ../utils/gnupg-registry.c) endif() add_executable(kwatchgnupg ${kwatchgnupg_SRCS}) target_link_libraries(kwatchgnupg KF5::DBusAddons KF5::XmlGui KF5::Notifications KF5::TextWidgets KF5::IconThemes KF5::Libkleo KF5::Crash ) install(TARGETS kwatchgnupg ${KDE_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES images/kwatchgnupg.png images/kwatchgnupg2.png DESTINATION ${KDE_INSTALL_DATADIR}/kwatchgnupg/pics) diff --git a/src/kwatchgnupg/kdlogtextwidget.cpp b/src/kwatchgnupg/kdlogtextwidget.cpp deleted file mode 100644 index 23279ae71..000000000 --- a/src/kwatchgnupg/kdlogtextwidget.cpp +++ /dev/null @@ -1,645 +0,0 @@ -/**************************************************************************** -** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved. -** -** This file is part of the KD Tools library. -** -** Licensees holding valid commercial KD Tools licenses may use this file in -** accordance with the KD Tools Commercial License Agreement provided with -** the Software. -** -** -** This file may be distributed and/or modified under the terms of the -** GNU Lesser General Public License version 2 and version 3 as published by the -** Free Software Foundation and appearing in the file LICENSE.LGPL included. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** Contact info@kdab.com if any conditions of this licensing are not -** clear to you. -** -**********************************************************************/ - -#include - -#include "kdlogtextwidget.h" - -#include -#include -#include -#include -#include - -#include -#include - -/*! - \class KDLogTextWidget - \brief A high-speed text display widget. - - This widget provides very fast display of large amounts of - line-oriented text, as commonly found in application log - viewers. The feature set and implementation are optimized for - frequent appends. - - You can set initial text using setLines(), and append lines with - calls to message(). You can limit the number of lines kept in the - view using setHistorySize(). - - Text formatting is currently limited to per-line text color, but is - expected to be enhanced on client request in upcoming versions. You - can pass the color to use to calls to message(). -*/ - -class KDLogTextWidget::Private -{ - friend class ::KDLogTextWidget; - KDLogTextWidget *const q; -public: - explicit Private(KDLogTextWidget *qq); - ~Private(); - - void updateCache() const; - - void triggerTimer() - { - if (!timer.isActive()) { - timer.start(500, q); - } - } - - void addPendingLines(); - void enforceHistorySize(); - void updateScrollRanges(); - QPair visibleLines(int top, int bottom) - { - return qMakePair(qMax(0, lineByYCoordinate(top)), - qMax(0, 1 + lineByYCoordinate(bottom))); - } - int lineByYCoordinate(int x) const; - - QPoint scrollOffset() const; - - QRect lineRect(int idx) const - { - Q_ASSERT(!cache.dirty); - return QRect(0, idx * cache.fontMetrics.lineSpacing, cache.dimensions.longestLineLength, cache.fontMetrics.lineSpacing - 1); - } - - struct Style { - QColor color; - - friend inline uint qHash(const Style &style) - { - return qHash(style.color.rgba()); - } - bool operator==(const Style &other) const - { - return this->color.rgba() == other.color.rgba(); - } - bool operator<(const Style &other) const - { - return this->color.rgba() < other.color.rgba(); - } - }; - - struct LineItem { - QString text; - unsigned int styleID; - }; - - unsigned int findOrAddStyle(const Style &style); - -private: - QHash styleByID; - QHash idByStyle; - - QVector lines, pendingLines; - - unsigned int historySize; - unsigned int minimumVisibleLines; - unsigned int minimumVisibleColumns; - - bool alternatingRowColors; - - QBasicTimer timer; - - mutable struct Cache { - enum { Dimensions = 1, FontMetrics = 2, All = FontMetrics | Dimensions }; - Cache() : dirty(All) {} - int dirty; - - struct { - int lineSpacing; - int ascent; - int averageCharWidth; - QVector lineWidths; - } fontMetrics; - - struct { - int indexOfLongestLine; - int longestLineLength; - } dimensions; - } cache; -}; - -/*! - Constructor. Creates an empty KDLogTextWidget. -*/ -KDLogTextWidget::KDLogTextWidget(QWidget *parent_) - : QAbstractScrollArea(parent_), d(new Private(this)) -{ - -} - -/*! - Destructor. -*/ -KDLogTextWidget::~KDLogTextWidget() {} - -/*! - \property KDLogTextWidget::historySize - - Specifies the maximum number of lines this widget will hold before - dropping old lines. The default is INT_MAX (ie. essentially unlimited). - - Get this property's value using %historySize(), and set it with - %setHistorySize(). -*/ -void KDLogTextWidget::setHistorySize(unsigned int hs) -{ - if (hs == d->historySize) { - return; - } - d->historySize = hs; - d->enforceHistorySize(); - d->updateScrollRanges(); - viewport()->update(); -} - -unsigned int KDLogTextWidget::historySize() const -{ - return d->historySize; -} - -/*! - \property KDLogTextWidget::text - - Contains the current %text as a single string. Equivalent to - \code - lines().join( "\n" ) - \endcode -*/ -QString KDLogTextWidget::text() const -{ - return lines().join(QLatin1Char('\n')); -} - -/*! - \property KDLogTextWidget::lines - - Contains the current %text as a string list. The default empty. - - Get this property's value using %lines(), and set it with - %setLines(). -*/ -void KDLogTextWidget::setLines(const QStringList &l) -{ - clear(); - for (const QString &s : l) { - message(s); - } -} - -QStringList KDLogTextWidget::lines() const -{ - QStringList result; - Q_FOREACH (const Private::LineItem &li, d->lines) { - result.push_back(li.text); - } - Q_FOREACH (const Private::LineItem &li, d->pendingLines) { - result.push_back(li.text); - } - return result; -} - -/*! - \property KDLogTextWidget::minimumVisibleLines - - Specifies the number of lines that should be visible at any one - time. The default is 1 (one). - - Get this property's value using %minimumVisibleLines(), and set it - using %setMinimumVisibleLines(). -*/ -void KDLogTextWidget::setMinimumVisibleLines(unsigned int num) -{ - if (num == d->minimumVisibleLines) { - return; - } - d->minimumVisibleLines = num; - updateGeometry(); -} - -unsigned int KDLogTextWidget::minimumVisibleLines() const -{ - return d->minimumVisibleLines; -} - -/*! - \property KDLogTextWidget::minimumVisibleColumns - - Specifies the number of columns that should be visible at any one - time. The default is 1 (one). The width is calculated using - QFontMetrics::averageCharWidth(), if that is available. Otherwise, - the width of \c M is used. - - Get this property's value using %minimumVisibleColumns(), and set it - using %setMinimumVisibleColumns(). -*/ -void KDLogTextWidget::setMinimumVisibleColumns(unsigned int num) -{ - if (num == d->minimumVisibleColumns) { - return; - } - d->minimumVisibleColumns = num; - updateGeometry(); -} - -unsigned int KDLogTextWidget::minimumVisibleColumns() const -{ - return d->minimumVisibleColumns; -} - -/*! - \property KDLogTextWidget::alternatingRowColors - - Specifies whether the background should be drawn using - row-alternating colors. The default is \c false. - - Get this property's value using %alternatingRowColors(), and set it - using %setAlternatingRowColors(). -*/ -void KDLogTextWidget::setAlternatingRowColors(bool on) -{ - if (on == d->alternatingRowColors) { - return; - } - d->alternatingRowColors = on; - update(); -} - -bool KDLogTextWidget::alternatingRowColors() const -{ - return d->alternatingRowColors; -} - -QSize KDLogTextWidget::minimumSizeHint() const -{ - d->updateCache(); - const QSize base = QAbstractScrollArea::minimumSizeHint(); - const QSize view(d->minimumVisibleColumns * d->cache.fontMetrics.averageCharWidth, - d->minimumVisibleLines * d->cache.fontMetrics.lineSpacing); - const QSize scrollbars(verticalScrollBar() ? verticalScrollBar()->minimumSizeHint().width() : 0, - horizontalScrollBar() ? horizontalScrollBar()->minimumSizeHint().height() : 0); - return base + view + scrollbars; -} - -QSize KDLogTextWidget::sizeHint() const -{ - if (d->minimumVisibleLines > 1 || d->minimumVisibleColumns > 1) { - return minimumSizeHint(); - } else { - return 2 * minimumSizeHint(); - } -} - -/*! - Clears the text. - - \post lines().empty() == true -*/ -void KDLogTextWidget::clear() -{ - d->timer.stop(); - d->lines.clear(); - d->pendingLines.clear(); - d->styleByID.clear(); - d->idByStyle.clear(); - d->cache.dirty = Private::Cache::All; - viewport()->update(); -} - -/*! - Appends \a str to the view, highlighting the line in \a color. - - \post lines().back() == str (modulo trailing whitespace and contained newlines) -*/ -void KDLogTextWidget::message(const QString &str, const QColor &color) -{ - const Private::Style s = { color }; - const Private::LineItem li = { str, d->findOrAddStyle(s) }; - d->pendingLines.push_back(li); - d->triggerTimer(); -} - -/*! - \overload - - Uses the default text color set in this widget's palette. -*/ -void KDLogTextWidget::message(const QString &str) -{ - const Private::LineItem li = { str, 0 }; - d->pendingLines.push_back(li); - d->triggerTimer(); -} - -void KDLogTextWidget::paintEvent(QPaintEvent *e) -{ - - d->updateCache(); - - QPainter p(viewport()); - - p.translate(-d->scrollOffset()); - - const QRect visible = p.matrix().inverted().mapRect(e->rect()); - - const QPair visibleLines - = d->visibleLines(visible.top(), visible.bottom()); - - Q_ASSERT(visibleLines.first <= visibleLines.second); - - const Private::Style defaultStyle = { p.pen().color() }; - - const Private::Cache &cache = d->cache; - - p.setPen(Qt::NoPen); - - p.setBrush(palette().base()); - - if (d->alternatingRowColors) { - - p.drawRect(visible); - -#if 0 // leaves garbage - for (unsigned int i = visibleLines.first % 2 ? visibleLines.first + 1 : visibleLines.first, end = visibleLines.second; i < end; i += 2) { - p.drawRect(d->lineRect(i)); - } - - if (visibleLines.second >= 0) { - const int lastY = d->lineRect(visibleLines.second - 1).y(); - if (lastY < visible.bottom()) { - p.drawRect(0, lastY + 1, cache.dimensions.longestLineLength, visible.bottom() - lastY); - } - } -#endif - - p.setBrush(palette().alternateBase()); - for (int i = (visibleLines.first % 2) ? visibleLines.first : visibleLines.first + 1, end = visibleLines.second; i < end; i += 2) { - p.drawRect(d->lineRect(i)); - } - - } else { - - p.drawRect(visible); - - } - - // ### unused optimization: paint lines by styles to minimise pen changes. - for (int i = visibleLines.first, end = visibleLines.second; i != end; ++i) { - const Private::LineItem &li = d->lines[i]; - Q_ASSERT(!li.styleID || d->styleByID.contains(li.styleID)); - const Private::Style &st = li.styleID ? d->styleByID[li.styleID] : defaultStyle; - - p.setPen(st.color); - p.drawText(0, i * cache.fontMetrics.lineSpacing + cache.fontMetrics.ascent, li.text); - } - -} - -void KDLogTextWidget::timerEvent(QTimerEvent *e) -{ - if (e->timerId() == d->timer.timerId()) { - d->addPendingLines(); - d->timer.stop(); - } else { - QAbstractScrollArea::timerEvent(e); - } -} - -void KDLogTextWidget::changeEvent(QEvent *e) -{ - QAbstractScrollArea::changeEvent(e); - d->cache.dirty |= Private::Cache::FontMetrics; -} - -void KDLogTextWidget::resizeEvent(QResizeEvent *) -{ - d->updateScrollRanges(); -} - -KDLogTextWidget::Private::Private(KDLogTextWidget *qq) - : q(qq), - styleByID(), - idByStyle(), - lines(), - pendingLines(), - historySize(0xFFFFFFFF), - minimumVisibleLines(1), - minimumVisibleColumns(1), - alternatingRowColors(false), - timer(), - cache() -{ - // PENDING(marc) find all the magic flags we need here... - QWidget *const vp = qq->viewport(); - vp->setBackgroundRole(QPalette::Base); - vp->setAttribute(Qt::WA_StaticContents); - vp->setAttribute(Qt::WA_NoSystemBackground); -#ifndef QT_NO_CURSOR - vp->setCursor(Qt::IBeamCursor); -#endif -} - -KDLogTextWidget::Private::~Private() {} - -void KDLogTextWidget::Private::updateCache() const -{ - - if (cache.dirty >= Cache::FontMetrics) { - const QFontMetrics &fm = q->fontMetrics(); - cache.fontMetrics.lineSpacing = fm.lineSpacing(); - cache.fontMetrics.ascent = fm.ascent(); - cache.fontMetrics.averageCharWidth = fm.averageCharWidth(); - - QVector &lw = cache.fontMetrics.lineWidths; - lw.clear(); - lw.reserve(lines.size()); - Q_FOREACH (const LineItem &li, lines) { - lw.push_back(fm.boundingRect(li.text).width()); - } - } - - if (cache.dirty >= Cache::Dimensions) { - const QVector &lw = cache.fontMetrics.lineWidths; - const QVector::const_iterator it = - std::max_element(lw.begin(), lw.end()); - if (it == lw.end()) { - cache.dimensions.indexOfLongestLine = -1; - cache.dimensions.longestLineLength = 0; - } else { - cache.dimensions.indexOfLongestLine = it - lw.begin(); - cache.dimensions.longestLineLength = *it; - } - } - - cache.dirty = false; -} - -unsigned int KDLogTextWidget::Private::findOrAddStyle(const Style &s) -{ - if (idByStyle.contains(s)) { - const unsigned int id = idByStyle[s]; - Q_ASSERT(styleByID.contains(id)); - Q_ASSERT(styleByID[id] == s); - return id; - } else { - static unsigned int nextID = 0; // remember, 0 is reserved - const unsigned int id = ++nextID; - idByStyle.insert(s, id); - styleByID.insert(id, s); - return id; - } -} - -void KDLogTextWidget::Private::enforceHistorySize() -{ - const size_t numLimes = lines.size(); - if (numLimes <= historySize) { - return; - } - const int remove = numLimes - historySize; - lines.erase(lines.begin(), lines.begin() + remove); - - // can't quickly update the dimensions if the fontMetrics aren't uptodate. - if (cache.dirty & Cache::FontMetrics) { - cache.dirty |= Cache::Dimensions; - return; - } - - QVector &lw = cache.fontMetrics.lineWidths; - - Q_ASSERT(lw.size() > remove); - lw.erase(lw.begin(), lw.begin() + remove); - - if (cache.dirty & Cache::Dimensions) { - return; - } - - if (cache.dimensions.indexOfLongestLine >= remove) { - cache.dimensions.indexOfLongestLine -= remove; - } else { - cache.dirty |= Cache::Dimensions; - } -} - -static void set_scrollbar_properties(QScrollBar &sb, int document, int viewport, int singleStep, Qt::Orientation o) -{ - const int min = 0; - const int max = std::max(0, document - viewport); - const int value = sb.value(); - const bool wasAtEnd = value == sb.maximum(); - sb.setRange(min, max); - sb.setPageStep(viewport); - sb.setSingleStep(singleStep); - sb.setValue(o == Qt::Vertical && wasAtEnd ? sb.maximum() : value); -} - -void KDLogTextWidget::Private::updateScrollRanges() -{ - - updateCache(); - - if (QScrollBar *const sb = q->verticalScrollBar()) { - const int document = lines.size() * cache.fontMetrics.lineSpacing; - const int viewport = q->viewport()->height(); - const int singleStep = cache.fontMetrics.lineSpacing; - set_scrollbar_properties(*sb, document, viewport, singleStep, Qt::Vertical); - } - - if (QScrollBar *const sb = q->horizontalScrollBar()) { - const int document = cache.dimensions.longestLineLength; - const int viewport = q->viewport()->width(); - const int singleStep = cache.fontMetrics.lineSpacing; // rather randomly chosen - set_scrollbar_properties(*sb, document, viewport, singleStep, Qt::Horizontal); - } -} - -void KDLogTextWidget::Private::addPendingLines() -{ - if (pendingLines.empty()) { - return; - } - - const int oldNumLines = lines.size(); - - lines += pendingLines; - - // if the cache isn't dirty, we can quickly update it without - // invalidation: - - if (!cache.dirty) { - - // update fontMetrics: - const QFontMetrics &fm = q->fontMetrics(); - QVector plw; - plw.reserve(pendingLines.size()); - Q_FOREACH (const LineItem &li, pendingLines) { - plw.push_back(fm.boundingRect(li.text).width()); - } - - // update dimensions: - const QVector::const_iterator it = - std::max_element(plw.constBegin(), plw.constEnd()); - if (*it >= cache.dimensions.longestLineLength) { - cache.dimensions.longestLineLength = *it; - cache.dimensions.indexOfLongestLine = oldNumLines + (it - plw.constBegin()); - } - } - - pendingLines.clear(); - - enforceHistorySize(); - updateScrollRanges(); - q->viewport()->update(); -} - -int KDLogTextWidget::Private::lineByYCoordinate(int y) const -{ - updateCache(); - if (cache.fontMetrics.lineSpacing == 0) { - return -1; - } - const int raw = y / cache.fontMetrics.lineSpacing; - if (raw < 0) { - return -1; - } - if (raw >= lines.size()) { - return lines.size() - 1; - } - return raw; -} - -static int get_scrollbar_offset(const QScrollBar *sb) -{ - return sb ? sb->value() : 0; -} - -QPoint KDLogTextWidget::Private::scrollOffset() const -{ - return QPoint(get_scrollbar_offset(q->horizontalScrollBar()), - get_scrollbar_offset(q->verticalScrollBar())); -} - diff --git a/src/kwatchgnupg/kdlogtextwidget.h b/src/kwatchgnupg/kdlogtextwidget.h deleted file mode 100644 index 251d73b8e..000000000 --- a/src/kwatchgnupg/kdlogtextwidget.h +++ /dev/null @@ -1,85 +0,0 @@ -/**************************************************************************** -** Copyright (C) 2001-2010 Klaralvdalens Datakonsult AB. All rights reserved. -** -** This file is part of the KD Tools library. -** -** Licensees holding valid commercial KD Tools licenses may use this file in -** accordance with the KD Tools Commercial License Agreement provided with -** the Software. -** -** -** This file may be distributed and/or modified under the terms of the -** GNU Lesser General Public License version 2 and version 3 as published by the -** Free Software Foundation and appearing in the file LICENSE.LGPL included. -** -** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -** -** Contact info@kdab.com if any conditions of this licensing are not -** clear to you. -** -**********************************************************************/ - -#ifndef __KDTOOLSGUI_KDLOGTEXTWIDGET_H__ -#define __KDTOOLSGUI_KDLOGTEXTWIDGET_H__ - -#include -#include -#include - -class QString; -class QStringList; -class QColor; - -class KDLogTextWidget : public QAbstractScrollArea -{ - Q_OBJECT - Q_PROPERTY(uint historySize READ historySize WRITE setHistorySize) - Q_PROPERTY(QString text READ text) - Q_PROPERTY(QStringList lines READ lines WRITE setLines) - Q_PROPERTY(uint minimumVisibleLines READ minimumVisibleLines WRITE setMinimumVisibleLines) - Q_PROPERTY(uint minimumVisibleColumns READ minimumVisibleColumns WRITE setMinimumVisibleColumns) - Q_PROPERTY(bool alternatingRowColors READ alternatingRowColors WRITE setAlternatingRowColors) - Q_CLASSINFO("description", "High-speed text display widget") -public: - explicit KDLogTextWidget(QWidget *parent = nullptr); - ~KDLogTextWidget() override; - - void setHistorySize(unsigned int size); - unsigned int historySize() const; - - QString text() const; - - void setLines(const QStringList &list); - QStringList lines() const; - - void setMinimumVisibleLines(unsigned int num); - unsigned int minimumVisibleLines() const; - - void setMinimumVisibleColumns(unsigned int num); - unsigned int minimumVisibleColumns() const; - - void setAlternatingRowColors(bool on); - bool alternatingRowColors() const; - - QSize minimumSizeHint() const override; - QSize sizeHint() const override; - -public Q_SLOTS: - void clear(); - void message(const QString &msg, const QColor &color); - void message(const QString &msg); - -protected: - void paintEvent(QPaintEvent *) override; - void timerEvent(QTimerEvent *) override; - void resizeEvent(QResizeEvent *) override; - void changeEvent(QEvent *) override; - -private: - class Private; - kdtools::pimpl_ptr d; -}; - -#endif /* __KDTOOLSGUI_KDLOGTEXTWIDGET_H__ */ - diff --git a/src/kwatchgnupg/kwatchgnupgmainwin.cpp b/src/kwatchgnupg/kwatchgnupgmainwin.cpp index b483aac79..ed524c932 100644 --- a/src/kwatchgnupg/kwatchgnupgmainwin.cpp +++ b/src/kwatchgnupg/kwatchgnupgmainwin.cpp @@ -1,284 +1,288 @@ /* kwatchgnupgmainwin.cpp This file is part of Kleopatra, the KDE keymanager Copyright (c) 2001,2002,2004 Klar�vdalens Datakonsult AB Kleopatra 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) any later version. Kleopatra 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In addition, as a special exception, the copyright holders give permission to link the code of this program with any edition of the Qt library by Trolltech AS, Norway (or with modified versions of Qt that use the same license as Qt), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than Qt. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ #include #include "kwatchgnupgmainwin.h" #include "kwatchgnupgconfig.h" #include "kwatchgnupg.h" #include "tray.h" #include #include -#include "kdlogtextwidget.h" +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include KWatchGnuPGMainWindow::KWatchGnuPGMainWindow(QWidget *parent) : KXmlGuiWindow(parent, Qt::Window), mConfig(nullptr) { createActions(); createGUI(); - mCentralWidget = new KDLogTextWidget(this); - KDAB_SET_OBJECT_NAME(mCentralWidget); + mCentralWidget = new QTextEdit(this); + mCentralWidget->setReadOnly(true); setCentralWidget(mCentralWidget); mWatcher = new KProcess; connect(mWatcher, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotWatcherExited(int,QProcess::ExitStatus))); connect(mWatcher, &QProcess::readyReadStandardOutput, this, &KWatchGnuPGMainWindow::slotReadStdout); slotReadConfig(); mSysTray = new KWatchGnuPGTray(this); QAction *act = mSysTray->action(QStringLiteral("quit")); if (act) { connect(act, &QAction::triggered, this, &KWatchGnuPGMainWindow::slotQuit); } setAutoSaveSettings(); } KWatchGnuPGMainWindow::~KWatchGnuPGMainWindow() { delete mWatcher; } void KWatchGnuPGMainWindow::slotClear() { mCentralWidget->clear(); - mCentralWidget->message(i18n("[%1] Log cleared", QDateTime::currentDateTime().toString(Qt::ISODate))); + mCentralWidget->append(i18n("[%1] Log cleared", QDateTime::currentDateTime().toString(Qt::ISODate))); } void KWatchGnuPGMainWindow::createActions() { QAction *action = actionCollection()->addAction(QStringLiteral("clear_log")); action->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history"))); action->setText(i18n("C&lear History")); connect(action, &QAction::triggered, this, &KWatchGnuPGMainWindow::slotClear); actionCollection()->setDefaultShortcut(action, QKeySequence(Qt::CTRL + Qt::Key_L)); (void)KStandardAction::saveAs(this, SLOT(slotSaveAs()), actionCollection()); (void)KStandardAction::close(this, SLOT(close()), actionCollection()); (void)KStandardAction::quit(this, SLOT(slotQuit()), actionCollection()); (void)KStandardAction::preferences(this, SLOT(slotConfigure()), actionCollection()); (void)KStandardAction::keyBindings(this, SLOT(configureShortcuts()), actionCollection()); (void)KStandardAction::configureToolbars(this, SLOT(slotConfigureToolbars()), actionCollection()); } void KWatchGnuPGMainWindow::configureShortcuts() { KShortcutsDialog::configure(actionCollection(), KShortcutsEditor::LetterShortcutsAllowed, this); } void KWatchGnuPGMainWindow::slotConfigureToolbars() { KEditToolBar dlg(factory()); dlg.exec(); } void KWatchGnuPGMainWindow::startWatcher() { disconnect(mWatcher, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotWatcherExited(int,QProcess::ExitStatus))); if (mWatcher->state() == QProcess::Running) { mWatcher->kill(); while (mWatcher->state() == QProcess::Running) { qApp->processEvents(QEventLoop::ExcludeUserInputEvents); } - mCentralWidget->message(i18n("[%1] Log stopped", QDateTime::currentDateTime().toString(Qt::ISODate))); + mCentralWidget->append(i18n("[%1] Log stopped", QDateTime::currentDateTime().toString(Qt::ISODate))); + mCentralWidget->ensureCursorVisible(); } mWatcher->clearProgram(); { const KConfigGroup config(KSharedConfig::openConfig(), "WatchGnuPG"); *mWatcher << config.readEntry("Executable", WATCHGNUPGBINARY); *mWatcher << QStringLiteral("--force"); *mWatcher << config.readEntry("Socket", WATCHGNUPGSOCKET); } mWatcher->setOutputChannelMode(KProcess::OnlyStdoutChannel); mWatcher->start(); const bool ok = mWatcher->waitForStarted(); if (!ok) { KMessageBox::sorry(this, i18n("The watchgnupg logging process could not be started.\nPlease install watchgnupg somewhere in your $PATH.\nThis log window is unable to display any useful information.")); } else { - mCentralWidget->message(i18n("[%1] Log started", QDateTime::currentDateTime().toString(Qt::ISODate))); + mCentralWidget->append(i18n("[%1] Log started", QDateTime::currentDateTime().toString(Qt::ISODate))); + mCentralWidget->ensureCursorVisible(); } connect(mWatcher, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotWatcherExited(int,QProcess::ExitStatus))); } void KWatchGnuPGMainWindow::setGnuPGConfig() { QStringList logclients; // Get config object QGpgME::CryptoConfig *cconfig = QGpgME::cryptoConfig(); if (!cconfig) { return; } //Q_ASSERT( cconfig ); KConfigGroup config(KSharedConfig::openConfig(), "WatchGnuPG"); const QStringList comps = cconfig->componentList(); for (QStringList::const_iterator it = comps.constBegin(); it != comps.constEnd(); ++it) { QGpgME::CryptoConfigComponent *comp = cconfig->component(*it); Q_ASSERT(comp); // Look for log-file entry in Debug group QGpgME::CryptoConfigGroup *group = comp->group(QStringLiteral("Debug")); if (group) { QGpgME::CryptoConfigEntry *entry = group->entry(QStringLiteral("log-file")); if (entry) { entry->setStringValue(QLatin1String("socket://") + config.readEntry("Socket", WATCHGNUPGSOCKET)); logclients << QStringLiteral("%1 (%2)").arg(*it, comp->description()); } entry = group->entry(QStringLiteral("debug-level")); if (entry) { entry->setStringValue(config.readEntry("LogLevel", "basic")); } } } cconfig->sync(true); if (logclients.isEmpty()) { KMessageBox::sorry(nullptr, i18n("There are no components available that support logging.")); } } void KWatchGnuPGMainWindow::slotWatcherExited(int, QProcess::ExitStatus) { if (KMessageBox::questionYesNo(this, i18n("The watchgnupg logging process died.\nDo you want to try to restart it?"), QString(), KGuiItem(i18n("Try Restart")), KGuiItem(i18n("Do Not Try"))) == KMessageBox::Yes) { - mCentralWidget->message(i18n("====== Restarting logging process =====")); + mCentralWidget->append(i18n("====== Restarting logging process =====")); + mCentralWidget->ensureCursorVisible(); startWatcher(); } else { KMessageBox::sorry(this, i18n("The watchgnupg logging process is not running.\nThis log window is unable to display any useful information.")); } } void KWatchGnuPGMainWindow::slotReadStdout() { if (!mWatcher) { return; } while (mWatcher->canReadLine()) { QString str = QString::fromUtf8(mWatcher->readLine()); if (str.endsWith(QLatin1Char('\n'))) { str.chop(1); } if (str.endsWith(QLatin1Char('\r'))) { str.chop(1); } - mCentralWidget->message(str); + mCentralWidget->append(str); + mCentralWidget->ensureCursorVisible(); if (!isVisible()) { // Change tray icon to show something happened // PENDING(steffen) mSysTray->setAttention(true); } } } void KWatchGnuPGMainWindow::show() { mSysTray->setAttention(false); KMainWindow::show(); } void KWatchGnuPGMainWindow::slotSaveAs() { const QString filename = QFileDialog::getSaveFileName(this, i18n("Save Log to File")); if (filename.isEmpty()) { return; } QFile file(filename); if (file.open(QIODevice::WriteOnly)) { - QTextStream(&file) << mCentralWidget->text(); + QTextStream(&file) << mCentralWidget->document()->toRawText(); } else KMessageBox::information(this, i18n("Could not save file %1: %2", filename, file.errorString())); } void KWatchGnuPGMainWindow::slotQuit() { disconnect(mWatcher, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotWatcherExited(int,QProcess::ExitStatus))); mWatcher->kill(); qApp->quit(); } void KWatchGnuPGMainWindow::slotConfigure() { if (!mConfig) { mConfig = new KWatchGnuPGConfig(this); mConfig->setObjectName(QStringLiteral("config dialog")); connect(mConfig, &KWatchGnuPGConfig::reconfigure, this, &KWatchGnuPGMainWindow::slotReadConfig); } mConfig->loadConfig(); mConfig->exec(); } void KWatchGnuPGMainWindow::slotReadConfig() { const KConfigGroup config(KSharedConfig::openConfig(), "LogWindow"); const int maxLogLen = config.readEntry("MaxLogLen", 10000); - mCentralWidget->setHistorySize(maxLogLen < 1 ? -1 : maxLogLen); + mCentralWidget->document()->setMaximumBlockCount(maxLogLen < 1 ? -1 : maxLogLen); setGnuPGConfig(); startWatcher(); } bool KWatchGnuPGMainWindow::queryClose() { if (!qApp->isSavingSession()) { hide(); return false; } return KMainWindow::queryClose(); } diff --git a/src/kwatchgnupg/kwatchgnupgmainwin.h b/src/kwatchgnupg/kwatchgnupgmainwin.h index 9f62d48fb..2226f017b 100644 --- a/src/kwatchgnupg/kwatchgnupgmainwin.h +++ b/src/kwatchgnupg/kwatchgnupgmainwin.h @@ -1,83 +1,83 @@ /* main.cpp This file is part of Kleopatra, the KDE keymanager Copyright (c) 2001,2002,2004 Klarälvdalens Datakonsult AB Kleopatra 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) any later version. Kleopatra 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, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA In addition, as a special exception, the copyright holders give permission to link the code of this program with any edition of the Qt library by Trolltech AS, Norway (or with modified versions of Qt that use the same license as Qt), and distribute linked combinations including the two. You must obey the GNU General Public License in all respects for all of the code used other than Qt. If you modify this file, you may extend this exception to your version of the file, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. */ #ifndef KWATCHGNUPGMAINWIN_H #define KWATCHGNUPGMAINWIN_H #include #include class KWatchGnuPGTray; class KWatchGnuPGConfig; class KProcess; -class KDLogTextWidget; +class QTextEdit; class KWatchGnuPGMainWindow : public KXmlGuiWindow { Q_OBJECT public: explicit KWatchGnuPGMainWindow(QWidget *parent = nullptr); ~KWatchGnuPGMainWindow(); private Q_SLOTS: void slotWatcherExited(int, QProcess::ExitStatus); void slotReadStdout(); void slotSaveAs(); void slotQuit(); void slotClear(); void slotConfigure(); void slotConfigureToolbars(); void configureShortcuts(); void slotReadConfig(); public Q_SLOTS: /* reimp */ void show(); protected: bool queryClose() override; private: void createActions(); void startWatcher(); void setGnuPGConfig(); KProcess *mWatcher; - KDLogTextWidget *mCentralWidget; + QTextEdit *mCentralWidget; KWatchGnuPGTray *mSysTray; KWatchGnuPGConfig *mConfig; }; #endif /* KWATCHGNUPGMAINWIN_H */