Russian Qt Forum

Компиляторы и платформы => Mac OS X => Тема начата: Igors от Апрель 08, 2021, 11:55



Название: Нативный QFileDialog
Отправлено: Igors от Апрель 08, 2021, 11:55
Добрый день

1) Заголовок/title пуст (хотя текст даю)

2) Имя файла должно быть selected но без extension (т.е. "Gro3" выбрано ".prj" нет)

Как порешать? OSX 10.14, Qt 5.12

Спасибо


Название: Re: Нативный QFileDialog
Отправлено: tux от Апрель 08, 2021, 12:10
Покажите сам код. Экстрасенсы на каникулах.


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 08, 2021, 12:39
Покажите сам код. Экстрасенсы на каникулах.
Кода море  :)
Код
C++ (Qt)
QString name = QFileDialog::getSaveFileName(0, "Create Project File", "/Users/igor/Documents/Gro3.prj");


Название: Re: Нативный QFileDialog
Отправлено: tux от Апрель 08, 2021, 18:28
А если написать как-то так:
Код:
    QFileDialog *dlg = new QFileDialog();
    dlg->setWindowTitle("Create Project File");
    dlg->selectFile("/Users/igor/Documents/Gro3.prj");
    int res = dlg->exec();
    if(res == QFileDialog::Accepted)
    {
        QString name = dlg->selectedFiles().at(0);
    }
Просто посмотреть.


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 09, 2021, 09:33
А если написать как-то так:
Пробовал и так - тот же эффект. Для QFileDialog вызов setWindowTitle заливает новое имя в "options", как и конструктор или статик. Само же нативное окно создается в начале exec вызовом NSSavePanel (Objective С). Вчера остаток дня пытался как-то "подлезть" к этому "хендлу", но все мэртво private  :'( Видимо придется писать нативный код вместо QFileDialog, др пути не видно


Название: Re: Нативный QFileDialog
Отправлено: kambala от Апрель 09, 2021, 10:14
добраться до уже открытой панели можно через небольшой хак:
Код
C++ (Qt)
   connect(b, &QPushButton::clicked, [this]{
       macosHack();
       QString name = QFileDialog::getSaveFileName(0, "Create Project File", "/Gro3.prj");
   });
 
// в .mm файле
#include <dispatch/dispatch.h>
#import <AppKit/AppKit.h>
 
void Widget::macosHack()
{
   dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
                      auto savePanel = static_cast<NSSavePanel *>(NSApp.keyWindow);
                  });
}


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 09, 2021, 11:23
добраться до уже открытой панели можно через небольшой хак:
Вот это подход! Правильно ли я понял что по сути мне нужно (NSApp.keyWindow) когда оно станет активной? И все эти dispatch'и - те же игры с таймером? Тогда может  "попробывать" QPlatformSurfaceEvent (которое приходит но имеет только факт создания) ?

И заодно: как убедиться что keyWindow - действительно экземпляр NSSavePanel (аналог dynamic_cast на Objective)?

Спасибо


Название: Re: Нативный QFileDialog
Отправлено: kambala от Апрель 09, 2021, 11:28
добраться до уже открытой панели можно через небольшой хак:
Вот это подход! Правильно ли я понял что по сути мне нужно (NSApp.keyWindow) когда оно станет активной? И все эти dispatch'и - те же игры с таймером? Тогда может  "попробывать" QPlatformSurfaceEvent (которое приходит но имеет только факт создания) ?

И заодно: как убедиться что keyWindow - действительно экземпляр NSSavePanel (аналог dynamic_cast на Objective)?

Спасибо
все верно. скорее всего где-то должен быть нативный notification о появлении нового окна (глубоко не копал) — это будет самый лучший подход (во всяком случае в iOS такое есть, и notification несет в себе хэндл окна).

про QPlatformSurfaceEvent ничего не могу сказать.

