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:55 | Nová verze

Po téměř 13 měsících vývoje od verze 0.11.0 byla vydána verze 0.12.0 hardwarově nenáročného desktopového prostředí LXQt (Lightweight Qt Desktop Environment, Wikipedie) vzniklého sloučením projektů Razor-qt a LXDE. Přehled novinek v příspěvku na blogu.

Ladislav Hagara | Komentářů: 0
včera 12:33 | Zajímavý software

Článek ne Medium představuje nejnovější stabilní verzi 2.0 svobodné decentralizované mikroblogovací platformy a sociální sítě podobné Twitteru Mastodon (Wikipedie). Detailní přehled novinek na GitHubu [Hacker News].

Ladislav Hagara | Komentářů: 0
včera 06:00 | Komunita

V Praze na půdě Elektrotechnické fakulty ČVUT dnes probíhá RT-Summit 2017 – setkání vývojářů linuxového jádra a uživatelů jeho real-time verze označované jako preempt-rt. Přednášky lze sledovat online na YouTube.

Ladislav Hagara | Komentářů: 0
20.10. 14:33 | Zajímavý projekt

Blender Animation Studio zveřejnilo první epizodu z připravovaného animovaného seriálu The Daily Dweebs o domácím mazlíčkovi jménem Dixey. Ke zhlédnutí také ve 3D s rozlišením 8K.

Ladislav Hagara | Komentářů: 0
20.10. 12:34 | Komunita

Aktualizovanou počítačovou hru Warhammer 40,000: Dawn of War III v ceně 39,99 eur běžící také na Linuxu lze o víkendu na Steamu hrát zdarma a případně ještě v pondělí koupit s 50% slevou. Do soboty 19:00 lze na Humble Bundle získat zdarma Steam klíč k počítačové hře Sid Meier's Civilization® III v ceně 4,99 eur běžící také ve Wine.

Ladislav Hagara | Komentářů: 0
20.10. 00:22 | Nasazení Linuxu

Společnost Samsung oznámila, že skrze dokovací stanici DeX a aplikaci Linux on Galaxy bude možno na Samsung Galaxy S8 a S8+ a Galaxy Note 8 provozovat Linux. Distribuce nebyly blíže upřesněny.

Phantom Alien | Komentářů: 19
19.10. 23:55 | Komunita

Společnost Purism na svém blogu oznámila, že její notebooky Librem jsou nově dodávány se zrušeným (neutralized and disabled) Intel Management Engine (ME). Aktualizací corebootu na již prodaných noteboocích lze Management Engine také zrušit. Více v podrobném článku.

Ladislav Hagara | Komentářů: 0
19.10. 21:44 | Nová verze

Organizace Apache Software Foundation (ASF) na svém blogu slaví páté výročí kancelářského balíku Apache OpenOffice jako jejího Top-Level projektu. Při této příležitosti byl vydán Apache OpenOffice 4.1.4 (AOO 4.1.4). Podrobnosti v poznámkách k vydání. Dlouhé čekání na novou verzi tak skončilo.

Ladislav Hagara | Komentářů: 6
19.10. 19:22 | Pozvánky

Již příští týden - 26. a 27. října se v Praze v hotelu Olšanka odehraje OpenWRT Summit. Na webu konference naleznete program a možnost zakoupení lístků - ty stojí 55 dolarů. Čtvrtek bude přednáškový a v pátek se budou odehrávat převážně workshopy a meetingy.

Miška | Komentářů: 1
19.10. 13:44 | Nová verze

Bylo vydáno Ubuntu 17.10 s kódovým názvem Artful Aardvark. Ke stažení jsou Ubuntu Desktop a Server, Ubuntu Cloud Images, Ubuntu Netboot, Kubuntu, Lubuntu a Lubuntu Alternate, Lubuntu Next, Ubuntu Budgie, Ubuntu Kylin, Ubuntu MATE, Ubuntu Studio a Xubuntu. Podrobnosti v poznámkách k vydání.

Ladislav Hagara | Komentářů: 23
Jak se vás potenciálně dotkne trend odstraňování analogového audio konektoru typu 3,5mm jack z „chytrých telefonů“?
 (10%)
 (1%)
 (1%)
 (1%)
 (75%)
 (13%)
