[libcamera-devel,v2,01/11] qcam: Add settings Dialog with Control tab
diff mbox series

Message ID 20220812124651.27496-2-utkarsh02t@gmail.com
State New
Headers show
Series
  • Introduce control interaction to qcam
Related show

Commit Message

Utkarsh Tiwari Aug. 12, 2022, 12:46 p.m. UTC
Implement a Settings QDialog and add its buttonon the toolbar.
We only create one instance of the SettingsWindow and its created the
first time user clicks on the button. We check its existence with
QPointer.

This Setting Dialog implements a QTabWidget which resides in a
QVBoxLayout so that it spans the whole QDialog.

The QTabWidget currently only holds the control tab.
This Tab lays out the respective ControlFrames in a QGridLayout listing
two controls in each row.

ControlFrames handles the UI for each respective controls.
It also implements the QVBoxLayout as for future when we want to add
more information in each frame.

Signed-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>
---
Difference from v1:
	1. Settings dialog now primarily uses QIcon::fromTheme("preferences-system")
	2. using namespace libcamera; added in ControlFrame
 src/qcam/assets/feathericons/feathericons.qrc |  1 +
 src/qcam/main_window.cpp                      | 17 ++++++++
 src/qcam/main_window.h                        |  5 +++
 src/qcam/meson.build                          |  5 +++
 src/qcam/settings/control_frame.cpp           | 28 +++++++++++++
 src/qcam/settings/control_frame.h             | 26 +++++++++++++
 src/qcam/settings/controls_tab.cpp            | 38 ++++++++++++++++++
 src/qcam/settings/controls_tab.h              | 24 ++++++++++++
 src/qcam/settings/settings_dialog.h           | 39 +++++++++++++++++++
 9 files changed, 183 insertions(+)
 create mode 100644 src/qcam/settings/control_frame.cpp
 create mode 100644 src/qcam/settings/control_frame.h
 create mode 100644 src/qcam/settings/controls_tab.cpp
 create mode 100644 src/qcam/settings/controls_tab.h
 create mode 100644 src/qcam/settings/settings_dialog.h

Comments

