Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум на CrossPlatform.RU _ Qt GUI _ Проблемы с функцией QFileDialog::getOpenFileName

Автор: AD 22.9.2009, 17:01

Я когда-то задавал подобный вопрос, приемлемого решения не нашлось на тот момент. Но теперь проблема стала снова и серьезно.

Дело в том, что при использовании функции getOpenFileName в стандартном виде:

QFileDialog::getOpenFileName(<object>, <text>, <directory>,
                        <filter_files>));

То эта функция лезет в сетевое окружение. Если сервер сети в данный момент не работает, то вывод окошка замедляется, а то и совсем зависает. Дело в том, что программа начинают с выбора загружаемых лог-файлов, а соответственно с этого окна. Но если сервера (и основной и резервный) в данный момент недоступны, то прога зависает и это окошко не появляется. Какими флагами, шаманствами и прочим можно заставить эту функцию не лезть в сетевое окружение???

Автор: SABROG 22.9.2009, 17:13

При использовании не статического метода exec() должен вызываться Qt'шный диалог выбора файлов, а не системный. Возможно через него повезет.

Автор: AD 22.9.2009, 17:14

Цитата(SABROG @ 22.9.2009, 18:13) *
При использовании не статического метода exec() должен вызываться Qt'шный диалог выбора файлов, а не системный. Возможно через него повезет.

В смысле? Можешь пояснить, пожалуйста?

Автор: SABROG 22.9.2009, 17:19

    QFileDialog dlg(this);
    dlg.exec();

Автор: AD 28.9.2009, 14:16

Сделал для функций следующие обертки. Не особо помогло. Чуть быстрее открывается, но задержка есть. Пока полного зависания не наблюдалось, но задержка раздражает:

QString getOpenFileName(QWidget* parent = 0, const QString& caption = QString(""),
                        const QString& directory = QString(""), const QString& filter = QString(""));
QStringList getOpenFileNames(QWidget* parent = 0, const QString& caption = QString(""),
                        const QString& directory = QString(""), const QString& filter = QString(""));


/// Вызов окна диалога для выбора открываемого файла
QString getOpenFileName(QWidget* parent, const QString& caption, const QString& directory,
                        const QString& filter)
{
    QFileDialog file_dialog(parent, caption, directory, filter);
    file_dialog.setViewMode(QFileDialog::Detail);
    file_dialog.setResolveSymlinks(false);
    file_dialog.setFileMode(QFileDialog::ExistingFile);
    if(!file_dialog.exec())
        return QString("");

    return file_dialog.selectedFile();
}

/// Вызов окна диалога для выбора открываемых файлов
QStringList getOpenFileNames(QWidget* parent, const QString& caption, const QString& directory,
                        const QString& filter)
{
    QFileDialog file_dialog(parent, caption, directory, filter);
    file_dialog.setViewMode(QFileDialog::Detail);
    file_dialog.setResolveSymlinks(false);
    file_dialog.setFileMode(QFileDialog::ExistingFiles);
    if(!file_dialog.exec())
        return QStringList();

    return file_dialog.selectedFiles();
}

Автор: AD 29.9.2009, 21:14

Проблема не решена. Очень нужна помощь! У кого-нибудь есть идеи решения? Буду благодарен!

Автор: SABROG 30.9.2009, 0:02

Сетевых дисков нет?

Автор: AD 30.9.2009, 0:29

Цитата(SABROG @ 30.9.2009, 1:02) *
Сетевых дисков нет?

Нет.

Автор: AD 30.9.2009, 17:48

Думаю, что все-таки есть решение этой проблемы. Ведь не тормозит точно абсолютно такое же окошко, что при вызове статической функции getOpenFileNames(), при открытии нового документа Word, Excel! Только что проверил - моментальное открытие.

Автор: AD 2.10.2009, 16:20

Не удается найти решение. А просто как воздух необходимо...
Помогите, пожалуйста! Этот стандартный диалог в Word, Excel, Power Point открывается моментально - это ведь значит, что проблему можно вылечить? Уже весь ассистент перелистал в поисках решения...

Автор: AD 6.10.2009, 10:30

Полез в исходники QFileDialog
Некоторое, непродолжительное время (от 3 до 5 секунд (несмертельно, эти задержки незаметны в релизном режиме)) зависает при создании диалогового окна на функции init, а в ней на функции - restoreState