Celkem 169 hlasů
 Komentářů: 7, poslední 19.10. 23:06
    Rozcestník

    Jak se dělá Plasmoid – 5 (drag&drop, konfigurační dialog)

    16. 2. 2010 | Dan Vrátil | Programování | 2235×

    V závěrečném dílu seriálu o tvorbě plasmoidů si ukážeme, jak lze do plasmoidu posílat vstup pomocí metody drag&drop a jak se přidává konfigurační dialog.

    Obsah

    Teorie

    link

    Ne vždy je nutné, aby měl plasmoid možnost uživatelského nastavení, ale občas se to hodí – příkladem mohou být plasmoidy, které pracují s nějakou online službou vyžadující přihlášení. U nich musí uživatel nastavit přihlašovací údaje v konfiguračním dialogu. Konfigurační dialog je pouze .ui soubor (lze vytvořit například v Qt Designeru – viz Programování v Qt). CMake z něj vygeneruje hlavičkový soubor, který lze includovat do zdrojových kódu plasmoidu, a s dialogem pak můžeme pracovat jako s běžnou třídou. Jako základní ovládací prvek dialogu se používá QWidget. Načtení dat z konfiguračního souboru do prvků v dialogu, propojení signálu a slotů atd. se provádí metodou createConfigurationInterface, která jako parametr přijímá ukazatel na KConfigDialog, což je základní implementace konfiguračních dialogů v KDE. Metoda musí být deklarována jako veřejná, protože ji volá Plasma, když uživatel požádá o otevření dialogu.

    Druhá věc, kterou si dnes ukážeme, je vstup dat přes drag&drop. To se dělá implementací standardní metody Qt dropEvent, jíž jediným parametrem je objekt QGraphicsSceneDragDropEvent popisující mj. přijatá data.

    Já jsem se rozhodl pro velice jednoduchý plasmoid na kompresi souborů. Po přetažení souborů do plasmoidu se soubory zkomprimují (metodu budeme nastavovat v konfiguračním dialogu) a následně se plasmoid zeptá, kam ho má uložit a pod jakým názvem. Vzhůru do toho.

    Programování

    link

    Začneme tím, že si v Qt Designeru vytvoříme konfigurační formulář. O Qt Designeru se podprobněji zmiňuje David Watzke ve článku Grafické programy v Qt 4 – 3 (Qt Creator a Designer). Zde je obrázek, jak může formulář vypadat a jak by se měly prvky jmenovat.

    qtdesigner

    compressor.h

    #ifndef COMPRESSOR_HEADER
    #define COMPRESSOR_HEADER
    
    // Hlavičkový soubor konfiguračního dialogu, který se automaticky vygeneruje z config.ui
    #include "ui_config.h"
    
    // Pár tříd, které se nám budou určitě hodit
    #include <KIcon>
    #include <KConfigDialog>
    #include <QtGui/QGraphicsSceneDragDropEvent>
    #include <QPainter>
    #include <QRect>
    #include <QStyleOptionGraphicsItem>
    #include <Plasma/Applet>
    
    class Compressor : public Plasma::Applet
    {
        Q_OBJECT
        Q_ENUMS(CompressionTypes)
        Q_ENUMS(CurrentStates);
        public:
           // Vytvoříme si vlastní výčet podporovaných kompresí
    	enum CompressionTypes { GZIPCompression = 0, 
    				BZIPCompression = 1 
    	};
    	enum CurrentStates { StateReady = 0, 
    			     StateWorking = 1,
    			     StateDone = 2,
    			     StateError = 3
    	};
    	// Konstruktor, destruktor
            Compressor(QObject *parent, const QVariantList &args);
            ~Compressor() {}
    	// Metoda volaná Plasmou, když uživatel požádá o zobrazení konfiguračního dialogu
    	void createConfigurationInterface(KConfigDialog *parent);
    	// Metoda volaná Plasmou, když je applet vytvořen 
            void init();
    
        private:
            KIcon m_icon;
    	// Zde budeme uchovávat typ komprese, která se má použít
    	CompressionTypes m_compressionType;
    	// Uchovává aktuální stav appletu (připraven, pracuji, hotovo, chyba)
    	CurrentStates m_currentState;
    	
    	// Toto je třída konfiguračního dialogu vygenerovaná z config.ui
    	Ui::CompressorConfig configDialog;
    	
    	// Tato metoda provede kompresi
    	void compress(QList<QUrl> files);
    	// Tato metoda nám umožní kreslit si na applet
    	void paintInterface(QPainter *p, const QStyleOptionGraphicsItem *, const QRect &contentsRect);
    	
        protected:
            // Metoda, která zajišťuje zpracování dat z drop události
    	void dropEvent(QGraphicsSceneDragDropEvent *event);
    	
        private slots:
            // Metoda, která se vykoná, když je komprese dokončena
    	void compressionDone(int exitCode);
    	// Metoda, která je zavolána, když uživatel potvrdí konfigurační dialog 
    	void configAccepted();
    	// Nastaví m_currentState na StateReady a překreslí applet
    	void setDefaultState();
    	
    };
     
    // Makro na export plasmoidu do KDE
    K_EXPORT_PLASMA_APPLET(compressor, Compressor)
    #endif
    

    Jak jsem zmiňoval na začátku – novinkou jsou dnes metody createConfigurationInterface pro vytvoření dialogu a dropEvent pro zpracování události drag&drop. Pokud vám vrtá hlavou, jak mohu includovat ui_config.h, když neexistuje, vězte, že jej generuje make, respektive program uic ze souboru config.ui. Přestože má soubor příponu .h, obsahuje i zdrojový kód metod, nejen jejich deklarace. Když applet zkompilujete, můžete se do souboru podívat, abyste lépe pochopili, jak to celé funguje. Uvnitř najdete třídu CompressorConfig (Ui je jmenný prostor). Název vygenerované třídy vychází z názvu hlavního QWidget. Pokud jste ho v Qt Designeru pojmenovali jinak, nezapomeňte upravit tento hlavičkový soubor, jinak se applet nepřeloží.

    compressor.cpp

    #include "compressor.h"
    
    // Třída pro snazší přístup ke konfiguraci plasmoidu
    #include <KConfigGroup>
    #include <QFileDialog>
    #include <QPixmap>
    #include <QRectF>
    #include <QStringList>
    #include <QTimer>
    // Přída pro práci s externími procesy
    #include <QtCore/QProcess>
    #include <QtGui/QGraphicsSceneDragDropEvent>
    
    Compressor::Compressor(QObject *parent, const QVariantList &args)
        : Plasma::Applet(parent, args),
        m_icon("application-x-bzip-compressed-tar")
    {
        // Přijímáme drag&drop
        setAcceptDrops(true);
        setBackgroundHints(DefaultBackground);
        // Máme k konfigurační rozhraní
        setHasConfigurationInterface(true);  
        resize(128,128);
        // Applet musí mít vždy tvar čtverce (kvůli ikoně)
        setAspectRatioMode(Plasma::KeepAspectRatio);
    }
    
    
    void Compressor::init()
    {
      // Načteme, jaký typ komprese se bude používat
      KConfigGroup cg = config();
      m_compressionType = (CompressionTypes)cg.readEntry("compressionType",0);
    }
    
    void Compressor::paintInterface(QPainter* p, const QStyleOptionGraphicsItem* , const QRect& contentsRect)
    {
    
      QPixmap pixmap;
      // Podle aktuálního stavu appletu načte ikonu
      switch (m_currentState) {
        case StateWorking:
          // Název ikony přímo neodpovídá tomu, co v našem případě reprezentuje, ale nenašel jsem lepší ikonu :-)
          pixmap = KIcon("system-software-update").pixmap(QSize(128,128));
          break;
        case StateDone:
          pixmap = KIcon("dialog-ok").pixmap(QSize(128,128));
          break;
        case StateError:
          pixmap = KIcon("dialog-error").pixmap(QSize(128,128));
          break;
        default:
        case StateReady:
          pixmap = KIcon("go-down").pixmap(QSize(128,128));
          break;
      }
      
      // Nakreslí zvolenou ikonu na plátno appletu
      p->drawPixmap(QRectF(contentsRect.left(),contentsRect.top(),contentsRect.width(),contentsRect.height()),
    		pixmap,
    		QRectF(0,0,128,128));  
    }
    
    
    void Compressor::createConfigurationInterface(KConfigDialog* parent)
    {
      // Vytvoří nový widget
      QWidget *widget = new QWidget(0);
      // Metoda setupUI vygeneruje a rozmístí jednotlivé ovládací prvky na QWidget tak,
      // jak jsme je rozmístili v config.ui
      configDialog.setupUi(widget);
      // Nastaví výchozí položku comboboxu pro výběr komprese
      configDialog.compressionType->setCurrentIndex((int)m_compressionType);
      // Sváže signál dialogu s naším slotem
      connect(parent, SIGNAL(accepted()), this, SLOT(configAccepted()));
      // Přida na konfigurační dialog nově vytvořený QWidget s rozhraním
      parent->addPage(widget,"General",icon());
    }
    
    void Compressor::configAccepted()
    {
      // Uloží vybraný typ komprese
      KConfigGroup cg = config();
      cg.writeEntry("compressionType",configDialog.compressionType->currentIndex());
    }
    
    
    void Compressor::dropEvent(QGraphicsSceneDragDropEvent *event)
    {
      // Oveří, jestli event obsahuje URL adresy (např. file:///home/progdan/soubor.txt)
      if(event->mimeData()->hasUrls()) {
        // Pokud ano, tak potvrdíme přijetí události
        event->acceptProposedAction();
        // Dočasně zakážeme přijímat nové drag&drop události
        setAcceptDrops(false);
        // Zavolámé metodu compress a předáme ji seznam URL adres
        compress(event->mimeData()->urls());
      }
    }
    
    void Compressor::compress(QList<QUrl> files)
    {
      QStringList params;
      
      // Nastaví aktuální stav a zažádá o překreslení
      m_currentState = StateWorking;
      update();
      
      // Podle typu komprese nastaví přepínče programu TAR
      switch (m_compressionType) {
        case GZIPCompression:
          params >> "czf";
          break;
        case BZIPCompression:
          params << "cjf";
          break;
      }
    
      // Jako další za přepínači následuje název cílového souboru. Po dokončení se uživatele
      // zeptáme, pod jakým skutečným názvem chce soubor uložit
      params << "/tmp/compressor.$$";
      // A za ním seznam jednotlivých souborů určených ke kompresi
      for (int i = 0; i < files.count(); i++) {
        // metoda toString převede QUrl na QString a odstraní počáteční file://
        params << files.at(i).toString(QUrl::RemoveScheme);
      }
      
      // Vytvoří nový proces
      QProcess *tar = new QProcess(this);
      // Sváže signal finished procesu tar s naším slotem compressionDone
      connect(tar,SIGNAL(finished(int)),this,SLOT(compressionDone(int)));
      // spustí program tar s příslušnými parametry
      tar->start("tar",params);
    }
    
    void Compressor::compressionDone(int exitCode)
    {
      QString filename;
      QString filter;
    
      // Pokud aplikace tar selhala
      if (exitCode > 0) {
        // Nastaví status error
        m_currentState = StateError;
        // Překreslí applet
        update(); 
        // Vytvoří timer, který za 3 sekundy zavolá slot setDefaultState, který nastaví původní ikonu
        QTimer::singleShot(3000,this,SLOT(setDefaultState()));
        // Obnovíme přijímání drag&drop
        setAcceptDrops(true);
        return;
      } 
      
      // Nastaví stav hotovo
      m_currentState = StateDone;
      // Zažádá o překreslení appletu
      update();
      // Vytvoří časovač, který po třech vteřinách zavolá etodu setDefaultState, která nastaví
      // stav appletu na StateReady a překreslí ikonu
      QTimer::singleShot(3000,this,SLOT(setDefaultState()));
      
     
      // Podle typu komprese nastaví filter pro dialog o uložení
      switch (m_compressionType) {
        case GZIPCompression:
          filter = "Gzipped tar (*.tar.gz)";
          break;
        case BZIPCompression:
          filter = "Bzipped tar (*.tar.bz2)";
          break;
      }
      
      // Vytvoří dialog o uložení
      filename = QFileDialog::getSaveFileName(0,
                                              QString("Uložit archiv do…"),
                                              QString(),
                                              filter);
      // Pokud uživatel dialog zavřel, bude filename prázdné, takže po sobě aspoň uklidíme
      if (filename.isEmpty()) {
        QProcess::execute("rm",QStringList() << "/tmp/compressor.$$");
      } else {
        // Pokud ho potvrdil tak přesuneme soubor z /tmp na nové místo
        QProcess::execute("mv",QStringList() << "/tmp/compressor.$$" << filename);
      }
    
      // Nakonec ještě obnovíme přijímání drag&drop událostí
      setAcceptDrops(true);
    }
    
    void Compressor::setDefaultState()
    {
      // Nastaví výchozí stav
      m_currentState = StateReady;
      // Zažádá o překreslení
      update();
    }
    
    #include "compressor.moc"
    

    Tady by vše mělo být jasné z komentářů. V kódu určitě chybí ošetření mnoha případů (například inicializace by měla selhat, pokud není nalezen program tar, applet by měl být trochu ukecanější ohledně toho, proč komprese selhala, měla by se kontrolovat práva na čtení a zápis atd.), ale to už si každý může zajistit sám. Pokud chcete applet pořádně otestovat a budete se snažit komprimovat velké soubory, dejte pozor, aby výsledný archiv nebyl větší než vaše /tmp (ano, i to by měl applet nějak řešit…).

    plasma-applet-compressor.desktop

    [Desktop Entry]
    Name=Compressor applet
    Name[cs]=Kompresor applet
    Type=Service
    
    X-KDE-ServiceTypes=Plasma/Applet
    X-KDE-Library=plasma_applet_compressor
    X-KDE-PluginInfo-Author=Dan Vrátil
    X-KDE-PluginInfo-Email=vratil@progdansoft.com
    X-KDE-PluginInfo-Name=compressor
    X-KDE-PluginInfo-Version=0.1
    X-KDE-PluginInfo-Website=http://www.abclinuxu.cz
    X-KDE-PluginInfo-Category=Utilities
    X-KDE-PluginInfo-Depends=
    X-KDE-PluginInfo-License=GPL
    X-KDE-PluginInfo-EnabledByDefault=true
    

    CMakeLists.txt

    # Jméno projektu
    project(compressor)
     
    # Co všechno potřebujeme?
    find_package(KDE4 REQUIRED)
    include(KDE4Defaults)
     
    add_definitions (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
    include_directories(
       ${CMAKE_SOURCE_DIR}
       ${CMAKE_BINARY_DIR}
       ${KDE4_INCLUDES}
       )
     
    # Přidá zdrojáky
    set(compressor_SRCS compressor.cpp)
    # Makro kde4_add_ui_files zajistí, že po spuštění make se nejprve z .ui souborů
    # vygenerují C++ třídy
    kde4_add_ui_files(compressor_SRCS config.ui)
     
    # Zajístí, aby se applet vložil do KDE
    kde4_add_plugin(plasma_applet_compressor ${compressor_SRCS})
    
    # Slinkuje applet
    target_link_libraries(plasma_applet_compressor 
                          ${KDE4_PLASMA_LIBS} ${KDE4_KDEUI_LIBS})
     
    # Nainstaluje knihovnu appletu
    install(TARGETS plasma_applet_compressor
            DESTINATION ${PLUGIN_INSTALL_DIR})
     
    # Nainstaluje .desktop soubor
    install(FILES plasma-applet-compressor.desktop
            DESTINATION ${SERVICES_INSTALL_DIR})
    

    Do CMakeLists.txt je nutné přidat makro kde4_add_ui_files, které zajistí vygenerování ui_config.hconfig.h.

    Závěr

    link

    Pro otestování přetáhněte pár souborů (najednou, jako výběr, nikoliv po jednom) do appletu a počkejte, než vyskočí dialog, kam chcete soubor uložit.

    Nakonec ještě přikládám archiv s kompletními kódy včetně config.ui.

    Tento díl je posledním dílem mého seriálu o plasmoidech. Samozřejmě, že má Plasma mnohem mnohem více možností než těch pár, které jsem tu popsal, ale i ty by vám měly stačit k pochopení, jak to vlastně celé funguje, a měli byste být schopni napsat jednodušší plasmoid. Jestli se chcete na věc podívat hlouběji, doporučuji projít si dokumentaci PlasmyPlasma addons.

    Pokud si myslíte, že je tu něco, co jsem nezmínil, a zároveň by to mohlo vydat na celý článek, projevte se prosím v diskuzi.

           

    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ář

    16.2.2010 11:13 Danoh | skóre: 4 | Bratislava
    Rozbalit Rozbalit vše Re: Jak se dělá Plasmoid – 5 (drag&drop, konfigurační dialog)
    QList>QUrl< ? :)
    porta patet et cor magis
    progdan avatar 16.2.2010 19:31 progdan | skóre: 34 | blog: Archař | Teplice/Brno
    Rozbalit Rozbalit vše Re: Jak se dělá Plasmoid – 5 (drag&drop, konfigurační dialog)
    Aneb kdyz se nam plete &gt; a &lt; :-)
    Collecting data is only the first step toward wisdom, but sharing data is the first step toward the community.
    16.2.2010 19:41 Robert Krátký | skóre: 94 | blog: Robertův bloček
    Rozbalit Rozbalit vše Re: Jak se dělá Plasmoid – 5 (drag&drop, konfigurační dialog)
    Sorry, to jsem byl asi já. Opraveno.
    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.