Witam. Dziś postanowiłem napisać kolejną część pewnych małoznanych aspektów związanych z QT. Niestety dzisiejszy wątek będzie nieco dłuższy i zastanawiam się czy nie podzielić go ale może obejdzie się bez tego
.
Przeglądając to forum napotykam się na wypowiedzi typu "no to dokumentacja w łapki i do dzieła "
o tyle o ile ich autorzy mają najczęściej racje i w żadnym wypadku nie próbuję ich tu ośmieszyć o tyle pomyślałem, że napewno znajdą się osoby które chciałyby kiedyś w przyszłości (albo może i już są w trakcie ) napisać aplikacje która przechowywała by różne dokumentacje do scalaków, elementów pasywnych itp. O tyle o ile już takie aplikacje istnieją to nie posiadają one jednej bardzo fajnej opcji a mianowicie przeglądania już zkatalogowanego datasheet'a
PDF czyli Portable Document Format jest jednym z najbardziej popularnych i najmniej rozumianych formatów plików wszelkiego rodzaju dokumentacji.
Dzisiejszy wpis będzie dotyczył właśnie możliwości QT dotyczących obsługi PDF.
Chciałbym również prosić o wyrozumiałość jeżeli chodzi o sekcje "syntax" ponieważ całość piszę w procesorze tekstu a dopiero na koniec wrzucę wszystko na forum, przy takiej ilości tekstu myślę, że zanim bym go całego napisał to dawno by wygasła sesja PHP i praca mogłaby przepaść. Drugą rzeczą o którą proszę jest wybaczenie mi błędów gramatycznych czy ortograficznych, spowodowane jest to tym, że aby openoffice nie mieszal mi w nazwach zmiennych itp. które będe tu prezentował musiałem wyłączyć autokorekte i sprawdzanie błędów a od jakiegoś czasu dość rzadko posługuję się językiem polskim więc przypuszczalnie jakieś błędy się pojawią. Wracając do tematu.
Istnieją dwie podstawowe metody które pozwalają ze strony programu obsłużyć format PDF (w dalszej części tego artykułu będe używał naprzemian dwóch nazw: PDF oraz dokument które będą się odnosiły do formatu PDF).
Pierwszą metodą jest wykonanie aplikacji zewnętrznej takiej jak Adobe Acrobat Reader znany z Windows czy Okular znany ze środowiska KDE pod Linux czy Windows. Wykonanie aplikacji zewnętrznej jest stosunkowo proste i ogranicza się do wykonania poniższego króciutkiego kodu:
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Gdzie nazwą programu jest jakiś czytnik dokumentów a Atrybuty to ścieżka do pliku *.pdf.
Drugą metodą jest skorzystanie z jakiejś biblioteki zernętrznej (tzw. 3-rd party) i obsłużenie dokumentu zgodnie z tą biblioteką. Najbardziej znanymi są:
Poppler stworzona przez grupę freedesktop.org oparta na licencji GPL v2
PoDoFo stworzona przez niemiecką grupę programistów na czele z Dominikiem Seichter'em, oparta na licencji LGPL.
Obie biblioteki są wolnym oprogramowaniem z otwartymi źródłami, obie są napisane w języku C++, obie sa bibliotekami multiplatformowymi. Różnicą pomiędzy tymi dwiema bibliotekami jest fakt, że Poppler posiada swoją implementacje dla Qt co pozwala na łatwiejsze jej wykorzystanie.
Minusem jest fakt, że w internecie nie ma zbyt wielu tutoriali które by prezentowały wykorzystanie Poppler'a dla Qt a dokumentacja jest dostępna jedynie online. Dokumentację można znaleźć na stronie
http://people.freedesktop.org/~aacid/docs/. Niemniej jednak uważam, że wykorzystanie tej biblioteki jest najlepszym rozwiązaniem.
Instalacja w dystrybucjach linuxa ogranicza się do wybrania pakietu Poppler-qt4-dev* lub Poppler-qt5-dev*, zostana zainstalowane pliki nagłówkowe oraz biblioteka. Dla systemu Windows bibliotekę należy ściągnąć ze strony projektu freedesktop.org. Do jej kompilacji niezbędne jest posiadanie kompilatora Gnu C/C++ (MinGW).
Przygotowanie aplikacji.
W swoim pierwszym małym artykule na tym forum napisalem, że będe starał się umieszczać kody pełne, tzn. takie które można przekopiować do pliku/ plików, skompilować i uruchomić. Tak samo będzie tym razem. Ponieważ przedstawię krok po kroku proces tworzenia takiej aplikacji artykuł stanie się nieco obszerny ale myślę, że osobą zainteresowanym tematem nie będzie to przeszkadzało.
Ze względów na zbyt dużą ilość informacji usunąłem z kodów sekcje obsługi spisów treści ponieważ wprowadzała nowy temat jakim jest parsowanie struktury dokumentów a niestety dopiero po jakimś czasie zorientowałem się, że mogłem przecież wysłać na forum dwa zipy, ale ze względu na i tak już dość późną porę myślę, że zostawię tak jak jest w chwili obecnej.
Przygotowujemy podłoże.
Jak to jest z każdą aplikacją okienkową musimy przygotować sobie pewien szablon programuz którego będziemy korzystali, czyli wygląd aplikacji po jej uruchomieniu.
Nasza aplikacja będzie składała się z plików okna głównego, pliku projektu oraz z pliku main który posłuży nam jedynie do zbudowania objektu okna i wyświetlenie go.
Pliki
- OknoGlowne.h -plik nagłówkowy podstawowej funkcjonalności aplikacji
- OknoGlowne.cpp -Plik z definicjami metod i właściwości
- main.cpp -plik main
- pdf.pro - plik projektu
Wiem, że możnaby było skorzystać jeszcze z pliku *.ui ze zdefiniowaną ramką ale uważam, że korzystanie z designerów podczas progreamowania ma jedynie sens w dwóch przypadkach:
1- kiedy chcemy jedynie na szybko sprawdzić funkcjonalność lub nie jesteśmy pewni czy program będzie miał taką szate graficzną jak zakładamy
2- kiedy w zespole tworzącym aplikacje są osoby nie będący programistami, wtedy stworzenie wyglądu okna/dialogu będzie dla nich możliwe.
dlatego całość zawsze staram się wykonac przez hand-code.
Aby nasza aplikacja mogła działać musimy wiedzieć jak jakich bibliotek będziemy używać
i tak dla tego przykładu będziemy korzystali z core, gui (w wersji Qt %.0 wzwyż również z widgets. Dodatkowo musimy zaimportować bibliotekę zewnętrzną dla Popplera, ponieważ ja korzystam z QT w wersji 4.8 zaimportuję bibliotekę poppler-qt4
Tak więc plik projektu wygląda w sposób następujący:
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Kolejną rzeczą jest plik main.cpp. Plik ten będzie nam służył jedynie do celu wyświetlenia okna głównego i wprowadzenia aplikacji w tzw. pętle systemową więc będzie on króciutki. Jego kod jest następujący:
main.cpp
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
.ss
Rzeczą która może wymagać wyjaśnienia jest skorzystanie z klasy QTextCodec. Ustawia ona kodowanie dla łańcuchów znaków (w tym wypadku znajdujących się w tr() ), korzystam z niej ponieważ mój system ma ustawione kodowanie na UTF-8 a bez niej teksty pojawiające się w aplikacji posiadały by tzw."Krzaczki" zamiast polskich liter.
Kolejną rzeczą jest zabranie się za okno główne, utworzenie przycisków, menu programu, paska narzędzi czyli tego wszystkiego co będzie związane z jej głównym działaniem.
Zaczynamy od pliku OknoGlowne.h gdzie będą znajdowały się wszystkie deklaracje użytych zmiennych, objektów itp.
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
Jak widać zaczynamy od zaimportowania plików nagłówkowych okna głównego oraz klasy QObject która jest klasą bazową dla całej biblioteki.
następnie tworze odnośniki do klas z których będe korzystał
class QAction;
........
...
...
Korzystanie z tego rodzaju deklaracji klas w pliku nagłówkowym zalicza się do "dobrego stylu programowania", mógłbym oczywiście dołączyć pełne biblioteki tych klas już w pliku nagłówkowym ale zasadą jest nieobciążanie pliku nagłówkowego innymi plikami nagłówkowymi.
W tym miejscu mówie poprostu kompilatorowi, że klasa taka jak QAction naprawde istnieje i nie ma się co martwić tym, że jeszcze nie znalazłe jej deklaracji
.
Następnie tworzymy docelowy nagłówek klacy czyli
class OknoGlowne który będzie dziedziczył funkcjonalność od klasy QMainWindow
W środku klasy występuje definicja Akcji jakie będą obsługiwane przez nasz program, menu oraz paska narzędzi.
Nazwy zmiennych(właściwości w C++) są oczywiście dowolne, jedynie moim przyzwyczajeniem jest korzystanie z takich a nie innych formatów nazw jak A_Otworz, M_Plik itp...
Gdy ustalimy jakie elementy będą się pojawiały w menu i na pasku zadań przychodzi pora na przemyślenie co będzie głównym elementem okna aplikacji. I tak przeglądając różne czytniki pdf widzimy najczęściej, że główne okno jest podzielone zazwyczaj na dwie sekcje, po lewej stronie jest zazwyczaj spis treści a po prawej aktualnie przeglądana strona. Obszar ze spisem treści można oczywście rozszerzać co ma wpływ na zmniejszanie się widoczności obszaru z aktualnie oglądaną stroną i do tego służy włąśnie taki objekt jak QSplitter. Więc postanowiłem nie odchodzić zbytnio od norm i tez wykorzystuje taką właściwość dzięki właśnie zastosowaniu splittera.
Aby nasza strona mogła się przesówać gdy będzie zbyt duża i nie zmieści się na ekranie wykorzystuję ScrollBar poprzez umieszczenie elementów w QScrollArea.
Następnie kilka zmiennych pomocniczych które będą odpowiedzialne za zapamiętanie stanu okna, pobranie nazwy pliku itp.
Kolejna rzecz to metody.
Metody takie jak
Kod:
configAction
configMenu
setMainWindow
pozostawiam prywatne dla klasy poniewać wykorzystanie ich przez osoby trzecie nie jest jakoś szczególnie potrzebne. Dla mnie to też jest informacja żeby zbytnio nie grzebać w ich zawartości w przyszłości.
Dochodzimy do mechanizmu slotów, w tym przypadku napisanych w taki sposób, że mogą być publiczne ale nie narobią szkód w razie błędnego użycia
Są to głównie sloty do obsługi okienka i dokumentu PDF prócz jednego który służy do wyświetlenia informacji o autorze.
Plik OknoGlowne.cpp
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
No tu już jest troszkę więcej. Na początku importujemy wszystkie te biblioteki których deklarację użyłem w pliku nagłówkowym (class QAction itp.) i parę dodatkowych z których będziemy korzystali w metodach znajdujących się w pliku .cpp. Ktoś mógłby zapytać czy da się to zrobić łatwiej. Oczywiście, że się da importując poprostu bibliotekę
Kod:
#include <QtGui>
Ale taki manewr powinien być wykorzystywany jedynie gdy testujemy aplikację podczas pisania i nie wiemy która klasa by lepiej się nadawała do spełnienia zadania, wtedy nie musimy wracać do początku pliku żeby załadować inną biblioteke tylko mamy już całe gui załadowane odrazu. Choć taka możliwość istnieje to przyznam, że moim nawykiem jest jednak ładowanie bibliotek jedynie wymaganych a nie wrzucanie całego GUI.
Ok.
Po załadowaniu bibliotek zaczynamy od napisania konstruktora czyli
język cpp-qt
Musisz się zalogować, aby zobaczyć kod źródłowy. Tylko zalogowani użytkownicy mogą widzieć kod.
To co się w nim znajduje odpowiada temu co zostanie wykonane podczas tworzenia objektu
Jednym słowem cała konfiguracja, definicja objektów itp. Wszystko to w tych paru linijkach
A dlatego, że wykonujemy poprostu po kolei kolejne metody odpowiedzialne za ustawienie mechanizmu akcji, połączeń sygnałów i slotów itp itd.
Ok, Co może wymagać wyjaśnienia odnośnie pozostałej części pliku .cpp
-Niektóre funkcje takie jak pomniejszSL() kt ore dodatkowo są tak zwanymi slotami pozostawiłem puste, dlatego, żeby można było spokojnie skompilować aplikacje na tym etapie i poprawić jej wygląd zanim przejdziemy dalej.
-Tworząc menu korzystam z zapisu mn.
Kod:
M_Plik = menuBar()->addMenu( tr("Plik") );
co nie tworzy nowego objektu tylko zwraca referencje do już istniejącego. Bo tak naprawde nie istnieje okno główne które nie posiada menu ale to menu jest poprostu puste, taki zapis wypełnia je co sprawia, że staje się dla nas widoczne
- Połączenie akcji z objektem qApp
Kod:
connect(A_OQt, SIGNAL(triggered()), qApp, SLOT(aboutQt()) );
oznacza, że dana rzecz w tym wypadku wyświetlenie okienka informacyjnego będzie odbywała się przez objekt globalny (zresztą statyczny) qApp który występuje w każdej aplikacji i posiada kopie najważniejszych zmiennnych systemu. Taki objekt jest tworzony już na starcie programu w funkcji main(){...} gdy tworzymy tzw. instancje aplikacji QApplication app(...)...
-Wykorzystanie QKeySequence jest tu używane do ustalenia klawiszy skrótów, czasem można zaóważyć, że sktóty tworzone są na sztywno a czasem pobierane są z ustawień systemu. Tak naprawde to zastanawiałem się czy ten dzisiejszy wpis nie będzie dotyczył właśnie tego ale wybór padł na obsługę PDF
.
Ok to chyba wszystko jak do tej pory, mamy gotowy widok aplikacji która pokazuje okno głowne, ma możliwość zmiany swojego rozmiaru, pozwala przejść do trybu pełnoekranowego co jest przydatną rzeczą, posiada pasek menu, pasek narzędzi który można pokazać lub ukryć i jest wstępnie przygotowana do pierwszego wczytania dowolnego PDF'a
Poniżej znajdują się pliczki spakowane zipem zawierające kod źródłowy oraz skompilowany plik wykonywalny dla debiana (jeżeli ktoś miałby możliwość skompilować to dla windows i umieścić tu to byłbyum wdzięczny) A za chwilkę już przedstawię główny mechanizm czyli obsługę biblioteki PDF.
Poniżej jeszcze tylko kilka fotek z działającą aplikacją gdyby ktoś aktualnie nie posiadał QT.
Niestety widzę, że forum nie obsługuje formatowania tekstu, ale mimo wszystko nie wygląda tragicznie więc zostawiam