VirtualBox

Changeset 4364 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 24, 2007 6:34:50 PM (17 years ago)
Author:
vboxsync
Message:

FE/Qt: Settings Dialogs: Automatically show the detailed message in the whatsthis pane pointing to the page and field that contain invalid input -- for all fields with validation.

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/include/QIWidgetValidator.h

    r4326 r4364  
    2424#include <qobject.h>
    2525#include <qvalidator.h>
     26#include <qvaluelist.h>
    2627
    2728class QIWidgetValidator : public QObject
     
    3031
    3132public:
    32     QIWidgetValidator( QWidget *widget, QObject *parent = 0, const char *name = 0 );
     33
     34    QIWidgetValidator (QWidget *aWidget, QObject *aParent = 0,
     35                       const char *aName = 0);
     36    QIWidgetValidator (const QString &aCaption,
     37                       QWidget *aWidget, QObject *aParent = 0,
     38                       const char *aName = 0);
    3339    ~QIWidgetValidator();
    3440
    35     QWidget *widget() const { return wgt; }
     41    QWidget *widget() const { return mWidget; }
    3642    bool isValid() const;
    3743    void rescan();
    3844
    39     void setOtherValid( bool valid ) { otherValid = valid; }
    40     bool isOtherValid() const { return otherValid; }
     45    QString warningText() const;
     46
     47    void setOtherValid (bool aValid) { mOtherValid = aValid; }
     48    bool isOtherValid() const { return mOtherValid; }
    4149
    4250signals:
    43     void validityChanged( const QIWidgetValidator *wval );
    44     void isValidRequested( QIWidgetValidator *wval );
     51
     52    void validityChanged (const QIWidgetValidator *aValidator);
     53    void isValidRequested (QIWidgetValidator *aValidator);
    4554
    4655public slots:
     56
    4757    void revalidate() { doRevalidate(); }
    4858
    4959private:
    50     QWidget *wgt;
    51     bool otherValid;
     60
     61    QString mCaption;
     62    QWidget *mWidget;
     63    bool mOtherValid;
     64
     65    struct Watched
     66    {
     67        Watched()
     68            : widget (NULL), buddy (NULL)
     69            , state (QValidator::Acceptable) {}
     70
     71        QWidget *widget;
     72        QWidget *buddy;
     73        QValidator::State state;
     74    };
     75
     76    QValueList <Watched> mWatched;
     77    Watched mLastInvalid;
    5278
    5379private slots:
    54     void doRevalidate() { emit validityChanged( this ); }
     80
     81    void doRevalidate() { emit validityChanged (this); }
    5582};
    5683
  • trunk/src/VBox/Frontends/VirtualBox/src/QIWidgetValidator.cpp

    r4323 r4364  
    2222#include <qlineedit.h>
    2323#include <qcombobox.h>
     24#include <qlabel.h>
     25
     26#include <iprt/assert.h>
     27
     28#include "VBoxGlobal.h"
    2429
    2530/** @class QIWidgetValidator
     
    7075 *  of the given widget.
    7176 *
    72  *  @param widget the widget whose children should be checked
    73  */
    74 QIWidgetValidator::QIWidgetValidator(
    75     QWidget *widget, QObject *parent, const char *name
    76 ) :
    77     QObject( parent, name ),
    78     wgt( widget ),
    79     otherValid( true )
     77 *  @param aWidget  Widget whose children should be checked.
     78 */
     79QIWidgetValidator::QIWidgetValidator (QWidget *aWidget, QObject *aParent,
     80                                      const char *aName)
     81    : QObject (aParent, aName)
     82    , mWidget (aWidget)
     83    , mOtherValid (true)
     84{
     85    rescan();
     86}
     87
     88/**
     89 *  Constructs a new instance that will check the validity of children
     90 *  of the given widget.
     91 *
     92 *  @param aCaption Caption to use for the warning message.
     93 *  @param aWidget  Widget whose children should be checked.
     94 */
     95QIWidgetValidator::QIWidgetValidator (const QString &aCaption,
     96                                      QWidget *aWidget, QObject *aParent,
     97                                      const char *aName)
     98    : QObject (aParent, aName)
     99    , mCaption (aCaption)
     100    , mWidget (aWidget)
     101    , mOtherValid (true)
    80102{
    81103    rescan();
     
    89111QIWidgetValidator::~QIWidgetValidator()
    90112{
    91     wgt = 0;
     113    mWidget = 0;
    92114    doRevalidate();
    93115}
     
    120142{
    121143    // wgt is null, we assume we're valid
    122     if (!wgt)
     144    if (!mWidget)
    123145        return true;
    124146
    125147    QIWidgetValidator *that = const_cast <QIWidgetValidator *> (this);
    126     emit that->isValidRequested( that );
     148    emit that->isValidRequested (that);
    127149    if (!isOtherValid())
    128150        return false;
    129151
    130     bool valid = true;
    131 
    132     QObjectList *list = wgt->queryList ("QLineEdit");
    133     QObjectListIterator it (*list);
    134     QObject *obj;
    135     while (valid && (obj = it.current()) != 0)
     152    QValidator::State state = QValidator::Acceptable;
     153
     154    for (QValueList <Watched>::ConstIterator it = mWatched.begin();
     155         it != mWatched.end(); ++ it)
    136156    {
    137         ++it;
    138         if (obj->inherits ("QLineEdit"))
    139         {
    140             QLineEdit *le = ((QLineEdit *) obj);
     157        Watched watched = *it;
     158
     159        if (watched.widget->inherits ("QLineEdit"))
     160        {
     161            QLineEdit *le = ((QLineEdit *) watched.widget);
     162            Assert (le->validator());
    141163            if (!le->validator() || !le->isEnabled())
    142164                continue;
    143             valid = le->hasAcceptableInput();
    144         }
    145         else if (obj->inherits ("QComboBox"))
    146         {
    147             QComboBox *cb = ((QComboBox *) obj);
    148             if (!cb->validator() || !cb->lineEdit() || !cb->isEnabled())
     165            int pos;
     166            state = le->validator()->validate (le->text(), pos);
     167        }
     168        else if (watched.widget->inherits ("QComboBox"))
     169        {
     170            QComboBox *cb = ((QComboBox *) watched.widget);
     171            Assert (cb->validator());
     172            if (!cb->validator() || !cb->isEnabled())
    149173                continue;
    150             valid = cb->lineEdit()->hasAcceptableInput();
     174            int pos;
     175            state = cb->lineEdit()->validator()->
     176                validate (cb->lineEdit()->text(), pos);
     177        }
     178
     179        if (state != QValidator::Acceptable)
     180        {
     181            that->mLastInvalid = watched;
     182            that->mLastInvalid.state = state;
     183            return false;
    151184        }
    152185    }
    153     delete list;
    154 
    155     return valid;
    156 }
    157 
    158 /**
    159  *  Rescans all (grand) children of the managed widget and connects itself to
    160  *  those that can be validated, in order to emit the validityChanged()
    161  *  signal to give its receiver an oportunity to do useful actions.
     186
     187    /* reset last invalid */
     188    that->mLastInvalid = Watched();
     189    return true;
     190}
     191
     192/**
     193 *  Rescans all (grand) children of the managed widget and:
     194 *
     195 *  1) remembers all supported widgets with validators to speed up further
     196 *     validation;
     197 *
     198 *  2) connects itself to those that can be validated, in order to emit the
     199 *     validityChanged() signal to give its receiver an oportunity to do
     200 *     useful actions.
     201 *
     202 *  Must be called every time a child widget is added or removed.
    162203 */
    163204void QIWidgetValidator::rescan()
    164205{
    165     if (!wgt)
     206    if (!mWidget)
    166207        return;
    167208
    168     QObjectList *list = wgt->queryList();
     209    mWatched.clear();
     210
     211    Watched watched;
     212
     213    QObjectList *list = mWidget->queryList();
     214    QObject *obj;
     215
     216    /* detect all widgets that support validation */
    169217    QObjectListIterator it (*list);
    170     QObject *obj;
    171218    while ((obj = it.current()) != 0)
    172219    {
     
    177224            if (!le->validator())
    178225                continue;
    179             // disconnect to avoid duplicate connections
     226            /* disconnect to avoid duplicate connections */
    180227            disconnect (le, SIGNAL (textChanged (const QString &)),
    181228                        this, SLOT (doRevalidate()));
     
    188235            if (!cb->validator() || !cb->lineEdit())
    189236                continue;
    190             // disconnect to avoid duplicate connections
     237            /* disconnect to avoid duplicate connections */
    191238            disconnect (cb, SIGNAL (textChanged (const QString &)),
    192239                        this, SLOT (doRevalidate()));
     
    194241                     this, SLOT (doRevalidate()));
    195242        }
     243
     244        watched.widget = (QWidget *) obj;
     245
     246        /* try to find a buddy widget in order to determine the title for
     247         * the watched widget which is used in the warning text */
     248        QObjectListIterator it2 (*list);
     249        while ((obj = it2.current()) != 0)
     250        {
     251            ++ it2;
     252            if (obj->inherits ("QLabel"))
     253            {
     254                QLabel *label = (QLabel *) obj;
     255                if (label->buddy() == watched.widget)
     256                {
     257                    watched.buddy = label;
     258                    break;
     259                }
     260            }
     261        }
     262
     263        /* memorize */
     264        mWatched << watched;
    196265    }
     266
     267    /* don't forget to delete the list */
    197268    delete list;
     269}
     270
     271/**
     272 *  Returns a message that describes the last detected error (invalid or
     273 *  incomplete input).
     274 *
     275 *  This message uses the caption text passed to the constructor as a page
     276 *  name to refer to. If the caption is NULL, this funciton will return a null
     277 *  string.
     278 *
     279 *  Also, if the failed widget has a buddy widget, this buddy widget's text
     280 *  will be used as a field name to refer to.
     281 */
     282QString QIWidgetValidator::warningText() const
     283{
     284    /* cannot generate an informative message if no caption provided */
     285    if (mCaption.isEmpty())
     286        return QString::null;
     287
     288    if (mLastInvalid.state == QValidator::Acceptable)
     289        return QString::null;
     290
     291    AssertReturn (mLastInvalid.widget, QString::null);
     292
     293    QString title;
     294    if (mLastInvalid.buddy != NULL)
     295    {
     296        if (mLastInvalid.buddy->inherits ("QLabel"))
     297            title = VBoxGlobal::
     298                removeAccelMark (((QLabel *) mLastInvalid.buddy)->text());
     299    }
     300
     301    QString state;
     302    if (mLastInvalid.state == QValidator::Intermediate)
     303        state = tr ("not complete", "value state");
     304    else
     305        state = tr ("invalid", "value state");
     306
     307    if (!title.isEmpty())
     308        return tr ("<qt>Value of the <b>%1</b> field "
     309                   "on the <b>%2</b> page is %3.</qt>")
     310            .arg (title, mCaption, state);
     311
     312    return tr ("<qt>One of the values "
     313               "on the <b>%1</b> page is %2.</qt>")
     314        .arg (mCaption, state);
    198315}
    199316
  • trunk/src/VBox/Frontends/VirtualBox/ui/VBoxGlobalSettingsDlg.ui

    r4071 r4364  
    13581358<functions>
    13591359    <function access="private">init()</function>
     1360    <function access="private" returnType="QString">pagePath( QWidget * )</function>
    13601361    <function access="private" returnType="bool">event( QEvent * )</function>
    13611362    <function access="protected">showEvent( QShowEvent * )</function>
  • trunk/src/VBox/Frontends/VirtualBox/ui/VBoxGlobalSettingsDlg.ui.h

    r4071 r4364  
    340340    /* General page */
    341341
    342 /// @todo (dmik) remove
    343 //    leVDIFolder->setValidator (new QRegExpValidator (QRegExp (".+"), this));
    344 //    leMachineFolder->setValidator (new QRegExpValidator (QRegExp (".+"), this));
    345 
    346     wvalGeneral = new QIWidgetValidator (pageGeneral, this);
     342    wvalGeneral = new QIWidgetValidator (pagePath (pageGeneral), pageGeneral, this);
    347343    connect (wvalGeneral, SIGNAL (validityChanged (const QIWidgetValidator *)),
    348344             this, SLOT (enableOk( const QIWidgetValidator *)));
     
    350346    /* Keyboard page */
    351347
    352     wvalKeyboard = new QIWidgetValidator( pageKeyboard, this );
     348    wvalKeyboard = new QIWidgetValidator (pagePath (pageKeyboard), pageKeyboard, this);
    353349    connect (wvalKeyboard, SIGNAL (validityChanged (const QIWidgetValidator *)),
    354350             this, SLOT (enableOk( const QIWidgetValidator *)));
     
    432428}
    433429
     430/**
     431 *  Returns a path to the given page of this settings dialog. See ::path() for
     432 *  details.
     433 */
     434QString VBoxGlobalSettingsDlg::pagePath (QWidget *aPage)
     435{
     436    QListViewItem *li = listView->
     437        findItem (QString::number (widgetStack->id (aPage)), 1);
     438    return ::path (li);
     439}
     440
    434441bool VBoxGlobalSettingsDlg::event (QEvent *aEvent)
    435442{
     
    526533    Q_UNUSED (wval);
    527534
     535    /* reset the warning text; interested parties will set it during
     536     * validation */
     537    setWarning (QString::null);
     538
     539    QString wvalWarning;
     540
    528541    /* detect the overall validity */
    529542    bool newValid = true;
     
    534547        while ((obj = it.current()) != 0)
    535548        {
    536             newValid &= ((QIWidgetValidator *) obj)->isValid();
    537             ++it;
     549            QIWidgetValidator *wval = (QIWidgetValidator *) obj;
     550            newValid = wval->isValid();
     551            if (!newValid)
     552            {
     553                wvalWarning = wval->warningText();
     554                break;
     555            }
     556            ++ it;
    538557        }
    539558        delete l;
    540559    }
    541560
     561    if (warningString.isNull() && !wvalWarning.isNull())
     562    {
     563        /* try to set the generic error message when invalid but no specific
     564         * message is provided */
     565        setWarning (wvalWarning);
     566    }
     567
    542568    if (valid != newValid)
    543569    {
    544570        valid = newValid;
    545571        buttonOk->setEnabled (valid);
     572        /// @todo in VBoxVMSettingsDlg.ui.h, this is absent at all. Is it
     573        /// really what we want?
     574#if 0
    546575        if (valid)
    547576            warningSpacer->changeSize (0, 0, QSizePolicy::Expanding);
    548577        else
    549578            warningSpacer->changeSize (0, 0);
     579#endif
    550580        warningLabel->setHidden (valid);
    551581        warningPixmap->setHidden (valid);
     
    846876    /* setup validation */
    847877
    848     QIWidgetValidator *wval = new QIWidgetValidator (settings, settings);
     878    QIWidgetValidator *wval =
     879        new QIWidgetValidator (pagePath (pageUSB), settings, settings);
    849880    connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
    850881             this, SLOT (enableOk (const QIWidgetValidator *)));
  • trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui

    r4354 r4364  
    31663166<functions>
    31673167    <function access="private">init()</function>
     3168    <function access="private" returnType="QString">pagePath( QWidget * )</function>
    31683169    <function>setup( const QString &amp;, const QString &amp; )</function>
    31693170    <function>getFromMachine( const CMachine &amp; machine )</function>
  • trunk/src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsDlg.ui.h

    r4324 r4364  
    562562    const uint MaxVRAM = sysProps.GetMaxGuestVRAM();
    563563
    564     leName->setValidator( new QRegExpValidator( QRegExp( ".+" ), this ) );
     564    leName->setValidator (new QRegExpValidator (QRegExp (".+"), this));
    565565
    566566    leRAM->setValidator (new QIntValidator (MinRAM, MaxRAM, this));
    567567    leVRAM->setValidator (new QIntValidator (MinVRAM, MaxVRAM, this));
    568568
    569     wvalGeneral = new QIWidgetValidator( pageGeneral, this );
     569    wvalGeneral = new QIWidgetValidator (pagePath (pageGeneral), pageGeneral, this);
    570570    connect (wvalGeneral, SIGNAL (validityChanged (const QIWidgetValidator *)),
    571571             this, SLOT(enableOk (const QIWidgetValidator *)));
     
    614614                                "and allows to quickly select a different hard disk."));
    615615
    616     wvalHDD = new QIWidgetValidator( pageHDD, this );
     616    wvalHDD = new QIWidgetValidator (pagePath (pageHDD), pageHDD, this);
    617617    connect (wvalHDD, SIGNAL (validityChanged (const QIWidgetValidator *)),
    618618             this, SLOT (enableOk (const QIWidgetValidator *)));
     
    649649                                   "drive and allows to quickly select a different image."));
    650650
    651     wvalDVD = new QIWidgetValidator (pageDVD, this);
     651    wvalDVD = new QIWidgetValidator (pagePath (pageDVD), pageDVD, this);
    652652    connect (wvalDVD, SIGNAL (validityChanged (const QIWidgetValidator *)),
    653653             this, SLOT (enableOk (const QIWidgetValidator *)));
     
    675675                                      "drive and allows to quickly select a different image."));
    676676
    677     wvalFloppy = new QIWidgetValidator (pageFloppy, this);
     677    wvalFloppy = new QIWidgetValidator (pagePath (pageFloppy), pageFloppy, this);
    678678    connect (wvalFloppy, SIGNAL (validityChanged (const QIWidgetValidator *)),
    679679             this, SLOT (enableOk (const QIWidgetValidator *)));
     
    761761                         "using a standard RDP client."));
    762762
    763     ULONG maxPort = 65535;
    764     leVRDPPort->setValidator (new QIntValidator (0, maxPort, this));
    765     leVRDPTimeout->setValidator (new QIntValidator (0, maxPort, this));
    766     wvalVRDP = new QIWidgetValidator (pageVRDP, this);
     763    leVRDPPort->setValidator (new QIntValidator (0, 0xFFFF, this));
     764    leVRDPTimeout->setValidator (new QIntValidator (this));
     765    wvalVRDP = new QIWidgetValidator (pagePath (pageVRDP), pageVRDP, this);
    767766    connect (wvalVRDP, SIGNAL (validityChanged (const QIWidgetValidator *)),
    768767             this, SLOT (enableOk (const QIWidgetValidator *)));
     
    878877    cbVRDPAuthType->insertItem (vboxGlobal().toString (CEnums::VRDPAuthGuest));
    879878    leVRDPTimeout->setAlignment (Qt::AlignRight);
     879}
     880
     881/**
     882 *  Returns a path to the given page of this settings dialog. See ::path() for
     883 *  details.
     884 */
     885QString VBoxVMSettingsDlg::pagePath (QWidget *aPage)
     886{
     887    QListViewItem *li = listView->
     888        findItem (QString::number (widgetStack->id (aPage)), 1);
     889    return ::path (li);
    880890}
    881891
     
    12981308
    12991309
    1300 void VBoxVMSettingsDlg::enableOk( const QIWidgetValidator *wval )
     1310void VBoxVMSettingsDlg::enableOk (const QIWidgetValidator *wval)
    13011311{
    13021312    Q_UNUSED (wval);
     
    13051315     * validation */
    13061316    setWarning (QString::null);
     1317
     1318    QString wvalWarning;
    13071319
    13081320    /* detect the overall validity */
     
    13141326        while ((obj = it.current()) != 0)
    13151327        {
    1316             newValid &= ((QIWidgetValidator *) obj)->isValid();
    1317             ++it;
     1328            QIWidgetValidator *wval = (QIWidgetValidator *) obj;
     1329            newValid = wval->isValid();
     1330            if (!newValid)
     1331            {
     1332                wvalWarning = wval->warningText();
     1333                break;
     1334            }
     1335            ++ it;
    13181336        }
    13191337        delete l;
     1338    }
     1339
     1340    if (warningString.isNull() && !wvalWarning.isNull())
     1341    {
     1342        /* try to set the generic error message when invalid but no specific
     1343         * message is provided */
     1344        setWarning (wvalWarning);
    13201345    }
    13211346
     
    13371362
    13381363    QString warningText;
    1339     QString pageTitle = ::path (listView->currentItem());
     1364    QString pageTitle = pagePath (pg);
    13401365
    13411366    if (pg == pageHDD)
     
    15061531            }
    15071532        }
    1508     }
    1509     else if (pg == pageVRDP)
    1510     {
    1511         if (pageVRDP->isEnabled())
    1512         {
    1513             valid = !(grbVRDP->isChecked() &&
    1514                     (leVRDPPort->text().isEmpty() || leVRDPTimeout->text().isEmpty()));
    1515             if (!valid && leVRDPPort->text().isEmpty())
    1516                 warningText = tr ("VRDP Port is not set ");
    1517             if (!valid && leVRDPTimeout->text().isEmpty())
    1518                 warningText = tr ("VRDP Timeout is not set ");
    1519         }
    1520         else
    1521             valid = true;
    15221533    }
    15231534
     
    21912202    page->loadList (mInterfaceList, mNoInterfaces);
    21922203    page->getFromAdapter (aAdapter);
    2193     tbwNetwork->addTab (page, QString (tr ("Adapter %1", "network"))
    2194                                        .arg (aAdapter.GetSlot()));
     2204    QString pageTitle = QString (tr ("Adapter %1", "network"))
     2205                                 .arg (aAdapter.GetSlot());
     2206    tbwNetwork->addTab (page, pageTitle);
    21952207
    21962208    /* fix the tab order so that main dialog's buttons are always the last */
     
    22002212
    22012213    /* setup validation */
    2202     QIWidgetValidator *wval = new QIWidgetValidator (pageNetwork, this);
     2214    QIWidgetValidator *wval =
     2215        new QIWidgetValidator (QString ("%1: %2")
     2216                               .arg (pagePath (pageNetwork), pageTitle),
     2217                               pageNetwork, this);
    22032218    connect (page->grbEnabled, SIGNAL (toggled (bool)), wval, SLOT (revalidate()));
    22042219    connect (page->cbNetworkAttachment, SIGNAL (activated (const QString &)),
     
    22282243    VBoxVMSerialPortSettings *page = new VBoxVMSerialPortSettings();
    22292244    page->getFromPort (aPort);
    2230     tbwSerialPorts->addTab (page, QString (tr ("Port %1", "serial ports"))
    2231                                                .arg (aPort.GetSlot()));
     2245    QString pageTitle = QString (tr ("Port %1", "serial ports"))
     2246                                 .arg (aPort.GetSlot());
     2247    tbwSerialPorts->addTab (page, pageTitle);
    22322248
    22332249    /* fix the tab order so that main dialog's buttons are always the last */
     
    22372253
    22382254    /* setup validation */
    2239     QIWidgetValidator *wval = new QIWidgetValidator (pageSerial, this);
     2255    QIWidgetValidator *wval =
     2256        new QIWidgetValidator (QString ("%1: %2")
     2257                               .arg (pagePath (pageSerial), pageTitle),
     2258                               pageSerial, this);
    22402259    connect (page->mSerialPortBox, SIGNAL (toggled (bool)),
    22412260             wval, SLOT (revalidate()));
     
    23552374    /* setup validation */
    23562375
    2357     QIWidgetValidator *wval = new QIWidgetValidator (settings, settings);
     2376    QIWidgetValidator *wval =
     2377        new QIWidgetValidator (pagePath (pageUSB), settings, settings);
    23582378    connect (wval, SIGNAL (validityChanged (const QIWidgetValidator *)),
    23592379             this, SLOT (enableOk (const QIWidgetValidator *)));
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette