diff --git a/src/kconfigdialog.h b/src/kconfigdialog.h --- a/src/kconfigdialog.h +++ b/src/kconfigdialog.h @@ -91,6 +91,24 @@ void settingsChanged(const QString &dialogName); public: + /** + * Describes ways the size of this dialog adapts to the page content widget. + */ + enum PageContentAlignment { + /** + * Page does not adapt to the content widget in any way. + * This means scrolling may be required to view the entire content. + */ + NoAlignment = 0, + + /** + * Page is resized by default to show the entire width of the content. + * Vertical scrolling may still be required to view the entire content. + */ + FitWidth = 1 + }; + Q_DECLARE_FLAGS(PageContentAlignments, PageContentAlignment) + /** * @param parent - The parent of this object. Even though the class * deletes itself the parent should be set so the dialog can be centered @@ -134,6 +152,30 @@ const QString &header = QString(), bool manage = true); + /** + * Adds page to the dialog and to KConfigDialogManager. When an + * application is done adding pages show() should be called to + * display the dialog. + * @param page - Pointer to the page that is to be added to the dialog. + * This object is reparented. + * @param itemName - Name of the page. + * @param contentAlignment - In which way to adapt the size of the page + * to the size of the "page" widget. + * @param pixmapName - Name of the icon that should be used, if needed, when + * displaying the page. The string may either be the name of a themed + * icon (e.g. "document-save"), which the internal icon loader will be + * used to retrieve, or an absolute path to the pixmap on disk. + * @param header - Header text use in the list modes. Ignored in Tabbed + * mode. If empty, the itemName text is used when needed. + * @param manage - Whether KConfigDialogManager should manage the page or not. + * @returns The KPageWidgetItem associated with the page. + */ + KPageWidgetItem *addPage(QWidget *page, const QString &itemName, + PageContentAlignment contentAlignment, + const QString &pixmapName = QString(), + const QString &header = QString(), + bool manage = true); + /** * Adds page to the dialog that is managed by a custom KConfigDialogManager. * This is useful for dialogs that contain settings spread over more than @@ -157,6 +199,32 @@ const QString &pixmapName = QString(), const QString &header = QString()); + /** + * Adds page to the dialog that is managed by a custom KConfigDialogManager. + * This is useful for dialogs that contain settings spread over more than + * one configuration file and thus have/need more than one KConfigSkeleton. + * When an application is done adding pages show() should be called to + * display the dialog. + * @param page - Pointer to the page that is to be added to the dialog. + * This object is reparented. + * @param config - Config object containing corresponding settings. + * @param itemName - Name of the page. + * @param contentAlignment - In which way to adapt the size of the page + * to the size of the "page" widget. + * @param pixmapName - Name of the icon that should be used, if needed, when + * displaying the page. The string may either be the name of a themed + * icon (e.g. "document-save"), which the internal icon loader will be + * used to retrieve, or an absolute path to the pixmap on disk. + * @param header - Header text use in the list modes. Ignored in Tabbed + * mode. If empty, the itemName text is used when needed. + * @returns The KPageWidgetItem associated with the page. + */ + KPageWidgetItem *addPage(QWidget *page, KCoreConfigSkeleton *config, + const QString &itemName, + PageContentAlignment contentAlignment, + const QString &pixmapName = QString(), + const QString &header = QString()); + /** * See if a dialog with the name 'name' already exists. * @see showDialog() @@ -273,5 +341,6 @@ Q_DISABLE_COPY(KConfigDialog) }; -#endif //KCONFIGDIALOG_H +Q_DECLARE_OPERATORS_FOR_FLAGS(KConfigDialog::PageContentAlignments) +#endif //KCONFIGDIALOG_H diff --git a/src/kconfigdialog.cpp b/src/kconfigdialog.cpp --- a/src/kconfigdialog.cpp +++ b/src/kconfigdialog.cpp @@ -37,6 +37,7 @@ #include #include #include +#include class Q_DECL_HIDDEN KConfigDialog::KConfigDialogPrivate { @@ -80,6 +81,7 @@ } KPageWidgetItem *addPageInternal(QWidget *page, const QString &itemName, + PageContentAlignment contentAlignment, const QString &pixmapName, const QString &header); void setupManagerConnections(KConfigDialogManager *manager); @@ -122,13 +124,24 @@ const QString &pixmapName, const QString &header, bool manage) +{ + return addPage(page, itemName, NoAlignment, pixmapName, header, manage); +} + +KPageWidgetItem *KConfigDialog::addPage(QWidget *page, + const QString &itemName, + PageContentAlignment contentAlignment, + const QString &pixmapName, + const QString &header, + bool manage) { Q_ASSERT(page); if (!page) { return nullptr; } - KPageWidgetItem *item = d->addPageInternal(page, itemName, pixmapName, header); + KPageWidgetItem *item = d->addPageInternal(page, itemName, contentAlignment, + pixmapName, header); if (manage) { d->manager->addWidget(page); } @@ -149,13 +162,24 @@ const QString &itemName, const QString &pixmapName, const QString &header) +{ + return addPage(page, config, itemName, NoAlignment, pixmapName, header); +} + +KPageWidgetItem *KConfigDialog::addPage(QWidget *page, + KCoreConfigSkeleton *config, + const QString &itemName, + PageContentAlignment contentAlignment, + const QString &pixmapName, + const QString &header) { Q_ASSERT(page); if (!page) { return nullptr; } - KPageWidgetItem *item = d->addPageInternal(page, itemName, pixmapName, header); + KPageWidgetItem *item = d->addPageInternal(page, itemName, contentAlignment, + pixmapName, header); d->managerForPage[page] = new KConfigDialogManager(page, config); d->setupManagerConnections(d->managerForPage[page]); @@ -170,23 +194,66 @@ return item; } + +// Helper class overriding sizeHint() in QScrollArea to fit the content QWidget horizontally. +class FittingScrollArea : public QScrollArea +{ +public: + FittingScrollArea(QWidget* parent, KConfigDialog::PageContentAlignment alignment) + : QScrollArea(parent), + alignment(alignment) + {} + + QSize sizeHint() const override + { + const QWidget* const contentWidget = widget(); + if (contentWidget == nullptr) { + return QScrollArea::sizeHint(); + } + + + switch (alignment) { + case KConfigDialog::NoAlignment: + return QScrollArea::sizeHint(); + case KConfigDialog::FitWidth: { + const int width = contentWidget->sizeHint().width() + verticalScrollBar()->width(); + const int height = QScrollArea::sizeHint().height(); + return QSize(width, height); + } + default: + // Should never occur + return QScrollArea::sizeHint(); + } + } + +private: + const KConfigDialog::PageContentAlignment alignment; +}; + KPageWidgetItem *KConfigDialog::KConfigDialogPrivate::addPageInternal(QWidget *page, const QString &itemName, + PageContentAlignment contentAlignment, const QString &pixmapName, const QString &header) { QWidget *frame = new QWidget(q); QVBoxLayout *boxLayout = new QVBoxLayout(frame); boxLayout->setMargin(0); boxLayout->setMargin(0); - QScrollArea *scroll = new QScrollArea(q); + QScrollArea *scroll = nullptr; + if (contentAlignment == NoAlignment) { + scroll = new QScrollArea(q); + scroll->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); + } else { + scroll = new FittingScrollArea(q, contentAlignment); + scroll->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Preferred ); + } scroll->setFrameShape(QFrame::NoFrame); scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); scroll->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); scroll->setWidget(page); scroll->setWidgetResizable(true); - scroll->setSizePolicy( QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding ); boxLayout->addWidget(scroll); KPageWidgetItem *item = new KPageWidgetItem(frame, itemName);