------------------------------------------------------------------------------
--                                                                          --
--                An Ada2005 binding to the Qt C++ framework                --
--                                                                          --
------------------------------------------------------------------------------
--                                                                          --
-- Copyright © 2008-2011 Vadim Godunko <vgodunko@gmail.com>                 --
--                                                                          --
-- QtAda is free software;  you can  redistribute it and/or modify it under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 2,  or (at your option) any later ver- --
-- sion. QtAda is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
-- for  more details.  You should have  received  a copy of the GNU General --
-- Public License distributed with QtAda;  see file COPYING.  If not, write --
-- to  the  Free Software Foundation,  51  Franklin  Street,  Fifth  Floor, --
-- Boston, MA 02110-1301, USA.                                              --
--                                                                          --
------------------------------------------------------------------------------
--  $Revision: 3841 $ $Date: 2011-05-18 00:05:17 +0400 (Wed, 18 May 2011) $
------------------------------------------------------------------------------
with Ada.Text_IO;

with Qt4.Actions.Constructors;
with Qt4.Applications;
with Qt4.Cursors;
with Qt4.Dates;
with Qt4.Dialogs;
with Qt4.Dock_Widgets.Constructors;
with Qt4.File_Dialogs;
with Qt4.Fonts;
with Qt4.Icons;
with Qt4.Menu_Bars;
pragma Warnings (Off, Qt4.Menu_Bars);
--  XXX Gnat Pro 6.1.0w (20070424-41)

with Qt4.Key_Sequences;
with Qt4.List_Widgets.Constructors;
with Qt4.Message_Boxes;
with Qt4.Objects;
with Qt4.Print_Dialogs.Constructors;
with Qt4.Printers;

with Qt4.Status_Bars;
pragma Warnings (Off, Qt4.Status_Bars);
--  XXX Gnat Pro 6.1.0w (20070424-41)

with Qt4.String_Lists;
with Qt4.Text_Char_Formats;
with Qt4.Text_Cursors;
with Qt4.Text_Documents;
with Qt4.Text_Edits.Constructors;
with Qt4.Text_Frames;
with Qt4.Text_Frame_Formats;
with Qt4.Text_Table_Formats;

with Main_Windows.MOC;
pragma Warnings (Off, Main_Windows.MOC);
--  Child package MOC must be included in the executable file.

