VirtualBox

Changeset 2042 in vbox for trunk


Ignore:
Timestamp:
Apr 12, 2007 10:41:29 AM (18 years ago)
Author:
vboxsync
Message:

1902: "Select Directory" dialogs are not native:

Own Win32 native file-open dialog moved into another thread (similar to open-folders dialog) to avoid Drag-n-Drop issue caused by COM initialization.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/VBoxGlobal.cpp

    r2022 r2042  
    296296#endif
    297297
    298 // Helpers for VBoxGlobal::getOpenFileName()
     298// Helpers for VBoxGlobal::getOpenFileName() & getExistingDirectory()
    299299/////////////////////////////////////////////////////////////////////////////
    300300
     
    421421    return 0;
    422422}
     423
     424/**
     425 *  QEvent class to carry Win32 API native dialog's result information
     426 */
     427class OpenNativeDialogEvent : public QEvent
     428{
     429public:
     430
     431    OpenNativeDialogEvent (const QString &aResult, QEvent::Type aType)
     432        : QEvent (aType), mResult (aResult) {}
     433
     434    const QString& result() { return mResult; }
     435
     436private:
     437
     438    QString mResult;
     439};
     440
     441/**
     442 *  QObject class reimplementation which is the target for OpenNativeDialogEvent
     443 *  event. It receives OpenNativeDialogEvent event from another thread,
     444 *  stores result information and exits event processing loop.
     445 */
     446class LoopObject : public QObject
     447{
     448public:
     449
     450    LoopObject (QEvent::Type aType) : mType (aType), mResult (QString::null) {}
     451    const QString& result() { return mResult; }
     452
     453private:
     454
     455    bool event (QEvent *aEvent)
     456    {
     457        if (aEvent->type() == mType)
     458        {
     459            OpenNativeDialogEvent *ev = (OpenNativeDialogEvent*) aEvent;
     460            mResult = ev->result();
     461            qApp->eventLoop()->exitLoop();
     462            return true;
     463        }
     464        return QObject::event (aEvent);
     465    }
     466
     467    QEvent::Type mType;
     468    QString mResult;
     469};
    423470
    424471#endif /* Q_WS_WIN */
     
    23802427
    23812428    /**
    2382      *  QEvent type for VBoxGetExistDirectoryEvent event
    2383      */
    2384     enum { GetExistDirectoryEventType = QEvent::User + 300 };
    2385 
    2386     /**
    23872429     *  QEvent class reimplementation to carry Win32 API native dialog's
    23882430     *  result folder information
    23892431     */
    2390     class VBoxGetExistDirectoryEvent : public QEvent
     2432    class GetExistDirectoryEvent : public OpenNativeDialogEvent
    23912433    {
    23922434    public:
    23932435
    2394         VBoxGetExistDirectoryEvent (const QString &aName)
    2395             : QEvent ((QEvent::Type) GetExistDirectoryEventType)
    2396             , mName (aName)
    2397             {}
    2398 
    2399         QString mName;
     2436        enum { TypeId = QEvent::User + 300 };
     2437
     2438        GetExistDirectoryEvent (const QString &aResult)
     2439            : OpenNativeDialogEvent (aResult, (QEvent::Type) TypeId) {}
    24002440    };
    24012441
     
    24572497            else
    24582498                result = QString::null;
    2459             QApplication::postEvent (mTarget, new VBoxGetExistDirectoryEvent (result));
     2499            QApplication::postEvent (mTarget, new GetExistDirectoryEvent (result));
    24602500
    24612501            /* Enable the parent widget again. */
     
    24722512    };
    24732513
    2474     class LoopObject : public QObject
    2475     {
    2476     public:
    2477 
    2478         LoopObject() : mFolder (QString::null) {}
    2479         const QString& folder() { return mFolder; }
    2480 
    2481     private:
    2482 
    2483         bool event (QEvent *e)
    2484         {
    2485             switch (e->type())
    2486             {
    2487                 case GetExistDirectoryEventType:
    2488                 {
    2489                     VBoxGetExistDirectoryEvent *ev = (VBoxGetExistDirectoryEvent *) e;
    2490                     mFolder = ev->mName;
    2491                     qApp->eventLoop()->exitLoop();
    2492                     return true;
    2493                 }
    2494                 default:
    2495                     break;
    2496             }
    2497             return QObject::event (e);
    2498         }
    2499 
    2500         QString mFolder;
    2501     };
    2502 
    25032514    QString dir = QDir::convertSeparators (aDir);
    2504     LoopObject loopObject;
     2515    LoopObject loopObject ((QEvent::Type) GetExistDirectoryEvent::TypeId);
    25052516    Thread openDirThread (aParent, &loopObject, dir, aCaption);
    25062517    openDirThread.start();
    25072518    qApp->eventLoop()->enterLoop();
    25082519    openDirThread.wait();
    2509     return loopObject.folder();
     2520    return loopObject.result();
    25102521
    25112522#else
     
    25302541 */
    25312542/* static */
    2532 QString VBoxGlobal::getOpenFileName (const QString &startWith,
    2533                                      const QString &filters,
    2534                                      QWidget       *parent,
    2535                                      const char    *name,
    2536                                      const QString &caption,
    2537                                      QString       *selectedFilter,
    2538                                      bool           resolveSymlinks)
     2543QString VBoxGlobal::getOpenFileName (const QString &aStartWith,
     2544                                     const QString &aFilters,
     2545                                     QWidget       *aParent,
     2546                                     const char    *aName,
     2547                                     const QString &aCaption,
     2548                                     QString       *aSelectedFilter,
     2549                                     bool           aResolveSymlinks)
    25392550{
    25402551#if defined Q_WS_WIN
    25412552
    2542     /* not yet implemented */
    2543     if (selectedFilter)
    2544         *selectedFilter = QString::null;
    2545 
    2546     QString result;
    2547 
    2548     QString workDir;
    2549     QString initSel;
    2550     QFileInfo fi (startWith);
    2551 
    2552     if (fi.isDir())
    2553         workDir = startWith;
    2554     else
    2555     {
    2556         workDir = fi.dirPath (true);
    2557         initSel = fi.fileName();
    2558     }
    2559 
    2560     workDir = QDir::convertSeparators (workDir);
    2561     if (!workDir.endsWith ("\\"))
    2562         workDir += "\\";
    2563 
    2564     QString title = caption.isNull() ? tr ("Select a file") : caption;
    2565 
    2566     if (parent)
    2567     {
    2568         QEvent e (QEvent::WindowBlocked);
    2569         QApplication::sendEvent (parent, &e);
    2570         qt_enter_modal (parent);
    2571     }
    2572 
    2573     QWidget *topParent = parent ? parent->topLevelWidget() : qApp->mainWidget();
    2574     QString winFilters = winFilter (filters);
    2575     AssertCompile (sizeof (TCHAR) == sizeof (QChar));
    2576     TCHAR buf [1024];
    2577     if (initSel.length() > 0 && initSel.length() < sizeof (buf))
    2578         memcpy (buf, initSel.ucs2(), (initSel.length() + 1) * sizeof (TCHAR));
    2579     else
    2580         buf [0] = 0;
    2581 
    2582     OPENFILENAME ofn;
    2583     memset (&ofn, 0, sizeof (OPENFILENAME));
    2584 
    2585     ofn.lStructSize = sizeof (OPENFILENAME);
    2586     ofn.hwndOwner = topParent ? topParent->winId() : 0;
    2587     ofn.lpstrFilter = (TCHAR *) winFilters.ucs2();
    2588     ofn.lpstrFile = buf;
    2589     ofn.nMaxFile = sizeof (buf) - 1;
    2590     ofn.lpstrInitialDir = (TCHAR *) workDir.ucs2();
    2591     ofn.lpstrTitle = (TCHAR *) title.ucs2();
    2592     ofn.Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY |
    2593                   OFN_EXPLORER | OFN_ENABLEHOOK |
    2594                   OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);
    2595     ofn.lpfnHook = OFNHookProc;
    2596 
    2597     if (GetOpenFileName (&ofn))
    2598     {
    2599         result = QString::fromUcs2 ((ushort *) ofn.lpstrFile);
    2600     }
    2601 
    2602     if (parent)
    2603     {
    2604         qt_leave_modal (parent);
    2605         QEvent e (QEvent::WindowUnblocked);
    2606         QApplication::sendEvent (parent, &e);
    2607     }
    2608 
    2609     // qt_win_eatMouseMove();
    2610     MSG msg = {0, 0, 0, 0, 0, 0, 0};
    2611     while (PeekMessage (&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
    2612     if (msg.message == WM_MOUSEMOVE)
    2613         PostMessage (msg.hwnd, msg.message, 0, msg.lParam);
    2614 
    2615     return result.isEmpty() ? result : QFileInfo (result).absFilePath();
     2553    /**
     2554     *  QEvent class reimplementation to carry Win32 API native dialog's
     2555     *  result folder information
     2556     */
     2557    class GetOpenFileNameEvent : public OpenNativeDialogEvent
     2558    {
     2559    public:
     2560
     2561        enum { TypeId = QEvent::User + 301 };
     2562
     2563        GetOpenFileNameEvent (const QString &aResult)
     2564            : OpenNativeDialogEvent (aResult, (QEvent::Type) TypeId) {}
     2565    };
     2566
     2567    /**
     2568     *  QThread class reimplementation to open Win32 API native file dialog
     2569     */
     2570    class Thread : public QThread
     2571    {
     2572    public:
     2573
     2574        Thread (QWidget *aParent, QObject *aTarget,
     2575                const QString &aStartWith, const QString &aFilters,
     2576                const QString &aCaption) :
     2577                mParent (aParent), mTarget (aTarget),
     2578                mStartWith (aStartWith), mFilters (aFilters),
     2579                mCaption (aCaption) {}
     2580
     2581        virtual void run()
     2582        {
     2583            QString result;
     2584
     2585            QString workDir;
     2586            QString initSel;
     2587            QFileInfo fi (mStartWith);
     2588
     2589            if (fi.isDir())
     2590                workDir = mStartWith;
     2591            else
     2592            {
     2593                workDir = fi.dirPath (true);
     2594                initSel = fi.fileName();
     2595            }
     2596
     2597            workDir = QDir::convertSeparators (workDir);
     2598            if (!workDir.endsWith ("\\"))
     2599                workDir += "\\";
     2600
     2601            QString title = mCaption.isNull() ? tr ("Select a file") : mCaption;
     2602
     2603            QWidget *topParent = mParent ? mParent->topLevelWidget() : qApp->mainWidget();
     2604            QString winFilters = winFilter (mFilters);
     2605            AssertCompile (sizeof (TCHAR) == sizeof (QChar));
     2606            TCHAR buf [1024];
     2607            if (initSel.length() > 0 && initSel.length() < sizeof (buf))
     2608                memcpy (buf, initSel.ucs2(), (initSel.length() + 1) * sizeof (TCHAR));
     2609            else
     2610                buf [0] = 0;
     2611
     2612            OPENFILENAME ofn;
     2613            memset (&ofn, 0, sizeof (OPENFILENAME));
     2614
     2615            ofn.lStructSize = sizeof (OPENFILENAME);
     2616            ofn.hwndOwner = topParent ? topParent->winId() : 0;
     2617            ofn.lpstrFilter = (TCHAR *) winFilters.ucs2();
     2618            ofn.lpstrFile = buf;
     2619            ofn.nMaxFile = sizeof (buf) - 1;
     2620            ofn.lpstrInitialDir = (TCHAR *) workDir.ucs2();
     2621            ofn.lpstrTitle = (TCHAR *) title.ucs2();
     2622            ofn.Flags = (OFN_NOCHANGEDIR | OFN_HIDEREADONLY |
     2623                          OFN_EXPLORER | OFN_ENABLEHOOK |
     2624                          OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST);
     2625            ofn.lpfnHook = OFNHookProc;
     2626
     2627            if (GetOpenFileName (&ofn))
     2628            {
     2629                result = QString::fromUcs2 ((ushort *) ofn.lpstrFile);
     2630            }
     2631
     2632            // qt_win_eatMouseMove();
     2633            MSG msg = {0, 0, 0, 0, 0, 0, 0};
     2634            while (PeekMessage (&msg, 0, WM_MOUSEMOVE, WM_MOUSEMOVE, PM_REMOVE));
     2635            if (msg.message == WM_MOUSEMOVE)
     2636                PostMessage (msg.hwnd, msg.message, 0, msg.lParam);
     2637
     2638            result = result.isEmpty() ? result : QFileInfo (result).absFilePath();
     2639
     2640            QApplication::postEvent (mTarget, new GetOpenFileNameEvent (result));
     2641        }
     2642
     2643    private:
     2644
     2645        QWidget *mParent;
     2646        QObject *mTarget;
     2647        QString mStartWith;
     2648        QString mFilters;
     2649        QString mCaption;
     2650    };
     2651
     2652    if (aSelectedFilter)
     2653        *aSelectedFilter = QString::null;
     2654    QString startWith = QDir::convertSeparators (aStartWith);
     2655    LoopObject loopObject ((QEvent::Type) GetOpenFileNameEvent::TypeId);
     2656    if (aParent) qt_enter_modal (aParent);
     2657    Thread openDirThread (aParent, &loopObject, startWith, aFilters, aCaption);
     2658    openDirThread.start();
     2659    qApp->eventLoop()->enterLoop();
     2660    openDirThread.wait();
     2661    if (aParent) qt_leave_modal (aParent);
     2662    return loopObject.result();
    26162663
    26172664#else
    26182665
    2619     return QFileDialog::getOpenFileName (startWith, filters, parent, name,
    2620                                          caption, selectedFilter, resolveSymlinks);
     2666    return QFileDialog::getOpenFileName (aStartWith, aFilters, aParent, aName,
     2667                                         aCaption, aSelectedFilter, aResolveSymlinks);
    26212668
    26222669#endif
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