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í
×
    včera 00:22 | Nová verze

    Byla vydána verze 1.96.0 programovacího jazyka Rust (Wikipedie). Podrobnosti v poznámkách k vydání. Vyzkoušet Rust lze například na stránce Rust by Example.

    Ladislav Hagara | Komentářů: 0
    28.5. 20:33 | IT novinky

    Společnosti IBM a Red Hat představily Project Lightwell s investicí 5 miliard dolarů. Jedná se o důvěryhodné clearingové centrum pro bezpečnost open source softwaru a zabezpečení dodavatelských řetězců s novým AI modelem a globální skupinou více než 20 000 softwarových inženýrů. Služby centra budou dostupné prostřednictvím komerčních předplatných. Project Lightwell staví na iniciativách jako Anthropic Glasswing nebo OpenAI Trust Access for Cyber.

    Ladislav Hagara | Komentářů: 1
    28.5. 18:22 | Nová verze

    Open source 3D herní a simulační engine Open 3D Engine (O3DE) byl vydán v nové verzi 26.05. Podrobný přehled novinek v poznámkách k vydání.

    Ladislav Hagara | Komentářů: 0
    28.5. 11:44 | IT novinky

    Český stát by v budoucnu mohl provozovat vlastní alternativu ke komunikačním aplikacím typu WhatsApp, Signal, Telegram, Facebook Messenger a podobně. Cílem je zajistit bezpečnou datovou komunikaci pro stát a jeho důležité subjekty, jako jsou bezpečnostní složky, ministerstva a další organizace.

    Ladislav Hagara | Komentářů: 23
    28.5. 11:22 | Pozvánky

    Už za týden, ve čtvrtek 4. června, se v Národní technické knihovně v pražských Dejvicích uskuteční další konference věnovaná tématům spojeným s IPv6 - Den IPv6. Program akce a registrační formulář jsou k dispozici na webu akce. Kapacita konference je omezená, proto organizátoři doporučují, aby se vážní zájemci přihlásili včas (k dnešnímu dni zbývá přibližně 30 volných míst). Konferenci Den IPv6 2026 organizují i letos společně sdružení CESNET, CZ.NIC a NIX.CZ.

    VSladek | Komentářů: 1
    28.5. 05:22 | IT novinky

    Zařízení Steam Deck OLED bylo znovu naskladněno, ale vlivem rostoucích cen pamětí a úložišť má novou, vyšší cenovku. Steam Deck OLED 512 GB stojí nově 779 EUR (stál 569 EUR) a Steam Deck OLED 1 TB stojí 919 EUR (stál 679 EUR). Samotné zařízení se nijak nezměnilo a nové ceny tedy pouze odráží aktuální náklady na komponenty a další globální logistické výzvy, se kterými se potýká celá branže.

    Ladislav Hagara | Komentářů: 0
    27.5. 22:22 | IT novinky

    Český telekomunikační úřad zahajuje novou etapu využívání vysokofrekvenčního rádiového spektra v pásmu 26 GHz. Toto pásmo bude od 1. 7. 2026 otevřeno pro provoz moderních bezdrátových sítí, zejména sítí páté generace (5G), pevných bezdrátových přístupových sítí (FWA) a lokálních či průmyslových sítí určených například pro výrobní areály, logistická centra nebo technologické kampusy. Současně s otevřením pásma 26 GHz přistoupil ČTÚ ke zpřístupnění informací o využívání rádiových kmitočtů v tomto pásmu.

    Ladislav Hagara | Komentářů: 9
    27.5. 22:11 | IT novinky

    Logitech představil myš Signature Comfort Plus M850 L s polstrovanou opěrkou dlaně pro větší pohodlí a sadu s touto myší a klávesnicí s integrovanou opěrkou dlaní Signature Comfort Plus Combo MK880.

    Ladislav Hagara | Komentářů: 1
    27.5. 16:33 | IT novinky

    Gaël Duval se rozepsal o novinkách a plánech Murena a /e/OS. Počet uživatelů telefonů Murena a mobilního operačního systému /e/OS bez aplikací a služeb od Googlu se blíží 100 000. Ambicí je, aby se /e/OS stal třetí mobilní platformou v Evropě i na světě, s potenciálem dostat se i na PC. Blíží se vydání nové verze 4 s funkcemi zálohování a obnova, import e-mailů z Gmailu a rozpoznávání hlasu. Murena Workspace přinese videohovory, elektronický podpis a správu zařízení (MDM).

    Ladislav Hagara | Komentářů: 4
    27.5. 15:22 | Komunita

    Dnes a zítra probíhá Ubuntu Summit 26.04. Na programu je řada zajímavých přednášek. Sledovat je lze na YouTube. Úvodní slovo měli Mark Shuttleworth a Jon Seager.

    Ladislav Hagara | Komentářů: 1
    Které desktopové prostředí na Linuxu používáte?
     (12%)
     (8%)
     (2%)
     (14%)
     (31%)
     (4%)
     (6%)
     (3%)
     (16%)
     (26%)
    Celkem 1755 hlasů
     Komentářů: 30, poslední 3.4. 20:20
    Rozcestník


    Dotaz: OOP návrh aplikace

    Beda0 avatar 1.10.2012 15:29 Beda0 | skóre: 29
    OOP návrh aplikace
    Přečteno: 824×
    Zdravím, dělám aplikaci v Qt, která načítá data a zobrazuje v grafické podobě. Data mohou pocházet z různých zdrojů - xml soubory, modbus po TCP a v budou přibývat další. Jaký konkrétní typ komunikace se použije závisí na nastavení programu. Pro načítání dat mam interface
        virtual int read(struktura1 *data)=0;
        virtual int write(struktura1 *data)=0;
        virtual int read(struktura2 *data)=0;
        virtual int write(struktura2 *data)=0;
    Tento interface pak je konkrétně implementován pro xml a modbus.

    Dále mám třídu readWriteFactory, která má metodu
    ReadWrite* ReadWriteFactory::chooseRWType(int type)
    {
        ReadWrite *ret;
        switch(type)
        {
        case 1:
            ret = new ReadWriteModbus();
            return ret;
            break;
        default :
            ret = new ReadWriteXML();
            return ret;
            break;
        }
    }
    tímhle si vytvořím instanci konkrétní třídy pro komunikaci, která splňuje interface a pak v programu neřeším, jakým způsobem data získávám. Instanci třídy si takhle vytvářim všude kde jí potřebuju - v každym widgetu, kterj potřebuje načítat nebo ukládat data. Dál pak používám jen rw->read(&data) kde data je struktura, kterou chci naplnit daty.

    Modbus na rozdíl od xml souborů potřebuje navázat spojení a udržovat někde identifikátor toho spojení. To je řešeno tím, že po spuštění aplikace se zjistí, jaký je nastavený typ spojení, pokud je to modbus, tak se zavolá funkce, která to spojí a identifikátor se uloží do globální proměnné. Pokaždký když pak volám rw->read pro modbus, tak se identifikátor spojení načte z globální proměnné. Vím, že to je navrženo špatně a chci to zlepšit. Dlouho jsem to chtěl předělat, ale dělal sem věci, které byly někde vidět a na tohle se nedostalo.

    Teď potřebuju aplikaci rozdělit do knihoven - datalogic a businesslogic budou v čistém C++ jako knihovny a v aplikaci zbude GUI v Qt. Problém je s používáním globálních proměnných.

    Už si s tím lámu docela dlouho hlavu, ale moc mi to nejde. Vymyslel jsem, že interface změním na
        virtual int read(struktura1 *data,connectionClass identifikator)=0;
        virtual int write(struktura1 *data,connectionClass identifikator)=0;
        virtual int read(struktura2 *data,connectionClass identifikator)=0;
        virtual int write(struktura2 *data,connectionClass identifikator)=0;
    Kde třída identifikator bude uchovávat informace o typu připojení a identifikátor spojení, pokud existuje. Mám představu, že vytvořím instanci třídy connectionClass na začátku programu nebo při manuálním spojení a tu pak budu předávat rw->read(&data,id).

    A teď jedna z věcí, která mi v OOP pořád nejde na rozum - jak mam předávat id? rw->read bude volaná někde úplně z nejnižšího QtWidgetu, kterej nad sebou má další 3 parent widgety - jak tam to id dostanu? Nejjednoduší by bylo udělat id nějakym způsobem globální, ale všude píšou, že to je špatně, že to neni thread safe a další věci.

    Je takhle navržená struktura správná? Jak mam správně předávat id?

    Doufám, že to je popsaný srozumitelně a nic sem nevynechal. Díky.

    Řešení dotazu:


    Odpovědi

    1.10.2012 23:34 Delaunay | skóre: 17 | blog:
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Redundantní předávání identifikátoru jako argument read() nebo write() je samozřejmě veskrze špatným řešením. Nejen z důvodu neefektivnosti, ale především z pohledu návrhu.

    C++ jsem už bohužel hodně let neviděl, ale nejspíše bych to přepsal takto (záměrně vypuštěna členská funkce write()):

    Struktury:
    typedef struct Data {} Data;
    typedef struct Data2 {} Data2;
    
    Třída pro zapouzdření případných kontextových dat:
    class Context
    {
        private:
            int sourceType;
            ModbusConnection* modbusConn;
    
        public:
            Context() : sourceType(0), modbusConn(0) {}
    
            int getSourceType();
            void setSourceType(int type);
    
            ModbusConnection* getModbusConnection();
            void setModbusConnection(ModbusConnection* conn);
    };
    
    Připojení k modbus:
    class ModbusConnection
    {
        public:
            ~ModbusConnection();
    };
    
    Rozhraní pro čtení:
    class Reader
    {
        public:
            virtual ~Reader() {}
            virtual int read(Data& data) = 0;
            virtual int read(Data2& data) = 0;
    };
    
    Třídy implementující čtení:
    class ModbusReader : public Reader
    {
        private:
            ModbusConnection* conn;
    
        public:
            ModbusReader(ModbusConnection* connection) : conn(connection) {}
            int read(Data& data);
            int read(Data2& data);
    };
    
    class XMLReader : public Reader
    {
        public:
            int read(Data& data);
            int read(Data2& data);
    };
    
    Factory třída:
    Reader* ReaderFactory::get(Context* context)
    {
        Reader *ret = 0;
        int type = context->getSourceType();
        switch(type)
        {
            case 1:
                ret = new ModbusReader(context->getModbusConnection());
                break;
            default :
                ret = new XMLReader();
        }
        return ret;
    }
    
    A konečně pak to vše nějak zavoláme:
    ModbusConnection modbus;
    
    Context context;
    context.setSourceType(1);
    context.setModbusConnection(&modbus);
    
    Reader *reader = ReaderFactory::get(&context);
    Data data;
    while (reader->read(data))
    {
        // .... 
    }
    delete(reader);
    
    Beda0 avatar 2.10.2012 12:24 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Díky, takhle nějak sem si to představoval, ale pár věcí mi pořád unikalo a dělal sem je špatně.

    Ale pořád mi uniká jedna zásadní věc - já potřebuju reader->read(data) volat na mnoha různejch místech - v několika objektech úplně jinde, než otvírám spojení a nevim, jak předávat instanci Reader.
    
    
    class MainClass
    {
    public: MainClass();
            ~MainClass();
    }
    
    MainClass()
    {
    odbusConnection modbus;
    
       Context context;
       context.setSourceType(1);
       context.setModbusConnection(&modbus);
    
       Reader *reader = ReaderFactory::get(&context);
       obj = new Class1();
    }
    
    ~MainClass()
    {
       delete(reader);
    }
    
    Class1()
    {
       obj = new Class2();
       obj = new Class3();
    }
    
    Class2()
    {
       Data data;
       reader->read(data);
    }
    
    Jediný, co mě napadá, je prostě to předávat v konstruktoru nějak takhle:
    
    class Class1
    {
       public Class1(Reader *reader);
    }
    class Class2
    {
       public Class2(Reader *reader);
    }
    Class1(Reader *reader)
    {
       obj = new Class2(reader);
       obj = new Class3(reader);
    }
    Class2(Reader *reader)
    {
       Data data;
       reader->read(data);
    }
    
    Ale nevím, jestli to je takhle správně a nelíbí s mi to, protože musím udělat vlastní třídu Class1 a nemůžu použít standardní (jsou to widgety GUI).
    Beda0 avatar 2.10.2012 12:36 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Ta poslední věta je nesmysl - stejně ty třídy dělám sám. Takže neni problém to takhle udělat, jen nevim, jestli je to takhle správně.
    Josef Kufner avatar 2.10.2012 12:42 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Ty nepotřebuješ volat reader->data všude možně. Ty to potřebuješ volat jen v jedné třídě, která patří v MVC pod písmenko M (model).

    Ty widgety nemají co hrabat na nějaký reader někde. Nech je jen přeposlat signály nadřazenýmu widgetu a tam dělej, co potřebuješ.

    Dependency injection přesně tohle řeší, uniká ti však ještě jedna vrstva abstrakce.
    Hello world ! Segmentation fault (core dumped)
    Beda0 avatar 2.10.2012 13:12 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Jo, to bude asi ono, snad mi to došlo... Díky moc za navedení správnym směrem.
    2.10.2012 22:38 XY
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Nieco podobne som riesil nedavno a dosiel som k velmi zaujimavej serii clankov:

    http://codebetter.com/jeremymiller/2007/07/26/the-build-your-own-cab-series-table-of-contents/

    Je to sice na dlhsie citanie, ale odporucam.
    Josef Kufner avatar 2.10.2012 00:42 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Proč máš break za returnem?

    Instance třídy, která komunikuje se nevyrábí znovu pokaždé, když ji potřebuješ, ale získáš jí od někud jinud. Veškeré otvírání spojení se udělá v konstruktoru a potřebné informace o spojení si uložíš do private proměnných v té instanci.

    Pro komunikaci pak používáš pořád ten jeden objekt. Žádný widget by neměl volat new pro vytvoření spojení, k tomu máme techniky známé pod označením "Dependency injection" (viz seriál na root.cz). Pokud je načítání omezené jen v rámci jednoho dialogu s progresbarem ći podobné jednorázové akce, použij Factory, tedy specializovanou třídu, která ti vytvoří instanci readeru dle zadaných parametrů. Tahle factory se ti bude hodit v každém případě.

    Ta factory by měla být napsána nějak obecně, aby při vytovoření nového rozhraní nebylo třeba do ní nic dopisovat. Během kompilace by bylo vhodné automaticky vygenerovat (jednoduchým skriptem) hlavičkový soubor se seznamem všech známých readerů (prosté pole struktur), které by pak ta factory procházela a podle něj vyráběla instance tříd.
    Hello world ! Segmentation fault (core dumped)
    Josef Kufner avatar 2.10.2012 00:45 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Jo a až si budeš tak číst o návrhových vzorech a narazíš na Singleton, tak ho přeskoč. Sice asi budeš mít pocit, že to je přesně to co potřebuješ, ale tento pocit je jen zákeřná iluze. A pokud jejímu pokušení podlehneš, budeš krutě litovat.
    Hello world ! Segmentation fault (core dumped)
    2.10.2012 11:20 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Proč máš break za returnem?
    Možná proto aby uspokojil některé validátory - už jsem je tam kdysi dopisoval, bo mě štvaly warning-y.
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    Josef Kufner avatar 2.10.2012 11:54 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Pokud je validátor tak hloupý, že nechápe return místo break, tak bych mu moc nevěřil.
    Hello world ! Segmentation fault (core dumped)
    2.10.2012 12:25 Šangala | skóre: 56 | blog: Dutá Vrba - Wally
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Je to určitě hloupost validátoru, nicméně když je to integrovaný a jinak plní svou službu dobře, tak cesta nejmenšího odporu je ty break dopsat (stejně jako třeba zbytečný zápis virtual ~InterfaceAsPureAbstractClass(){/* nothing to do */};).
    Dělalo mě to buď ve Fazolích nebo Zatmění, ale už si nepamatuji jazyk ale asi C++ nebo PHP. Ale každopádně teď (rozuměj NOW()- 2 years) v Zatmění s C++ to nedělá…
    To, že trpíš stihomamem, ještě neznamená, že po tobě nejdou. ⰞⰏⰉⰓⰀⰜⰉ ⰗⰞⰅⰜⰘ ⰈⰅⰏⰉ ⰒⰑⰎⰉⰁⰕⰅ ⰏⰉ ⰒⰓⰄⰅⰎ ·:⁖⁘⁙†
    Beda0 avatar 2.10.2012 12:29 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Break sem tam zapomněl, předtim to vypadalo jinak a return byl až na konci.

    Díky za odkaz na seriál, přečetl jsem to, ale jestli sem to pochopil správně, tak to neřeší můj hlavní problém viz komentář výše.
    2.10.2012 21:09 biolog
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Jak píše Josef, vytvářet pořád nové instance komunikace je nepraktické. Není to užitečné nyní ani později a jiným, složitější protokolům by to mohlo vadit. Předpokládám že "widget" znamená "Qt grafický prvek".

    Moje řešení:

    Když se spouští tvá aplikace, na základě command-lajny nebo konfiguráku vytvoříš ModbusReader nebo XMLReader. V případě ModbusReader jí při vytváření předáš číslo TCP portu, nebo rovnou TCP stream, nebo co se ti líbí. Pokud budeš vytvářet ModbusReader nebo XMLReader z více míst (asi ne), nebo ten kód na rozhodování se mezi nimi a jejich vytváření bude delší než cca 10 řádek (asi ne), tak ten kód dáš do samostatné funkce. Můžeš jí říkat factory, ale stejně nebude mít žádný stav.

    Při spouštení aplikace při vytváření těch widgetů jim předáš ten ModbusReader nebo XMLReader.

    Pokud chceš, tak ten ModbusReader nebo XMLReader ulož do globální proměnné, ale není to potřeba, a hlavně widgety používají ten svůj správný (sdílený) objekt, a tedy nevýhoda globálních proměnných tady nehraje roli.

    Pokud by bylo potřeba k ModbusReader a XMLReader přidat dalšího potomka rozhraní ReadWrite, tak upravíš ten kód na vytváření (ať už je v samostané "factory" funkci nebo ne). Pokud bude potřeba mít více XML nebo Modbus zdrojů (se svými vlastními widgety), tak jen upravíš ten kód, který ví o command-lajně a konfiguráku, proste tam kudy jde ta informace o connectování.

    Je to tak snadné, že psát sem kód by bylo trapné.
    Beda0 avatar 3.10.2012 11:25 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Tak jsem to vyřešil, asi nejjednodušší bude malá ukázka kódu:
    
    Class Trida : public QMainWindow{
    Q_OBJECT
    
    public:
        QWidget *novyWidget;
    public slots:
        void readData(Struktura* data);
        void //tady budou sloty pro cteni a zapis vsech struktur a dalsi veci - connect, disconnect atd.
    private:
        ReadWrite *readWrite;
    }
    
    
    
    Trida::Trida(QWidget *parent) : QMainWindow(parent){
        cnt = new Context();
        cnt->set....
        //tady naplnim obsah cnt z konfiguracniho souboru
        //cnt uchovava informace pro vsechny spojeni - ip, port, modbus_identifikator_spojeni,
        //umisteni_xml_souboru, jestli je to nekam aktkualne pripojeno a dalsi...
    
        ReadWriteFactory *readWriteFactory = new ReadWriteFactory();
        readWrite = readWriteFactory->sellect(cnt);//tohle mi vrati jeden konkretni typ spojeni
        readWrite->setContext(cnt);
        readWrite->connect(); //pripojim se - pro typy pripojeni, ktere nevyzaduji spojeni to neni potreba,
                       // ale nicemu to nevadi
    
        novyWidget = new NovyWidget();
        connect(novyWidget,SIGNAL(readData(Struktura*)),this,SLOT(readData(Struktura*)));
        //pomoci signalu a slotu spojim pozadavaky na data se slotem, kterej je tady
        //budu pridavat vic slotu - na cteni, zapis, disconnect, novej connect atd...
    }
    
    Trida::~Trida()
    {
        readWrite->disconnect();
        delete ui;
    }
    void Trida::readData(Struktura* data)
    {
        readWrite->read(data);
    }
    
    Vlastni cteni dat se pak dela vyslanim signalu
    Struktura *data;
    data = new Struktura;
    emit readData(data);
    
    Všem díky moc za pomoc.
    Josef Kufner avatar 3.10.2012 16:50 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Základní myšlenkou Dependency Injection je oddělení závislostí a delegace starosti o ně mimo závisející objekty.

    Použití factory je fajn, ale pořád závisíš na té factory. Takže to prostě vykopej ven celé.
    • Slot a signál je v pohodě, asi bych jen přijímající slot pojmenoval vhodněji.
    • Z kostruktoru Tridy vykopej použití factory a ponech tam jen propojení vnořeného widgetu.
    • Ve funkci main, když vyrábíš okno, vyrob i Factory a tu předej tomu oknu (jako parametr konstruktoru).
    Hello world ! Segmentation fault (core dumped)
    Beda0 avatar 4.10.2012 23:08 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    "Takže to prostě vykopej ven celé" Co celé?

    To mam do main přesunout jen vytváření factory a jako parametr konstruktoru předat instanci factory? Nebo tam ma přesunout všechno - i naplnění context a vytvoření instance ReadWrite a pak předávat konstruktoru instanci ReadWrite?

    To první chápu smysl, ale je to jen jeden řádek
    ReadWriteFactory *readWriteFactory = new ReadWriteFactory();
    To druhý nevim jak, protože v potřebuju za běhu aplikace měnit typy připojení = mazat a vytvářet nový instance ReadWrite...
    Josef Kufner avatar 4.10.2012 23:33 Josef Kufner | skóre: 70
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    To mam do main přesunout jen vytváření factory a jako parametr konstruktoru předat instanci factory?
    Ano.
    Nebo tam ma přesunout všechno - i naplnění context a vytvoření instance ReadWrite
    To je práce pro tu factory.
    To druhý nevim jak, protože v potřebuju za běhu aplikace měnit typy připojení = mazat a vytvářet nový instance ReadWrite...
    Takže si budeš hrát s factory, kterou dostaneš zvenčí (z main). Ono se mi tam trošku namíchaly dvě myšlenky, kdy první pocházela z doby než jsem si uvědomil, že asi nebudeš chtít pracovat jen nad jedním spojením.
    Hello world ! Segmentation fault (core dumped)
    Beda0 avatar 5.10.2012 00:34 Beda0 | skóre: 29
    Rozbalit Rozbalit vše Re: OOP návrh aplikace
    Jo, takhle už mi to je jasný... díky moc za pomoc, osvětlil si mi spoustu věcí. Evidentně sem v tom měl daleko větší zmatek, než sem si připouštěl na začátku.

    Založit nové vláknoNahoru

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

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