Byla vydána beta verze openSUSE Leap 16. Ve výchozím nastavení s novým instalátorem Agama.
Devadesátková hra Brány Skeldalu prošla portací a je dostupná na platformě Steam. Vyšel i parádní blog autora o portaci na moderní systémy a platformy včetně Linuxu.
Lidi dělají divné věci. Například spouští Linux v Excelu. Využít je emulátor RISC-V mini-rv32ima sestavený jako knihovna DLL, která je volaná z makra VBA (Visual Basic for Applications).
Revolut nabídne neomezený mobilní tarif za 12,50 eur (312 Kč). Aktuálně startuje ve Velké Británii a Německu.
Společnost Amazon miliardáře Jeffa Bezose vypustila na oběžnou dráhu první várku družic svého projektu Kuiper, který má z vesmíru poskytovat vysokorychlostní internetové připojení po celém světě a snažit se konkurovat nyní dominantnímu Starlinku nejbohatšího muže planety Elona Muska.
Poslední aktualizací začal model GPT-4o uživatelům příliš podlézat. OpenAI jej tak vrátila k předchozí verzi.
Google Chrome 136 byl prohlášen za stabilní. Nejnovější stabilní verze 136.0.7103.59 přináší řadu novinek z hlediska uživatelů i vývojářů. Podrobný přehled v poznámkách k vydání. Opraveno bylo 8 bezpečnostních chyb. Vylepšeny byly také nástroje pro vývojáře.
Homebrew (Wikipedie), správce balíčků pro macOS a od verze 2.0.0 také pro Linux, byl vydán ve verzi 4.5.0. Na stránce Homebrew Formulae lze procházet seznamem balíčků. K dispozici jsou také různé statistiky.
Byl vydán Mozilla Firefox 138.0. Přehled novinek v poznámkách k vydání a poznámkách k vydání pro vývojáře. Řešeny jsou rovněž bezpečnostní chyby. Nový Firefox 138 je již k dispozici také na Flathubu a Snapcraftu.
Šestnáctý ročník ne-konference jOpenSpace se koná 3. – 5. října 2025 v Hotelu Antoň v Telči. Pro účast je potřeba vyplnit registrační formulář. Ne-konference neznamená, že se organizátorům nechce připravovat program, ale naopak dává prostor všem pozvaným, aby si program sami složili z toho nejzajímavějšího, čím se v poslední době zabývají nebo co je oslovilo. Obsah, který vytvářejí všichni účastníci, se skládá z desetiminutových
… více »KIO je technologie, která zajišťuje téměř vše okolo vstupně-výstupních operací v KDE. V rámcí API sdružuje vše, co se týká práce se soubory, či adresáři. Jmenný prostor KIO ale zapouzdřuje i třídy pro práci s SSL, záložkami, různé dialogy a další.
Nad lokálním souborovým systémem umí vytvořit další virtuální vrstvu, do které se připojí i vzdálená uložiště tak, že je můžete procházet jako lokální. Nemusí se samozřejmě vždy jednat o vzdálené úložiště, díky KIO můžete procházet i archivy, manuálové stránky atd. Samotný přístup ke uložištím pak zajišťují speciální procesy, tzv. KIO Slaves.KIO Jobs jsou nástroje určené pro kopírování, přesouvání a mazání souborů či adresářů a dokáží vcelku usnadnit práci se soubory. Nemusíte se starat vůbec o nic, stačí předat KUrl zdrojového a cílového souboru či adresáře, připojit se na signály a pak už sledovat průběh operace.
#include <KIO/CopyJob> #include <KUrl> ... ... KUrl source("/home/dan/Music"); KUrl destination("/mnt/backups"); KUrl link("/home/dan/Hudba"); // Zkopiruje slozku /home/dan/Music do /mnt/backups KIO::CopyJob *copyJob = KIO::copy(source, destination, HideProgressInfo | Overwrite); // Presune slozku /home/dan/Music do /mnt/backups KIO::CopyJob *moveJob = KIO::move(source, destination, HideProgressInfo | Overwrite); // Vytvori symlink z /home/dan/Music do /home/dan/Hudba KIO::CopyJob *linkJob = KIO::link(source, link, HideProgressInfo);
Příznak HideProgressInfo skryje grafické zobrazení průběhu (tzn. že kopírování se neobjeví v notifikacích v systémové části panelu). S příznakem Overwrite kopírování neselže, pokud adresář nebo soubor existují.
KIO::CopyJob pak disponuje mnoha sloty a signály, přes které je možné ovlivňovat a sledovat průběh. Pro sledování jsou zajímavé signály totalFiles() a totalDirs(), které jsou vyvolány, když proces spočítá, kolik souborů a adresářů se bude zpracovávat. Signály processedFiles() a processedDirs() průběžně informují o počtu zpracovaných souborů, respektive adresářů. processedSize() informuje o velikosti přenesených dat v bajtech. Pokud chcete zobrazovat, jak se jmenuje aktuálně kopírovaný soubor, můžete poslouchat signál copying(). Signál je vyvolán každých 200ms, aby nedocházelo ke zbytečnému zpomalování procesu. Existují také analogické signály moving() a linking(). U KIO::link() se vytvoří buď klasický unixový symlink, nebo, pokud source a destination používají jiné protokoly nebo jsou vzdálené, se vytvoří .desktop odkaz. Když je celý Job hotový, emituje se signál result().
Pomocí metod doSuspend(), doResume() a doKill() můžete proces pozastavit, znovu spustit a nebo úplně zrušit. U prvních dvou metod je vyvolán signál suspended(), respektive resumed().
Pro ukázku v praxi vytvoříme jednoduchý program pro kopírování a přesouvání adresářů.
... ... void MainWindow::copyDir() { KFileItem src_item = src_model->itemForIndex(src_treeView->currentIndex()); KFileItem dest_item = dest_model->itemForIndex(dest_treeView->currentIndex()); ... ... if (sender() == copy_btn) current_job = KIO::copy(src_item.url(), dest_item.url(), KIO::HideProgressInfo); else current_job = KIO::move(src_item.url(), dest_item.url(), KIO::HideProgressInfo); // Informuje o celkovem poctu souboru, adresaru a bajtu, ktere se budou prenaset connect(current_job, SIGNAL(totalAmount(KJob*, KJob::Unit, qulonglong)), this, SLOT(setTotalAmount(KJob*, KJob::Unit, qulonglong))); // Informuje o jiz prenesenem mnozstvi souboru, adresaru a bajtu connect(current_job, SIGNAL(processedAmount(KJob*, KJob::Unit, qulonglong)), this, SLOT(setProcessedAmount(KJob*, KJob::Unit, qulonglong))); // Informuje o prave prenasenem souboru connect(current_job, SIGNAL(copying(KIO::Job*, KUrl, KUrl)), this, SLOT(setCurrentFile(KIO::Job*, KUrl, KUrl))); // Informuje o procentualnim progresu connect(current_job, SIGNAL(percent(KJob*, ulong)), this, SLOT(setPercent(KJob*, ulong))); // Informuje, ze prenos byl dokoncen connect(current_job, SIGNAL(finished(KJob*)), this, SLOT(jobFinished(KJob*))); // Informuje, ze prenos byl pozastaven connect(current_job, SIGNAL(suspended(KJob*)), this, SLOT(setProcessSuspended(KJob*))); // Informuje, ze prenos byl znovu spusten connect(current_job, SIGNAL(resumed(KJob*)), this, SLOT(setProcessResumed(KJob*))); // Informuje o aktualni rychlosti prenosu (v bajtech za sekundu) connect(current_job, SIGNAL(speed(KJob*, ulong)), this, SLOT(setSpeed(KJob*, ulong))); // Pri kliknuti na suspend_btn pozatavi prenos connect(suspend_btn, SIGNAL(clicked(bool)), current_job, SLOT(suspend())); // Pri kliknuti na kill_btn zrusi prenos connect(kill_btn, SIGNAL(clicked(bool)), current_job, SLOT(kill())); processed_dirs = 0; processed_files = 0; ... ... // Zobrazi dalsi prvky UI progress_bar->setVisible(true); progress_label->setVisible(true); suspend_btn->setVisible(true); kill_btn->setVisible(true); disableUI(true); // Nastavi titulek status = "Running"; } ... ...
V copyDir() vytvoříme nový KIO::CopyJob a napojíme se na některého jeho signály. Protože nás zajímá počet celkových a zpracovaných souborů, adresářů i bajtů (tedy všechno), použijeme místo signálů a slotů pro jednotlivé hodnoty trochu univerzálnější přístup: totalAmount() a processedAmount(). Druhým parametrem těchto signálů je výčtový typ KJob::Unit, který určuje, jaká hodnota se předává ve třetím parametru.
... ... void MainWindow::setTotalAmount(KJob* job, KJob::Unit unit, qulonglong amount) { switch (unit) { case KJob::Bytes: total_size = amount; break; case KJob::Files: total_files = amount; break; case KJob::Directories: total_dirs = amount; break; } updateUI(); Q_UNUSED(job) } void MainWindow::setProcessedAmount(KJob* job, KJob::Unit unit, qulonglong amount) { switch (unit) { case KJob::Bytes: processed_size = amount; break; case KJob::Files: processed_files = amount; break; case KJob::Directories: processed_dirs = amount; break; } updateUI(); Q_UNUSED(job) } ... ...
Obdobně můžete sbírat i další informace jako rychlost přenosu, aktuálně přenášený soubor nebo průběh přenosu v procentech:
... ... void MainWindow::setCurrentFile(KIO::Job* job, KUrl src, KUrl dest) { current_src = src; current_dest = dest; updateUI(); Q_UNUSED(job) } void MainWindow::setSpeed(KJob* job, ulong speed) { current_speed = speed; updateUI(); Q_UNUSED(job) } void MainWindow::setPercent(KJob* job, ulong percentage) { current_percentage = percentage; updateUI(); Q_UNUSED(job); } ... ... void MainWindow::updateUI() { progress_bar->setValue(current_percentage); QString str; str = "%1
Files: %2 of %3
Dirs: %4 of %5
Size: %6 of %7 MiB
Speed: %8 MiB/s
%9 -> %10"; str = str.arg(status, QString::number(processed_files), QString::number(total_files), QString::number(processed_dirs), QString::number(total_dirs), QString::number(processed_size/1048576), QString::number(total_size/1048576), QString::number(current_speed/1048576)).arg( current_src.path(), current_dest.path()); progress_label->setText(str); }
Metodou updateUI() už jen aktualizujeme uživatelské rozhraní.
Pokud proces během kopírování nebo přesunu narazí na existující složku nebo adresář, zeptá se klasickým KDE dialogem na další akci (přepsat, ignorovat, ...), stejně tak pokud se mu nepodaří přečíst nebo zapsat nějaký soubor. Všechny dialogy a okna jsou řešeny automaticky. Toto chování lze potlačít nastavením vlastností pomocí metod setAutoSkip(), setDefaultPermissions(), setWriteIntoExistingDirectories() nebo příznakem Overwrite v konstruktoru KIO::Job.
Mimo KIO::CopyJob existuje ještě například KIO::PreviewJob, který pro soubor zadaný v konstruktoru vygeneruje náhled se o zadaných rozměrech a vrátí ho jako QPixmap signálem gotPreview(), KIO::DeleteJob pro odstraňovaní souborů či adresářů, KIO::listDir() pro získání obsahu adresáře (případně KIO::listRecursive() pro rekurzivní výpis), nebo KIO::mimetype() pro získání MIME typu.
Možná jste si všimli, že pokud procházíte nějaké vzdálené úložiště, spouští se na pozadí automaticky procesy s názvy jako kio_ftp, kio_http a další. Těmto procesům se říká KIO Slaves a právě ony zajišťují komunikaci se serverem a zkrze své API zpřístupňují informace o obsahu adresářů koncovým aplikacím. Nejde vlastně o samostatné spustitelné soubory, ale o pluginy aplikace kdeinit4.
Pomocí KIO Slaves lze zobrazovat cokoliv, co lze alespoň trochu zorganizovat do stromové struktury (adresáře, soubory). Pro ukázku toho, jak to může vypadat, jsem připravil KIO Slave, který umí procházet složku Software zde na AbcLinuxu.
Každý KIO Slave musí musí mít funkci kdemain() a samotné třídy otroka, odvozené od KIO::SlaveBase nebo KIO::TCPSlave.
#include <KIO/SlaveBase> #include <kio/udsentry.h> #include <QByteArray> #include <QtWebKit/QWebElement> class ABCSlave:public QObject, public KIO::SlaveBase { Q_OBJECT public: ABCSlave (const QByteArray & pool, const QByteArray & app); void stat (const KUrl & url); void listDir (const KUrl & url); private: QWebElement getWebPage(QString path); KIO::UDSEntry dirEntry(QWebElement item); KIO::UDSEntry articleEntry(QWebElement item); };
V této ukázkce jsem reimplementoval pouze metody stat() a listDir(). První zmíněná metoda slouží ke zjišťování informací o zadané URL (jedná se o soubor, nebo adresář, jaká jsou přístupová práva, MIME typ atd.). V druhé metodě se pak generuje seznam souborů či adresářů na uvedené URL. Dále existují metody copy(), move(), rename(), del(), chmod(), chown(),
Informace o adresáři nebo souboru se předávají pomocí objektů KIO::UDSEntry(), jak uvidíte v kódu níže. V ukázce nastavuji jen několik základních nejdůležitějších informací, no ve skutečnosti jich je mnohem více.
... ... // Vyexportuje funkce kdemain() extern "C" { KDE_EXPORT int kdemain (int argc, char **argv); } // Hlavni funkce knihovny int kdemain (int argc, char **argv) { // Vytvori novou aplikaci QApplication app(argc, argv); // Nahlasi se KDE jako nova instance kio_abc KComponentData instance ("kio_abc"); // Vytvori novy ABCSlave ABCSlave *slave = new ABCSlave (argv[2], argv[3]); slave->dispatchLoop (); delete slave; return 0; }
Důležité je funkci kdemain() nadeklarovat jako "extern". Tato funkce je ekvivalentem klasické main(). Důležité je nezapomenout spustit hlavní smyčku (KIO::SlaveBase::dispatchLoop()), a v případě, že potřebujete používat signály a sloty, tak je potřeba vytvořit objekt QApplication().
void ABCSlave::listDir(const KUrl& url) { // Nacte webovou stranku QWebElement webelement = getWebPage(url.path()); // Najde vsechny &al;UL> QWebElementCollection uls = webelement.findAll("ul"); QWebElement treemenu; // Prohleda vsechny <UL>, skonci, kdyz najde <UL id="treemenu1"> for (int i = 0; i < uls.count(); i++) { if (uls.at(i).attribute("id", "") == "treemenu1") { treemenu = uls.at(i); break; } } // Projde vsechny potomky v nalezenem <UL> QWebElement item = treemenu.firstChild(); listEntry(dirEntry(item), false); while (!item.nextSibling().isNull()) { item = item.nextSibling(); // Kazdeho potomka prida do listEntry() jako adresare listEntry(dirEntry(item), false); } // Najde vsechny tabulky QWebElementCollection tables = webelement.findAll("table"); QWebElement sw_table; // Projde vsechny tabulky, hleda <table class="sw-polozky"> for (int i = 0; i < tables.count(); i++) { if (tables.at(i).attribute("class", "") == "sw-polozky") { sw_table = tables.at(i); break; } } /* V nalezene tabulce najde vsechny odkazy a vlozi je do listEntry() jako soubory */ QWebElementCollection links = sw_table.findAll("a"); for (int i = 0; i < links.count(); i++) { listEntry(articleEntry(links.at(i)), false); } // Odesle celou frontu listEntry(KIO::UDSEntry(), true); // Hotovo! finished(); }
Metoda listDir() generuje obsah adresáře. V našem případě načte webovou stránku a potom prochází zdrojový kód a hledá určité speicifické elementy. Každý objevený prvek se do seznamu přidává metodou listEntry(), která se předá objekt KIO::UDSEntry. Druhý parametr metody indikuje, jestli už jsou všechny záznamy připraveny. Doporučuji nejdřív naakumulovat všechny záznamy a až potom zavolat listEntry() s prázdným KIO::UDSEntry() v prvním a hodnotou TRUE v druhém parametru. Při TRUE se všechna data odešlou klientovi k vizualizaci. Důležité je informovat signálem finished(), že procházení adresáře bylo dokončeno a už nic víc měnit nebudeme.
V případě selhání emitujeme signál error(), kde prvním argumentem je identifkátor chyby a druhým textový popis. Textový popis může být prázný (defaultní chyby mají vlastní popis), ale u kódů jako ERR_UNKNOWN nebo ERR_INTERNAL je vhodné krátce informovat o tom, co se pokazilo.
void ABCSlave::stat(const KUrl &url) { KIO::UDSEntry entry; // O korenovem adresari vime, ze je to adresar, a ze do nej maji pristup vsichni if ((url == "") || (url == "/")) { entry.insert(KIO::UDSEntry::UDS_NAME, "."); entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.insert(KIO::UDSEntry::UDS_USER, "root"); entry.insert(KIO::UDSEntry::UDS_GROUP, "root"); entry.insert(KIO::UDSEntry::UDS_ACCESS, S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); statEntry(entry); finished(); return; } // Pokud se nejedna o korenovy adresar, tak nacte stranku na dane adrese QWebElement web = getWebPage(url.path()); QWebElementCollection uls = web.findAll("ul"); // Pokud v ni najde <UL id="treeemenu1">, tak se jedna o adresar QWebElement treemenu; for (int i = 0; i < uls.count(); i++) { if (uls.at(i).attribute("id", "") == "treemenu1") { entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); entry.insert(KIO::UDSEntry::UDS_NAME, url.directory()); entry.insert(KIO::UDSEntry::UDS_URL, url.path()); statEntry(entry); finished(); return; } } // Pokud je na dane strance <div class="sw"> jedna se o stranku // konkretniho programu, tedy je to soubor QWebElementCollection divs = web.findAll("div"); for (int i = 0; i < divs.count(); i++) { if (divs.at(i).attribute("class", "") == "sw") { entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "text/html"); entry.insert(KIO::UDSEntry::UDS_NAME, divs.at(i).findFirst("h1").toPlainText()); entry.insert(KIO::UDSEntry::UDS_URL, "http://www.abclinuxu.cz/"+url.url()); statEntry(entry); finished(); return; } } // No a pokud nenajdeme ani slozku ani clanek, tak jsme asi neco udelali spatne error(KIO::ERR_DOES_NOT_EXIST, ""); }
Naše metoda stat() obsluhuje tři případy: když zadaná URL ukazuje na kořenový adresář, když obsahuje podsložky nebo soubory, či když je to už samotný článek. Pomocí této metody si klientská aplikace může zjišťovat detailnější informace o obsahu libovolného adresáře či souboru. Standardní chování je, že si klient nejprve zjistí informace o adresáři, do kterého právě vstupuje a až po jeho načtení postupně načítá informace o jednotlivých podadresářích nebo souborech.
Metodou KIO::UDSEntry::insert() se do záznamu přidávaji další a další informace. Já v této ukázce vkládám jen ty nejdůležitější: typ (soubor vs. adresář), název, cestu, u souborů pak ještě MIME typ. Po vložení informace opět nesmíme zapomenout na sigál finished(). Pokud se funkce dostane až na konec, emituje se chyba.
KIO::UDSEntry ABCSlave::dirEntry(QWebElement item) { // V predanem HTML radku najde odkaz QWebElement link = item.findFirst("a"); KIO::UDSEntry entry; // Precteme text z <a> </a> entry.insert(KIO::UDSEntry::UDS_NAME, link.toPlainText()); // Typ: slozka entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFDIR); QString url = link.attribute("href", ""); if (url.left(10) == "/software/") url.remove(0,10); // Adresa, na kterou slozka odkazuje entry.insert(KIO::UDSEntry::UDS_URL, "abc:/"+url); return entry; } KIO::UDSEntry ABCSlave::articleEntry(QWebElement item) { KIO::UDSEntry entry; // Nazev clanku entry.insert(KIO::UDSEntry::UDS_NAME, item.toPlainText()); // Typ: regularni soubor entry.insert(KIO::UDSEntry::UDS_FILE_TYPE, S_IFREG); QString url = item.attribute("href", ""); if (url.left(10) == "/software/") url.remove(0, 10); // Adresa, na ktere se clanek nachazi entry.insert(KIO::UDSEntry::UDS_URL, "http://www.abclinuxu.cz/software/"+url); // MIME Type entry.insert(KIO::UDSEntry::UDS_MIME_TYPE, "text/html"); return entry; }
Další ukázka vytváření vlastních KIO::UDSEntry.
Poslední částí KIO Slave je soubor .protocol, který obsahuje informace o schopnostech našeho otroka. Soubor může vypadat například takto:
[Protocol] exec=kio_abc protocol=abc input=stream output=filesystem listing=Name,Type deleting=false linking=false reading=true writing=false moving=false source=false
exec je název knihovny bez přípony. protocol je název protokolu. Když do Dolphina či Konqueroru napíšete abc:/, KDE automaticky použijí našeho otroka. listing říká, jaké všechny informace v základě o položkách dodáváme. Následující direktivy informují o schopnostech otroka - ten náš umí pouze číst. Soubor .protocol se instaluje do /usr/share/kde4/services.
Když projekt přeložíte a nainstalujete, můžete ho otestovat vepsáním abc:/ do adresního řádku libovolného KDE správce souborů. Po chvíli načítání by se měl objevit seznam adresářů identický s tím v sekci Software.
Pokud se chcete podívat trochu hlouběji do KIO Slaves, podívejte se třeba do zdrojových kódu kio_ftp (kdelibs/kioslave/ftp), nebo kio_archive (kdebase-runtime/kioslave/archive).
KIO je prostředek pro snadnou práci se vstupně-výstupními operacemi a umožňuje pohodlný přístup i ke vzdáleným úložištím. Samotný přístup je možný díky procesům zvaným KIO Slaves. V KDE je ve výchozí instalaci k dispozici na 90 různých KIO Slaves, které podporují všelijaké síťové protokoly i lokální soubory.
V příští části se dostaneme k mnohými zatracované technologii Akonadi. Úplně nakonec ještě archiv se zdrojovými kódy příkladů.
Nástroje: Tisk bez diskuse
Tiskni
Sdílej:
V první ukázce se volá pouze KIO::copy() a hned na to KIO::move(). Z toho by člověk nabyl dojmu, že se jedná o blokující funkce (až se dokončí KIO::copy(), zahájí se KIO::move()).
Jenže v následující ukázce MainWindow::copyDir() se volá KIO::copy() a teprve po té se registrují signály, dodělávají widgety a podobně. Tady to vypadá, že volání KIO::copy() pouze připraví objekt, ale nic se ještě nevykoná (kdyby ano, tak by celá úloha mohla skončit, ještě než se dotaneme k nastavení signálů). V dalším kódu se ale nikde objektu current_job neříká, aby zahájil činnost, ani se nikde nečeká na jeho ukončení.
Jak to tedy je?
connect(current_job, SIGNAL(finished(KJob*)),
this, SLOT(jobFinished(KJob*)));
Prvni signal emituje KIO::Job 200ms po spusteni, takze hlavni proces ma dost casu se na signaly KIO Jobu povesit, a o nic neprisel.
jinak, nez pres notifikacni panel v Plasme se to uz v KDE4 vytahnout neda
Veď práve, do 4.5 mi to išlo ešte okenným spôsobom. Asi si budem musieť kuiserver opraviť sám.
KIO::CopyJob *linkJob = KIO::link(source, link, HideProgressInfo);
Diky, opraveno.