Kieran Bingham Aug. 22, 2022, 10:52 p.m. UTC | #1
Quoting Utkarsh Tiwari via libcamera-devel (2022-08-12 13:46:41)
> Implement a Settings QDialog and add its buttonon the toolbar.
> We only create one instance of the SettingsWindow and its created the
> first time user clicks on the button. We check its existence with
> QPointer.
> 
> This Setting Dialog implements a QTabWidget which resides in a
> QVBoxLayout so that it spans the whole QDialog.
> 
> The QTabWidget currently only holds the control tab.
> This Tab lays out the respective ControlFrames in a QGridLayout listing
> two controls in each row.
> 
> ControlFrames handles the UI for each respective controls.
> It also implements the QVBoxLayout as for future when we want to add
> more information in each frame.
> 
> Signed-off-by: Utkarsh Tiwari <utkarsh02t@gmail.com>
> ---
> Difference from v1:
>         1. Settings dialog now primarily uses QIcon::fromTheme("preferences-system")
>         2. using namespace libcamera; added in ControlFrame
>  src/qcam/assets/feathericons/feathericons.qrc |  1 +
>  src/qcam/main_window.cpp                      | 17 ++++++++
>  src/qcam/main_window.h                        |  5 +++
>  src/qcam/meson.build                          |  5 +++
>  src/qcam/settings/control_frame.cpp           | 28 +++++++++++++
>  src/qcam/settings/control_frame.h             | 26 +++++++++++++
>  src/qcam/settings/controls_tab.cpp            | 38 ++++++++++++++++++
>  src/qcam/settings/controls_tab.h              | 24 ++++++++++++
>  src/qcam/settings/settings_dialog.h           | 39 +++++++++++++++++++
>  9 files changed, 183 insertions(+)
>  create mode 100644 src/qcam/settings/control_frame.cpp
>  create mode 100644 src/qcam/settings/control_frame.h
>  create mode 100644 src/qcam/settings/controls_tab.cpp
>  create mode 100644 src/qcam/settings/controls_tab.h
>  create mode 100644 src/qcam/settings/settings_dialog.h
> 
> diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc
> index c5302040..3078c26f 100644
> --- a/src/qcam/assets/feathericons/feathericons.qrc
> +++ b/src/qcam/assets/feathericons/feathericons.qrc
> @@ -5,6 +5,7 @@
>         <file>camera-off.svg</file>
>         <file>play-circle.svg</file>
>         <file>save.svg</file>
> +       <file>settings.svg</file>
>         <file>stop-circle.svg</file>
>         <file>x-circle.svg</file>
>  </qresource>
> diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
> index ce70cc02..7861c34b 100644
> --- a/src/qcam/main_window.cpp
> +++ b/src/qcam/main_window.cpp
> @@ -239,6 +239,12 @@ int MainWindow::createToolbars()
>         saveRaw_ = action;
>  #endif
>  
> +       /* Settings Dialog open action */
> +       action = toolbar_->addAction(QIcon::fromTheme("preferences-system",
> +                                                     QIcon(":settings.svg")),
> +                                    "Open Settings Window");
> +       connect(action, &QAction::triggered, this, &MainWindow::openSettingsDialog);
> +
>         return 0;
>  }
>  
> @@ -262,6 +268,17 @@ void MainWindow::updateTitle()
>         setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps");
>  }
>  
> +void MainWindow::openSettingsDialog()
> +{
> +       if (settingsDialog_) {
> +               settingsDialog_->show();
> +               return;
> +       }
> +
> +       settingsDialog_ = new SettingsDialog(camera_, this);
> +       settingsDialog_->show();

This could be simplifed with swapping the conditional around:

{
	if (!settingsDialog_)
		settingsDialog_ = new SettingsDiaglog(camera_, this);

	settingsDialog_->show();
}

But what happens when the camera_ changes ? (Perhaps that gets updated
on camera change, and I'll see it later?).

Could the dialog always be created during construction of MainWindow and
then the settings open button would just call settingsDialog_->show()
directly?

I don't know if application/GUI design is better to construct on demand,
or pre-construct. I guess there's no point constructing the window if it
never gets called ...



> +}
> +
>  /* -----------------------------------------------------------------------------
>   * Camera Selection
>   */
> diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
> index c7cba5e9..856a71b1 100644
> --- a/src/qcam/main_window.h
> +++ b/src/qcam/main_window.h
> @@ -23,12 +23,14 @@
>  #include <QMainWindow>
>  #include <QMutex>
>  #include <QObject>
> +#include <QPointer>
>  #include <QPushButton>
>  #include <QQueue>
>  #include <QTimer>
>  
>  #include "../cam/capture_script.h"
>  #include "../cam/stream_options.h"
> +#include "settings/settings_dialog.h"
>  
>  #include "cam_select_dialog.h"
>  #include "viewfinder.h"
> @@ -94,6 +96,8 @@ private:
>         void loadCaptureScript();
>         void stopCaptureScript();
>  
> +       void openSettingsDialog();
> +
>         /* UI elements */
>         QToolBar *toolbar_;
>         QAction *startStopAction_;
> @@ -108,6 +112,7 @@ private:
>         QTimer titleTimer_;
>  
>         CameraSelectorDialog *cameraSelectorDialog_;
> +       QPointer<SettingsDialog> settingsDialog_;
>  
>         /* Options */
>         const OptionsParser::Options &options_;
> diff --git a/src/qcam/meson.build b/src/qcam/meson.build
> index 70a18d7e..7a785fd0 100644
> --- a/src/qcam/meson.build
> +++ b/src/qcam/meson.build
> @@ -24,12 +24,17 @@ qcam_sources = files([
>      'main.cpp',
>      'main_window.cpp',
>      'message_handler.cpp',
> +    'settings/control_frame.cpp',
> +    'settings/controls_tab.cpp',
>      'viewfinder_qt.cpp',
>  ])
>  
>  qcam_moc_headers = files([
>      'cam_select_dialog.h',
>      'main_window.h',
> +    'settings/control_frame.h',
> +    'settings/controls_tab.h',
> +    'settings/settings_dialog.h',
>      'viewfinder_qt.h',
>  ])
>  
> diff --git a/src/qcam/settings/control_frame.cpp b/src/qcam/settings/control_frame.cpp
> new file mode 100644
> index 00000000..8b1162db
> --- /dev/null
> +++ b/src/qcam/settings/control_frame.cpp
> @@ -0,0 +1,28 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
> + *
> + * control_frame.cpp - qcam - Control frame
> + */
> +
> +#include "control_frame.h"
> +
> +#include <libcamera/controls.h>
> +
> +#include <QFrame>
> +#include <QLabel>
> +#include <QString>
> +#include <QVBoxLayout>
> +
> +using namespace libcamera;
> +
> +ControlFrame::ControlFrame(const ControlId *control, QWidget *parent)
> +       : QFrame(parent), control_(control)
> +{
> +       /* Main layout for the frame */
> +       QVBoxLayout *frameVLayout = new QVBoxLayout(this);
> +
> +       frameVLayout->addWidget(new QLabel(QString::fromStdString(control_->name())));
> +
> +       setFrameStyle(QFrame::StyledPanel);
> +}
> diff --git a/src/qcam/settings/control_frame.h b/src/qcam/settings/control_frame.h
> new file mode 100644
> index 00000000..10690674
> --- /dev/null
> +++ b/src/qcam/settings/control_frame.h
> @@ -0,0 +1,26 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
> + *
> + * control_frame.h - qcam - Control frame
> + */
> +
> +#pragma once
> +
> +#include <libcamera/controls.h>
> +
> +#include <QFrame>
> +#include <QWidget>
> +
> +class ControlFrame : public QFrame
> +{
> +       Q_OBJECT
> +
> +public:
> +       ControlFrame(const libcamera::ControlId *control,
> +                    QWidget *parent);
> +       ~ControlFrame() = default;
> +
> +private:
> +       const libcamera::ControlId *control_;
> +};
> diff --git a/src/qcam/settings/controls_tab.cpp b/src/qcam/settings/controls_tab.cpp
> new file mode 100644
> index 00000000..33ed9332
> --- /dev/null
> +++ b/src/qcam/settings/controls_tab.cpp
> @@ -0,0 +1,38 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
> + *
> + * controls_tab.cpp - qcam - Controls Tab
> + */
> +
> +#include "controls_tab.h"
> +
> +#include <memory>
> +
> +#include <libcamera/camera.h>
> +
> +#include <QGridLayout>
> +#include <QLabel>
> +#include <QWidget>
> +
> +#include "control_frame.h"
> +
> +ControlsTab::ControlsTab(std::shared_ptr<libcamera::Camera> camera_,
> +                        QWidget *parent)
> +       : QWidget(parent)
> +{
> +       /* Main Layout for the tab */
> +       QGridLayout *controlGLayout = new QGridLayout(this);
> +
> +       int controlCount = 0;
> +       for (auto &[control, info] : camera_->controls()) {
> +               ControlFrame *controlFrame = new ControlFrame(control, this);
> +
> +               controlGLayout->addWidget(controlFrame, controlCount / 2,
> +                                         controlCount % 2);
> +               controlCount++;
> +       }
> +
> +       if (controlCount == 0)

Do you really need to count them ? Can you get the size from
camera_controls().size() ?


> +               controlGLayout->addWidget(new QLabel("No controls available"));
> +}
> diff --git a/src/qcam/settings/controls_tab.h b/src/qcam/settings/controls_tab.h
> new file mode 100644
> index 00000000..6a63f334
> --- /dev/null
> +++ b/src/qcam/settings/controls_tab.h
> @@ -0,0 +1,24 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
> + *
> + * controls_tab.h - qcam - Controls Tab
> + */
> +
> +#pragma once
> +
> +#include <memory>
> +
> +#include <libcamera/camera.h>
> +
> +#include <QVBoxLayout>
> +#include <QWidget>
> +
> +class ControlsTab : public QWidget
> +{
> +       Q_OBJECT
> +
> +public:
> +       ControlsTab(std::shared_ptr<libcamera::Camera> camera_, QWidget *parent);
> +       ~ControlsTab() = default;
> +};
> diff --git a/src/qcam/settings/settings_dialog.h b/src/qcam/settings/settings_dialog.h
> new file mode 100644
> index 00000000..c2fa61ea
> --- /dev/null
> +++ b/src/qcam/settings/settings_dialog.h
> @@ -0,0 +1,39 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +/*
> + * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
> + *
> + * settings_dialog.h - qcam - Settings Dialog
> + */
> +
> +#pragma once
> +
> +#include <memory>
> +
> +#include <QDialog>
> +#include <QTabWidget>
> +#include <QVBoxLayout>
> +#include <QWidget>
> +
> +#include "controls_tab.h"
> +class SettingsDialog : public QDialog
> +{
> +       Q_OBJECT
> +
> +public:
> +       SettingsDialog(std::shared_ptr<libcamera::Camera> camera, QWidget *parent)
> +               : QDialog(parent)
> +       {
> +               /*Main layout for dialog */

		/* Main


> +               QVBoxLayout *settingVLayout = new QVBoxLayout(this);
> +
> +               /* Main TabWidget which would hold other tabs */
> +               QTabWidget *settingTabWidget = new QTabWidget;
> +               settingVLayout->addWidget(settingTabWidget);
> +
> +               ControlsTab *controlsTab = new ControlsTab(camera, this);
> +               settingTabWidget->addTab(controlsTab, "Controls");
> +
> +               setWindowTitle("Settings");
> +       }
> +       ~SettingsDialog() = default;
> +};
> -- 
> 2.25.1
>

Patch
diff mbox series

diff --git a/src/qcam/assets/feathericons/feathericons.qrc b/src/qcam/assets/feathericons/feathericons.qrc
index c5302040..3078c26f 100644
--- a/src/qcam/assets/feathericons/feathericons.qrc
+++ b/src/qcam/assets/feathericons/feathericons.qrc
@@ -5,6 +5,7 @@ 
 	<file>camera-off.svg</file>
 	<file>play-circle.svg</file>
 	<file>save.svg</file>
+	<file>settings.svg</file>
 	<file>stop-circle.svg</file>
 	<file>x-circle.svg</file>
 </qresource>
diff --git a/src/qcam/main_window.cpp b/src/qcam/main_window.cpp
index ce70cc02..7861c34b 100644
--- a/src/qcam/main_window.cpp
+++ b/src/qcam/main_window.cpp
@@ -239,6 +239,12 @@  int MainWindow::createToolbars()
 	saveRaw_ = action;
 #endif
 
+	/* Settings Dialog open action */
+	action = toolbar_->addAction(QIcon::fromTheme("preferences-system",
+						      QIcon(":settings.svg")),
+				     "Open Settings Window");
+	connect(action, &QAction::triggered, this, &MainWindow::openSettingsDialog);
+
 	return 0;
 }
 