QFileDialog::QFileDialog(QWidget *parent,
                     const QString &caption,
                     const QString &directory,
                     const QString &filter)
    : QDialog(*new QFileDialogPrivate, parent, 0)
{
    Q_D(QFileDialog);
    d->init(directory, filter, caption);
}

Ну а далее основательно зависает на функции exec(), а в ней на строчках:
int QDialog::exec()
{
// ...

(void) eventLoop.exec();

/// ............
}

Автор: AD 6.10.2009, 13:53

Тут возник вопрос такой! :) есть ли возможность программно отключать сеть на время работы этого диалога? Т.е. есть ли возможности включения/выключения сети ПРОГРАММНО?

Автор: kwisp 6.10.2009, 16:30

Я бегло просмотрел асситент. не обнаружил.
если и ты не найдешь по форумам и в ассистенте, то могу предложить стопнуть сеть через внешний процесс. :)
с помощью объекта класса QProcess()


П.С.
вот такие костыли :)

Автор: AD 6.10.2009, 17:10

Понимаю, что неидеальное решение, но попробовать стоит! Попробую через Windows функцию GetOpenFileName реализовать диалог открытия. Если повезет, то такой вариант и оставлю. Если вдруг буду переносить код, то реализую подобные функции-обертки для Linux, Unix, MacOS! :)

Автор: AD 6.10.2009, 17:44

Ура! :) Стандартная функция Windows GetOpenFileName работает отлично! :)

P.S. Выходит, что-то у троллей с QFileDialog не так! Надо будет отчет об ошибке отправить.
Юра, ты ведь уже подобные вещи отправлял! Сможешь отправить баг-репорт? Ну смысл ошибки ты уже знаешь по этой теме!

Автор: AD 7.10.2009, 8:23

Вот реализация "оберток":

/// Вызов окна диалога для выбора открываемого файла
QString getOpenFileName(QWidget* parent, const char* caption, const char* directory, const char* filter)
{
    const int NAME_SIZE = 550;
    char fname[NAME_SIZE] = {0};        ///< буфер для имени файла
    bool result = false;

#ifdef Q_WS_WIN
    OPENFILENAME ofn;                    ///< структура диалога открытия файла
    ::ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = 88;
    ofn.hwndOwner = (parent) ? parent -> winId() : 0;
    ofn.lpstrFile = fname;
    ofn.nMaxFile = sizeof(fname);
    ofn.lpstrFilter = filter;
    ofn.nFilterIndex = 0;
    ofn.lpstrFileTitle = 0;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = directory;
    ofn.lpstrTitle = caption;
    ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if(::GetOpenFileName(&ofn) == 1) result = true;
#endif // Q_WS_WIN

    return (result) ? QString(fname) : QString("");
}

/// Вызов окна диалога для выбора открываемых файлов
QStringList getOpenFileNames(QWidget* parent, const char* caption, const char* directory, const char* filter)
{
    const int NAME_SIZE = 5500;
    char fname[NAME_SIZE] = {0};        ///< буфер для имени файла
    QStringList list;

#ifdef Q_WS_WIN
    OPENFILENAME ofn;                    ///< структура диалога открытия файла
    ::ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = 88;
    ofn.hwndOwner = (parent) ? parent -> winId() : 0;
    ofn.lpstrFile = fname;
    ofn.nMaxFile = sizeof(fname);
    ofn.lpstrFilter = filter;
    ofn.nFilterIndex = 0;
    ofn.lpstrFileTitle = 0;
    ofn.nMaxFileTitle = 0;
    ofn.lpstrInitialDir = directory;
    ofn.lpstrTitle = caption;
    ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;

    if(::GetOpenFileName(&ofn) == 1)
    {
        if(ofn.nFileExtension)
            list << QString(fname);
        else if(ofn.nFileOffset)
        {
            QString path(QString(fname) + QDir::separator()), name("");
            for(int i=ofn.nFileOffset, j=ofn.nFileOffset+1; fname[i]!=0 || fname[j]!=0 || j<sizeof(fname); ++i,
                ++j)
            {
                if(fname[i] != 0)
                    name += QChar(fname[i]);
                if(fname[j] == 0)
                    list << QString(path + name),
                    name.clear(),
                    ++i, ++j;
                if(fname[i] == 0 && fname[j] == 0)
                    break;
            }
        }
    }
#endif // Q_WS_WIN

    return list;
}

Форум Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)