Index: addons/katebuild-plugin/CMakeLists.txt
===================================================================
--- addons/katebuild-plugin/CMakeLists.txt
+++ addons/katebuild-plugin/CMakeLists.txt
@@ -9,7 +9,7 @@
SelectTargetView.cpp
)
-ki18n_wrap_ui(katebuild_SRCS build.ui SelectTargetUi.ui)
+ki18n_wrap_ui(katebuild_SRCS build.ui SelectTargetUi.ui katebuild_config_page.ui)
# resource for ui file and stuff
qt5_add_resources(katebuild_SRCS plugin.qrc)
Index: addons/katebuild-plugin/katebuild_config_page.ui
===================================================================
--- /dev/null
+++ addons/katebuild-plugin/katebuild_config_page.ui
@@ -0,0 +1,70 @@
+
+
+ ConfigPage
+
+
+
+ 0
+ 0
+ 688
+ 428
+
+
+
+ Form
+
+
+ -
+
+
+ Behavior
+
+
+
-
+
+
+ <html><head/><body><p>Where possible will tool tips replaced by "What's This?" help, also on this page but not immediately. You know? To activate this help mode try Shift-F1</p><p>The main intention was to have a way to get rid of the tool tips on the error list.</p></body></html>
+
+
+ Avoid tool tips
+
+
+
+ -
+
+
+ <html><head/><body><p>Will hide the view when the current build was successful but the previous build was not</p></body></html>
+
+
+ Obliging hide on successful build
+
+
+
+ -
+
+
+ Don't popup on build start
+
+
+
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 251
+
+
+
+
+
+
+
+
+
Index: addons/katebuild-plugin/plugin_katebuild.h
===================================================================
--- addons/katebuild-plugin/plugin_katebuild.h
+++ addons/katebuild-plugin/plugin_katebuild.h
@@ -29,19 +29,22 @@
#include
#include
#include
+#include
#include
#include
#include
#include
#include
#include
#include
+#include
#include
#include
#include "ui_build.h"
+#include "ui_katebuild_config_page.h"
#include "targets.h"
/******************************************************************/
@@ -76,6 +79,8 @@
// reimplemented: read and write session config
void readSessionConfig(const KConfigGroup& config) override;
void writeSessionConfig(KConfigGroup& config) override;
+ // The settings from the config page
+ void readConfig();
bool buildCurrentTarget();
@@ -130,7 +135,20 @@
bool checkLocal(const QUrl &dir);
void clearBuildResults();
- void displayBuildResult(const QString &message, KTextEditor::Message::MessageType level);
+ /**
+ * Display a user information on the current active view.
+ * @parm message the text to show
+ * @parm type the message type
+ * @parm autoHideDelay the time the message will be shown. When 0 is the
+ * delay set to a sane default, when -1 is auto hide disabled
+ * @parm updateOnly when true will an already shown message text updated
+ * to @p message and the parameter @p type and @p autoHideDelay
+ * will be ignored. Should there no old message exist will a new
+ * message created with respect of all arguments
+ *
+ * @see KTextEditor::message
+ */
+ void postMessage(const QString &message, KTextEditor::Message::MessageType type, int autoHideDelay = 0, bool updateOnly = false);
KTextEditor::MainWindow *m_win;
QWidget *m_toolView;
@@ -142,6 +160,8 @@
QString m_stdOut;
QString m_stdErr;
QString m_currentlyBuildingTarget;
+ int m_hideViewOnSuccess = 0; //!< Hide view when > 0
+ bool m_troubleOnLastRun = false; //!< Hide view when true
bool m_buildCancelled;
int m_displayModeBeforeBuild;
QString m_make_dir;
@@ -155,12 +175,13 @@
QString m_prevItemContent;
QModelIndex m_previousIndex;
QPointer m_infoMessage;
-
-
- /**
- * current project plugin view, if any
- */
+ QTimer m_progressLimiter; //!< Single shot, as long running, don't update progess info
QObject *m_projectPluginView = nullptr;
+
+ // Config Page Settings
+ bool m_isSetAutoHide = false;
+ bool m_isSetNoToolTip = false;
+ bool m_isSetNoPopUp = false;
};
@@ -176,7 +197,43 @@
~KateBuildPlugin() override {}
QObject *createView(KTextEditor::MainWindow *mainWindow) override;
+ int configPages() const override;
+ KTextEditor::ConfigPage *configPage (int number = 0, QWidget *parent = nullptr) override;
+ void readConfig();
+
+private:
+ QVector m_views; // FIXME Only to track config page changes, do all this smarter!
};
+//BEGIN ConfigPage
+class KateBuildPluginConfigPage : public KTextEditor::ConfigPage
+ , private Ui::ConfigPage
+{
+ Q_OBJECT
+
+public:
+ explicit KateBuildPluginConfigPage(QWidget *parent, KateBuildPlugin *plugin);
+ ~KateBuildPluginConfigPage() override;
+
+ QString name() const override;
+ QString fullName() const override;
+ QIcon icon() const override;
+
+ void apply() override;
+ void reset() override { loadSettings(); }
+ void defaults() override { ; }
+
+ void loadSettings();
+
+private Q_SLOTS:
+ void modified();
+
+private:
+ bool m_modified = false;
+ KateBuildPlugin *m_plugin;
+
+};
+//END ConfigPage
+
#endif
Index: addons/katebuild-plugin/plugin_katebuild.cpp
===================================================================
--- addons/katebuild-plugin/plugin_katebuild.cpp
+++ addons/katebuild-plugin/plugin_katebuild.cpp
@@ -44,39 +44,70 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
#include
#include
-
#include "SelectTargetView.h"
+
K_PLUGIN_FACTORY_WITH_JSON (KateBuildPluginFactory, "katebuildplugin.json", registerPlugin();)
static const QString DefConfigCmd = QStringLiteral("cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/usr/local ../");
static const QString DefConfClean;
static const QString DefTargetName = QStringLiteral("all");
static const QString DefBuildCmd = QStringLiteral("make");
static const QString DefCleanCmd = QStringLiteral("make clean");
+static const bool OnlyUpdateMessageText = true;
+static const int NeverHide = 60 * 60 * 1000; // 1hour delay, quirk to avoid forced "Close" button
-/******************************************************************/
+//BEGIN KateBuildPlugin
KateBuildPlugin::KateBuildPlugin(QObject *parent, const VariantList&):
KTextEditor::Plugin(parent)
{
// KF5 FIXME KGlobal::locale()->insertCatalog("katebuild-plugin");
}
-/******************************************************************/
QObject *KateBuildPlugin::createView (KTextEditor::MainWindow *mainWindow)
{
- return new KateBuildView(this, mainWindow);
+ auto view = new KateBuildView(this, mainWindow);
+
+ m_views.append(view);
+
+ return view;
+}
+
+int KateBuildPlugin::configPages() const
+{
+ return 1;
+}
+
+KTextEditor::ConfigPage *KateBuildPlugin::configPage(int number, QWidget *parent)
+{
+ if (number != 0) {
+ return nullptr;
+ }
+
+ return new KateBuildPluginConfigPage(parent, this);
+}
+
+void KateBuildPlugin::readConfig()
+{
+ // Be aware that we can have more than one view!
+ for (int i = 0; i < m_views.size(); ++i) {
+ m_views.at(i)->readConfig();
+ }
}
+//END
+
/******************************************************************/
KateBuildView::KateBuildView(KTextEditor::Plugin *plugin, KTextEditor::MainWindow *mw)
: QObject (mw)
@@ -101,7 +132,7 @@
m_toolView = mw->createToolView(plugin, QStringLiteral("kate_plugin_katebuildplugin"),
KTextEditor::MainWindow::Bottom,
- QIcon::fromTheme(QStringLiteral("application-x-ms-dos-executable")),
+ QIcon::fromTheme(QStringLiteral("run-build")),
i18n("Build Output"));
QAction *a = actionCollection()->addAction(QStringLiteral("select_target"));
@@ -191,6 +222,10 @@
// Connect signals from project plugin to our slots
m_projectPluginView = m_win->pluginView(QStringLiteral("kateprojectplugin"));
slotPluginViewCreated(QStringLiteral("kateprojectplugin"), m_projectPluginView);
+
+ m_progressLimiter.setSingleShot(true);
+ m_progressLimiter.setInterval(100);
+ readConfig();
}
@@ -309,6 +344,13 @@
slotAddProjectTarget();
}
+void KateBuildView::readConfig()
+{
+ KConfigGroup config(KSharedConfig::openConfig(), "Build");
+ m_isSetAutoHide = config.readEntry("AutoHide", false);
+ m_isSetNoToolTip = config.readEntry("NoToolTips", false);
+ m_isSetNoPopUp = config.readEntry("NoPopUp", false);
+}
/******************************************************************/
void KateBuildView::slotNext()
@@ -446,9 +488,10 @@
// add tooltips in all columns
// The enclosing ... enables word-wrap for long error messages
- item->setData(0, Qt::ToolTipRole, filename);
- item->setData(1, Qt::ToolTipRole, QStringLiteral("%1").arg(message));
- item->setData(2, Qt::ToolTipRole, QStringLiteral("%1").arg(message));
+ const int role = m_isSetNoToolTip ? Qt::WhatsThisRole : Qt::ToolTipRole;
+ item->setData(0, role, filename);
+ item->setData(1, role, QStringLiteral("%1").arg(message));
+ item->setData(2, role, QStringLiteral("%1").arg(message));
}
/******************************************************************/
@@ -507,7 +550,10 @@
m_buildUi.u_tabWidget->setCurrentIndex(1);
m_displayModeBeforeBuild = m_buildUi.displayModeSlider->value();
m_buildUi.displayModeSlider->setValue(0);
- m_win->showToolView(m_toolView);
+
+ if (!m_isSetNoPopUp) {
+ m_win->showToolView(m_toolView);
+ }
// set working directory
m_make_dir = dir;
@@ -541,9 +587,6 @@
{
if (m_proc.state() != QProcess::NotRunning) {
m_buildCancelled = true;
- QString msg = i18n("Building %1 cancelled", m_currentlyBuildingTarget);
- m_buildUi.buildStatusLabel->setText(msg);
- m_buildUi.buildStatusLabel2->setText(msg);
m_proc.terminate();
return true;
}
@@ -576,6 +619,7 @@
void KateBuildView::slotBuildDefaultTarget() {
QModelIndex defaultTarget = m_targetsUi->targetsModel.defaultTarget(m_targetsUi->targetsView->currentIndex());
m_targetsUi->targetsView->setCurrentIndex(defaultTarget);
+ m_hideViewOnSuccess = 2;
buildCurrentTarget();
}
@@ -599,17 +643,18 @@
/******************************************************************/
bool KateBuildView::buildCurrentTarget()
{
- if (m_proc.state() != QProcess::NotRunning) {
- displayBuildResult(i18n("Already building..."), KTextEditor::Message::Warning);
- return false;
+ if (m_proc.state() == QProcess::Running) {
+ m_win->showToolView(m_toolView);
+ m_hideViewOnSuccess = 0;
+ return true;
}
QFileInfo docFInfo = docUrl().toLocalFile(); // docUrl() saves the current document
QModelIndex ind = m_targetsUi->targetsView->currentIndex();
m_previousIndex = ind;
if (!ind.isValid()) {
- KMessageBox::sorry(nullptr, i18n("No target available for building."));
+ postMessage(i18n("No target available for building."), KTextEditor::Message::Error);
return false;
}
@@ -622,7 +667,7 @@
if (workDir.isEmpty()) {
dir = docFInfo.absolutePath();
if (dir.isEmpty()) {
- KMessageBox::sorry(nullptr, i18n("There is no local file or directory specified for building."));
+ postMessage(i18n("There is no local file or directory specified for building."), KTextEditor::Message::Error);
return false;
}
}
@@ -641,29 +686,58 @@
buildCmd.replace(QStringLiteral("%f"), docFInfo.absoluteFilePath());
buildCmd.replace(QStringLiteral("%d"), docFInfo.absolutePath());
}
+
+ --m_hideViewOnSuccess;
m_filenameDetectorGccWorked = false;
m_currentlyBuildingTarget = QStringLiteral("%1: %2").arg(targetSet, cmdName);
m_buildCancelled = false;
QString msg = i18n("Building target %1 ...", m_currentlyBuildingTarget);
m_buildUi.buildStatusLabel->setText(msg);
m_buildUi.buildStatusLabel2->setText(msg);
+ postMessage(i18n("Building target..."), KTextEditor::Message::Information, NeverHide);
+
return startProcess(dir, buildCmd);
}
/******************************************************************/
-void KateBuildView::displayBuildResult(const QString &msg, KTextEditor::Message::MessageType level)
+void KateBuildView::postMessage(const QString &msg, KTextEditor::Message::MessageType type, int autoHideDelay/* = 0*/, bool updateOnly/* = false*/)
{
KTextEditor::View *kv = m_win->activeView();
if (!kv) return;
- delete m_infoMessage;
- m_infoMessage = new KTextEditor::Message(xi18nc("@info", "Make Results:%1", msg), level);
- m_infoMessage->setWordWrap(true);
- m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
- m_infoMessage->setAutoHide(5000);
- m_infoMessage->setAutoHideMode(KTextEditor::Message::Immediate);
- m_infoMessage->setView(kv);
- kv->document()->postMessage(m_infoMessage);
+ QString msgType;
+ switch (type) {
+ // TODO KF6 How about a function in KTextEditor::Message to get these translated message type names?
+ case KTextEditor::Message::Positive:
+ case KTextEditor::Message::Information:
+ msgType = i18n("Info");
+ break;
+ case KTextEditor::Message::Warning:
+ msgType = i18n("Warning");
+ break;
+ case KTextEditor::Message::Error:
+ msgType = i18n("Error");
+ break;
+ }
+
+ if (updateOnly && m_infoMessage) {
+ m_infoMessage->setText(xi18nc("@info", "Make %1%2", msgType, msg));
+
+ } else {
+ delete m_infoMessage;
+ // FIXME Add a minimum width to the message box, looks sometimes too titchy
+ // m_infoMessage->setMinimumWidth(123) will not work, it's only an QOject
+ // and attempts to add spaces failed. Update: Since we have the hourglass it looks much better
+ // FIXME Sometimes on the change "progress info"->"we are done" the "progress info"
+ // becomes the new size of "we are done" which cause an ungly line break. Ideas?
+ m_infoMessage = new KTextEditor::Message(xi18nc("@info", "Make %1%2", msgType, msg), type);
+ m_infoMessage->setWordWrap(true);
+ m_infoMessage->setPosition(KTextEditor::Message::BottomInView);
+ m_infoMessage->setAutoHide(autoHideDelay);
+ m_infoMessage->setAutoHideMode(KTextEditor::Message::Immediate);
+ m_infoMessage->setView(kv);
+ kv->document()->postMessage(m_infoMessage);
+ }
}
/******************************************************************/
@@ -691,7 +765,12 @@
m_win->showToolView(m_toolView);
}
- if (m_numErrors || m_numWarnings) {
+ if (m_buildCancelled) {
+ buildStatus = i18n("Building %1 cancelled", m_currentlyBuildingTarget);
+ postMessage(i18n("Build cancelled"), KTextEditor::Message::Information);
+
+ } else if (m_numErrors || m_numWarnings) {
+ m_troubleOnLastRun = true;
QStringList msgs;
if (m_numErrors) {
msgs << i18np("Found one error.", "Found %1 errors.", m_numErrors);
@@ -701,21 +780,22 @@
msgs << i18np("Found one warning.", "Found %1 warnings.", m_numWarnings);
buildStatus = i18n("Building %1 had warnings.", m_currentlyBuildingTarget);
}
- displayBuildResult(msgs.join(QLatin1Char('\n')), m_numErrors ? KTextEditor::Message::Error : KTextEditor::Message::Warning);
- }
- else if (exitCode != 0) {
- displayBuildResult(i18n("Build failed."), KTextEditor::Message::Warning);
- }
- else {
- displayBuildResult(i18n("Build completed without problems."), KTextEditor::Message::Positive);
- }
+ postMessage(msgs.join(QLatin1Char('\n')), m_numErrors ? KTextEditor::Message::Error : KTextEditor::Message::Warning);
- if (!m_buildCancelled) {
- m_buildUi.buildStatusLabel->setText(buildStatus);
- m_buildUi.buildStatusLabel2->setText(buildStatus);
- m_buildCancelled = false;
+ } else if (exitCode != 0) {
+ postMessage(i18n("Build failed."), KTextEditor::Message::Error);
+
+ } else {
+ postMessage(i18n("Build completed without problems."), KTextEditor::Message::Positive);
+ if (m_isSetAutoHide && (m_hideViewOnSuccess > 0) && m_troubleOnLastRun) {
+ m_win->hideToolView(m_toolView);
+ }
+ m_troubleOnLastRun = false;
}
+ m_buildUi.buildStatusLabel->setText(buildStatus);
+ m_buildUi.buildStatusLabel2->setText(buildStatus);
+ m_hideViewOnSuccess = 0;
}
@@ -729,6 +809,10 @@
l.remove(QLatin1Char('\r'));
m_stdOut += l;
+ QRegularExpression regExp = QRegularExpression(QStringLiteral("^\\[\\s*([\\d\\%]+)\\]"));
+ QString hourglass(QStringLiteral("--------------"));
+ static int hourglassIdx = -1;
+
// handle one line at a time
do {
const int end = m_stdOut.indexOf(QLatin1Char('\n'));
@@ -738,6 +822,15 @@
m_buildUi.plainTextEdit->appendPlainText(line);
//qDebug() << line;
+ QRegularExpressionMatch match = regExp.match(line);
+ if (match.hasMatch() && !m_progressLimiter.isActive()) {
+ m_progressLimiter.start();
+ hourglassIdx = (++hourglassIdx > hourglass.size() - 1) ? 0 : hourglassIdx;
+ hourglass.replace(hourglassIdx, 1, QLatin1Char('>'));
+ postMessage(i18n("Building target\n%1 %2 %1", hourglass, QStringLiteral("%1").arg(match.captured(1), 4, QLatin1Char(' ')))
+ , KTextEditor::Message::Information, NeverHide, OnlyUpdateMessageText);
+ }
+
if (m_newDirDetector.match(line).hasMatch()) {
//qDebug() << "Enter/Exit dir found";
int open = line.indexOf(QLatin1Char('`'));
@@ -1059,6 +1152,80 @@
}
}
+//BEGIN ConfigPage
+KateBuildPluginConfigPage::KateBuildPluginConfigPage(QWidget *parent, KateBuildPlugin *plugin)
+ : KTextEditor::ConfigPage(parent)
+ , m_plugin(plugin)
+{
+ setupUi(this);
+ loadSettings();
+
+ // FIXME Add observeChanges(..) to master class like in KateConfigPage, best may in KTextEditor::ConfigPage
+ connect(autoHide, &QAbstractButton::toggled, this, &KateBuildPluginConfigPage::modified);
+ connect(avoidPopUp, &QAbstractButton::toggled, this, &KateBuildPluginConfigPage::modified);
+ connect(avoidToolTips, &QAbstractButton::toggled, this, &KateBuildPluginConfigPage::modified);
+}
+
+KateBuildPluginConfigPage::~KateBuildPluginConfigPage()
+{}
+
+// FIXME Should be part of master class
+void KateBuildPluginConfigPage::modified()
+{
+ m_modified = true;
+ emit changed();
+}
+QString KateBuildPluginConfigPage::name() const
+{
+ return i18n("Build");
+}
+
+QString KateBuildPluginConfigPage::fullName() const
+{
+ return i18n("%1 Settings", name());
+}
+
+QIcon KateBuildPluginConfigPage::icon() const
+{
+ return QIcon::fromTheme(QStringLiteral("project_rebuild"));
+}
+
+void KateBuildPluginConfigPage::apply()
+{
+ if (!m_modified) {
+ return;
+ }
+
+ m_modified = false;
+
+ KConfigGroup config(KSharedConfig::openConfig(), "Build");
+
+ config.writeEntry("AutoHide", autoHide->isChecked());
+ config.writeEntry("NoPopUp", avoidPopUp->isChecked());
+ config.writeEntry("NoToolTips", avoidToolTips->isChecked());
+
+ config.sync();
+
+ m_plugin->readConfig();
+}
+
+void KateBuildPluginConfigPage::loadSettings()
+{
+ KConfigGroup config(KSharedConfig::openConfig(), "Build");
+
+ autoHide->setChecked(config.readEntry("AutoHide", false));
+ avoidPopUp->setChecked(config.readEntry("NoPopUp", false));
+ avoidToolTips->setChecked(config.readEntry("NoToolTips", false));
+
+ // In oposite to the statet WhatsThis help, we don't remove what's not there, but add :-)
+ if (!avoidToolTips->isChecked()) {
+ autoHide->setToolTip(autoHide->whatsThis());
+ avoidPopUp->setToolTip(avoidPopUp->whatsThis());
+ avoidToolTips->setToolTip(avoidToolTips->whatsThis());
+ }
+}
+
+//END ConfigPage
#include "plugin_katebuild.moc"