summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFriedrich W. H. Kossebau <[email protected]>2017-09-06 04:03:36 +0200
committerFriedrich W. H. Kossebau <[email protected]>2017-09-06 04:12:26 +0200
commit9c4a8eed4571849acb108d7bfe92a7974f8a9a0d (patch)
tree742dffef393ebc5288c4964130cf12c272e43cc8
parentf4d69f5d7343b7e013dc162f263eb3add4400015 (diff)
KUIViewer: show all widget types in-pane, using QMdiArea
fix also taking screenshots via commandline, by querying the part directly to deliver the pixmap, via a special private interface
-rw-r--r--kuiviewer/kuiviewer.cpp16
-rw-r--r--kuiviewer/kuiviewer_part.cpp116
-rw-r--r--kuiviewer/kuiviewer_part.h19
-rw-r--r--kuiviewer/kuiviewer_part_interface.h40
-rw-r--r--kuiviewer/main.cpp12
5 files changed, 164 insertions, 39 deletions
diff --git a/kuiviewer/kuiviewer.cpp b/kuiviewer/kuiviewer.cpp
index cf99275..22c671b 100644
--- a/kuiviewer/kuiviewer.cpp
+++ b/kuiviewer/kuiviewer.cpp
@@ -21,6 +21,7 @@
#include "kuiviewer.h"
#include "kuiviewer_part.h"
+#include "kuiviewer_part_interface.h"
// KF
#include <KActionCollection>
@@ -124,23 +125,16 @@ void KUIViewer::fileOpen()
void KUIViewer::takeScreenshot(const QString& filename, int w, int h)
{
- if (!m_part) {
+ auto uiviewerInterface = qobject_cast<KUIViewerPartInterface*>(m_part);
+ if (!uiviewerInterface) {
return;
}
- showMinimized();
-
if (w != -1 && h != -1) {
// resize widget to the desired size
- m_part->widget()->setMinimumSize(w, h);
- m_part->widget()->setMaximumSize(w, h);
- m_part->widget()->repaint();
- // resize app to be as large as desired size
- adjustSize();
- // Disable the saving of the size
- setAutoSaveSettings(QStringLiteral("MainWindow"), false);
+ uiviewerInterface->setWidgetSize(QSize(w, h));
}
- const QPixmap pixmap = m_part->widget()->grab();
+ const QPixmap pixmap = uiviewerInterface->renderWidgetAsPixmap();
pixmap.save(filename, "PNG");
}
diff --git a/kuiviewer/kuiviewer_part.cpp b/kuiviewer/kuiviewer_part.cpp
index 488d395..a5a20d9 100644
--- a/kuiviewer/kuiviewer_part.cpp
+++ b/kuiviewer/kuiviewer_part.cpp
@@ -2,6 +2,7 @@
* This file is part of the kuiviewer package
* Copyright (c) 2003 Richard Moore <[email protected]>
* Copyright (c) 2003 Ian Reinhart Geiser <[email protected]>
+ * Copyright (c) 2017 Friedrich W. H. Kossebau <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -41,7 +42,9 @@
#include <QFormBuilder>
#include <QStyle>
#include <QStyleFactory>
-#include <QVBoxLayout>
+#include <QScrollArea>
+#include <QMdiArea>
+#include <QMdiSubWindow>
K_PLUGIN_FACTORY(KUIViewerPartFactory, registerPlugin<KUIViewerPart>();)
@@ -50,6 +53,8 @@ KUIViewerPart::KUIViewerPart(QWidget* parentWidget,
QObject* parent,
const QVariantList& /*args*/)
: KParts::ReadOnlyPart(parent)
+ , m_subWindow(nullptr)
+ , m_view(nullptr)
{
// we need an instance
KAboutData about(QStringLiteral("kuiviewerpart"),
@@ -62,9 +67,9 @@ KUIViewerPart::KUIViewerPart(QWidget* parentWidget,
setComponentData(about);
// this should be your custom internal widget
- m_widget = new QWidget(parentWidget);
- QVBoxLayout* widgetVBoxLayout = new QVBoxLayout(m_widget);
- widgetVBoxLayout->setMargin(0);
+ m_widget = new QMdiArea(parentWidget);
+ m_widget->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ m_widget->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
// notify the part that this is our internal widget
setWidget(m_widget);
@@ -133,24 +138,56 @@ bool KUIViewerPart::openFile()
{
// m_file is always local so we can use QFile on it
QFile file(localFilePath());
- if (!file.open(QIODevice::ReadOnly)) {
+
+ if (!file.open(QIODevice::ReadOnly|QIODevice::Text)) {
+ qCDebug(KUIVIEWERPART) << "Could not open UI file: " << file.errorString();
return false;
}
- delete m_view;
+ if (m_subWindow) {
+ m_widget->removeSubWindow(m_subWindow);
+ delete m_view;
+ delete m_subWindow;
+ m_subWindow = nullptr;
+ }
+
QFormBuilder builder;
builder.setPluginPath(designerPluginPaths());
- m_view = builder.load(&file, m_widget);
+ m_view = builder.load(&file, nullptr);
- file.close();
updateActions();
if (!m_view) {
+ qCDebug(KUIVIEWERPART) << "Could not load UI file: " << builder.errorString();
return false;
}
- m_view->show();
- slotStyle(0);
+ // hack ahead:
+ // UI files have a size set for the widget they define. The QMdiSubWindow relies on sizeHint()
+ // during the show event though it seems, to calculate the initial window size, and then discards
+ // the widget size initially set from the builder in the following layout-ruled geometry update.
+ // Enforcing the initial size by manually setting it afterwards to the widget itself seems not possible,
+ // due to the layout government based on window size.
+ // To inject the initial widget size into the initial window geometry, as hack the min and max sizes are
+ // temporarily set to the wanted size and, once the window is shown, reset to their initial values.
+ const QSize widgetSize = m_view->size();
+ const QSize origWidgetMinimumSize = m_view->minimumSize();
+ const QSize origWidgetMaximumSize = m_view->maximumSize();
+ restyleView(m_style->currentText());
+ m_view->setMinimumSize(widgetSize);
+ m_view->setMaximumSize(widgetSize);
+
+ const Qt::WindowFlags windowFlags(Qt::SubWindow|Qt::CustomizeWindowHint|Qt::WindowTitleHint);
+ m_subWindow = m_widget->addSubWindow(m_view, windowFlags);
+ // prevent focus stealing by adding the window in disabled state
+ m_subWindow->setEnabled(false);
+ m_subWindow->show();
+ // and restore minimum size
+ m_view->setMinimumSize(origWidgetMinimumSize);
+ m_view->setMaximumSize(origWidgetMaximumSize);
+
+ m_widget->setActiveSubWindow(m_subWindow);
+ m_subWindow->setEnabled(true);
return true;
}
@@ -163,28 +200,59 @@ void KUIViewerPart::updateActions()
m_copy->setEnabled(hasView);
}
-void KUIViewerPart::slotStyle(int)
+void KUIViewerPart::restyleView(const QString& styleName)
+{
+ QStyle* style = QStyleFactory::create(styleName);
+
+ m_view->setStyle(style);
+
+ const QList<QWidget*> childWidgets = m_view->findChildren<QWidget*>();
+ for (auto child : childWidgets) {
+ child->setStyle(style);
+ }
+}
+
+void KUIViewerPart::setWidgetSize(const QSize& size)
{
if (m_view.isNull()) {
- updateActions();
return;
}
- const QString styleName = m_style->currentText();
- QStyle* style = QStyleFactory::create(styleName);
- qCDebug(KUIVIEWERPART) << "Change style: " << styleName;
+ // hack: enforce widget size by setting min/max sizes to wanted size
+ // and then have layout update the complete window
+ const QSize origWidgetMinimumSize = m_view->minimumSize();
+ const QSize origWidgetMaximumSize = m_view->maximumSize();
+ m_view->setMinimumSize(size);
+ m_view->setMaximumSize(size);
+ m_subWindow->updateGeometry();
+ // restore
+ m_view->setMinimumSize(origWidgetMinimumSize);
+ m_view->setMaximumSize(origWidgetMaximumSize);
+}
+
+QPixmap KUIViewerPart::renderWidgetAsPixmap() const
+{
+ if (m_view.isNull()) {
+ return QPixmap();
+ }
- m_widget->hide();
- QApplication::setOverrideCursor(Qt::WaitCursor);
- m_widget->setStyle(style);
+ return m_view->grab();
+}
- const QList<QWidget*> l = m_widget->findChildren<QWidget*>();
- for (int i = 0; i < l.size(); ++i) {
- l.at(i)->setStyle(style);
+void KUIViewerPart::slotStyle(int)
+{
+ if (m_view.isNull()) {
+ updateActions();
+ return;
}
- m_widget->show();
- QApplication::restoreOverrideCursor();
+ m_view->hide();
+
+ const QString styleName = m_style->currentText();
+ qCDebug(KUIVIEWERPART) << "Style selectd:" << styleName;
+ restyleView(styleName);
+
+ m_view->show();
/* the style changed, update the configuration */
if (m_styleFromConfig != styleName) {
@@ -208,7 +276,7 @@ void KUIViewerPart::slotGrab()
return;
}
- const QPixmap pixmap = m_widget->grab();
+ const QPixmap pixmap = m_view->grab();
QApplication::clipboard()->setPixmap(pixmap);
}
diff --git a/kuiviewer/kuiviewer_part.h b/kuiviewer/kuiviewer_part.h
index b18c4f3..50b5c95 100644
--- a/kuiviewer/kuiviewer_part.h
+++ b/kuiviewer/kuiviewer_part.h
@@ -2,6 +2,7 @@
* This file is part of the kuiviewer package
* Copyright (c) 2003 Richard Moore <[email protected]>
* Copyright (c) 2003 Ian Reinhart Geiser <[email protected]>
+ * Copyright (c) 2017 Friedrich W. H. Kossebau <[email protected]>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -21,12 +22,17 @@
#ifndef KUIVIEWERPART_H
#define KUIVIEWERPART_H
+#include "kuiviewer_part_interface.h"
+
// KF
#include <KParts/ReadOnlyPart>
// Qt
#include <QPointer>
+#include <QSize>
class KSelectAction;
+class QMdiArea;
+class QMdiSubWindow;
/**
* This is a "Part". It that does all the real work in a KPart
@@ -36,9 +42,10 @@ class KSelectAction;
* @author Richard Moore <[email protected]>
* @version 0.1
*/
-class KUIViewerPart : public KParts::ReadOnlyPart
+class KUIViewerPart : public KParts::ReadOnlyPart, public KUIViewerPartInterface
{
Q_OBJECT
+ Q_INTERFACES(KUIViewerPartInterface)
public:
/**
@@ -56,6 +63,10 @@ public Q_SLOTS:
void slotGrab();
void updateActions();
+public:
+ void setWidgetSize(const QSize& size) override;
+ QPixmap renderWidgetAsPixmap() const override;
+
protected:
/**
* This must be implemented by each part
@@ -63,7 +74,11 @@ protected:
bool openFile() override;
private:
- QWidget* m_widget;
+ void restyleView(const QString& styleName);
+
+private:
+ QMdiArea* m_widget;
+ QMdiSubWindow* m_subWindow;
QPointer<QWidget> m_view;
KSelectAction* m_style;
QAction* m_copy;
diff --git a/kuiviewer/kuiviewer_part_interface.h b/kuiviewer/kuiviewer_part_interface.h
new file mode 100644
index 0000000..eeb3b34
--- /dev/null
+++ b/kuiviewer/kuiviewer_part_interface.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the kuiviewer package
+ * Copyright (c) 2017 Friedrich W. H. Kossebau <[email protected]>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef KUIVIEWERPARTINTERFACE_H
+#define KUIVIEWERPARTINTERFACE_H
+
+#include <QObject>
+
+class QPixmap;
+class QSize;
+
+
+class KUIViewerPartInterface
+{
+public:
+ virtual ~KUIViewerPartInterface() {}
+
+ virtual void setWidgetSize(const QSize& size) = 0;
+ virtual QPixmap renderWidgetAsPixmap() const = 0;
+};
+
+Q_DECLARE_INTERFACE(KUIViewerPartInterface, "org.kde.KUIViewerPartInterface")
+
+#endif // KUIVIEWERPARTINTERFACE_H
diff --git a/kuiviewer/main.cpp b/kuiviewer/main.cpp
index 2eaac27..c0343c7 100644
--- a/kuiviewer/main.cpp
+++ b/kuiviewer/main.cpp
@@ -76,16 +76,24 @@ int main(int argc, char** argv)
KUIViewer* widget = new KUIViewer;
widget->show();
} else {
+ const bool takeScreenshot = parser.isSet(takeScreenshotOptionKey);
KUIViewer* widget = new KUIViewer;
+ // show before loading, so widget geometries will be properly updated when requested
+ // TODO: investigate how to do this properly with perhaps showevents & Co.?
+ if (takeScreenshot) {
+ widget->showMinimized();
+ } else {
+ widget->show();
+ }
+
widget->load(QUrl::fromUserInput(positionalArguments.at(0), QDir::currentPath()));
- if (parser.isSet(takeScreenshotOptionKey)) {
+ if (takeScreenshot) {
widget->takeScreenshot(parser.value(takeScreenshotOptionKey),
parser.value(screenshotWidthOptionKey).toInt(),
parser.value(screenshotHeightOptionKey).toInt());
return 0;
}
- widget->show();
}
}