проверить класс:
Код
Objective-C
/*BOOL*/ bool isSavePanel = [NSApp.keyWindow isKindOfClass:[NSSavePanel class]];


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 10, 2021, 09:44
Получить NSSavePanel до отрисовки не удалось, реализовал полностью нативный вариант. То конечно громко сказано, скопировал Qt код и вставил свой сетуп (перед примечаниями)
Код
C++ (Qt)
QString CocoaFileSave( const QString & iPrompt, const QString & thePath )
{
   NSSavePanel * savePanel = [NSSavePanel savePanel];
 
   QFileInfo info(thePath);
 
   [savePanel setDirectoryURL: [NSURL fileURLWithPath:info.absolutePath().toNSString()]];
   [savePanel setNameFieldStringValue:info.fileName().toNSString()];
 
   [savePanel setAllowsOtherFileTypes:YES];
   [savePanel setExtensionHidden:NO];
   [savePanel setCanCreateDirectories:YES];
   [savePanel setNameFieldLabel:iPrompt.toNSString()];
   [savePanel setShowsTagField:NO];
   [savePanel setAccessoryView:nil];
 
   // Call processEvents in case the event dispatcher has been interrupted, and needs to do
   // cleanup of modal sessions. Do this before showing the native dialog, otherwise it will
   // close down during the cleanup.
   qApp->processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers);
 
   // Make sure we don't interrupt the runModal call below.
   clearCurrentThreadCocoaEventDispatcherInterruptFlag();
 
   auto result = [savePanel runModal];
 
   QAbstractEventDispatcher::instance()->interrupt();
   if (result != NSModalResponseOK) return QString();
 
   return QString::fromNSString([[savePanel URL] path]).normalized(QString::NormalizationForm_C);
}
 
С памятью надеюсь что ихний сборщик мусора уберет. Работает (аттач), правда текст в title так и не появился, эта пропердь не работает. Насколько я понял, начиная с какой-то версии OSX это убрали. Взамен можно написать текст вверху в области клиента. Ну меня больше устроил prompt слева от имени файла. А selection само рассосвлось, я ничего не делал.

Мелкая проблемка возникает с ф-цией "clear..". В оригинале это статик метод QCocoaEventDispatcher, но так не линкует. Конечно я подкинул libqcocoa.dylib (диспатчер точно там), но линкер его не видит - и все тут! Пришлось скопировать метод к себе и там порезать один qobject_cast (по тем же причинам). Конечно любопытно что за бяка, но тратить еще неск дней на это не могу.


Название: Re: Нативный QFileDialog
Отправлено: kambala от Апрель 10, 2021, 11:30
Цитировать
С памятью надеюсь что ихний сборщик мусора уберет
лучше не надеяться, а самому об этом позаботиться:
Код
Objective-C
@autoreleasepool {
// код
}
или
Код
Objective-C
auto pool = [NSAutoreleasePool new];
// код
[pool release];
return some_cpp_object;
 
нужный вариант зависит от испольвания ARC.
Цитировать
В оригинале это статик метод QCocoaEventDispatcher, но так не линкует. Конечно я подкинул libqcocoa.dylib (диспатчер точно там), но линкер его не видит - и все тут!
если символ не объявлен экспортируемым и/или либа собрана с symbols hidden by default, то линкер не увидит этот метод.


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 10, 2021, 11:47
нужный вариант зависит от испольвания ARC.
Ладно, откроем ихний букварь
Цитировать
Important

If you use Automatic Reference Counting (ARC), you cannot use autorelease pools directly. Instead, you use @autoreleasepool blocks. For example, in place of:
А я и не знаю что я юзаю, тупенько переписал  :) Кто удалит savePanel и неск NSString?

если символ не объявлен экспортируемым и/или либа собрана с symbols hidden by default, то линкер не увидит этот метод.
То ясно, но почему из QFileDialog все линкуется ?


Название: Re: Нативный QFileDialog
Отправлено: kambala от Апрель 10, 2021, 14:27
А я и не знаю что я юзаю, тупенько переписал  :) Кто удалит savePanel и неск NSString?
проверить очень просто: компилятор пропустит лишь один из двух вариантов :) или поискать во флажках компилятора -fobjc-arc (в проекте Xcode там также есть отдельная настройка).

когда нативного кода немало, то лучше все-таки включать ARC, чтоб память руками не чистить (не вызывать release/autorelease руками).
То ясно, но почему из QFileDialog все линкуется ?
без подглядывания в правила сборки Qt не скажешь


Название: Re: Нативный QFileDialog
Отправлено: Igors от Апрель 10, 2021, 16:08
проверить очень просто: компилятор пропустит лишь один из двух вариантов :) или поискать во флажках компилятора -fobjc-arc (в проекте Xcode там также есть отдельная настройка).
У меня off, Немного почитал про освобождение, пока не очень понял. Ну ладно, а попастись на готовом (в лучших традициях форума)
Код:
QMacAutoReleasePool pool; // добавить первой строкой
?


Название: Re: Нативный QFileDialog
Отправлено: kambala от Апрель 10, 2021, 20:02
да, так тоже должно сработать