File indexing completed on 2024-05-12 05:26:19

0001 /*
0002  * Copyright (C) 2014 Aaron Seigo <aseigo@kde.org>
0003  *
0004  *   This program is free software; you can redistribute it and/or modify
0005  *   it under the terms of the GNU General Public License as published by
0006  *   the Free Software Foundation; either version 2 of the License, or
0007  *   (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *   GNU General Public License for more details.
0013  *
0014  *   You should have received a copy of the GNU General Public License
0015  *   along with this program; if not, write to the
0016  *   Free Software Foundation, Inc.,
0017  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
0018  */
0019 
0020 #include "state.h"
0021 
0022 #include <QCoreApplication>
0023 #include <QDebug>
0024 #include <QEventLoop>
0025 #include <QTextStream>
0026 
0027 #include "common/log.h"
0028 
0029 static bool s_hasEventLoop = false;
0030 
0031 class State::Private
0032 {
0033 public:
0034     Private() : outStream(stdout)
0035     {
0036     }
0037 
0038     QEventLoop *eventLoop()
0039     {
0040         if (!event) {
0041             event = new QEventLoop;
0042         }
0043 
0044         return event;
0045     }
0046 
0047     int debugLevel = 0;
0048     QEventLoop *event = 0;
0049     bool timing = false;
0050     QTextStream outStream;
0051     QList<QStringList> table;
0052 };
0053 
0054 State::State() : d(new Private)
0055 {
0056 }
0057 
0058 void State::print(const QString &message, unsigned int indentationLevel) const
0059 {
0060     for (unsigned int i = 0; i < indentationLevel; ++i) {
0061         d->outStream << "\t";
0062     }
0063 
0064     d->outStream << message;
0065 }
0066 
0067 void State::printLine(const QString &message, unsigned int indentationLevel) const
0068 {
0069     print(message, indentationLevel);
0070     d->outStream << "\n";
0071     d->outStream.flush();
0072 }
0073 
0074 void State::printError(const QString &errorMessage, const QString &errorCode) const
0075 {
0076     printLine("ERROR" + (errorCode.isEmpty() ? "" : " " + errorCode) + ": " + errorMessage);
0077 }
0078 
0079 void State::stageTableLine(const QStringList &line) const
0080 {
0081     d->table << line;
0082 }
0083 
0084 void State::printTable(const QList<QStringList> &table) const
0085 {
0086     //First let's find out the maximum size for each column depending on the content
0087     QVector<int> columnSizes;
0088     columnSizes.fill(0, 10);
0089     for (const auto &row : table) {
0090         for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) {
0091             if (columnSizes.size() <= columnIndex) {
0092                 columnSizes.append(0);
0093             }
0094             columnSizes[columnIndex] = qMax(columnSizes[columnIndex], row[columnIndex].size());
0095         }
0096     }
0097     //And now print the table
0098     for (const auto &row : table) {
0099         for (int columnIndex = 0; columnIndex < row.size(); columnIndex++) {
0100             if (columnIndex > 0) {
0101                 d->outStream << " | ";
0102             }
0103             d->outStream << row[columnIndex].leftJustified(columnSizes[columnIndex], ' ', true);
0104         }
0105         d->outStream << "\n";
0106     }
0107     d->outStream.flush();
0108 }
0109 
0110 void State::flushTable() const
0111 {
0112     printTable(d->table);
0113     d->table.clear();
0114 }
0115 
0116 void State::setDebugLevel(unsigned int level)
0117 {
0118     if (level < 7) {
0119         d->debugLevel = level;
0120     }
0121 }
0122 
0123 unsigned int State::debugLevel() const
0124 {
0125     return d->debugLevel;
0126 }
0127 
0128 int State::commandStarted() const
0129 {
0130     SinkTrace() << "Command started";
0131     if (!s_hasEventLoop) {
0132         return QCoreApplication::exec();
0133     } else if (!d->eventLoop()->isRunning()) {
0134         return d->eventLoop()->exec();
0135     }
0136 
0137     return 0;
0138 }
0139 
0140 void State::commandFinished(int returnCode) const
0141 {
0142     SinkTrace() << "Command finished. Exit code: " << returnCode;
0143     if (!s_hasEventLoop) {
0144         QCoreApplication::exit(returnCode);
0145     } else {
0146         d->eventLoop()->exit(returnCode);
0147     }
0148 }
0149 
0150 void State::setHasEventLoop(bool evented)
0151 {
0152     s_hasEventLoop = evented;
0153 }
0154 
0155 bool State::hasEventLoop()
0156 {
0157     return s_hasEventLoop;
0158 }
0159 
0160 void State::setCommandTiming(bool time)
0161 {
0162     d->timing = time;
0163 }
0164 
0165 bool State::commandTiming() const
0166 {
0167     return d->timing;
0168 }
0169 
0170 void State::setLoggingLevel(const QString &level) const
0171 {
0172     Sink::Log::setDebugOutputLevel(Sink::Log::debugLevelFromName(level.toLatin1()));
0173 }
0174 
0175 QString State::loggingLevel() const
0176 {
0177     // do not turn this into a single line return: that core dumps due to allocation of
0178     // the byte array in Sink::Log
0179     QByteArray rv = Sink::Log::debugLevelName(Sink::Log::debugOutputLevel());
0180     return rv.toLower();
0181 }