Forum

Author Topic: Asking user multiple input in dialogue  (Read 7277 times)

gEEvEE

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Asking user multiple input in dialogue
« on: August 05, 2019, 02:20:46 PM »
Hi All,

I want to make a dialogue in which I ask the user something (with Metashape.app.getInt) and also ask if this should be applied on all the cameras or only the selected ones. So all this should be in one dialogue, not in consecutive ones. How can I program this? Does Metashape support this?

Cheers,

Geert

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 15472
    • View Profile
Re: Asking user multiple input in dialogue
« Reply #1 on: August 05, 2019, 03:55:11 PM »
Hello Geert,

Such functionality should be done with the help of PySide2 module that allows to create custom dialog boxes which could include different types of GUI elements (check boxes, input lines, combo boxes and etc.).

You can find the examples of how it could be done in the following scripts:
https://github.com/agisoft-llc/metashape-scripts/blob/master/src/masking_by_color_dialog.py
https://github.com/agisoft-llc/metashape-scripts/blob/master/src/split_in_chunks_dialog.py
If you prefer to have a smaller example, like you've mentioned with two combo box options and int input field, I can post it here.
Best regards,
Alexey Pasumansky,
Agisoft LLC

gEEvEE

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Re: Asking user multiple input in dialogue
« Reply #2 on: August 05, 2019, 04:22:29 PM »
Hi Alexey,

yes, such an example would be very, very helpful. Besides, I would also like to mimic a part of the batching dialogue (the part in which I can select specific chunks).
If you could share some pieces of code without much effort, that would be great!

Cheers,

Geert

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 15472
    • View Profile
Re: Asking user multiple input in dialogue
« Reply #3 on: August 05, 2019, 06:17:32 PM »
Hello Geert,

Please check the following script:

Code: [Select]
import Metashape
from PySide2 import QtGui, QtCore, QtWidgets


class ProgDlg(QtWidgets.QDialog):

def __init__(self, parent):
QtWidgets.QDialog.__init__(self, parent)
self.setWindowTitle("Custom Processing")

self.btnQuit = QtWidgets.QPushButton("&Exit")
self.btnP1 = QtWidgets.QPushButton("&Process!")
self.pBar = QtWidgets.QProgressBar()
self.pBar.setTextVisible(False)

self.applyTxt = QtWidgets.QLabel("Apply to:")
self.radioBtn_all = QtWidgets.QRadioButton("All cameras")
self.radioBtn_sel = QtWidgets.QRadioButton("Selected cameras")
self.radioBtn_all.setChecked(True)
self.radioBtn_sel.setChecked(False)

self.intTxt = QtWidgets.QLabel("Input int:")
self.intEdt = QtWidgets.QLineEdit()
self.onlyInt = QtGui.QIntValidator()
self.intEdt.setPlaceholderText("input int here")
self.intEdt.setValidator(self.onlyInt)


layout = QtWidgets.QGridLayout()
#layout.setSpacing(5)
layout.addWidget(self.applyTxt, 0, 0)
layout.addWidget(self.radioBtn_all, 1, 0)
layout.addWidget(self.radioBtn_sel, 2, 0)
layout.addWidget(self.intTxt, 0, 1)
layout.addWidget(self.intEdt, 0, 2)
layout.addWidget(self.pBar, 3, 0)
layout.addWidget(self.btnP1, 3, 1)
layout.addWidget(self.btnQuit, 3, 2)
self.setLayout(layout)

proc = lambda : self.process()

QtCore.QObject.connect(self.btnP1, QtCore.SIGNAL("clicked()"), proc)
QtCore.QObject.connect(self.btnQuit, QtCore.SIGNAL("clicked()"), self, QtCore.SLOT("reject()"))

self.exec()

def process(self):
global app
print("Script started...")
self.btnP1.setDisabled(True)
self.btnQuit.setDisabled(True)
self.pBar.setValue(0)


my_int = self.intEdt.text()
if not my_int.isdigit():
print("Invalid input, script aborted")
return 0
my_int = int(my_int)

selected = False
if self.radioBtn_sel.isChecked():
selected = True
elif self.radioBtn_all.isChecked():
selected = False

doc = Metashape.app.document
chunk = doc.chunk #active chunk
if selected:
cameras = [camera for camera in chunk.cameras if camera.selected]
else:
cameras = chunk.cameras

processed = 0
for camera in cameras:
print(camera.label + " " + str(my_int))
processed += 1
self.pBar.setValue(processed / len(cameras) * 100)
app.processEvents() #update GUI
self.pBar.setValue(100)


self.btnP1.setDisabled(False)
self.btnQuit.setDisabled(False)
print("Script finished.")
return 1


def custom_process():
global app
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dlg = ProgDlg(parent)


label = "Custom menu/Custom Processing"
Metashape.app.addMenuItem(label, custom_process)
print("To execute this script press {}".format(label))

It has the possibility of applying the processing to all or selected cameras and option to input int value. Some simple "processing" function is added that just print out the camera labels and input int.
Best regards,
Alexey Pasumansky,
Agisoft LLC

gEEvEE

  • Jr. Member
  • **
  • Posts: 66
    • View Profile
Re: Asking user multiple input in dialogue
« Reply #4 on: August 05, 2019, 09:40:58 PM »
Alexey,

You're a legend! many thanks.
One question: why do you use the <return 0> or <return 1> for?
Could I use <raise Exception("some string")> instead?

Cheers,

Geert


Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 15472
    • View Profile
Re: Asking user multiple input in dialogue
« Reply #5 on: August 07, 2019, 12:29:49 PM »
Hello Geert,

The script returns 1, when the operation is successful and 0, when the operation fails due to certain conditions. If necessary, you can use raise exception approach instead.
Best regards,
Alexey Pasumansky,
Agisoft LLC