@@ -262,6 +268,17 @@  void MainWindow::updateTitle()
 	setWindowTitle(title_ + " : " + QString::number(fps, 'f', 2) + " fps");
 }
 
+void MainWindow::openSettingsDialog()
+{
+	if (settingsDialog_) {
+		settingsDialog_->show();
+		return;
+	}
+
+	settingsDialog_ = new SettingsDialog(camera_, this);
+	settingsDialog_->show();
+}
+
 /* -----------------------------------------------------------------------------
  * Camera Selection
  */
diff --git a/src/qcam/main_window.h b/src/qcam/main_window.h
index c7cba5e9..856a71b1 100644
--- a/src/qcam/main_window.h
+++ b/src/qcam/main_window.h
@@ -23,12 +23,14 @@ 
 #include <QMainWindow>
 #include <QMutex>
 #include <QObject>
+#include <QPointer>
 #include <QPushButton>
 #include <QQueue>
 #include <QTimer>
 
 #include "../cam/capture_script.h"
 #include "../cam/stream_options.h"
+#include "settings/settings_dialog.h"
 
 #include "cam_select_dialog.h"
 #include "viewfinder.h"
@@ -94,6 +96,8 @@  private:
 	void loadCaptureScript();
 	void stopCaptureScript();
 
+	void openSettingsDialog();
+
 	/* UI elements */
 	QToolBar *toolbar_;
 	QAction *startStopAction_;
