lazarus/lcl/interfaces/qt6/qtwsdialogs.pp

1051 lines
34 KiB
ObjectPascal

{
*****************************************************************************
* QtWSDialogs.pp *
* -------------- *
* *
* *
*****************************************************************************
*****************************************************************************
This file is part of the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
}
unit QtWSDialogs;
{$mode objfpc}{$H+}
interface
{$I qtdefines.inc}
uses
// Libs
qt6,
qtobjects, qtwidgets, qtproc,
// RTL + LCL
SysUtils, Classes, LCLType, LazUTF8, LazFileUtils, Dialogs, Controls, Forms, Graphics,
// Widgetset
WSDialogs, WSLCLClasses;
type
{ TQtWSCommonDialog }
TQtWSCommonDialog = class(TWSCommonDialog)
private
protected
class function GetDialogParent(const ACommonDialog: TCommonDialog): QWidgetH;
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class procedure DestroyHandle(const ACommonDialog: TCommonDialog); override;
class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
end;
{ TQtWSFileDialog }
TQtWSFileDialog = class(TWSFileDialog)
private
protected
class function GetQtFilterString(const AFileDialog: TFileDialog;
var ASelectedFilter: WideString): WideString;
class procedure UpdateProperties(const AFileDialog: TFileDialog; QtFileDialog: TQtFileDialog);
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
end;
{ TQtWSOpenDialog }
TQtWSOpenDialog = class(TWSOpenDialog)
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class function QueryWSEventCapabilities(const ACommonDialog: TCommonDialog): TCDWSEventCapabilities; override;
end;
{ TQtWSSaveDialog }
TQtWSSaveDialog = class(TWSSaveDialog)
published
class function QueryWSEventCapabilities(const ACommonDialog: TCommonDialog): TCDWSEventCapabilities; override;
end;
{ TQtWSSelectDirectoryDialog }
TQtWSSelectDirectoryDialog = class(TWSSelectDirectoryDialog)
protected
class procedure UpdateProperties(const AFileDialog: TSelectDirectoryDialog; QtFileDialog: TQtFileDialog);
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
class function QueryWSEventCapabilities(const ACommonDialog: TCommonDialog): TCDWSEventCapabilities; override;
end;
{ TQtWSColorDialog }
TQtWSColorDialog = class(TWSColorDialog)
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
class function QueryWSEventCapabilities(const ACommonDialog: TCommonDialog): TCDWSEventCapabilities; override;
end;
{ TQtWSColorButton }
TQtWSColorButton = class(TWSColorButton)
published
end;
{ TQtWSFontDialog }
TQtWSFontDialog = class(TWSFontDialog)
published
class function CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle; override;
class procedure ShowModal(const ACommonDialog: TCommonDialog); override;
class function QueryWSEventCapabilities(const ACommonDialog: TCommonDialog): TCDWSEventCapabilities; override;
end;
implementation
uses ExtDlgs, qtint;
{$ifndef QT_NATIVE_DIALOGS}
const
QtDialogCodeToModalResultMap: array[QDialogDialogCode] of TModalResult =
(
{QDialogRejected} mrCancel,
{QDialogAccepted} mrOk
);
{$endif}
{ TQtWSSaveDialog }
class function TQtWSSaveDialog.QueryWSEventCapabilities(
const ACommonDialog: TCommonDialog): TCDWSEventCapabilities;
begin
Result := [cdecWSNoCanCloseSupport];
end;
{ TQtWSCommonDialog }
class function TQtWSCommonDialog.GetDialogParent(const ACommonDialog: TCommonDialog): QWidgetH;
begin
if ACommonDialog.Owner is TWinControl then
Result := TQtWidget(TWinControl(ACommonDialog.Owner).Handle).Widget
else
if (QtWidgetSet.GetActiveWindow <> 0) then
Result := TQtWidget(QtWidgetSet.GetActiveWindow).Widget
else
if Assigned(Application.MainForm) and Application.MainForm.Visible then
Result := TQtWidget(Application.MainForm.Handle).Widget
else
Result := nil;
{$IFDEF MSWINDOWS}
if Assigned(Result) then
begin
if (QWidget_windowFlags(Result) and QtTool <> 0) or
(QWidget_windowFlags(Result) and QtDrawer <> 0) or
(QWidget_windowFlags(Result) and QtSheet <> 0) or
(QWidget_windowFlags(Result) and QtPopup <> 0) then
Result := QApplication_desktop;
end;
{$ENDIF}
end;
{------------------------------------------------------------------------------
Function: TQtWSCommonDialog.CreateHandle
Params: None
Returns: Nothing
Dummy handle creator. On Qt we don't need a Handle for common dialogs
------------------------------------------------------------------------------}
class function TQtWSCommonDialog.CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle;
begin
Result := TLCLHandle(TQtDialog.Create(ACommonDialog, GetDialogParent(ACommonDialog)));
TQtDialog(Result).AttachEvents;
end;
{------------------------------------------------------------------------------
Function: TQtWSCommonDialog.DestroyHandle
Params: None
Returns: Nothing
Dummy handle destructor. On Qt we don't need a Handle for common dialogs
------------------------------------------------------------------------------}
class procedure TQtWSCommonDialog.DestroyHandle(const ACommonDialog: TCommonDialog);
begin
if ACommonDialog.HandleAllocated then
TQtDialog(ACommonDialog.Handle).Release;
end;
class procedure TQtWSCommonDialog.ShowModal(const ACommonDialog: TCommonDialog);
begin
TQtDialog(ACommonDialog.Handle).exec;
end;
{ TQtWSFileDialog }
class function TQtWSFileDialog.GetQtFilterString(const AFileDialog: TFileDialog;
var ASelectedFilter: WideString): WideString;
const
FULLWIDTH_LEFT_PARENTHESIS_UTF8 = #$EF#$BC#$88;
FULLWIDTH_RIGHT_PARENTHESIS_UTF8 = #$EF#$BC#$89;
function ReplaceExtensionDelimiter(const ASource: String): String; inline;
begin
// replace *.ext1;*.ext2 by *.ext1 *.ext2
Result := StringReplace(ASource, ';', ' ', [rfReplaceAll]);
end;
function GetExtensionString(const ASource: String): String; inline;
begin
Result := '(' + ReplaceExtensionDelimiter(ASource) + ')';
end;
var
TmpFilter, strExtensions, DialogFilter, S, S1: string;
ParserState, Position, i, L: Integer;
List: TStrings;
begin
{------------------------------------------------------------------------------
This is a parser that converts LCL filter strings to Qt filter strings
The parses states are:
0 - Initial state, is reading a string to be displayed on the filter
1 - Is reading the extensions to be filtered
2 - Reached the end of extensions text, now it will write
A LCL filter string looks like this:
Text files (*.txt *.pas)|*.txt *.pas|Binaries (*.exe)|*.exe
And a Qt filter string looks like this
Text files (*.txt *.pas)
Binaries (*.exe)
The following LCL filter simply cannot be represented under Qt, because Qt
always appends a string with the extensions on the combo box
Text files|*.txt *.pas|Binaries|*.exe
To solve this this algorithm will try to find (*.txt) or similar on the display text
and will remove it. This algorithm is far from perfect and may cause trouble on some
special cases, but should work 99% of the time.
------------------------------------------------------------------------------}
ParserState := 0;
Position := 1;
TmpFilter := AFileDialog.Filter;
ASelectedFilter := '';
DialogFilter := TmpFilter;
TmpFilter := '';
List := TStringList.Create;
try
S1 := '';
L := Length(DialogFilter);
for i := 1 to L + 1 do
begin
if (i = L + 1) or (DialogFilter[i] = '|') then
begin
ParserState := ParserState + 1;
S := Copy(DialogFilter, Position, i - Position);
if ParserState = 1 then
begin
S := StringReplace(S, ' (', FULLWIDTH_LEFT_PARENTHESIS_UTF8, []);
S := StringReplace(S, '(', FULLWIDTH_LEFT_PARENTHESIS_UTF8, []);
S := StringReplace(S, ')', FULLWIDTH_RIGHT_PARENTHESIS_UTF8, []);
S1 := S;
List.Add(S1);
TmpFilter := TmpFilter + S1;
end else
//if ParserState = 2 then
begin
strExtensions := GetExtensionString(S);
List.Strings[List.Count - 1] := S1 + ' ' + strExtensions;
TmpFilter := TmpFilter + ' ' + strExtensions;
if i <> L + 1 then
TmpFilter := TmpFilter + ';;';
ParserState := 0;
end;
Position := i + 1;
end;
end;
// Remember that AFileDialog.FilterIndex is a 1-based index and that
// List has a zero-based index
if (AFileDialog.FilterIndex > 0) and (List.Count >= AFileDialog.FilterIndex) then
ASelectedFilter := List{%H-}.Strings[AFileDialog.FilterIndex - 1]
else
if (List.Count > 0) then
ASelectedFilter := List{%H-}.Strings[0];
finally
List.Free;
end;
if (AFileDialog is TSaveDialog) and (trim(TmpFilter)='()') then
Result := ''
else
Result := {%H-}TmpFilter;
end;
class procedure TQtWSFileDialog.UpdateProperties(
const AFileDialog: TFileDialog; QtFileDialog: TQtFileDialog);
var
ATitle: WideString;
{$ifndef QT_NATIVE_DIALOGS}
AInitDir: WideString;
{$ENDIF}
s: String;
begin
ATitle := AFileDialog{%H-}.Title;
QtFileDialog.setWindowTitle(@ATitle);
{$ifndef QT_NATIVE_DIALOGS}
s := AFileDialog.InitialDir;
if UTF8Pos('$HOME', S) > 0 then
begin
{$IFDEF MSWINDOWS}
AInitDir := GetEnvironmentVariableUTF8('HOMEDRIVE') +
GetEnvironmentVariableUTF8('HOMEPATH');
{$ELSE}
AInitDir := UTF8ToUTF16(GetEnvironmentVariableUTF8('HOME'));
{$ENDIF}
s := StringReplace(S,'$HOME', UTF8Encode(AInitDir),[rfReplaceAll]);
end else
if (S = '') then
S := GetCurrentDirUTF8;
if not DirectoryExistsUTF8(S) then
S := GetCurrentDirUTF8;
QtFileDialog.setDirectory(UTF8ToUTF16(S));
{$else}
s := AFileDialog.InitialDir;
if S = '' then
S := GetCurrentDirUTF8;
if DirectoryExistsUTF8(S) then
QtFileDialog.setDirectory(S);
{$endif}
QtFileDialog.setHistory(AFileDialog.HistoryList);
QtFileDialog.setFilter(GetQtFilterString(AFileDialog, ATitle));
QtFileDialog.setSelectedFilter(ATitle);
QtFileDialog.setConfirmOverwrite(ofOverwritePrompt in TOpenDialog(AFileDialog).Options);
QtFileDialog.setReadOnly(ofReadOnly in TOpenDialog(AFileDialog).Options);
QtFileDialog.setSizeGripEnabled(ofEnableSizing in TOpenDialog(AFileDialog).Options);
if ofViewDetail in TOpenDialog(AFileDialog).Options then
QtFileDialog.setViewMode(QFileDialogDetail)
else
QtFileDialog.setViewMode(QFileDialogList);
if ofAllowMultiSelect in TOpenDialog(AFileDialog).Options then
QtFileDialog.setFileMode(QFileDialogExistingFiles)
else
if ofFileMustExist in TOpenDialog(AFileDialog).Options then
QtFileDialog.setFileMode(QFileDialogExistingFile)
else
QtFileDialog.setFileMode(QFileDialogAnyFile);
if (AFileDialog.FileName <> '') and
not DirectoryExistsUTF8(AFileDialog.FileName) then
begin
ATitle := AFileDialog{%H-}.FileName;
if (AFileDialog is TSaveDialog) or FileExistsUTF8(AFileDialog.FileName) then
QFileDialog_selectFile(QFileDialogH(QtFileDialog.Widget), @ATitle);
{$ifndef QT_NATIVE_DIALOGS}
if (AFileDialog is TOpenPictureDialog) then
TQtFilePreviewDialog(QtFileDialog).CurrentChangedEvent(@ATitle);
{$ENDIF}
end;
{$ifndef QT_NATIVE_DIALOGS}
// set kbd shortcuts in case when we are not native dialog.
QtFileDialog.setShortcuts(AFileDialog is TOpenDialog);
{$endif}
end;
class function TQtWSFileDialog.CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle;
var
FileDialog: TQtFileDialog;
begin
FileDialog := TQtFileDialog.Create(ACommonDialog, TQtWSCommonDialog.GetDialogParent(ACommonDialog));
{$ifdef darwin}
QWidget_setWindowFlags(FileDialog.Widget, QtDialog or QtWindowSystemMenuHint or QtCustomizeWindowHint);
{$endif}
QFileDialog_setOption(QFileDialogH(FileDialog.Widget),
QFileDialogOptionDontUseNativeDialog, False);
FileDialog.AttachEvents;
Result := TLCLHandle(FileDialog);
end;
{------------------------------------------------------------------------------
Function: TQtWSFileDialog.ShowModal
Params: None
Returns: Nothing
------------------------------------------------------------------------------}
class procedure TQtWSFileDialog.ShowModal(const ACommonDialog: TCommonDialog);
var
ReturnText: WideString;
FileDialog: TFileDialog;
ReturnList: QStringListH;
i: integer;
QtFileDialog: TQtFileDialog;
{$ifdef QT_NATIVE_DIALOGS}
selectedFilter, saveFileName, saveFilter, saveTitle, sDir: WideString;
Flags: Cardinal;
{$endif}
ActiveWin: HWND;
s: string;
begin
{------------------------------------------------------------------------------
Initialization of variables
------------------------------------------------------------------------------}
ReturnText := '';
FileDialog := TFileDialog(ACommonDialog);
QtFileDialog := TQtFileDialog(FileDialog.Handle);
UpdateProperties(FileDialog, QtFileDialog);
{$ifdef QT_NATIVE_DIALOGS}
sDir := '';
if UTF8Pos('$HOME', FileDialog.InitialDir) > 0 then
begin
sDir := FileDialog.InitialDir;
{$IFDEF MSWINDOWS}
saveFileName := GetEnvironmentVariableUTF8('HOMEDRIVE') +
GetEnvironmentVariableUTF8('HOMEPATH');
{$ELSE}
saveFileName := GetEnvironmentVariableUTF8('HOME');
{$ENDIF}
sDir := StringReplace(sDir,'$HOME', UTF8Encode(saveFileName),[rfReplaceAll]);
saveFileName := GetUTF8String(SDir) + PathDelim + ExtractFileName(FileDialog.Filename);
end;
{$endif}
{------------------------------------------------------------------------------
Code to call the dialog
------------------------------------------------------------------------------}
if (FileDialog is TSaveDialog) or (FileDialog is TSavePictureDialog) then
QtFileDialog.setAcceptMode(QFileDialogAcceptSave)
else
if (FileDialog is TOpenDialog) or (FileDialog is TOpenPictureDialog) then
QtFileDialog.setAcceptMode(QFileDialogAcceptOpen)
else
if ACommonDialog is TSelectDirectoryDialog then
begin
QtFileDialog.setFileMode(QFileDialogDirectory);
QFileDialog_setOption(QFileDialogH(QtFileDialog.Widget), QFileDialogOptionShowDirsOnly, True);
end;
ActiveWin := QtWidgetSet.GetActiveWindow;
if ACommonDialog is TSaveDialog then
begin
{$ifdef QT_NATIVE_DIALOGS}
selectedFilter:='';
saveFilter := GetQtFilterString(TSaveDialog(ACommonDialog), selectedFilter);
if sDir = '' then
sDir := FileDialog.InitialDir;
if (SDir <> '') and (SDir[length(SDir)] <> PathDelim) then
SDir := SDir + PathDelim;
if (FileDialog.FileName <> '') and
(ExtractFileName(FileDialog.FileName) <> FileDialog.FileName) then
saveFileName := GetUtf8String(FileDialog.Filename)
else
saveFileName := GetUtf8String(SDir+FileDialog.Filename);
saveTitle := GetUTF8String(FileDialog.Title);
Flags := 0;
if not (ofOverwritePrompt in TSaveDialog(FileDialog).Options) then
Flags := Flags or QFileDialogOptionDontConfirmOverwrite;
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
try
{$ENDIF}
QFileDialog_getSaveFileName(@ReturnText,
QWidget_parentWidget(QtFileDialog.Widget), @SaveTitle, @saveFileName,
@saveFilter, @selectedFilter, Flags);
{$IFDEF HASX11}
finally
Clipboard.EndX11SelectionLock;
end;
{$ENDIF}
if ReturnText <> '' then
begin
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.FileName := s;
{$else}
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
FileDialog.UserChoice := mrOK;
end else
FileDialog.UserChoice := mrCancel;
{$else}
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
QFileDialog_setOption(QFileDialogH(QtFileDialog.Widget),
QFileDialogOptionDontConfirmOverwrite,
not (ofOverwritePrompt in TSaveDialog(FileDialog).Options));
FileDialog.UserChoice := QtDialogCodeToModalResultMap[QDialogDialogCode(QtFileDialog.exec)];
ReturnList := QStringList_create;
try
QtFileDialog.selectedFiles(ReturnList);
FileDialog.Files.Clear;
for i := 0 to QStringList_size(ReturnList) - 1 do
begin
QStringList_at(ReturnList, @ReturnText, i);
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.Files.Add(s);
if i = 0 then
FileDialog.FileName := s;
{$else}
FileDialog.Files.Add(UTF16ToUTF8(ReturnText));
if i = 0 then
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
end;
// ReturnText := FileDialog.Files.Text;
finally
QStringList_destroy(ReturnList);
end;
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
{$ENDIF}
{$endif}
end else
begin
{$ifdef QT_NATIVE_DIALOGS}
saveFilter := GetQtFilterString(TOpenDialog(ACommonDialog), selectedFilter);
if sDir = '' then
sDir := FileDialog.InitialDir;
if (SDir <> '') and (SDir[length(SDir)] <> PathDelim) then
SDir := SDir + PathDelim;
if (FileDialog.FileName <> '') and
(ExtractFileName(FileDialog.FileName) <> FileDialog.FileName) then
saveFileName := GetUtf8String(FileDialog.Filename)
else
saveFileName := GetUtf8String(SDir+FileDialog.Filename);
saveTitle := GetUTF8String(FileDialog.Title);
Flags := 0;
if (ofReadOnly in TOpenDialog(FileDialog).Options) then
Flags := Flags or QFileDialogOptionReadOnly;
if (ofAllowMultiSelect in TOpenDialog(FileDialog).Options) then
begin
ReturnText := '';
ReturnList := QStringList_create;
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
try
QFileDialog_getOpenFileNames(ReturnList,
QWidget_parentWidget(QtFileDialog.Widget), @SaveTitle, @saveFileName,
@saveFilter, @selectedFilter, Flags);
FileDialog.Files.Clear;
for i := 0 to QStringList_size(ReturnList) - 1 do
begin
QStringList_at(ReturnList, @ReturnText, i);
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.Files.Add(s);
if i = 0 then
FileDialog.FileName := s;
{$else}
FileDialog.Files.Add(UTF16ToUTF8(ReturnText));
if i = 0 then
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
end;
{assign to ReturnText first filename}
if QStringList_size(ReturnList) > 0 then
QStringList_at(ReturnList, @ReturnText, 0);
finally
QStringList_destroy(ReturnList);
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
{$ENDIF}
end;
end else
begin
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
try
{$ENDIF}
QFileDialog_getOpenFileName(@ReturnText,
QWidget_parentWidget(QtFileDialog.Widget), @SaveTitle, @saveFileName,
@saveFilter, @selectedFilter, Flags);
{$IFDEF HASX11}
finally
Clipboard.EndX11SelectionLock;
end;
{$ENDIF}
end;
if ReturnText <> '' then
begin
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.FileName := s;
{$else}
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
FileDialog.UserChoice := mrOK;
end else
FileDialog.UserChoice := mrCancel;
{$else}
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
FileDialog.UserChoice := QtDialogCodeToModalResultMap[QDialogDialogCode(QtFileDialog.exec)];
ReturnList := QStringList_create;
try
QtFileDialog.selectedFiles(ReturnList);
FileDialog.Files.Clear;
for i := 0 to QStringList_size(ReturnList) - 1 do
begin
QStringList_at(ReturnList, @ReturnText, i);
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.Files.Add(s);
if i = 0 then
FileDialog.FileName := s;
{$else}
FileDialog.Files.Add(UTF16ToUTF8(ReturnText));
if i = 0 then
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
end;
//ReturnText := FileDialog.Files.Text;
finally
QStringList_destroy(ReturnList);
end;
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
{$ENDIF}
{$endif}
end;
if ActiveWin <> 0 then
begin
if QtWidgetSet.IsValidHandle(ActiveWin) then
QtWidgetSet.SetActiveWindow(ActiveWin);
end;
end;
{ TQtWSOpenDialog }
class function TQtWSOpenDialog.CreateHandle(const ACommonDialog: TCommonDialog
): TLCLHandle;
var
FileDialog: TQtFilePreviewDialog;
begin
if (ACommonDialog is TPreviewFileDialog) then
begin
FileDialog := TQtFilePreviewDialog.Create(ACommonDialog, TQtWSCommonDialog.GetDialogParent(ACommonDialog));
{$ifdef darwin}
QWidget_setWindowFlags(FileDialog.Widget, QtDialog or QtWindowSystemMenuHint or QtCustomizeWindowHint);
{$endif}
{$ifndef QT_NATIVE_DIALOGS}
QFileDialog_setOption(QFileDialogH(FileDialog.Widget),
QFileDialogOptionDontUseNativeDialog, True);
FileDialog.initializePreview(TPreviewFileDialog(ACommonDialog).PreviewFileControl);
{$endif}
FileDialog.AttachEvents;
Result := TLCLHandle(FileDialog);
end else
Result := TQtWSFileDialog.CreateHandle(ACommonDialog);
end;
class function TQtWSOpenDialog.QueryWSEventCapabilities(
const ACommonDialog: TCommonDialog): TCDWSEventCapabilities;
begin
Result := [cdecWSNoCanCloseSupport];
end;
{ TQtWSSelectDirectoryDialog }
class procedure TQtWSSelectDirectoryDialog.UpdateProperties(
const AFileDialog: TSelectDirectoryDialog; QtFileDialog: TQtFileDialog);
var
ATitle: WideString;
AInitDir: WideString;
s: String;
begin
ATitle := AFileDialog{%H-}.Title;
QtFileDialog.setWindowTitle(@ATitle);
{$ifndef QT_NATIVE_DIALOGS}
s := AFileDialog.InitialDir;
if UTF8Pos('$HOME', AFileDialog.InitialDir) > 0 then
begin
{$IFDEF MSWINDOWS}
AInitDir := GetEnvironmentVariableUTF8('HOMEDRIVE') +
GetEnvironmentVariableUTF8('HOMEPATH');
{$ELSE}
AInitDir := UTF8ToUTF16(GetEnvironmentVariableUTF8('HOME'));
{$ENDIF}
s := StringReplace(S,'$HOME', UTF8Encode(AInitDir),[rfReplaceAll]);
end;
if not DirectoryExistsUTF8(S) then
S := GetCurrentDirUTF8;
QtFileDialog.setDirectory(S{%H-});
{$else}
S := AFileDialog.InitialDir;
if not DirectoryExistsUTF8(S) then
S := GetCurrentDirUTF8;
QtFileDialog.setDirectory(S);
{$endif}
QtFileDialog.setSizeGripEnabled(ofEnableSizing in TSelectDirectoryDialog(AFileDialog).Options);
if ofViewDetail in TSelectDirectoryDialog(AFileDialog).Options then
QtFileDialog.setViewMode(QFileDialogDetail)
else
QtFileDialog.setViewMode(QFileDialogList);
{$ifndef QT_NATIVE_DIALOGS}
// set kbd shortcuts in case when we are not native dialog.
QtFileDialog.setShortcuts(False);
{$endif}
end;
class function TQtWSSelectDirectoryDialog.CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle;
var
FileDialog: TQtFileDialog;
begin
FileDialog := TQtFileDialog.Create(ACommonDialog, TQtWSCommonDialog.GetDialogParent(ACommonDialog));
{$ifdef darwin}
QWidget_setWindowFlags(FileDialog.Widget, QtDialog or
QtWindowSystemMenuHint or QtCustomizeWindowHint);
{$endif}
QFileDialog_setOption(QFileDialogH(FileDialog.Widget),
QFileDialogOptionDontUseNativeDialog, False);
FileDialog.setFileMode(QFileDialogDirectory);
QFileDialog_setOption(QFileDialogH(FileDialog.Widget), QFileDialogOptionShowDirsOnly, True);
FileDialog.AttachEvents;
Result := TLCLHandle(FileDialog);
end;
{------------------------------------------------------------------------------
Function: TQtWSSelectDirectoryDialog.ShowModal
Params: None
Returns: Nothing
------------------------------------------------------------------------------}
class procedure TQtWSSelectDirectoryDialog.ShowModal(const ACommonDialog: TCommonDialog);
var
ReturnText: WideString;
{$ifdef QT_NATIVE_DIALOGS}
saveFileName: WideString;
saveTitle: WideString;
{$endif}
FileDialog: TSelectDirectoryDialog;
QtFileDialog: TQtFileDialog;
{$ifndef QT_NATIVE_DIALOGS}
ReturnList: QStringListH;
i: Integer;
{$endif}
s: string;
begin
{------------------------------------------------------------------------------
Initialization of variables
------------------------------------------------------------------------------}
ReturnText := '';
FileDialog := TSelectDirectoryDialog(ACommonDialog);
QtFileDialog := TQtFileDialog(FileDialog.Handle);
UpdateProperties(FileDialog, QtFileDialog);
{------------------------------------------------------------------------------
Code to call the dialog
------------------------------------------------------------------------------}
{$ifdef QT_NATIVE_DIALOGS}
saveTitle := GetUTF8String(FileDialog.Title);
// saveFileName := GetUtf8String(FileDialog.InitialDir);
if UTF8Pos('$HOME', FileDialog.InitialDir) > 0 then
begin
s := FileDialog.InitialDir;
{$IFDEF MSWINDOWS}
saveFileName := GetEnvironmentVariableUTF8('HOMEDRIVE') +
GetEnvironmentVariableUTF8('HOMEPATH');
{$ELSE}
saveFileName := GetEnvironmentVariableUTF8('HOME');
{$ENDIF}
s := StringReplace(S,'$HOME', UTF8Encode(saveFileName),[rfReplaceAll]);
saveFileName := GetUTF8String(s);
end else
saveFileName := GetUtf8String(FileDialog.InitialDir);
QFileDialog_getExistingDirectory(@ReturnText,
QWidget_parentWidget(QtFileDialog.Widget), @SaveTitle, @saveFileName);
if ReturnText <> '' then
begin
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.FileName := s;
{$else}
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
FileDialog.UserChoice := mrOK;
end else
FileDialog.UserChoice := mrCancel;
{$else}
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
FileDialog.UserChoice := QtDialogCodeToModalResultMap[QDialogDialogCode(QtFileDialog.exec)];
ReturnList := QStringList_create;
try
QtFileDialog.selectedFiles(ReturnList);
FileDialog.Files.Clear;
for i := 0 to QStringList_size(ReturnList) - 1 do
begin
QStringList_at(ReturnList, @ReturnText, i);
{$ifdef MSWINDOWS}
s := UTF16ToUTF8(ReturnText);
s := StringReplace(s, '/','\', [rfReplaceAll]);
FileDialog.Files.Add(s);
if i = 0 then
FileDialog.FileName := s;
{$else}
FileDialog.Files.Add(UTF16ToUTF8(ReturnText));
if i = 0 then
FileDialog.FileName := UTF16ToUTF8(ReturnText);
{$endif}
end;
//ReturnText := FileDialog.Files.Text;
finally
QStringList_destroy(ReturnList);
end;
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
{$ENDIF}
{$endif}
end;
class function TQtWSSelectDirectoryDialog.QueryWSEventCapabilities(
const ACommonDialog: TCommonDialog): TCDWSEventCapabilities;
begin
Result := [cdecWSNoCanCloseSupport];
end;
{ TQtWSColorDialog }
class function TQtWSColorDialog.CreateHandle(const ACommonDialog: TCommonDialog): TLCLHandle;
begin
Result := 0;
end;
{------------------------------------------------------------------------------
Function: TQtWSColorDialog.ShowModal
Params: None
Returns: Nothing
------------------------------------------------------------------------------}
class procedure TQtWSColorDialog.ShowModal(const ACommonDialog: TCommonDialog);
var
AColor: TColorRef;
AQColor, ARetColor: TQColor;
ReturnBool: Boolean;
ATitle: WideString;
ColorDialog: TColorDialog absolute ACommonDialog;
AOptions: QColorDialogColorDialogOptions;
{$IFDEF HASX11}
AWND: HWND;
{$ENDIF}
procedure FillCustomColors;
var
i, AIndex, CustomColorCount: integer;
AColor: TColor;
AQColor: TQColor;
begin
CustomColorCount := QColorDialog_customCount();
AQColor := Default(TQColor);
for i := 0 to ColorDialog.CustomColors.Count - 1 do
if ExtractColorIndexAndColor(ColorDialog.CustomColors, i, AIndex, AColor) then
if AIndex < CustomColorCount then
begin
ColorRefToTQColor(AColor, AQColor);
QColorDialog_setCustomColor(AIndex, @AQColor{QRgb(AColor)});
end;
end;
begin
AColor := ColorToRgb(ColorDialog.Color);
AQColor.Alpha := Word(ColorDialog.AlphaChannel) * $0101;
AQColor.ColorSpec := 1;
AQColor.Pad := 0;
ColorRefToTQColor(AColor, AQColor);
FillCustomColors;
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
ATitle := UTF8ToUTF16(ACommonDialog.Title);
ARetColor := Default(TQColor);
AOptions := 0; // here we add possible options from ColorDialog.Options, see QColorDialogColorDialogOptions for possible options.
if (cdShowAlphaChannel in ColorDialog.Options) then
AOptions := AOptions or QColorDialogShowAlphaChannel;
if (cdNoButtons in ColorDialog.Options) then
AOptions := AOptions or QColorDialogNoButtons;
if (cdDontUseNativeDialog in ColorDialog.Options) then
AOptions := AOptions or QColorDialogDontUseNativeDialog;
if (cdNoEyeDropperButton in ColorDialog.Options) then
AOptions := AOptions or QColorDialogNoEyeDropperButton;
ReturnBool := QColorDialog_getColor(@ARetColor, @AQColor, TQtWSCommonDialog.GetDialogParent(ACommonDialog), @ATitle, QColorDialogShowAlphaChannel);
if ReturnBool then
begin
TQColorToColorRef(ARetColor, AColor);
ColorDialog.Color := TColor(AColor);
ColorDialog.AlphaChannel := ARetColor.Alpha and $FF;
end;
if ReturnBool then
ACommonDialog.UserChoice := mrOk
else
ACommonDialog.UserChoice := mrCancel;
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
if (QtWidgetSet.WindowManagerName = 'xfwm4') and (QApplication_activeModalWidget() <> nil) then
begin
AWND := HwndFromWidgetH(QApplication_activeModalWidget());
if (AWND <> 0) and (X11GetActivewindow <> TQtWidget(AWND).Widget) then
X11Raise(QWidget_winID(TQtWidget(AWND).Widget));
end;
{$ENDIF}
//Since TQtWSColorDialog.CreateHandle returns 0, in TCommonDialog.Close DoClose will not be called,
//so call it from here
ACommonDialog.DoClose;
end;
class function TQtWSColorDialog.QueryWSEventCapabilities(
const ACommonDialog: TCommonDialog): TCDWSEventCapabilities;
begin
Result := [cdecWSPerformsDoClose, cdecWSNoCanCloseSupport];
end;
{ TQtWSFontDialog }
class function TQtWSFontDialog.CreateHandle(const ACommonDialog: TCommonDialog
): TLCLHandle;
begin
Result := 0;
end;
{------------------------------------------------------------------------------
Function: TQtWSFontDialog.ShowModal
Params: None
Returns: Nothing
------------------------------------------------------------------------------}
class procedure TQtWSFontDialog.ShowModal(const ACommonDialog: TCommonDialog);
var
ReturnFont, CurrentFont: QFontH;
ReturnBool: Boolean;
Str: WideString;
{$IFDEF HASX11}
AWND: HWND;
{$ENDIF}
begin
{------------------------------------------------------------------------------
Code to call the dialog
------------------------------------------------------------------------------}
CurrentFont := TQtFont(TFontDialog(ACommonDialog).Font.Reference.Handle).FHandle;
{$IFDEF HASX11}
Clipboard.BeginX11SelectionLock;
{$ENDIF}
ReturnFont := QFont_create;
try
QFontDialog_getFont(ReturnFont, @ReturnBool, CurrentFont,
TQtWSCommonDialog.GetDialogParent(ACommonDialog));
QFont_family(ReturnFont, @Str);
TFontDialog(ACommonDialog).Font.Name := UTF16ToUTF8(Str);
if QFont_pixelSize(ReturnFont) = -1 then
TFontDialog(ACommonDialog).Font.Size := QFont_pointSize(ReturnFont)
else
TFontDialog(ACommonDialog).Font.Height := QFont_pixelSize(ReturnFont);
TFontDialog(ACommonDialog).Font.Style := [];
if QFont_bold(ReturnFont) then
TFontDialog(ACommonDialog).Font.Style := TFontDialog(ACommonDialog).Font.Style + [fsBold];
if QFont_italic(ReturnFont) then
TFontDialog(ACommonDialog).Font.Style := TFontDialog(ACommonDialog).Font.Style + [fsItalic];
if QFont_strikeOut(ReturnFont) then
TFontDialog(ACommonDialog).Font.Style := TFontDialog(ACommonDialog).Font.Style + [fsStrikeOut];
if QFont_underline(ReturnFont) then
TFontDialog(ACommonDialog).Font.Style := TFontDialog(ACommonDialog).Font.Style + [fsUnderline];
if QFont_fixedPitch(ReturnFont) then
TFontDialog(ACommonDialog).Font.Pitch := fpFixed
else
TFontDialog(ACommonDialog).Font.Pitch := fpDefault;
finally
QFont_destroy(ReturnFont);
{$IFDEF HASX11}
Clipboard.EndX11SelectionLock;
{$ENDIF}
end;
if ReturnBool then
ACommonDialog.UserChoice := mrOk
else
ACommonDialog.UserChoice := mrCancel;
{$IFDEF HASX11}
if (QtWidgetSet.WindowManagerName = 'xfwm4') and (QApplication_activeModalWidget() <> nil) then
begin
AWND := HwndFromWidgetH(QApplication_activeModalWidget());
if (AWND <> 0) and (X11GetActivewindow <> TQtWidget(AWND).Widget) then
X11Raise(QWidget_winID(TQtWidget(AWND).Widget));
end;
{$ENDIF}
//Since TQtWSFontDialog.CreateHandle returns 0, in TCommonDialog.Close DoClose will not be called,
//so call it from here
ACommonDialog.DoClose;
end;
class function TQtWSFontDialog.QueryWSEventCapabilities(
const ACommonDialog: TCommonDialog): TCDWSEventCapabilities;
begin
Result := [cdecWSPerformsDoClose, cdecWSNoCanCloseSupport];
end;
end.