abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×

    dnes 00:11 | Nová verze

    Jonathan Thomas oznámil vydání nové verze 4.1 video editoru OpenShot (Wikipedie). Zdrojové kódy OpenShotu jsou k dispozici na GitHubu. Ke stažení je i balíček ve formátu AppImage. Stačí jej stáhnout, nastavit právo na spouštění a spustit.

    Ladislav Hagara | Komentářů: 0
    včera 23:33 | Zajímavý článek

    Při běžné migraci virtuálního stroje mezi hypervizory se jeho MAC adresa přesune na jiný leaf switch. EVPN tuto změnu distribuuje pomocí BGP Type-2 route a MAC mobility sequence number. Problém nastává, pokud útočník podvrhne zdrojovou MAC adresu jiného zařízení. Leaf může změnu interpretovat jako legitimní přesun MAC a rozšířit ji přes BGP do celé fabric. Výsledkem může být přesměrování provozu určeného původnímu zařízení. Autor článku rozebírá možnosti detekce pomocí sledování MAC moves, BGP route reflektorů a kontroly na přístupové vrstvě.

    vencour | Komentářů: 0
    včera 15:11 | Nová verze

    Vývojáři desktopového prostředí Enlightenment (Wikipedie) a souvisejících knihoven Enlightenment Foundation Libraries (EFL) vydali nové verze. Enlightenment byl vydán ve verzi 0.28.0 a Enlightenment Foundation Libraries ve verzi 1.29.

    Ladislav Hagara | Komentářů: 3
    včera 13:55 | Zajímavý článek

    Cloudflare zjistil, že některé odpovědi modelu GLM-5.3 obsahovaly části dat z předchozích požadavků jiných zákazníků. Příčinou byla kombinace chybné konfigurace a chyby v inference enginu SGLang. Model podporoval kontextové okno 1 048 576 tokenů, ale GPU KV cache pool měl kapacitu pouze 681 280 tokenů. Při překročení kapacity docházelo k nesprávnému zpracování odmítnutého požadavku. Decode část systému následně pracovala se starými

    … více »
    vencour | Komentářů: 1
    včera 13:00 | Zajímavý článek

    Vývojáři Knot Resolver vysvětlují, jak změnili rozhodování o tom, které DNS záznamy ponechat v cache a které odstranit. Článek obsahuje skutečná měření: devět hodin DNS provozu při 2 000 QPS, srovnání cache o velikosti 25 MB a 40 GB a také porovnání s BIND 9, kromě algoritmů obsahuje konkrétní doporučení pro konfiguraci a diagnostiku.

    vencour | Komentářů: 0
    30.10. 13:44 | IT novinky

    Největší kryptoměnová burza světa Binance se stala terčem útoku, při kterém podvodníci odcizili během několika minut kryptoměny v hodnotě přibližně 6,3 miliardy dolarů. Jedná se o největší kryptoměnovou krádež v historii, přibližně čtyřikrát větší než loňský útok na burzu Bybit. Binance se podařilo ve spolupráci s partnery zmrazit aspoň aktiva v hodnotě zhruba 3 miliard dolarů a slíbila, že veškeré ztráty pokryje z vlastních prostředků.

    Ladislav Hagara | Komentářů: 16
    30.10. 02:16 | Bezpečnostní upozornění

    Zranitelnost CVE-2026-98432 s CVSS 9.8 odhalila AI od společnosti Anthropic. Jedná se o kritickou chybu v implementaci MPTCP (multipath TCP). Debian vydal patche 16.10. a 22.10., ale např. Ubuntu je zatím bez opravy. Více informací na The Hacker News.

    Max | Komentářů: 20
    29.10. 23:22 | Zajímavý software

    Na Slovensku vznikla úplne nová rally hra, ktorá je zadarmo a funguje vo Windowse, Linuxe či na Macu. Greenie Rally má viac ako 50 tratí a vozidiel, šampionáty či turnaje. Má retro feeling a imituje automobilové hry z prelomu tisícročí. Vyskúšate prejsť všetky mapy na Škode 130RS?

    Stanislav Hoferek | Komentářů: 13
    29.10. 14:33 | Komunita

    Do základního systému NetBSD -current byl přidán nový editor atto jako alternativa k editorům vi a xedit.

    Ladislav Hagara | Komentářů: 1
    29.10. 14:11 | IT novinky

    Společnost System76 představila kompaktní 11litrový Thelio Prime Desktop. S procesorem AMD Ryzen 9000. S Pop!_OS 24.04 LTS s desktopovým prostředím COSMIC nebo Ubuntu 24.04 LTS.

    Ladislav Hagara | Komentářů: 0
    Které desktopové prostředí na Linuxu používáte?
     (9%)
     (7%)
     (4%)
     (21%)
     (30%)
     (9%)
     (5%)
     (2%)
     (14%)
     (20%)
    Celkem 2959 hlasů
     Komentářů: 34, poslední 26.10. 08:24
    Rozcestník

    Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)

    30. 4. 2009 | David Watzke | Programování | 10977×

    V tomto díle si ukážeme použití WebKitu ve webovém prohlížeči s taby a použití Phononu v jednoduchém přehrávači zvuku. Také si řekneme, jak z programu vyvolat další okno a co je to modálnost oken.

    Webový prohlížeč (WebKit a taby)

    WebKit je framework pro vykreslování HTML, jehož port je v Qt dostupný od verze 4.4.

    Qt poskytuje widget QWebView, což je z uživatelského hlediska prostor pro vykreslení webové stránky. Když jej propojíme s několika málo ovládacími prvky, tak získáme relativně schopný webový prohlížeč s podporou tabů a sotva dvěma sty řádky kódu (viz níže). Pro představu: načtení stránky spočívá ve spuštění metody load() s argumentem URL.

    Rozhraní s taby poskytuje třída QTabWidget, jejíž použití je celkem prosté. Do rozhraní se přidávají taby metodou addTab(), které se jako argument mj. předá widget, který bude na tabu zobrazený. Po zavolání metody setTabsClosable(true) lze taby i zavírat. Obsluhu zavření musíte poskytnout vy sami. K dispozici máte signál tabCloseRequested() s indexem jako argument. Ten tedy napojíte na váš slot, který se postará o korektní zničení tabu na daném indexu. Odstranění tabu obstarává metoda removeTab(), která však nesmaže widget, který na tabu byl zobrazený, takže ve většině případů je lepší smazat tento widget, což rovněž zapříčiní zavření tabu. Přepínání tabů funguje i bez zásahů, ale v případě potřeby lze obsloužit reakcí na signál currentChanged() s indexem nového tabu jako argument, čehož v ukázce využívám.

    Při pročítání kódu si všimněte praktického použití QRegExp, o kterém jsme mluvili minule. Novinkou je zde odpojení signálů od slotů. Chceme-li jednoduše odpojit všechno, co je napojené na signály widgetu, můžeme zavolat buď metodu daného widgetu:

    widget->disconnect()

    nebo statickou metodu třídy QObject:

    disconnect(widget, 0, 0, 0)

    Pro více ukázek se podívejte do dokumentace k QObject::disconnect().

    Při vytváření GUI projektu v Qt Creatoru nezapomeňte povolit modul QtWebKit nebo případně přidat do .pro souboru:

    QT += webkit

    To zajistí doplnění cest ke hlavičkovým souborům a linkování s knihovnami WebKitu.

    browser.h: API.

    #ifndef BROWSER_H
    #define BROWSER_H
    
    #include <QMainWindow>
    #include <QUrl>
    
    class QLabel;
    class QLineEdit;
    class QProgressBar;
    class QTabWidget;
    class QWebView;
    
    class Browser : public QMainWindow
    {
    	Q_OBJECT
    
    public:
    	Browser(QWidget *parent = 0);
    
    private:
    	QLabel* statusLabel;
    	QLineEdit* urlBar;
    	QProgressBar* loading;
    	QTabWidget* tabs;
    	// "web" je widget poskytující webový prohlížeč
    	QWebView* web;
    
    private slots:
    	void addNewTab();
    	void tabChanged(int);
    	void closeTab(int);
    	void setLoadingStatus(bool);
    
    	void loadUrl();
    	void setUrl(QUrl);
    	void changeTitle(QString);
    
    	void goBack();
    	void goForward();
    	void reload();
    	void stop();
    };
    
    #endif // BROWSER_H
    

    browser.cpp: Z důvodu přehlednosti jsem navrhl GUI ručně, místo použití Designeru, který by mi v tomto případě práci ani příliš neusnadnil. Novinkou je zde použití qobject_cast místo static_cast pro přetypování. qobject_cast se chová podobně jako dynamic_cast v C++, ale má několik výhod; například nepotřebuje RTTI. Funguje pouze na objekty, které přímo či nepřímo dědí QObject a jsou deklarovány s makrem Q_OBJECT.

    #include "browser.h"
    
    #include <QAction>
    #include <QKeySequence>
    #include <QLabel>
    #include <QLineEdit>
    #include <QProgressBar>
    #include <QPushButton>
    #include <QRegExp>
    #include <QStatusBar>
    #include <QStyle>
    #include <QTabWidget>
    #include <QToolBar>
    #include <QWebView>
    
    Browser::Browser(QWidget *parent)
    	: QMainWindow(parent), web(0)
    {
    	// vytvoříme widgety:
    	// políčko pro URL
    	urlBar = new QLineEdit;
    	// rozhraní s taby
    	tabs = new QTabWidget;
    	// tlačítko napravo od tabů pro vytvoření nového
    	QPushButton* newTabBtn = new QPushButton(style()->standardIcon(QStyle::SP_FileDialogNewFolder), "", tabs);
    	// text ve stavovém řádku
    	statusLabel = new QLabel;
    	// průběh načítání stránky ve stavovém řádku
    	loading = new QProgressBar;
    	// panel nástrojů (obsahující ovládací prvky prohlížeče)
    	QToolBar* toolBar = addToolBar(tr("Controls"));
    
    	// přidáme akce do panelu nástrojů a rovnou je napojíme na sloty
    	toolBar->addAction(style()->standardIcon(QStyle::SP_ArrowBack), tr("Back"), this, SLOT(goBack()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_ArrowForward), tr("Forward"), this, SLOT(goForward()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_BrowserReload), tr("Reload"), this, SLOT(reload()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_BrowserStop), tr("Stop"), this, SLOT(stop()));
    	// uložíme si ukazatel akce pro vytvoření nového tabu
    	QAction* actionAddTab = toolBar->addAction(style()->standardIcon(QStyle::SP_FileDialogNewFolder),
    						   tr("New tab"), this, SLOT(addNewTab()));
    	// a přiřadíme jí klávesovou zkratku
    	actionAddTab->setShortcut(QKeySequence("Ctrl+T"));
    	// přidáme adresní řádek
    	toolBar->addWidget(urlBar);
    	toolBar->addAction(style()->standardIcon(QStyle::SP_CommandLink), tr("Go"), this, SLOT(loadUrl()));
    
    	// propojíme tlačítko pro přidání tabů
    	connect(newTabBtn, SIGNAL(clicked()), this, SLOT(addNewTab()));
    
    	// reakce na změnu aktuálního tabu
    	connect(tabs, SIGNAL(currentChanged(int)), this, SLOT(tabChanged(int)));
    	// reakce na zavření daného tabu
    	connect(tabs, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
    	// reakce stisknutí Enteru v adresním řádku
    	connect(urlBar, SIGNAL(returnPressed()), this, SLOT(loadUrl()));
    
    	// přidáme tlačítko vedle tabů
    	tabs->setCornerWidget(newTabBtn);
    	// povolíme přesouvání tabů
    	tabs->setMovable(true);
    
    	// nastavíme pevnou šířku ukazateli průběhu
    	loading->setFixedWidth(100);
    
    	// nastavíme hlavnímu oknu:
    	// hlavní widget (rozhraní s taby)
    	setCentralWidget(tabs);
    	// a stavový řádek
    	setStatusBar(new QStatusBar);
    	// popisek ve stavovém řádku nebude zvětšovat okno
    	statusBar()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
    	// přidáme do stavového řádku popisek
    	statusBar()->addWidget(statusLabel);
    	// a ukazatel průběhu
    	statusBar()->addPermanentWidget(loading);
    
    	// vytvoříme první tab
    	addNewTab();
    	// nastavíme do adresního řádku adresu abclinuxu
    	urlBar->setText("http://www.abclinuxu.cz");
    	// a stránku načteme
    	loadUrl();
    
    	// nastavíme výchozí velikost okna
    	resize(950, 700);
    }
    
    // vytvoří nový tab
    void Browser::addNewTab()
    {
    	// přidáme tab
    	int index = tabs->addTab(new QWebView, tr("New tab"));
    
    	// pokud máme víc než 1 tab,
    	if(tabs->count() > 1)
    	{
    		// přepneme se na tab nově vytvořený
    		tabs->setCurrentIndex(index);
    		// a povolíme zavírání tabů
    		tabs->setTabsClosable(true);
    	}
    
    	// vyprázdníme adresní řádek
    	urlBar->setText("");
    	// vynulujeme ukazatel průběhu načítání
    	loading->reset();
    	// nastavíme titulek okna
    	setWindowTitle("WebKit browser");
    }
    
    void Browser::tabChanged(int index)
    {
    	// pokud si zavřeme poslední tab, dostaneme index o hodnotě -1
    	// a k tomu by nemělo dojít, takže v debug. verzi shodíme program
    	Q_ASSERT(index >= 0);
    	// v obyčejné verzi se problém pokusíme obejít přidáním nového tabu
    	if(index < 0)
    	{
    		addNewTab();
    		return;
    	}
    
    	if(web)
    	{
    		// odpojíme tab ze kterého přepínáme od GUI slotů (viz níže)
    		disconnect(web, SIGNAL(urlChanged(QUrl)), this, SLOT(setUrl(QUrl)));
    		disconnect(web, SIGNAL(titleChanged(QString)), this, SLOT(changeTitle(QString)));
    		disconnect(web, SIGNAL(loadProgress(int)), loading, SLOT(setValue(int)));
    		disconnect(web, SIGNAL(loadFinished(bool)), this, SLOT(setLoadingStatus(bool)));
    		disconnect(web->page(), SIGNAL(linkHovered(QString,QString,QString)), statusLabel, SLOT(setText(QString)));
    	}
    
    	// získáme prohlížeč aktuálního tabu
    	web = qobject_cast<QWebView*>( tabs->widget(index) );
    
    	// a napojíme jej na GUI:
    	// projeví změnu URL z prohlížeče do adresního řádku
    	connect(web, SIGNAL(urlChanged(QUrl)), this, SLOT(setUrl(QUrl)));
    	// nastaví titulek stránky jako titulek okna a tabu
    	connect(web, SIGNAL(titleChanged(QString)), this, SLOT(changeTitle(QString)));
    	// zobrazuje průběh načítání
    	connect(web, SIGNAL(loadProgress(int)), loading, SLOT(setValue(int)));
    	connect(web, SIGNAL(loadFinished(bool)), this, SLOT(setLoadingStatus(bool)));
    	// když kurzor najede na odkaz, zobrazíme jeho cíl ve stavovém řádku
    	connect(web->page(), SIGNAL(linkHovered(QString,QString,QString)), statusLabel, SLOT(setText(QString)));
    
    	// načteme správnou adresu do adresního řádku
    	setUrl(web->url());
    	// vyprázdníme text ve stavovém řádku
    	statusLabel->setText("");
            // změníme titulek okna
            setWindowTitle(tabs->tabText(tabs->currentIndex()));
    }
    
    // zavře tab s daným indexem
    void Browser::closeTab(int index)
    {
    	// v případě, že zavíráme aktuální tab, nastavíme web na 0, aby se tabChanged() nepokoušelo
    	// odpojovat neexistující widget
    	if(tabs->widget(index) == web)
    		web = 0;
    
    	// smazání widgetu zavře tab
    	delete tabs->widget(index);
    
    	// pokud po zavření akt. tabu zbyl už jen jeden, zakážeme jeho zavření
    	if(tabs->count() < 2)
    		tabs->setTabsClosable(false);
    }
    
    // informuje ve stavovém řádku o úspěšnosti načtení stránky
    void Browser::setLoadingStatus(bool ok)
    {
    	QString text = tr("OK");
    	if(!ok) text = tr("Loading failed");
    	statusLabel->setText(text);
    }
    
    // načte adresu zadanou v adresním řádku
    void Browser::loadUrl()
    {
    	QString url = urlBar->text();
    
    	// pokud daná adresa neobsahuje protokol, předpokládáme http://
    	if(!url.contains(QRegExp("^[a-z]+://")))
    		url.prepend("http://");
    
    	// načteme připravenou adresu
    	web->load(QUrl(url, QUrl::TolerantMode));
    }
    
    // nastaví dané URL do adresního řádku
    void Browser::setUrl(QUrl url)
    {
    	// z URL odstraníme přihlašovací informace
    	urlBar->setText(url.toString(QUrl::RemoveUserInfo));
    }
    
    // nastaví titulek okna a aktuálního tabu
    void Browser::changeTitle(QString title)
    {
    	if(title.isEmpty())
    		title = web->url().toString(QUrl::RemoveUserInfo);
    
    	setWindowTitle(title);
    	tabs->setTabText(tabs->currentIndex(), title);
    }
    
    // "Zpět" v prohlížeči
    void Browser::goBack()
    {
    	web->back();
    }
    
    // "Vpřed" v prohlížeči
    void Browser::goForward()
    {
    	web->forward();
    }
    
    // "Obnovit" v prohlížeči
    void Browser::reload()
    {
    	web->reload();
    }
    
    // "Stop" v prohlížeči
    void Browser::stop()
    {
    	web->stop();
    }
    

    Zdrojáky si můžete stáhnout v archívu browser.tar.bz2.

    Webový prohlížeč založený na WebKitu

    qt 4 browser linux qt 4 browser windows

    Přehrávač zvuku (Phonon, modálnost oken)

    Phonon je multiplatformní multimediální framework, který umožňuje přehrávat multimédia přes různé enginy, jako je Xine a GStreamer. Byl vyvinut pro použití v KDE 4 a Qt jej obsahuje od verze 4.4. Phonon pro KDE 4 je kompatibilní s tím, který je součástí Qt, takže pokud máte KDE 4, tak do .pro souboru přidejte kromě

    QT += phonon

    což zajistí linkování s tímto modulem, navíc ještě

    INCLUDEPATH += /usr/include/KDE

    Tímto umožníte chod vašeho Qt programu, který používá Phonon, uživatelům KDE 4 (na unixech).

    Základní použití Phononu pro přehrávání zvuku je velice jednoduché. Stačí si vytvořit objekt reprezentující zvukový výstup (Phonon::AudioOutput), objekt pro samotné přehrávání (Phonon::MediaObject) a následně tyto dva objekty propojit pomocí Phonon::createPath(). Teď už jen předáme objektu pro přehrávání nějaké URL pomocí setCurrentSource() a můžeme zavolat play() pro zahájení přehrávání. Tolik tedy k Phononu.

    Když chcete za běhu programu zobrazit okno (např. dialog s nastavením), postup je podobný jako při zobrazování hlavního okna metodou QWidget::show(). Teď před námi ovšem stojí jedno rozhodnutí: bude naše okno modální? Modální okno blokuje přístup k ostatním oknům programu, zatímco nemodální se otevře jako nezávislé okno, obvykle s vlastní položkou v pruhu úloh na panelu. Tato vlastnost se nastavuje metodou setWindowModality() a dává smysl pochopitelně jen u oken. Modálnost se rozděluje na dvě varianty, buď okno blokuje přístup k celému programu (výchozí chování) nebo jen k rodičovskému oknu.

    Často se místo běžného okna (QWidget) hodí použít dialog (QDialog), jehož použití uvidíte v následující ukázce, kde nám poslouží jako dialog s nastavením. Existuje několik možností jak dialog zobrazit:

    Metoda (slot) Modálnost Okamžitý return
    show() respektuje nastavení, výchozí = nemodálníano
    exec() vynutí modální dialogne, vrací návratovou hodnotu
    open() vynutí modální dialog blokující rodičovské oknoano

    Jaký režim tedy používat - modální, nebo nemodální? Je to na vás. Vhodné je rozhodnout se na základě účelu daného dialogu. Pokud jde o velice jednoduchý dialog, jako třeba ten v mé ukázce, tak tam asi modálnost nikomu vadit nebude, ale pokud půjde třeba o rozsáhlejší dialog s nastavením, které bude možné aktivovat tlačítkem "Použít", potom stojí za zvážení použití nemodální okno. Důvod, proč někteří programátoři používají modální okna i tam, kde se přiliš nehodí, může být fakt, že nemodální jsou trochu složitější na naprogramování, jelikož slot pro zobrazení okna ihned vrací a programátor musí sám hlídat, aby stejný dialog nebylo možné vyvolat dvakrát. Rozdíl si můžete prohlédnout v ukázce obsažené v dokumentaci.

    main.cpp: Nastavíme název programu a organizace (nebo doménu) kvůli nastavení (QSettings) a Phononu, který to vyžaduje pro D-Bus.

    #include <QApplication>
    #include "player.h"
    
    int main(int argc, char *argv[])
    {
    	QApplication a(argc, argv);
    	a.setApplicationName("SimplePhononPlayer");
    	a.setOrganizationDomain("watzke.cz");
    
    	Player w;
    	w.setWindowTitle(a.applicationName());
    	w.show();
    
    	return a.exec();
    }
    

    player.h: API.

    #ifndef PLAYER_H
    #define PLAYER_H
    
    #include <QMainWindow>
    #include <QSettings>
    #include <Phonon/AudioOutput>
    #include <Phonon/MediaObject>
    class QLabel;
    
    using namespace Phonon;
    
    class Player : public QMainWindow
    {
    	Q_OBJECT
    
    public:
    	Player(QWidget *parent = 0);
    	~Player();
    
    private:
    	AudioOutput* ao;
    	MediaObject* mo;
    
    	QLabel* statusLabel;
    	QSettings settings;
    
    private slots:
    	void openSettings();
    	void playFile();
    	void setStatusMessage(Phonon::State, Phonon::State);
    };
    
    #endif // PLAYER_H
    

    player.cpp: Zde je novinkou použití makra Q_UNUSED. Nestojí za tím žádná věda, slouží to čistě jen k umlčení kompilátoru, který by si jinak stěžoval na nevyužitou proměnnou, které díky tomuto můžete nastavit smysluplný název.

    #include "player.h"
    #include "settings.h"
    
    #include <QFileDialog>
    #include <QLabel>
    #include <QToolBar>
    #include <QStatusBar>
    #include <QStyle>
    
    #include <Phonon/VolumeSlider>
    #include <Phonon/SeekSlider>
    
    Player::Player(QWidget *parent)
    	: QMainWindow(parent)
    {
    	// vytvoříme zvukový výstup,
    	ao = new AudioOutput(this);
    	// objekt pro přehrávání multimédií
    	mo = new MediaObject(this);
    	// a propojíme je spolu
    	Phonon::createPath(mo, ao);
    
    	// vytvoříme a naplníme panel nástrojů
    	QToolBar* toolBar = addToolBar(tr("Controls"));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_DialogOpenButton),
    			   tr("Select a file"), this, SLOT(playFile()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_ComputerIcon),
    			   tr("Settings"), this, SLOT(openSettings()));
    	toolBar->addSeparator();
    	toolBar->addAction(style()->standardIcon(QStyle::SP_MediaStop),
    			   tr("Stop"), mo, SLOT(stop()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_MediaPause),
    			   tr("Pause"), mo, SLOT(pause()));
    	toolBar->addAction(style()->standardIcon(QStyle::SP_MediaPlay),
    			   tr("Play"), mo, SLOT(play()));
    	toolBar->addSeparator();
    	// přidáme widget pro ovládání hlasitosti, který Phonon nabízí
    	toolBar->addWidget(new VolumeSlider(ao));
    	// vynutíme si text vedle ikon
    	toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    
    	// jako hlavní widget nastavíme posuvník, který je součástí Phononu
    	setCentralWidget(new SeekSlider(mo));
    
    	// vytvoříme stavový řádek
    	setStatusBar(new QStatusBar);
    	// a na něm textovou oblast pro zobrazování informací
    	statusBar()->addWidget(statusLabel = new QLabel(tr("Idle")));
    	// dlouhé hlášky ve stavovém řádku nebudou roztahovat okno
    	statusBar()->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Preferred);
    	// skryjeme úchyt pro změnu velikosti okna
    	statusBar()->setSizeGripEnabled(false);
    
    	// změna stavu přehrávání vyvolá zobrazení patřičné informace
    	connect(mo, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
    		this, SLOT(setStatusMessage(Phonon::State,Phonon::State)));
    
    	// nastavíme výchozí velikost okna na doporučené hodnoty
    	resize(sizeHint());
    
    	// obnovíme geometrii okna; pokud není uložená, použijeme aktuální (žádná změna)
    	restoreGeometry(settings.value("geometry", saveGeometry()).toByteArray());
    }
    
    Player::~Player()
    {       // pokud je nastavené zapamatování geometrie okna, uložíme ji, jinak záznam smažeme
    	if(settings.value("Settings/rememberGeometry", false).toBool())
    		settings.setValue("geometry", saveGeometry());
    	else
    		settings.remove("geometry");
    }
    
    // otevře okno s nastavením
    void Player::openSettings()
    {
    	// vytvoříme okno
    	Settings window(settings);
    	// vynutíme modálnost a zobrazíme okno
    	window.exec();
    }
    
    // spustí přehrávání zvoleného souboru
    void Player::playFile()
    {
    	QString fileName = QFileDialog::getOpenFileName(this, tr("Select an audio file"));
    
    	if(fileName.isEmpty())
    		return;
    
    	mo->setCurrentSource(fileName);
    	mo->play();
    }
    
    // nastaví informaci o stavu do stavového řádku
    void Player::setStatusMessage(Phonon::State newState, Phonon::State prevState)
    {
    	Q_UNUSED(prevState);
    
    	QString status;
    
    	switch(newState)
    	{
    	case Phonon::LoadingState:
    		status = tr("Loading") + "...";
    		break;
    	case Phonon::StoppedState:
    		status = tr("Stopped");
    		break;
    	case Phonon::PlayingState:
    		status = tr("Playing ") + mo->currentSource().fileName();
    		break;
    	case Phonon::BufferingState:
    		status = tr("Buffering") + "...";
    		break;
    	case Phonon::PausedState:
    		status = tr("Paused");
    		break;
    	case Phonon::ErrorState:
    		status = tr("Error: ") + mo->errorString();
    		break;
    	default:
    		break;
    	}
    
    	if(!status.isEmpty())
    	{
    		statusLabel->setText(status);
    		// když uživatel najede kurzorem na informaci, zobrazí se mu v tooltipu,
    		// což se může hodit, když se informace nevejde do okna celá
    		statusLabel->setToolTip(status);
    	}
    }
    

    settings.h: API.

    #ifndef SETTINGS_H
    #define SETTINGS_H
    
    #include <QDialog>
    #include <QSettings>
    
    class QCheckBox;
    
    class Settings : public QDialog
    {
    	Q_OBJECT
    
    public:
    	Settings(QSettings& settings);
    
    private:
    	QSettings* m_settings;
    	QCheckBox* geometryCb;
    
    protected:
    	void accept();
    };
    
    #endif // SETTINGS_H
    

    settings.cpp:

    #include "settings.h"
    
    #include <QCheckBox>
    #include <QDialogButtonBox>
    #include <QVBoxLayout>
    
    Settings::Settings(QSettings& settings)
    {
    	// uložíme si ukazatel na instanci objektu s nastavením
    	m_settings = &settings;
    
    	// vytvoříme zaškrtávací pole
    	geometryCb = new QCheckBox(tr("Remember main window's geometry"));
    	// a std. dialogová tlačítka,
    	QDialogButtonBox* dialogButtons = new QDialogButtonBox;
    	// konkrétně "OK" a "Zrušit"
    	dialogButtons->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
    
    	// propojíme signály tlačítek s patřičnými sloty
    	connect(dialogButtons, SIGNAL(accepted()), this, SLOT(accept()));
    	connect(dialogButtons, SIGNAL(rejected()), this, SLOT(reject()));
    
    	// vytvoříme rozložení ovl. prvků
    	QVBoxLayout* layout = new QVBoxLayout(this);
    	layout->addWidget(geometryCb);
    	layout->addWidget(dialogButtons);
    
    	// zaškrtávací pole odráží aktuální hodnotu nastavení
    	if(m_settings->value("Settings/rememberGeometry", false).toBool())
    		geometryCb->setChecked(true);
    
    	// titulek okna
    	setWindowTitle(tr("Settings"));
    }
    
    // uloží nastavení a zavře dialog
    void Settings::accept()
    {
    	m_settings->setValue("Settings/rememberGeometry", geometryCb->isChecked());
    	done(QDialog::Accepted);
    }
    

    Zdrojáky si můžete stáhnout v archívu okna.tar.bz2.

    Přehrávač zvuku založený na Phononu

    Závěr

    V příštím díle si ukážeme, jak vytvářet překlady programů a jak k programům přibalit různá data (např. obrázky, zvuky, atp.).

           

    Hodnocení: 100 %

            špatné • dobré        

    Nástroje: Tisk bez diskuse

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    Komentáře

    Vložit další komentář

    Petr Bravenec avatar 30.4.2009 07:40 Petr Bravenec | skóre: 43 | blog: Bravenec
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken

     Geniální. S Qt si hraju už dlouho a oceňuji, že mi někdo strčí pod nos takovou studnici nápadů. Tahat tyhle věci někde ze zdrojáků hotových aplikací je únavné - tady mám nápad přímo a bez příkras :-)

    Petr Bravenec - Hobrasoft s.r.o.
    mirec avatar 30.4.2009 08:07 mirec | skóre: 33 | blog: mirecove_dristy | Poprad
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    Keď sme pri webkite minule som sa hral s webkitom .. a podarilo sa mi napísať browser s podporou ARGB ;) Celkom sranda cez web s polopriehľadným pozadím stránky vidieť plochu ;)
    LinuxOS.sk | USE="-fotak -zbytocnosti -farebne_lcd +vydrz +odolnost +java" emerge telefon
    30.4.2009 11:00 Jan Molič
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    Děkuji za výborný článek! Přesně tohle jsou ta počáteční "nakopnutí", která člověk ocení, když má začít v něčem programovat a naprosto se v tom neorientuje.
    David Watzke avatar 30.4.2009 22:10 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    Díky. Jsem rád, že se líbí. Snažím se vybírat užitečný věci.
    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon
    Martin Stiborský avatar 30.4.2009 17:57 Martin Stiborský | skóre: 26 | blog: Stibiho bláboly | Opava
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)

    Fakt skvělý seriál. Dík za vysvětlení "modálnosti". Hned využiji.


    Kvík ..
    mirec avatar 30.4.2009 18:37 mirec | skóre: 33 | blog: mirecove_dristy | Poprad
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    Tá modálnosť je geniálna vec. Teda presne povedané to, že exec sa vráti do funkcie až po zatvorení okna .. na jednoduchšie dialógy veľmi efektívne a hlavne nezablokuje main loop.
    LinuxOS.sk | USE="-fotak -zbytocnosti -farebne_lcd +vydrz +odolnost +java" emerge telefon
    Jardík avatar 30.4.2009 22:52 Jardík | skóre: 40 | blog: jarda_bloguje
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    A co třeba někdy CSS skinování widgetů ...
    Věřím v jednoho Boha.
    David Watzke avatar 30.4.2009 23:00 David Watzke | skóre: 74 | blog: Blog... | Praha
    Rozbalit Rozbalit vše Re: Grafické programy v Qt 4 - 6 (WebKit, Phonon, taby, modálnost oken)
    To je dobrej nápad, někdy o tom napíšu.
    “Being honest may not get you a lot of friends but it’ll always get you the right ones” ―John Lennon

    Založit nové vlákno • Nahoru

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.