package body Main_Windows is

   -----------
   -- About --
   -----------

   procedure About (Self : not null access Main_Window'Class) is
   begin
      Qt4.Message_Boxes.About
       (Self,
        Qt4.Strings.From_Utf_16 ("About Dock Widgets"),
        Qt4.Strings.From_Utf_16
         ("The <b>Dock Widgets</b> example demonstrates how to " &
          "use Qt's dock widgets. You can enter your own text, " &
          "click a customer to add a customer name and " &
          "address, and click standard paragraphs to add them."));
   end About;

   --------------
   -- About_Qt --
   --------------

   procedure About_Qt (Self : not null access Main_Window'Class) is
   begin
      Qt4.Message_Boxes.About_Qt (Self);
   end About_Qt;

   -------------------
   -- Add_Paragraph --
   -------------------

   procedure Add_Paragraph
    (Self      : not null access Main_Window'Class;
     Paragraph : Qt4.Strings.Q_String)
   is
   begin
      if Paragraph.Is_Empty then
         return;
      end if;

      declare
         Document :
           constant not null access Qt4.Text_Documents.Q_Text_Document'Class
             := Self.Text_Edit.Document;
         Cursor : constant Qt4.Text_Cursors.Q_Text_Cursor
           := Document.Find (Qt4.Strings.From_Utf_16 ("Yours sincerely,"));

      begin
         if Cursor.Is_Null then
            return;
         end if;

         Cursor.Begin_Edit_Block;
         Cursor.Move_Position
          (Qt4.Text_Cursors.Previous_Block,
           Qt4.Text_Cursors.Move_Anchor,
           2);
         Cursor.Insert_Block;
         Cursor.Insert_Text (Paragraph);
         Cursor.Insert_Block;
         Cursor.End_Edit_Block;
      end;
   end Add_Paragraph;

   ------------
   -- Create --
   ------------

   function Create return not null Main_Window_Access is
      Self : constant Main_Window_Access := new Main_Window;

   begin
      Qt4.Main_Windows.Directors.Constructors.Initialize (Self);

      Self.Text_Edit := Qt4.Text_Edits.Constructors.Create;
      Self.Set_Central_Widget (Self.Text_Edit);
      Self.Create_Actions;
      Self.Create_Menus;
      Self.Create_Tool_Bars;
      Self.Create_Status_Bar;
      Self.Create_Dock_Windows;

      Self.Set_Window_Title (Qt4.Strings.From_Utf_16 ("Dock Widgets"));

      Self.New_Letter;

      return Self;
   end Create;

   --------------------
   -- Create_Actions --
   --------------------

   procedure Create_Actions (Self : not null access Main_Window'Class) is
   begin
      Self.New_Letter_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Icons.Create (Qt4.Strings.From_Utf_16 ("images/new.png")),
          Qt4.Strings.From_Utf_16 ("&New Letter"),
          Self);
      Self.New_Letter_Act.Set_Shortcut
       (Qt4.Key_Sequences.Create (Qt4.Strings.From_Utf_16 ("Ctrl+N")));
      Self.New_Letter_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Create a new form letter"));

      Qt4.Objects.Connect
       (Self.New_Letter_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("newLetter()"));

      Self.Save_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Icons.Create (Qt4.Strings.From_Utf_16 ("images/save.png")),
          Qt4.Strings.From_Utf_16 ("&Save..."),
          Self);
      Self.Save_Act.Set_Shortcut
       (Qt4.Key_Sequences.Create (Qt4.Strings.From_Utf_16 ("Ctrl+S")));
      Self.Save_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Save the current form letter"));
      Qt4.Objects.Connect
       (Self.Save_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("save()"));

      Self.Print_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Icons.Create (Qt4.Strings.From_Utf_16 ("images/print.png")),
          Qt4.Strings.From_Utf_16 ("&Print..."),
          Self);
      Self.Print_Act.Set_Shortcut
       (Qt4.Key_Sequences.Create (Qt4.Strings.From_Utf_16 ("Ctrl+P")));
      Self.Print_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Print the current form letter"));
      Qt4.Objects.Connect
       (Self.Print_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("print()"));

      Self.Undo_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Icons.Create (Qt4.Strings.From_Utf_16 ("images/undo.png")),
          Qt4.Strings.From_Utf_16 ("&Undo"),
          Self);
      Self.Undo_Act.Set_Shortcut
       (Qt4.Key_Sequences.Create (Qt4.Strings.From_Utf_16 ("Ctrl+Z")));
      Self.Undo_Act.Set_Status_Tip
        (Qt4.Strings.From_Utf_16 ("Undo the last editing action"));
      Qt4.Objects.Connect
       (Self.Undo_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("undo()"));

      Self.Quit_Act :=
        Qt4.Actions.Constructors.Create
          (Qt4.Strings.From_Utf_16 ("&Quit"), Self);
      Self.Quit_Act.Set_Shortcut
       (Qt4.Key_Sequences.Create (Qt4.Strings.From_Utf_16 ("Ctrl+Q")));
      Self.Quit_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Quit the application"));
      Qt4.Objects.Connect
       (Self.Quit_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("close()"));

      Self.About_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Strings.From_Utf_16 ("&About"), Self);
      Self.About_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Show the application's About box"));
      Qt4.Objects.Connect
       (Self.About_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("about()"));

      Self.About_Qt_Act :=
        Qt4.Actions.Constructors.Create
         (Qt4.Strings.From_Utf_16 ("About &Qt"), Self);
      Self.About_Qt_Act.Set_Status_Tip
       (Qt4.Strings.From_Utf_16 ("Show the Qt library's About box"));
      Qt4.Objects.Connect
       (Self.About_Qt_Act,
        Qt4.Signal ("triggered()"),
        Self,
        Qt4.Slot ("aboutQt()"));
   end Create_Actions;

   -------------------------
   -- Create_Dock_Windows --
   -------------------------

   procedure Create_Dock_Windows (Self : not null access Main_Window'Class) is
      use type Qt4.Dock_Widget_Area;

   begin
      declare
         Dock : constant not null access Qt4.Dock_Widgets.Q_Dock_Widget'Class
           := Qt4.Dock_Widgets.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("Customers"), Self);

         Item_List : Qt4.String_Lists.Q_String_List;

      begin
         Self.Customer_List := Qt4.List_Widgets.Constructors.Create (Dock);

         Dock.Set_Allowed_Areas
         (+Qt4.Left_Dock_Widget_Area +Qt4.Right_Dock_Widget_Area);

         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("John Doe, Harmony Enterprises, 12 Lakeside, Ambleton"));

         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Jane Doe, Memorabilia, 23 Watersedge, Beaton"));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Tammy Shea, Tiblanka, 38 Sea Views, Carlton"));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Tim Sheen, Caraba Gifts, 48 Ocean Way, Deal"));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Sol Harvey, Chicos Coffee, 53 New Springs, Eccleston"));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Sally Hobart, Tiroli Tea, 67 Long River, Fedula"));

         Self.Customer_List.Add_Items (Item_List);

         Dock.Set_Widget (Self.Customer_List);
         Self.Add_Dock_Widget (Qt4.Right_Dock_Widget_Area, Dock);
         Self.View_Menu.Add_Action (Dock.Toggle_View_Action);

         Qt4.Objects.Connect
          (Self.Customer_List,
           Qt4.Signal ("currentTextChanged(QString)"),
           Self,
           Qt4.Slot ("insertCustomer(QString)"));
      end;

      declare
         Dock : constant not null access Qt4.Dock_Widgets.Q_Dock_Widget'Class
           := Qt4.Dock_Widgets.Constructors.Create
               (Qt4.Strings.From_Utf_16 ("Paragraphs"), Self);

         Item_List : Qt4.String_Lists.Q_String_List;

      begin
         Self.Paragraphs_List := Qt4.List_Widgets.Constructors.Create (Dock);

         Item_List.Append
          (Qt4.Strings.From_Utf_16
             ("Thank you for your payment which we have received today."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
             ("Your order has been dispatched and should be with you " &
               "within 28 days."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("We have dispatched those items that were in stock. The " &
               "rest of your order will be dispatched once all the " &
               "remaining items have arrived at our warehouse. No " &
               "additional shipping charges will be made."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("You made a small overpayment (less than $5) which we " &
               "will keep on account for you, or return at your request."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("You made a small underpayment (less than $1), but we have " &
               "sent your order anyway. We'll add this underpayment to " &
               "your next bill."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("Unfortunately you did not send enough money. Please remit " &
               "an additional $. Your order will be dispatched as soon as " &
               "the complete amount has been received."));
         Item_List.Append
          (Qt4.Strings.From_Utf_16
            ("You made an overpayment (more than $5). Do you wish to " &
               "buy more items, or should we return the excess to you?"));

         Self.Paragraphs_List.Add_Items (Item_List);
         Dock.Set_Widget (Self.Paragraphs_List);
         Self.Add_Dock_Widget (Qt4.Right_Dock_Widget_Area, Dock);
         Self.View_Menu.Add_Action (Dock.Toggle_View_Action);

         Qt4.Objects.Connect
          (Self.Paragraphs_List,
           Qt4.Signal ("currentTextChanged(QString)"),
           Self,
           Qt4.Slot ("addParagraph(QString)"));
      end;
   end Create_Dock_Windows;

   ------------------
   -- Create_Menus --
   ------------------

   procedure Create_Menus (Self : not null access Main_Window'Class) is
      Sep : Qt4.Actions.Q_Action_Access;
      pragma Warnings (Off, Sep);

   begin
      Self.File_Menu :=
        Qt4.Menus.Q_Menu_Access
         (Self.Menu_Bar.Add_Menu (Qt4.Strings.From_Utf_16 ("&File")));
      Self.File_Menu.Add_Action (Self.New_Letter_Act);
      Self.File_Menu.Add_Action (Self.Save_Act);
      Self.File_Menu.Add_Action (Self.Print_Act);
      Sep := Qt4.Actions.Q_Action_Access (Self.File_Menu.Add_Separator);
      Self.File_Menu.Add_Action (Self.Quit_Act);

      Self.Edit_Menu :=
        Qt4.Menus.Q_Menu_Access
         (Self.Menu_Bar.Add_Menu (Qt4.Strings.From_Utf_16 ("&Edit")));
      Self.Edit_Menu.Add_Action (Self.Undo_Act);

      Self.View_Menu :=
        Qt4.Menus.Q_Menu_Access
         (Self.Menu_Bar.Add_Menu (Qt4.Strings.From_Utf_16 ("&View")));

      Sep := Qt4.Actions.Q_Action_Access (Self.Menu_Bar.Add_Separator);

      Self.Help_Menu :=
        Qt4.Menus.Q_Menu_Access
         (Self.Menu_Bar.Add_Menu (Qt4.Strings.From_Utf_16 ("&Help")));
      Self.Help_Menu.Add_Action (Self.About_Act);
      Self.Help_Menu.Add_Action (Self.About_Qt_Act);
   end Create_Menus;

   -----------------------
   -- Create_Status_Bar --
   -----------------------

   procedure Create_Status_Bar (Self : not null access Main_Window'Class) is
   begin
      Self.Status_Bar.Show_Message (Qt4.Strings.From_Utf_16 ("Ready"));
   end Create_Status_Bar;

   ----------------------
   -- Create_Tool_Bars --
   ----------------------

   procedure Create_Tool_Bars (Self : not null access Main_Window'Class)
   is
   begin
      Self.File_Tool_Bar :=
        Qt4.Tool_Bars.Q_Tool_Bar_Access
         (Self.Add_Tool_Bar (Qt4.Strings.From_Utf_16 ("File")));
      Self.File_Tool_Bar.Add_Action (Self.New_Letter_Act);
      Self.File_Tool_Bar.Add_Action (Self.Save_Act);
      Self.File_Tool_Bar.Add_Action (Self.Print_Act);

      Self.Edit_Tool_Bar :=
        Qt4.Tool_Bars.Q_Tool_Bar_Access
         (Self.Add_Tool_Bar (Qt4.Strings.From_Utf_16 ("Edit")));
      Self.Edit_Tool_Bar.Add_Action (Self.Undo_Act);
   end Create_Tool_Bars;

   ---------------------
   -- Insert_Customer --
   ---------------------

   procedure Insert_Customer
    (Self     : not null access Main_Window'Class;
     Customer : Qt4.Strings.Q_String)
   is
   begin
      if Customer.Is_Empty then
         return;
      end if;

      declare
         Customer_List : constant Qt4.String_Lists.Q_String_List
           := Customer.Split (Qt4.Strings.From_Utf_16 (", "));

         Document :
           constant not null access Qt4.Text_Documents.Q_Text_Document'Class
             := Self.Text_Edit.Document;

         Cursor : Qt4.Text_Cursors.Q_Text_Cursor
           := Document.Find (Qt4.Strings.From_Utf_16 ("NAME"));

      begin
         if not Cursor.Is_Null then
            Cursor.Begin_Edit_Block;
            Cursor.Insert_Text (Customer_List.Value (0));

            declare
               Old_Cursor : constant Qt4.Text_Cursors.Q_Text_Cursor := Cursor;

            begin
               Cursor := Document.Find (Qt4.Strings.From_Utf_16 ("ADDRESS"));

               if not Cursor.Is_Null then
                  for I in 1 .. Customer_List.Size loop
                     Cursor.Insert_Block;
                     Cursor.Insert_Text (Customer_List.Value (I));
                  end loop;

                  Cursor.End_Edit_Block;

               else
                  Old_Cursor.End_Edit_Block;
               end if;
            end;
         end if;
      end;
   end Insert_Customer;

   ----------------
   -- New_Letter --
   ----------------

   procedure New_Letter (Self : not null access Main_Window'Class) is
   begin
      Self.Text_Edit.Clear;

      declare
         Cursor           : constant Qt4.Text_Cursors.Q_Text_Cursor
         := Self.Text_Edit.Text_Cursor;
      begin

         begin
            Cursor.Move_Position (Qt4.Text_Cursors.Start);
         exception
            when others =>
               null;
         end;

         declare
            use type Qt4.Alignment_Flag;

            Top_Frame        : constant Qt4.Text_Frames.Q_Text_Frame_Access
              := Qt4.Text_Frames.Q_Text_Frame_Access (Cursor.Current_Frame);
            Top_Frame_Format : Qt4.Text_Frame_Formats.Q_Text_Frame_Format
              := Top_Frame.Frame_Format;
            Text_Format      : Qt4.Text_Char_Formats.Q_Text_Char_Format;
            Bold_Format      : Qt4.Text_Char_Formats.Q_Text_Char_Format;
            Italic_Format    : Qt4.Text_Char_Formats.Q_Text_Char_Format;
            Table_Format     : Qt4.Text_Table_Formats.Q_Text_Table_Format;

         begin
            Top_Frame_Format.Set_Padding (16.0);
            Top_Frame.Set_Frame_Format (Top_Frame_Format);

            Bold_Format.Set_Font_Weight (Qt4.Fonts.Weight_Bold);
            Italic_Format.Set_Font_Italic (True);
            Table_Format.Set_Border (1.0);

            Table_Format.Set_Cell_Padding (16.0);
            Table_Format.Set_Alignment (+Qt4.Align_Right);

            Cursor.Insert_Table (1, 1, Table_Format);
            Cursor.Insert_Text
             (Qt4.Strings.From_Utf_16 ("The Firm"), Bold_Format);
            Cursor.Insert_Block;
            Cursor.Insert_Text (Qt4.Strings.From_Utf_16 ("321 City Street"),
                                Text_Format);
            Cursor.Insert_Block;
            Cursor.Insert_Text (Qt4.Strings.From_Utf_16 ("Industry Park"));
            Cursor.Insert_Block;
            Cursor.Insert_Text (Qt4.Strings.From_Utf_16 ("Some Country"));
            Cursor.Set_Position (Top_Frame.Last_Position);
            Cursor.Insert_Text (Qt4.Dates.Current_Date.To_String
                                 (Qt4.Strings.From_Utf_16 ("d MMMM yyyy")),
                                  Text_Format);
            Cursor.Insert_Block;
            Cursor.Insert_Block;
            Cursor.Insert_Text
             (Qt4.Strings.From_Utf_16 ("Dear "), Text_Format);
            Cursor.Insert_Text
             (Qt4.Strings.From_Utf_16 ("NAME"), Italic_Format);
            Cursor.Insert_Text (Qt4.Strings.From_Utf_16 (","), Text_Format);

            for I in 1 .. 3 loop
               Cursor.Insert_Block;
            end loop;

            Cursor.Insert_Text (Qt4.Strings.From_Utf_16 ("Yours sincerely,"),
                                Text_Format);

            for I in 1 .. 3 loop
               Cursor.Insert_Block;
            end loop;

            Cursor.Insert_Text
             (Qt4.Strings.From_Utf_16 ("The Boss"), Text_Format);
            Cursor.Insert_Block;
            Cursor.Insert_Text
             (Qt4.Strings.From_Utf_16 ("ADDRESS"), Italic_Format);
         end;
      end;
   end New_Letter;

   -----------
   -- Print --
   -----------

   procedure Print (Self : not null access Main_Window'Class) is
      use type Qt4.Dialogs.Dialog_Code;

      Printer : Qt4.Printers.Q_Printer := Qt4.Printers.Create;
      Dialog  : constant Qt4.Print_Dialogs.Q_Print_Dialog_Access
        := Qt4.Print_Dialogs.Constructors.Create (Printer, Self);

   begin
      if Dialog.Exec /= Qt4.Dialogs.Accepted then
         return;
      end if;

      Self.Text_Edit.Document.Print (Printer);
      Self.Status_Bar.Show_Message (Qt4.Strings.From_Utf_16 ("Ready"), 2.0);
   end Print;

   ----------
   -- Save --
   ----------

   procedure Save (Self : not null access Main_Window'Class) is
      File_Name : constant Qt4.Strings.Q_String :=
        Qt4.File_Dialogs.Get_Save_File_Name
         (Self,
          Qt4.Strings.From_Utf_16 ("Choose a file name"),
          Qt4.Strings.From_Utf_16 ("."),
          Qt4.Strings.From_Utf_16 ("HTML (*.html *.htm)"));

      Button : Qt4.Message_Boxes.Standard_Button;
      pragma Unreferenced (Button);
      --  Переменная реально нигде не используется

      use type Qt4.Strings.Q_String;

   begin
      if File_Name.Is_Empty then
         return;
      end if;

      declare
         My_File : Ada.Text_IO.File_Type;

      begin
         Ada.Text_IO.Create (File => My_File,
                             Mode => Ada.Text_IO.Out_File,
                             Name => File_Name.To_Local_8_Bit);

      Qt4.Applications.Set_Override_Cursor
       (Qt4.Cursors.Create (Qt4.Wait_Cursor));
      Ada.Text_IO.Put_Line (My_File, Self.Text_Edit.To_Html.To_Local_8_Bit);
      Qt4.Applications.Restore_Override_Cursor;
      Self.Status_Bar.Show_Message
       (Qt4.Strings.From_Utf_16 ("Saved ") & File_Name, 2.0);
      Ada.Text_IO.Close (My_File);

      exception
         when others =>
            Button := Qt4.Message_Boxes.Warning
                      (Self,
                       Qt4.Strings.From_Utf_16 ("Dock Widgets"),
                       Qt4.Strings.From_Utf_16 ("Cannot write file")
                        & File_Name
                        & Qt4.Strings.From_Utf_16 ("Some Error"));

      end;
   end Save;

   ----------
   -- Undo --
   ----------

   procedure Undo (Self : not null access Main_Window'Class) is
   begin
      Self.Text_Edit.Document.Undo;
   end Undo;

end Main_Windows;
