2

Is it possible to move widgets in QFileDialog's window? Example during opening or saving file. I would like to make a space between file name's line edit and file type's combo box, so I need to move combo box one row lower. Is it possible to make modification like this?

enter image description here

enter image description here

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Ieners
  • 21
  • 2

1 Answers1

1

To do this requires modifications to the layout of the widgets that make up the QFileDialog. A complete example follows. You'd want to add your own content (widgets, layouts, etc.) into the freed-up space - the necessary details are returned from modDialog. The SO::SpaceButtons option takes the buttons out of the internal QDialogButtonBox and lays them out around the inserted row. Otherwise, the space extends only within the first two columns, and the button box remains unchanged.

Screenshot of the modified file dialog

// filedialog-mod-49371087
#include <QtWidgets>
#include <initializer_list>

struct GridPos {
   int row = -1, col = -1, rowSpan = {}, colSpan = {};
   GridPos(QGridLayout * layout, QWidget * widget) {
      int index = layout->indexOf(widget);
      if (index >= 0)
         layout->getItemPosition(index, &row, &col, &rowSpan, &colSpan);
   }
   GridPos(int r, int c, int rs, int cs) : row(r), col(c), rowSpan(rs), colSpan(cs) {}
   bool operator==(const GridPos & o) const {
      return o.row == row && o.col == col && o.rowSpan == rowSpan && o.colSpan == colSpan;
   }
};

namespace SO {
enum ModDialogOption { SpaceButtons = 1 };
Q_DECLARE_FLAGS(ModDialogOptions, ModDialogOption)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(SO::ModDialogOptions)

struct ModDialogResult {
   QGridLayout *layout;
   int row;
   int colSpan;
};

ModDialogResult modDialog(QFileDialog * dialog, SO::ModDialogOptions options = {}) {
   auto *layout = qobject_cast<QGridLayout*>(dialog->layout());
   auto *fileNameLabel = dialog->findChild<QLabel*>("fileNameLabel");
   auto *fileNameEdit = dialog->findChild<QLineEdit*>("fileNameEdit");
   auto *buttonBox = dialog->findChild<QDialogButtonBox*>("buttonBox");
   auto *fileTypeLabel = dialog->findChild<QLabel*>("fileTypeLabel");
   auto *fileTypeCombo = dialog->findChild<QComboBox*>("fileTypeCombo");
   auto const buttons = buttonBox->findChildren<QPushButton*>();
   // ensure that the dialog has expected layout
   Q_ASSERT((GridPos{layout, fileNameLabel} == GridPos{2, 0, 1, 1}));
   Q_ASSERT((GridPos{layout, fileNameEdit} == GridPos{2, 1, 1, 1}));
   Q_ASSERT((GridPos{layout, buttonBox} == GridPos{2, 2, 2, 1}));
   Q_ASSERT((GridPos{layout, fileTypeLabel} == GridPos{3, 0, 1, 1}));
   Q_ASSERT((GridPos{layout, fileTypeCombo} == GridPos{3, 1, 1, 1}));
   Q_ASSERT(buttons.size() == 2);

   // remove widgets and layouts
   for (auto *w : std::initializer_list<QWidget*>{buttonBox, fileTypeLabel, fileTypeCombo})
      layout->removeWidget(w);

   // add widgets in new locations
   if (options & SO::SpaceButtons) {
      for (auto *b : buttons) b->setParent(dialog);
      buttonBox->hide();
      layout->addWidget(buttons.at(0), 2, 2, 1, 1);
      layout->addWidget(buttons.at(1), 4, 2, 1, 1);
   } else {
      layout->addWidget(buttonBox, 2, 2, 3, 1);
   }
   layout->addWidget(fileTypeLabel, 4, 0, 1, 1);
   layout->addWidget(fileTypeCombo, 4, 1, 1, 1);

   return {layout, 3, 3};
}

int main(int argc, char **argv) {
   QApplication app{argc, argv};
   QFileDialog dialog;
   dialog.setOption(QFileDialog::DontUseNativeDialog);
   auto mod = modDialog(&dialog, SO::SpaceButtons);
   mod.layout->addItem(new QSpacerItem(0, 50), mod.row, 0);
   dialog.show();
   return app.exec();
}
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313