@@ -108,6 +112,7 @@  private:
 	QTimer titleTimer_;
 
 	CameraSelectorDialog *cameraSelectorDialog_;
+	QPointer<SettingsDialog> settingsDialog_;
 
 	/* Options */
 	const OptionsParser::Options &options_;
diff --git a/src/qcam/meson.build b/src/qcam/meson.build
index 70a18d7e..7a785fd0 100644
--- a/src/qcam/meson.build
+++ b/src/qcam/meson.build
@@ -24,12 +24,17 @@  qcam_sources = files([
     'main.cpp',
     'main_window.cpp',
     'message_handler.cpp',
+    'settings/control_frame.cpp',
+    'settings/controls_tab.cpp',
     'viewfinder_qt.cpp',
 ])
 
 qcam_moc_headers = files([
     'cam_select_dialog.h',
     'main_window.h',
+    'settings/control_frame.h',
+    'settings/controls_tab.h',
+    'settings/settings_dialog.h',
     'viewfinder_qt.h',
 ])
 
diff --git a/src/qcam/settings/control_frame.cpp b/src/qcam/settings/control_frame.cpp
new file mode 100644
index 00000000..8b1162db
--- /dev/null
+++ b/src/qcam/settings/control_frame.cpp
@@ -0,0 +1,28 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
+ *
+ * control_frame.cpp - qcam - Control frame
+ */
+
+#include "control_frame.h"
+
+#include <libcamera/controls.h>
+
+#include <QFrame>
+#include <QLabel>
+#include <QString>
+#include <QVBoxLayout>
+
+using namespace libcamera;
+
+ControlFrame::ControlFrame(const ControlId *control, QWidget *parent)
+	: QFrame(parent), control_(control)
+{
+	/* Main layout for the frame */
+	QVBoxLayout *frameVLayout = new QVBoxLayout(this);
+
+	frameVLayout->addWidget(new QLabel(QString::fromStdString(control_->name())));
+
+	setFrameStyle(QFrame::StyledPanel);
+}
diff --git a/src/qcam/settings/control_frame.h b/src/qcam/settings/control_frame.h
new file mode 100644
index 00000000..10690674
--- /dev/null
+++ b/src/qcam/settings/control_frame.h
@@ -0,0 +1,26 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
+ *
+ * control_frame.h - qcam - Control frame
+ */
+
+#pragma once
+
+#include <libcamera/controls.h>
+
+#include <QFrame>
+#include <QWidget>
+
+class ControlFrame : public QFrame
+{
+	Q_OBJECT
+
+public:
+	ControlFrame(const libcamera::ControlId *control,
+		     QWidget *parent);
+	~ControlFrame() = default;
+
+private:
+	const libcamera::ControlId *control_;
+};
diff --git a/src/qcam/settings/controls_tab.cpp b/src/qcam/settings/controls_tab.cpp
new file mode 100644
index 00000000..33ed9332
--- /dev/null
+++ b/src/qcam/settings/controls_tab.cpp
@@ -0,0 +1,38 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
+ *
+ * controls_tab.cpp - qcam - Controls Tab
+ */
+
+#include "controls_tab.h"
+
+#include <memory>
+
+#include <libcamera/camera.h>
+
+#include <QGridLayout>
+#include <QLabel>
+#include <QWidget>
+
+#include "control_frame.h"
+
+ControlsTab::ControlsTab(std::shared_ptr<libcamera::Camera> camera_,
+			 QWidget *parent)
+	: QWidget(parent)
+{
+	/* Main Layout for the tab */
+	QGridLayout *controlGLayout = new QGridLayout(this);
+
+	int controlCount = 0;
+	for (auto &[control, info] : camera_->controls()) {
+		ControlFrame *controlFrame = new ControlFrame(control, this);
+
+		controlGLayout->addWidget(controlFrame, controlCount / 2,
+					  controlCount % 2);
+		controlCount++;
+	}
+
+	if (controlCount == 0)
+		controlGLayout->addWidget(new QLabel("No controls available"));
+}
diff --git a/src/qcam/settings/controls_tab.h b/src/qcam/settings/controls_tab.h
new file mode 100644
index 00000000..6a63f334
--- /dev/null
+++ b/src/qcam/settings/controls_tab.h
@@ -0,0 +1,24 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
+ *
+ * controls_tab.h - qcam - Controls Tab
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <libcamera/camera.h>
+
+#include <QVBoxLayout>
+#include <QWidget>
+
+class ControlsTab : public QWidget
+{
+	Q_OBJECT
+
+public:
+	ControlsTab(std::shared_ptr<libcamera::Camera> camera_, QWidget *parent);
+	~ControlsTab() = default;
+};
diff --git a/src/qcam/settings/settings_dialog.h b/src/qcam/settings/settings_dialog.h
new file mode 100644
index 00000000..c2fa61ea
--- /dev/null
+++ b/src/qcam/settings/settings_dialog.h
@@ -0,0 +1,39 @@ 
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2022, Utkarsh Tiwari <utkarsh02t@gmail.com>
+ *
+ * settings_dialog.h - qcam - Settings Dialog
+ */
+
+#pragma once
+
+#include <memory>
+
+#include <QDialog>
+#include <QTabWidget>
+#include <QVBoxLayout>
+#include <QWidget>
+
+#include "controls_tab.h"
+class SettingsDialog : public QDialog
+{
+	Q_OBJECT
+
+public:
+	SettingsDialog(std::shared_ptr<libcamera::Camera> camera, QWidget *parent)
+		: QDialog(parent)
+	{
+		/*Main layout for dialog */
+		QVBoxLayout *settingVLayout = new QVBoxLayout(this);
+
+		/* Main TabWidget which would hold other tabs */
+		QTabWidget *settingTabWidget = new QTabWidget;
+		settingVLayout->addWidget(settingTabWidget);
+
+		ControlsTab *controlsTab = new ControlsTab(camera, this);
+		settingTabWidget->addTab(controlsTab, "Controls");
+
+		setWindowTitle("Settings");
+	}
+	~SettingsDialog() = default;
+};