diff options
Diffstat (limited to 'konq-plugins')
303 files changed, 36141 insertions, 0 deletions
diff --git a/konq-plugins/Makefile.am b/konq-plugins/Makefile.am new file mode 100644 index 0000000..5949b5a --- /dev/null +++ b/konq-plugins/Makefile.am @@ -0,0 +1,6 @@ +SUBDIRS = crashes khtmlsettingsplugin kimgalleryplugin dirfilter uachanger \ + babelfish validators domtreeviewer webarchiver sidebar kuick \ + imagerotation minitools microformat autorefresh fsview searchbar \ + arkplugin akregator rellinks mediarealfolder + + diff --git a/konq-plugins/README b/konq-plugins/README new file mode 100644 index 0000000..5ab9b1b --- /dev/null +++ b/konq-plugins/README @@ -0,0 +1,91 @@ +Konqueror Plugins +===================================================================== +This module contains plugins that interact with Konqueror. + +babelfish +------------------- +This works on KHTMLPart. It uses AltaVista's BabelFish site to +translate the current page to whatever language you want (within +reason). + +dirfilter +------------------- +This works on KonqDirPart. This allows you to filter the current +directory in a variety of ways. + +domtreeviewer +------------------- +Displays the document object model (DOM) in a dialog box. + +htmlvalidator +------------------- +This works on KHTMLPart. It uses the w3c HTML validator to validate +the current page. This is very handy when creating web pages. + +cssvalidator +------------------- +This works on KHTMLPart. It uses the w3c HTML validator to validate +the current page. This is very handy when debugging Cascading Style Sheets. + +khtmlsettingsplugin +------------------- +This works on KHTMLPart. This allows you to enable or disable a bunch +of HTML settings without going through the settings dialog. + +kimgalleryplugin +------------------- +This works on KonqDirPart. It creates an HTML page with thumbnails of +all the images in the current directory. + +uachanger +------------------- +This works on KHTMLPart. It allows you to change the user agent +without going through the settings dialog. + +kuick +------------------- +This works on KonqPopupMenuPlugin. It allows to select a bunch of files +and copy and move them really quick. + +smbmounter +------------------- +This works on KonqDirPart. It works together with the smbro ioslave +and provides two menus items to smbmount/umount the current samba share. + +autorefresh +------------------- +This works on any readonly part (though currently it only plugs into +khtmlpart). It lets you tell konqueror to refresh a page automatically +after a specific period. This is useful for things like news pages, +and should be very nice for people using kiosk mode. + +sidebar +------------------ +In this subdirectory you will find plugins for konqueror's extended sidebar + +sidebar/mediaplayer +------------------- +It's a small embedded mediaplayer, onto which you can drag songs or videos for preview + +fsview +------------------- +Graphical Disk Usage as konqueror plugin for inode/directory, for local files. + +arkplugin +------------------- +This lets you quickly archive or unarchive files from Konqueror, using Ark + +akregator +------------------- +This works on KHTMLPart and allows you to add feeds to Akregator directly from Konqueror. + +mediarealfolder +------------------- +This adds a service menu to konqueror allowing to open a medium mountpoint +directly by right clicking on it. + +minitools +------------------- +This plugin adds implementation for so-called bookmarklets. Bookmarklets are little +Javascript programs which can be saved and used like normal web page bookmarks. Therefore, +they are simple "one-click" tools that can add substantial functionality to the browser. diff --git a/konq-plugins/akregator/Makefile.am b/konq-plugins/akregator/Makefile.am new file mode 100644 index 0000000..c6964d1 --- /dev/null +++ b/konq-plugins/akregator/Makefile.am @@ -0,0 +1,25 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libakregatorkonqplugin.la libakregatorkonqfeedicon.la + +libakregatorkonqplugin_la_SOURCES = akregatorplugin.cpp pluginbase.cpp +libakregatorkonqplugin_la_LIBADD = -lkonq $(LIB_KHTML) +libakregatorkonqplugin_la_LDFLAGS = -module $(KDE_PLUGIN) -avoid-version -no-undefined $(all_libraries) + +libakregatorkonqfeedicon_la_SOURCES = konqfeedicon.cpp feeddetector.cpp pluginbase.cpp +libakregatorkonqfeedicon_la_LIBADD = -lkonq $(LIB_KHTML) +libakregatorkonqfeedicon_la_LDFLAGS = -module $(KDE_PLUGIN) -avoid-version -no-undefined $(all_libraries) + +konqplugindir = $(kde_servicesdir) +konqplugin_DATA = akregator_konqplugin.desktop +konqfeedicondir = $(kde_datadir)/khtml/kpartplugins +konqfeedicon_DATA = akregator_konqfeedicon.desktop akregator_konqfeedicon.rc + +rssicondir = $(kde_datadir)/akregator/pics +rssicon_DATA = rss.png + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/akregator_konqplugin.pot diff --git a/konq-plugins/akregator/akregator_konqfeedicon.desktop b/konq-plugins/akregator/akregator_konqfeedicon.desktop new file mode 100644 index 0000000..9f304f7 --- /dev/null +++ b/konq-plugins/akregator/akregator_konqfeedicon.desktop @@ -0,0 +1,116 @@ +[Desktop Entry] +Name=Konq Feed Icon Plugin +Name[bg]=Икона на новини +Name[ca]=Icona de l'extensió d'enllaços del Konq +Name[cs]=Modul pro zdroje +Name[da]=Konq Kilde-ikon plugin +Name[de]=RSS-Quellen-Symbol in Konqueror +Name[el]=Πρόσθετο εικονιδίου ροής του Konq +Name[eo]=Enhavpiktograma kromaĵo por Konkeranto +Name[es]=Icono del complemento de fuentes para Konq +Name[et]=Konquerori RSS-kanali ikooni plugin +Name[eu]=Konq Feed ikono plugina +Name[fa]=وصلۀ شمایل خوراندن Konq +Name[fi]=Konq syöte kuvakesovelma +Name[fr]=Module d'icône de flux pour Konqueror +Name[fy]=Konq Feed-piktogram-plugin +Name[ga]=Breiseán Deilbhín Fotha Konq +Name[gl]=Plugin de Ícone RSS de Konqueror +Name[hi]=कॉन्क. फ़ीड प्रतीक प्लगइन +Name[hr]=Konq dodatak ikone tekućih novosti +Name[hu]=Konqueror csatornaikon-modul +Name[is]=Konq íforrit fyrir flæðismámyndir +Name[it]=Plugin di visualizzazione icone per fonti +Name[ja]=Konq フィードアイコン プラグイン +Name[ka]=Konq არხის ხატულის მოდული +Name[kk]=Konq ақпар таңбашасының плагин модулі +Name[km]=កម្មវិធីជំនួយរូបតំណាងមតិព័ត៌មានរបស់ Konq +Name[lt]=Konq kanalų ženkliuko priedas +Name[mk]=Приклучок за икона за довод за Konqueror +Name[ms]=Plugin Ikon Suapan Konq +Name[nb]=Programtillegg for Konq-ikon for nyhetskilde +Name[nds]=Konqueror-Moduul för't RSS-Stroomlüttbild +Name[ne]=कङ्क फिड प्रतिमा प्लगइन +Name[nl]=Konq Feed-pictogram-plugin +Name[nn]=Programtillegg for kjeldeikon i Konqueror +Name[pa]=Konq ਫੀਡ ਆਈਕਾਨ ਪਲੱਗਇਨ +Name[pl]=Wtyczka Konq z ikoną RSS +Name[pt]='Plugin' de Ícone de Fonte do Konqueror +Name[pt_BR]=Plug-in do Ícone de Fontes do Konq +Name[ru]=Модуль лент новостей Konq +Name[sk]=Modul ikony kŕmitka pre Konq +Name[sl]=Vstavek za Konqueror z ikono vira +Name[sr]=Прикључак Konqueror-а за икону довода +Name[sr@Latn]=Priključak Konqueror-a za ikonu dovoda +Name[sv]=Konqueror-insticksprogram med kanalikon +Name[ta]=Konq பீட் சின்னச் சொருகுப்பொருள் +Name[tr]=Konq Besleme Simge Eklentisi +Name[uk]=Втулок піктограми подачі для Konqueoror +Name[uz]=Konqueror yangiliklar tasmasi nishonchasi plagini +Name[uz@cyrillic]=Konqueror янгиликлар тасмаси нишончаси плагини +Name[vi]=Bổ sung biểu tượng nguồn tin Konq +Name[zh_CN]=Konq 种子图标插件 +Name[zh_TW]=Konq Feed 圖示外掛程式 +Icon=akregator +Comment=Displays feed icon in statusbar when the page has RSS feed +Comment[bg]=Показване на иконата на новите, ако сайта има новини във формат RSS +Comment[ca]=Mostra la icona d'enllaços a la barra d'estat quan la pàgina té enllaç RSS +Comment[cs]=Zobrazí na panelu ikonku, pokud má stránka RSS +Comment[da]=Viser kildeikon i statusfelt når siden har RSS-kilde +Comment[de]=Zeigt das Quellen-Symbol in der Statusleiste, wenn die Seite eine RSS-Quelle hat +Comment[el]=Εμφανίζει το εικονίδιο ροής στη γραμμή κατάστασης όταν η σελίδα έχει ροή RSS +Comment[eo]=Montras enhavan piktogramon en statolistelo kiam la paĝo havas RSS enhavon +Comment[es]=Muestra el icono de las fuentes en la barra de estado cuando la página tiene fuentes RSS +Comment[et]=Näitab olekuribal kanaliikooni, kui saidil on RSS-kanal +Comment[eu]=Orriak RSS iturbururik badu, egoera-barran ikonoa bistaratzen du +Comment[fa]=هنگامی که صفحه خوراندن RSS را دارد، شمایل خوراندن را در میله وضعیت نمایش میدهد +Comment[fi]=Näyttää syötekuvakkeen tilapalkissa jos sivulla on RSS-syöte +Comment[fr]=Affiche une icône de flux RSS dans la barre d'état lorsque la page en possède +Comment[fy]=Toant in feed-piktogram yn de statusbalke as der in RSS-feed op de side stiet +Comment[ga]=Taispeáin deilbhín fotha sa bharra stádais nuair atá fotha RSS ar an leathanach +Comment[gl]=Mostra o ícone de fonte na barra de estado cando a páxina ten unha fonte RSS +Comment[hr]=Prikazivanje ikone tekućih novosti u traci stanja ako web-stranica ima RSS novosti +Comment[hu]=Csatornaikont jelenít meg az állapotsorban, ha az oldalhoz RSS-csatorna tartozik +Comment[is]=Sýna straumtáknmynd í stöðuslá þegar síða inniheldur RSS straum +Comment[it]=Mostra l'icona nella barra di stato quando la pagina ha una fonte RSS +Comment[ja]=RSS フィードを提供しているページでステータスバーにフィードアイコンを表示します +Comment[ka]=სტატუსის ზოლზე აჩვენებს არხის ხატულას როდესაც გვერდს RSS არხი აქვს +Comment[kk]=Бетте RSS ақпары бар болса күй-жай жолағында оның таңбашасын көрсету +Comment[km]=បង្ហាញរូបតំណាងមតិព័ត៌មាននៅក្នុងរបារស្ថានភាព នៅពេលទំព័រមានមតិព័ត៌មាន RSS +Comment[lt]=Rodo kanalo ikoną būsenos juostoje kai puslapis turi RSS kanalą +Comment[mk]=Прикажува икона на доток во статусната линија кога страницата има RSS-доток +Comment[ms]=Memaparkan ikon suapan dalam bar status apabila halaman mempunyai suapan RSS +Comment[nb]=Viser ikon for nyhetskilde på statuslinja når nettstedet har en RSS-kilde +Comment[nds]=Wiest dat RSS-Lüttbild op den Statusbalken, wenn de Siet en RSS-Narichtenstroom bargt. +Comment[ne]=पृष्ठमा आरएसएस फिड हुदाँ स्थितिपट्टीमा फिड प्रतिमा प्रदर्शन गर्दछ +Comment[nl]=Toont een feed-pictogram in de statusbalk als de pagina een RSS-feed bevat +Comment[nn]=Viser eit kjeldeikon på statuslinja når sida har ei RSS-kjelde +Comment[pl]=Wyświetla ikonę RSS w pasku stanu, jeśli strona zawiera źródło wiadomości RSS +Comment[pt]=Mostra o ícone de fonte na barra de estado quando a página tem uma fonte RSS +Comment[pt_BR]=Mostra um ícone na barra de status quando a página possui uma fonte de notícias RSS +Comment[ru]=Показать в строке состояния значок ленты, если у страницы есть лента новостей +Comment[sk]=Zobrazí ikonu kŕmitka v stavovom riadku keď strana obsahuje RSS kŕmitko +Comment[sl]=Prikaže ikono vira v vrstici stanja, če ima stran vir RSS ali Atom +Comment[sr]=Приказује икону довода у статусној траци када страна има RSS довод +Comment[sr@Latn]=Prikazuje ikonu dovoda u statusnoj traci kada strana ima RSS dovod +Comment[sv]=Visar kanalikon i statusraden när sidan har en RSS-kanal +Comment[ta]=RSS ஃபீட் இருக்கும்போது நிலைப்பட்டியலில் ஃபீட் சின்னத்தை காட்டுகிறது +Comment[tr]=Eğer sayfa RSS kaynaklı ise kaynak simgesini durum çubuğunda göster +Comment[uk]=Показує піктограму подачі в рядку стану, коли сторінка має подачу RSS +Comment[uz]=Sahifada RSS tasmasi mavjud boʻlsa, holat panelida RSS nishonchasini koʻrsatish +Comment[uz@cyrillic]=Саҳифада RSS тасмаси мавжуд бўлса, ҳолат панелида RSS нишончасини кўрсатиш +Comment[vi]=Hiển thị biểu tương nguồn tin trên thanh trạng thái khi trang Mạng có nguồn tin RSS +Comment[zh_CN]=当页面有 RSS 种子的时候在状态栏显示种子图标 +Comment[zh_TW]=當網頁有 RSS feed 時,於狀態列顯示 feed 圖示 +Type=Service +X-KDE-Library=libakregatorkonqfeedicon +X-KDE-PluginInfo-Author=Teemu Rytilahti +X-KDE-PluginInfo-Email=tpr@d5k.net +X-KDE-PluginInfo-Name=konqfeedicon +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-Website=http://akregator.sourceforge.net +X-KDE-PluginInfo-Category=Statusbar +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +X-KDE-ParentApp=konqueror diff --git a/konq-plugins/akregator/akregator_konqfeedicon.rc b/konq-plugins/akregator/akregator_konqfeedicon.rc new file mode 100644 index 0000000..63f97fe --- /dev/null +++ b/konq-plugins/akregator/akregator_konqfeedicon.rc @@ -0,0 +1,3 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="konqfeedicon" library="libakregatorkonqfeedicon" version="1"> +</kpartplugin> diff --git a/konq-plugins/akregator/akregator_konqplugin.desktop b/konq-plugins/akregator/akregator_konqplugin.desktop new file mode 100644 index 0000000..d033ce5 --- /dev/null +++ b/konq-plugins/akregator/akregator_konqplugin.desktop @@ -0,0 +1,54 @@ +[Desktop Entry] +Type=Service +Name=Add Feed to Akregator +Name[bg]=Добавяне на източник към Akregator +Name[ca]=Afegeix un enllaç a aKregator +Name[cs]=Přidat zprávy do aKregatoru +Name[da]=Tilføj kilde til Akregator +Name[de]=Nachrichtenquelle zu Akregator hinzufügen +Name[el]=Προσθήκη ροής στον aKregator +Name[eo]=Aldonu enhavon al Akregatoro +Name[es]=Añadir fuente a aKregator +Name[et]=Lisa kanal Akregatorile +Name[eu]=Akregator-era sarrera bat gehitzen du +Name[fa]=افزودن خوراندن به Akregator +Name[fi]=Lisää syöte aKregatoriin +Name[fr]=Ajouter ce flux à Akregator +Name[fy]=Feed oan Akregator taheakje +Name[ga]=Cuir Fotha le Akregator +Name[gl]=Engadir Fonte ao Akregator +Name[hr]=Dodaj tekuće novosti u Akregator +Name[hu]=Csatorna hozzáadása az Akregatorhoz +Name[is]=Bæta straum við Akregator +Name[it]=Aggiunge fonti ad aKregator +Name[ja]=AKregator にフィードを追加 +Name[ka]=არხის Akregator-ისთვის დამატება +Name[kk]=Ақпарды Akregator-ға қосу +Name[km]=បន្ថែមមតិព័ត៌មានទៅ Akregator +Name[lt]=Įdėti kanalą į Akregator +Name[mk]=Додај доток кон Акрегатор +Name[ms]=Tambah Suapan kepada Akregator +Name[nb]=Legg til kilde til aKregator +Name[nds]=Nachrichtenstroom na Akregator tofögen +Name[ne]=एक्रिगेटरमा फिड थप्नुहोस् +Name[nl]=Feed aan Akregator toevoegen +Name[nn]=Legg til kjelde i Akregator +Name[pl]=Dodaj źródło wiadomości do aKregatora +Name[pt]=Adicionar Fonte ao Akregator +Name[pt_BR]=Adicionar fonte de notícias ao aKregator +Name[ru]=Добавить ленту новостей в Akregator +Name[sk]=Pridať kŕmitko do Akregator +Name[sl]=Dodaj vir v Akregator +Name[sr]=Додај довод у Akregator +Name[sr@Latn]=Dodaj dovod u Akregator +Name[sv]=Lägg till en kanal till Akregator +Name[ta]=aKregatorக்கு உள்ளீட்டை சேர் +Name[tr]=Akregator'a Besleme Ekle +Name[uk]=Додати подачу в Akregator +Name[uz]=Akregator dasturiga yangiliklar tasmasini qoʻshish +Name[uz@cyrillic]=Akregator дастурига янгиликлар тасмасини қўшиш +Name[vi]=Thêm nguồn tin vào Akregator +Name[zh_CN]=在 Akregator 中添加种子 +Name[zh_TW]=將 Feed 加入 Akregator +X-KDE-Library=libakregatorkonqplugin +ServiceTypes=KonqPopupMenu/Plugin,all/all diff --git a/konq-plugins/akregator/akregatorplugin.cpp b/konq-plugins/akregator/akregatorplugin.cpp new file mode 100644 index 0000000..a2a82f2 --- /dev/null +++ b/konq-plugins/akregator/akregatorplugin.cpp @@ -0,0 +1,135 @@ +/* This file is part of the KDE project + + Copyright (C) 2004 Gary Cramblitt <garycramblitt@comcast.net> + + Adapted from kdeutils/ark/konqplugin by + Georg Robbers <Georg.Robbers@urz.uni-hd.de> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "akregatorplugin.h" +#include "pluginbase.h" + +#include <kapplication.h> +#include <kmimetype.h> +#include <kdebug.h> +#include <kaction.h> +#include <kinstance.h> +#include <klocale.h> +#include <konq_popupmenu.h> +#include <kpopupmenu.h> +#include <kgenericfactory.h> +#include <kurl.h> +#include <khtml_part.h> +#include <khtmlview.h> +#include <kmessagebox.h> + +#include <qdir.h> +#include <qcstring.h> +#include <qobject.h> +#include <qstringlist.h> + +using namespace Akregator; + +typedef KGenericFactory<AkregatorMenu, KonqPopupMenu> AkregatorMenuFactory; +K_EXPORT_COMPONENT_FACTORY( libakregatorkonqplugin, AkregatorMenuFactory("akregatorkonqplugin") ) + +AkregatorMenu::AkregatorMenu( KonqPopupMenu * popupmenu, const char *name, const QStringList& /* list */ ) + : KonqPopupMenuPlugin( popupmenu, name), PluginBase(), m_conf(0), m_part(0) +{ + kdDebug() << "AkregatorMenu::AkregatorMenu()" << endl; + if ( QCString( kapp->name() ) == "kdesktop" && !kapp->authorize("editable_desktop_icons" ) ) + return; + + // Do nothing if user has turned us off. + // TODO: Not yet implemented in aKregator settings. + /*m_conf = new KConfig( "akregatorrc" ); + m_conf->setGroup( "AkregatorKonqPlugin" ); + if ( !m_conf->readBoolEntry( "Enable", true ) ) + return; + */ + + KHTMLView* view = 0L; + + if (popupmenu && popupmenu->parent() && popupmenu->parent()->inherits("KHTMLView")) + view = static_cast<KHTMLView*>(popupmenu->parent()); + + if (view) + m_part = view->part(); + + KGlobal::locale()->insertCatalogue("akregator_konqplugin"); + m_feedMimeTypes << "text/rss" << "text/rdf" << "text/xml"; + // Get the list of URLs clicked on from Konqi. + //KFileItemList m_list = popupmenu->fileItemList(); + // See if any are RSS feeds. + + KFileItemList list = popupmenu->fileItemList(); + KFileItem* it = list.first(); + while (it != 0) + { + if (isFeedUrl(it)) + { + kdDebug() << "AkregatorMenu: found feed URL " << it->url().prettyURL() << endl; + KAction *action = new KAction( i18n( "Add Feed to Akregator" ), "akregator", 0, this, SLOT( slotAddFeed() ), actionCollection(), "akregatorkonqplugin_mnu" ); + addAction( action ); + addSeparator(); + m_feedURL = it->url().url(); + break; + } + + it = list.next(); + } +} + +AkregatorMenu::~AkregatorMenu() +{ + KGlobal::locale()->removeCatalogue("akregator_konqplugin"); + delete m_conf; +} + +bool AkregatorMenu::isFeedUrl(const QString &url) +{ + if (url.contains(".htm", false) != 0) return false; + if (url.contains("rss", false) != 0) return true; + if (url.contains("rdf", false) != 0) return true; + if (url.contains("xml", false) != 0) return true; + return false; +} + +bool AkregatorMenu::isFeedUrl(const KFileItem * item) +{ + if ( m_feedMimeTypes.contains( item->mimetype() ) ) + return true; + else + { + QString url = item->url().url(); + // If URL ends in .htm or .html, it is not a feed url. + return isFeedUrl(url); + } + return false; +} + +void AkregatorMenu::slotAddFeed() +{ + QString url = m_part ? fixRelativeURL(m_feedURL, m_part->baseURL()) : m_feedURL; + if(akregatorRunning()) + addFeedsViaDCOP(QStringList(url)); + else + addFeedViaCmdLine(url); +} + +#include "akregatorplugin.moc" diff --git a/konq-plugins/akregator/akregatorplugin.h b/konq-plugins/akregator/akregatorplugin.h new file mode 100644 index 0000000..8074f2f --- /dev/null +++ b/konq-plugins/akregator/akregatorplugin.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE project + + Copyright (C) 2003 Georg Robbers <Georg.Robbers@urz.uni-hd.de> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _AKREGATORPLUGIN_H_ +#define _AKREGATORPLUGIN_H_ + +#include <konq_popupmenu.h> +#include <kfileitem.h> +#include <kconfig.h> + +#include "pluginbase.h" + +class KAction; +class KHTMLPart; + +namespace Akregator +{ + +class AkregatorMenu : public KonqPopupMenuPlugin, PluginBase +{ + Q_OBJECT +public: + AkregatorMenu( KonqPopupMenu *, const char *name, const QStringList &list ); + virtual ~AkregatorMenu(); + +public slots: + void slotAddFeed(); + +protected: + bool isFeedUrl(const QString &s); + bool isFeedUrl(const KFileItem *item); + +private: + QStringList m_feedMimeTypes; + KConfig *m_conf; + KHTMLPart *m_part; + QString m_feedURL; +}; + +} + +#endif + diff --git a/konq-plugins/akregator/feeddetector.cpp b/konq-plugins/akregator/feeddetector.cpp new file mode 100644 index 0000000..928a282 --- /dev/null +++ b/konq-plugins/akregator/feeddetector.cpp @@ -0,0 +1,147 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <qregexp.h> +#include <qstring.h> +#include <qstringlist.h> +#include <qvaluelist.h> +#include <kcharsets.h> + +#include "feeddetector.h" + + +using namespace Akregator; + +FeedDetectorEntryList FeedDetector::extractFromLinkTags(const QString& s) +{ + //reduce all sequences of spaces, newlines etc. to one space: + QString str = s.simplifyWhiteSpace(); + + // extracts <link> tags + QRegExp reLinkTag("<[\\s]?LINK[^>]*REL[\\s]?=[\\s]?\\\"[\\s]?(ALTERNATE|SERVICE\\.FEED)[\\s]?\\\"[^>]*>", false); + + // extracts the URL (href="url") + QRegExp reHref("HREF[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", false); + // extracts type attribute + QRegExp reType("TYPE[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", false); + // extracts the title (title="title") + QRegExp reTitle("TITLE[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", false); + + int pos = 0; + int matchpos = 0; + + // get all <link> tags + QStringList linkTags; + //int strlength = str.length(); + while ( matchpos != -1 ) + { + matchpos = reLinkTag.search(str, pos); + if (matchpos != -1) + { + linkTags.append( str.mid(matchpos, reLinkTag.matchedLength()) ); + pos = matchpos + reLinkTag.matchedLength(); + } + } + + FeedDetectorEntryList list; + + for ( QStringList::Iterator it = linkTags.begin(); it != linkTags.end(); ++it ) + { + QString type; + int pos = reType.search(*it, 0); + if (pos != -1) + type = reType.cap(1).lower(); + + // we accept only type attributes indicating a feed + if ( type != "application/rss+xml" && type != "application/rdf+xml" + && type != "application/atom+xml" && type != "text/xml" ) + continue; + + QString title; + pos = reTitle.search(*it, 0); + if (pos != -1) + title = reTitle.cap(1); + + title = KCharsets::resolveEntities(title); + + QString url; + pos = reHref.search(*it, 0); + if (pos != -1) + url = reHref.cap(1); + + url = KCharsets::resolveEntities(url); + + // if feed has no title, use the url as preliminary title (until feed is parsed) + if ( title.isEmpty() ) + title = url; + + if ( !url.isEmpty() ) + list.append(FeedDetectorEntry(url, title) ); + } + + + return list; +} + +QStringList FeedDetector::extractBruteForce(const QString& s) +{ + QString str = s.simplifyWhiteSpace(); + + QRegExp reAhrefTag("<[\\s]?A[^>]?HREF=[\\s]?\\\"[^\\\"]*\\\"[^>]*>", false); + + // extracts the URL (href="url") + QRegExp reHref("HREF[\\s]?=[\\s]?\\\"([^\\\"]*)\\\"", false); + + QRegExp rssrdfxml(".*(RSS|RDF|XML)", false); + + int pos = 0; + int matchpos = 0; + + // get all <a href> tags and capture url + QStringList list; + //int strlength = str.length(); + while ( matchpos != -1 ) + { + matchpos = reAhrefTag.search(str, pos); + if ( matchpos != -1 ) + { + QString ahref = str.mid(matchpos, reAhrefTag.matchedLength()); + int hrefpos = reHref.search(ahref, 0); + if ( hrefpos != -1 ) + { + QString url = reHref.cap(1); + + url = KCharsets::resolveEntities(url); + + if ( rssrdfxml.exactMatch(url) ) + list.append(url); + } + + pos = matchpos + reAhrefTag.matchedLength(); + } + } + + return list; + +} diff --git a/konq-plugins/akregator/feeddetector.h b/konq-plugins/akregator/feeddetector.h new file mode 100644 index 0000000..b557e33 --- /dev/null +++ b/konq-plugins/akregator/feeddetector.h @@ -0,0 +1,77 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef AKREGATORFEEDDETECTOR_H +#define AKREGATORFEEDDETECTOR_H + +#include <qstring.h> +#include <qvaluelist.h> + +class QStringList; + +namespace Akregator +{ + + class FeedDetectorEntry + { + public: + FeedDetectorEntry() {} + FeedDetectorEntry(const QString& url, const QString& title) + : m_url(url), m_title(title) {} + + const QString& url() const { return m_url; } + const QString& title() const { return m_title; } + + private: + const QString m_url; + const QString m_title; + }; + + typedef QValueList<FeedDetectorEntry> FeedDetectorEntryList; + + /** a class providing functions to detect linked feeds in HTML sources */ + class FeedDetector + { + public: + /** \brief searches an HTML page for feeds listed in @c <link> tags + @c <link> tags with @c rel attribute values @c alternate or + @c service.feed are considered as feeds + @param s the html source to scan (the actual source, no URI) + @return a list containing the detected feeds + */ + static FeedDetectorEntryList extractFromLinkTags(const QString& s); + + /** \brief searches an HTML page for slightly feed-like looking links and catches everything not running away quickly enough. + Extracts links from @c <a @c href> tags which end with @c xml, @c rss or @c rdf + @param s the html source to scan (the actual source, no URI) + @return a list containing the detected feeds + */ + static QStringList extractBruteForce(const QString& s); + + private: + FeedDetector() {} + }; +} + +#endif //AKREGATORFEEDDETECTOR_H diff --git a/konq-plugins/akregator/konqfeedicon.cpp b/konq-plugins/akregator/konqfeedicon.cpp new file mode 100644 index 0000000..436a4be --- /dev/null +++ b/konq-plugins/akregator/konqfeedicon.cpp @@ -0,0 +1,222 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "konqfeedicon.h" +#include "feeddetector.h" +#include "pluginbase.h" + +#include <dcopref.h> +#include <kapplication.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <khtml_part.h> +#include <kiconloader.h> +#include <klibloader.h> +#include <kmessagebox.h> +#include <kparts/statusbarextension.h> +#include <kprocess.h> +#include <kstandarddirs.h> +#include <kstatusbar.h> +#include <kurllabel.h> +#include <kurl.h> + +#include <qcursor.h> +#include <qobjectlist.h> +#include <qpixmap.h> +#include <qstringlist.h> +#include <qstylesheet.h> +#include <qtimer.h> +#include <qtooltip.h> + +using namespace Akregator; + +typedef KGenericFactory<KonqFeedIcon> KonqFeedIconFactory; +K_EXPORT_COMPONENT_FACTORY(libakregatorkonqfeedicon, + KonqFeedIconFactory("akregatorkonqfeedicon")) + +KonqFeedIcon::KonqFeedIcon(QObject *parent, const char *name, const QStringList &) + : KParts::Plugin(parent, name), PluginBase(), m_part(0), m_feedIcon(0), m_statusBarEx(0), m_menu(0) +{ + KGlobal::locale()->insertCatalogue("akregator_konqplugin"); + + m_part = dynamic_cast<KHTMLPart*>(parent); + if(!m_part) { kdDebug() << "couldn't get part" << endl; return; } + // FIXME: need to do this because of a bug in khtmlpart, it's fixed now for 3.4 (and prolly backported for 3.3.3?) + //connect(m_part->view(), SIGNAL(finishedLayout()), this, SLOT(addFeedIcon())); + QTimer::singleShot(0, this, SLOT(waitPartToLoad())); +} + +void KonqFeedIcon::waitPartToLoad() +{ + connect(m_part, SIGNAL(completed()), this, SLOT(addFeedIcon())); + connect(m_part, SIGNAL(completed(bool)), this, SLOT(addFeedIcon())); // to make pages with metarefresh to work + connect(m_part, SIGNAL(started(KIO::Job *)), this, SLOT(removeFeedIcon())); + addFeedIcon(); +} + +KonqFeedIcon::~KonqFeedIcon() +{ + KGlobal::locale()->removeCatalogue("akregator_konqplugin"); + m_statusBarEx = KParts::StatusBarExtension::childObject(m_part); + if (m_statusBarEx) + { + m_statusBarEx->removeStatusBarItem(m_feedIcon); + // the feed icon is child of the statusbar extension, so if the statusbar is deleted, + // the icon was deleted by the status bar + delete m_feedIcon; + } + // the icon is deleted in every case + m_feedIcon = 0L; + + delete m_menu; + m_menu = 0L; +} + +bool KonqFeedIcon::feedFound() +{ + DOM::NodeList linkNodes = m_part->document().getElementsByTagName("link"); + + if (linkNodes.length() == 0) + return false; + + unsigned int i; + QString doc = ""; + + for (i = 0; i < linkNodes.length(); i++) + { + DOM::Node node = linkNodes.item(i); + doc += "<link "; + for (unsigned int j = 0; j < node.attributes().length(); j++) + { + doc += node.attributes().item(j).nodeName().string() + "=\""; + doc += QStyleSheet::escape(node.attributes().item(j).nodeValue().string()).replace("\"", """); + doc += "\" "; + } + doc += "/>"; + } + + m_feedList = FeedDetector::extractFromLinkTags(doc); + return m_feedList.count() != 0; +} + +void KonqFeedIcon::contextMenu() +{ + delete m_menu; + m_menu = new KPopupMenu(m_part->widget()); + if(m_feedList.count() == 1) { + m_menu->insertTitle(m_feedList.first().title()); + m_menu->insertItem(SmallIcon("bookmark_add"), i18n("Add Feed to Akregator"), this, SLOT(addFeeds()) ); + } + else { + m_menu->insertTitle(i18n("Add Feeds to Akregator")); + connect(m_menu, SIGNAL(activated(int)), this, SLOT(addFeed(int))); + int id = 0; + for(FeedDetectorEntryList::Iterator it = m_feedList.begin(); it != m_feedList.end(); ++it) { + m_menu->insertItem(SmallIcon("bookmark_add"), (*it).title(), id); + id++; + } + //disconnect(m_menu, SIGNAL(activated(int)), this, SLOT(addFeed(int))); + m_menu->insertSeparator(); + m_menu->insertItem(SmallIcon("bookmark_add"), i18n("Add All Found Feeds to Akregator"), this, SLOT(addFeeds()), 0, 50000 ); + } + m_menu->popup(QCursor::pos()); +} + +void KonqFeedIcon::addFeedIcon() +{ + if(!feedFound() || m_feedIcon) { + return; + } + + m_statusBarEx = KParts::StatusBarExtension::childObject(m_part); + if(!m_statusBarEx) return; + + m_feedIcon = new KURLLabel(m_statusBarEx->statusBar()); + + // from khtmlpart's ualabel + m_feedIcon->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small)); + m_feedIcon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + m_feedIcon->setUseCursor(false); + //FIXME hackish + m_feedIcon->setPixmap(QPixmap(locate("data", "akregator/pics/rss.png"))); + + QToolTip::remove(m_feedIcon); + QToolTip::add(m_feedIcon, i18n("Monitor this site for updates (using news feed)")); + + m_statusBarEx->addStatusBarItem(m_feedIcon, 0, true); + + connect(m_feedIcon, SIGNAL(leftClickedURL()), this, SLOT(contextMenu())); +} + +void KonqFeedIcon::removeFeedIcon() +{ + m_feedList.clear(); + if(m_feedIcon) + { + m_statusBarEx->removeStatusBarItem(m_feedIcon); + delete m_feedIcon; + m_feedIcon = 0L; + } + + // Close the popup if it's open, otherwise we crash + delete m_menu; + m_menu = 0L; +} + +void KonqFeedIcon::addFeed(int id) +{ + if(id == 50000) return; + if(akregatorRunning()) + addFeedsViaDCOP(QStringList(fixRelativeURL(m_feedList[id].url(), m_part->baseURL()))); + else + addFeedViaCmdLine(fixRelativeURL(m_feedList[id].url(), m_part->baseURL())); +} + +// from akregatorplugin.cpp +void KonqFeedIcon::addFeeds() +{ + if(akregatorRunning()) + { + QStringList list; + for ( FeedDetectorEntryList::Iterator it = m_feedList.begin(); it != m_feedList.end(); ++it ) + list.append(fixRelativeURL((*it).url(), m_part->baseURL())); + addFeedsViaDCOP(list); + } + else { + kdDebug() << "KonqFeedIcon::addFeeds(): use command line" << endl; + KProcess *proc = new KProcess; + *proc << "akregator" << "-g" << i18n("Imported Feeds"); + + for ( FeedDetectorEntryList::Iterator it = m_feedList.begin(); it != m_feedList.end(); ++it ) { + *proc << "-a" << fixRelativeURL((*it).url(), m_part->baseURL()); + } + + proc->start(KProcess::DontCare); + delete proc; + + } +} + +#include "konqfeedicon.moc" +// vim: ts=4 sw=4 et diff --git a/konq-plugins/akregator/konqfeedicon.h b/konq-plugins/akregator/konqfeedicon.h new file mode 100644 index 0000000..ba3bb8c --- /dev/null +++ b/konq-plugins/akregator/konqfeedicon.h @@ -0,0 +1,77 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KONQFEEDICON_H +#define KONQFEEDICON_H + +#include <qguardedptr.h> +#include <kparts/plugin.h> +#include <kpopupmenu.h> +#include "feeddetector.h" +#include "pluginbase.h" + +/** +@author Teemu Rytilahti +*/ +class KURLLabel; +class KHTMLPart; +class QStringList; + +namespace KParts { + class StatusBarExtension; +} + +namespace Akregator { +class KonqFeedIcon : public KParts::Plugin, PluginBase +{ + Q_OBJECT +public: + KonqFeedIcon(QObject *parent, const char *name, const QStringList &); + + ~KonqFeedIcon(); + +private: + /** + * Tells you if there is feed(s) on the page. + * @return true when there is feed(s) available + */ + bool feedFound(); + + QGuardedPtr<KHTMLPart> m_part; + KURLLabel *m_feedIcon; + KParts::StatusBarExtension *m_statusBarEx; + FeedDetectorEntryList m_feedList; + QGuardedPtr<KPopupMenu> m_menu; + +private slots: + void waitPartToLoad(); + void contextMenu(); + void addFeedIcon(); + void removeFeedIcon(); + void addFeeds(); + void addFeed(int id); +}; + +} +#endif diff --git a/konq-plugins/akregator/pluginbase.cpp b/konq-plugins/akregator/pluginbase.cpp new file mode 100644 index 0000000..4c6b5b1 --- /dev/null +++ b/konq-plugins/akregator/pluginbase.cpp @@ -0,0 +1,102 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kurl.h> +#include <kprocess.h> +#include <dcopref.h> +#include <khtml_part.h> +#include <klocale.h> + +#include "feeddetector.h" +#include "pluginbase.h" +#include <qstringlist.h> + +#include <kdebug.h> + +using namespace Akregator; + +PluginBase::PluginBase() +{} + +PluginBase::~PluginBase() +{} + +bool PluginBase::akregatorRunning() +{ + DCOPRef akr("akregator", "akregator"); + DCOPReply reply = akr.call("interfaces"); // FIXME hackish but works :) -tpr 20041203 + return reply.isValid(); +} + +void PluginBase::addFeedsViaDCOP(const QStringList& urls) +{ + kdDebug() << "PluginBase::addFeedsViaDCOP" << endl; + DCOPRef akr("akregator", "AkregatorIface"); + akr.send("addFeedsToGroup", urls, i18n("Imported Feeds") ); + /*if(!reply.isValid()) { + KMessageBox::error( 0, i18n( "Akregator feed icon - DCOP Call failed" ), + i18n( "The DCOP call addFeedToGroup failed" )); +}*/ +} + +void PluginBase::addFeedViaCmdLine(QString url) +{ + KProcess *proc = new KProcess; + *proc << "akregator" << "-g" << i18n("Imported Feeds"); + *proc << "-a" << url; + proc->start(KProcess::DontCare); + delete proc; +} + +// handle all the wild stuff that KURL doesn't handle +QString PluginBase::fixRelativeURL(const QString &s, const KURL &baseurl) +{ + QString s2=s; + KURL u; + if (KURL::isRelativeURL(s2)) + { + if (s2.startsWith("//")) + { + s2=s2.prepend(baseurl.protocol()+":"); + u=s2; + } + else if (s2.startsWith("/")) + { + KURL b2(baseurl); + b2.setPath(QString()); // delete path and query, so that only protocol://host remains + b2.setQuery(QString()); + u = KURL(b2, s2.remove(0,1)); // remove leading "/" + } + else + { + u = KURL(baseurl, s2); + } + } + else + u=s2; + + u.cleanPath(); + //kdDebug() << "AKREGATOR_PLUGIN_FIXURL: " << "url=" << s << " baseurl=" << baseurl.url() << " fixed=" << u.url() << endl; + return u.url(); +} diff --git a/konq-plugins/akregator/pluginbase.h b/konq-plugins/akregator/pluginbase.h new file mode 100644 index 0000000..8dcecf5 --- /dev/null +++ b/konq-plugins/akregator/pluginbase.h @@ -0,0 +1,60 @@ +/* + This file is part of Akregator. + + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef PLUGINBASE_H +#define PLUGINBASE_H + +class FeedDetectorEntry; +class KHTMLPart; +class QString; +class QStringList; + +namespace Akregator +{ + +class PluginBase +{ + public: + PluginBase(); + ~PluginBase(); + + public: + /** + * Tells you if aKregator is running. + * @return true when aKregator is running + */ + bool akregatorRunning(); + /** + * Adds feed to aKregator via DCOP. + */ + void addFeedsViaDCOP(const QStringList& urls); + /** + * Adds feed to aKregator via command line. + */ + void addFeedViaCmdLine(QString url); + QString fixRelativeURL(const QString &s, const KURL &baseurl); +}; + +} +#endif diff --git a/konq-plugins/akregator/rss.png b/konq-plugins/akregator/rss.png Binary files differnew file mode 100644 index 0000000..3008a51 --- /dev/null +++ b/konq-plugins/akregator/rss.png diff --git a/konq-plugins/akregator/rss.svgz b/konq-plugins/akregator/rss.svgz Binary files differnew file mode 100644 index 0000000..498d5e3 --- /dev/null +++ b/konq-plugins/akregator/rss.svgz diff --git a/konq-plugins/arkplugin/Makefile.am b/konq-plugins/arkplugin/Makefile.am new file mode 100644 index 0000000..0f6ec44 --- /dev/null +++ b/konq-plugins/arkplugin/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libarkplugin.la + +libarkplugin_la_SOURCES = arkplugin.cpp +libarkplugin_la_LIBADD = -lkonq +libarkplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_servicesdir) +plugins_DATA = ark_plugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = arkplugin.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/ark_plugin.pot diff --git a/konq-plugins/arkplugin/ark_plugin.desktop b/konq-plugins/arkplugin/ark_plugin.desktop new file mode 100644 index 0000000..b46694a --- /dev/null +++ b/konq-plugins/arkplugin/ark_plugin.desktop @@ -0,0 +1,59 @@ +[Desktop Entry] +Type=Service +Name=Compress/Extract Files +Name[bg]=Компресиране/извличане на файлове +Name[bs]=Kompresuj/ekstraktuj datoteke +Name[ca]=Comprimeix/extrau fitxers +Name[cs]=Komprimovat/rozbalit soubory +Name[da]=Komprimér/Udpak filer +Name[de]=Dateien komprimieren/extrahieren +Name[el]=Συμπίεση/Εξαγωγή αρχείων +Name[eo]=Kunpremu/Elpaku dosierojn +Name[es]=Comprimir/Extraer archivos +Name[et]=Failide pakkimine/lahtipakkimine +Name[eu]=Fitxategiak konprimitu/atera +Name[fa]=فشردهسازی/استخراج پروندهها +Name[fi]=Pakkaa/Pura tiedostoja +Name[fr]=Compacter / extraire des fichiers +Name[fy]=Triemmen ynpakke/útpakke +Name[ga]=Comhbhrúigh/Bain Comhaid Amach +Name[gl]=Comprimir/Extrair Ficheiros +Name[he]=דחוס/פרוס קבצים +Name[hi]=फ़ाइलों को संपीडित करें/निकालें +Name[hr]=Komprimiranje i rastvaranje tekstualnih datoteka +Name[hu]=Tömörítés/kitömörítés +Name[is]=Þjappa/taka út skrár +Name[it]=Comprimi/estrai file +Name[ja]=ファイルを圧縮/展開 +Name[ka]=ფაილების შეკუნშვა/ამოღება +Name[kk]=Файлдарды сығу/тарқату +Name[km]=បង្ហាប់/ស្រង់ចេញឯកសារ +Name[lt]=Suspausti/išspausti bylas +Name[mk]=Компресија/отпакување датотеки +Name[ms]=Mampat/Ekstrak Fail +Name[nb]=Komprimer/pakk ut filer +Name[nds]=Dateien komprimeren/utpacken +Name[ne]=फाइल सङ्कुचन/निष्कर्षण +Name[nl]=Bestanden inpakken/uitpakken +Name[nn]=Komprimer/pakk ut filer +Name[pa]=ਫਾਇਲਾਂ ਸਮੇਟੋ/ਖੋਲੋ +Name[pl]=Kompresja/dekompresja plików +Name[pt]=Comprimir/Extrair Ficheiros +Name[pt_BR]=Compactar/Extrair Arquivos +Name[ru]=Сжатие/распаковка файлов +Name[sk]=Zabaliť/rozbaliť súbory +Name[sl]=Stisni/Izvleci datoteke +Name[sr]=Компресуј/извуци фајлове +Name[sr@Latn]=Kompresuj/izvuci fajlove +Name[sv]=Komprimera eller packa upp filer +Name[ta]=கோப்பினை சுருக்கு/எடு +Name[tg]=Фишурдан/кушодани файлҳо +Name[tr]=Dosyaları Sıkıştır/Ayıkla +Name[uk]=Стиснення/розпакування файлів +Name[uz]=Fayllarni qisish/ajratish +Name[uz@cyrillic]=Файлларни қисиш/ажратиш +Name[vi]=Nén/Giải nén tập tin +Name[zh_CN]=压缩/解压文件 +Name[zh_TW]=壓縮/解壓縮檔案 +X-KDE-Library=libarkplugin +ServiceTypes=KonqPopupMenu/Plugin,all/all diff --git a/konq-plugins/arkplugin/arkplugin.cpp b/konq-plugins/arkplugin/arkplugin.cpp new file mode 100644 index 0000000..35e610e --- /dev/null +++ b/konq-plugins/arkplugin/arkplugin.cpp @@ -0,0 +1,566 @@ +/* This file is part of the KDE project + + Copyright (C) 2003 Georg Robbers <Georg.Robbers@urz.uni-hd.de> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "arkplugin.h" + +#include <kapplication.h> +#include <kstandarddirs.h> +#include <kmimetype.h> +#include <kdebug.h> +#include <kaction.h> +#include <kinstance.h> +#include <klocale.h> +#include <konq_popupmenu.h> +#include <kpopupmenu.h> +#include <kgenericfactory.h> +#include <kurl.h> +#include <kio/netaccess.h> + +#include <qdir.h> +#include <qcstring.h> +#include <qsignalmapper.h> +#include <qobject.h> + +typedef KGenericFactory<ArkMenu, KonqPopupMenu> ArkMenuFactory; +K_EXPORT_COMPONENT_FACTORY( libarkplugin, ArkMenuFactory("arkplugin") ) + +ArkMenu::ArkMenu( KonqPopupMenu * popupmenu, const char *name, const QStringList& /* list */ ) + : KonqPopupMenuPlugin( popupmenu, name), + m_compAsMapper( 0 ), m_addToMapper( 0 ), m_conf( 0 ) +{ + if ( ( QCString( kapp->name() ) == "kdesktop" && !kapp->authorize("editable_desktop_icons" ) ) + || ( KStandardDirs::findExe( "ark" ).isNull() ) ) + return; + + m_conf = new KConfig( "arkrc" ); + m_conf->setGroup( "ark" ); + + if ( !m_conf->readBoolEntry( "KonquerorIntegration", true ) ) + return; + + KGlobal::locale()->insertCatalogue("ark_plugin"); + + extMimeTypes(); + KFileItemList itemList = popupmenu->fileItemList(); + for ( KFileItem *item = itemList.first(); item; item = itemList.next() ) + { + m_urlList.append( item->url() ); + m_urlStringList.append( item->url().url() ); + } + m_dir = popupmenu->url().url() + "/"; + unsigned int itemCount = m_urlList.count(); + KFileItemListIterator it( itemList ); + KFileItem * item; + bool hasArchives = false; + bool hasOther = false; + while ( ( item = it.current() ) != 0 ) + { + ++it; + if ( m_extractMimeTypes.contains( item->mimetype() ) ) + { + hasArchives = true; + } + else + { + hasOther = true; + } + + if ( hasArchives && hasOther ) + break; + } + + QString ext; + KActionMenu * actionMenu; + KAction * action; + if ( hasOther && itemList.first()->name()!="." && popupmenu->protocolInfo().supportsWriting() ) // don't try to compress if we right click on a folder without files selected + { + compMimeTypes(); + actionMenu = new KActionMenu( i18n( "Compress" ), "ark", actionCollection(), "ark_compress_menu" ); + m_ext = m_conf->readEntry( "LastExtension", ".tar.gz" ); + if ( itemCount == 1 ) + { + item = itemList.first(); + m_name = itemList.first()->name(); + action = new KAction( i18n( "Compress as %1" ).arg( m_name + m_ext ), 0, this, + SLOT( slotCompressAsDefault() ), actionCollection() ); + } + else + { + action = new KAction( KMimeType::mimeType( m_conf->readEntry( + "LastMimeType", "application/x-tgz" ) )->comment(), + 0, this, SLOT( slotCompressAsDefault() ), actionCollection() ); + } + actionMenu->insert( action ); + + m_compAsMenu = new KActionMenu( i18n( "Compress As" ), actionCollection(), "arkcmpasmnu" ); + actionMenu->insert( m_compAsMenu ); + + + m_addToMenu = new KActionMenu( i18n( "Add To" ), actionCollection(), "arkaddtomnu" ); + if ( itemList.first()->url().isLocalFile() ) + actionMenu->insert( m_addToMenu ); + + connect( m_compAsMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotPrepareCompAsMenu() ) ); + connect( m_addToMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotPrepareAddToMenu() ) ); + + + action = new KAction( i18n( "Add to Archive..." ), 0, this, + SLOT( slotAdd() ), actionCollection() ); + actionMenu->insert( action ); + addAction( actionMenu ); + } + + if ( !hasOther && hasArchives ) + { + if ( popupmenu->protocolInfo().supportsWriting() ) + { + actionMenu = new KActionMenu( i18n( "Extract" ), "ark", actionCollection(), "ark_extract_menu" ); + + action = new KAction( i18n( "Extract Here" ), 0, this, + SLOT( slotExtractHere() ), actionCollection() ); + actionMenu->insert( action ); + // stolen from arkwidget.cpp + if ( itemCount == 1 ) + { + QString targetName = itemList.first()->name(); + stripExtension( targetName ); + action = new KAction( i18n( "Extract to %1" ).arg( targetName ), 0, this, + SLOT( slotExtractToSubfolders() ), actionCollection() ); + } + else + { + action = new KAction( i18n( "Extract to Subfolders" ), 0, this, + SLOT( slotExtractToSubfolders() ), actionCollection() ); + } + actionMenu->insert( action ); + action = new KAction( i18n( "Extract To..." ), 0 , this, + SLOT( slotExtractTo() ), actionCollection() ); + actionMenu->insert( action ); + addAction( actionMenu ); + } + else + { + action = new KAction( i18n( "Extract To..." ), "ark", 0, this, SLOT( slotExtractTo() ), actionCollection(), "ark_extract_menu" ); + addAction( action ); + } + } + addSeparator(); +} + +ArkMenu::~ArkMenu() +{ + delete m_conf; +} + +void ArkMenu::slotPrepareCompAsMenu() +{ + disconnect( m_compAsMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotPrepareCompAsMenu() ) ); + + KAction * action; + m_compAsMapper = new QSignalMapper( this, "compAsMapper" ); + QString ext; + QStringList newExt; + unsigned int counter = 0; + QCString actionName; + QStringList::Iterator eit; + QStringList::Iterator mit; + mit = m_archiveMimeTypes.begin(); + for ( ; mit != m_archiveMimeTypes.end(); ++mit ) + { + newExt = KMimeType::mimeType(*mit)->patterns(); + eit = newExt.begin(); + (*eit).remove( '*' ); + if ( *eit == ".tar.bz" ) // tbz mimetype, has tar.bz as first entry :} + *eit = ".tar.bz2"; + if ( m_urlList.count() == 1 ) + { + action = new KAction( m_name + (*eit), 0, m_compAsMapper, + SLOT( map() ), actionCollection() ); + } + else + { + ext = KMimeType::mimeType(*mit)->comment(); + action = new KAction( ext, 0, m_compAsMapper, + SLOT( map() ), actionCollection() ); + } + + m_compAsMenu->insert( action ); + m_compAsMapper->setMapping( action, counter ); + + ++counter; + ++eit; + while( eit != newExt.end() ) + { + (*eit).remove( '*' ); + ++eit; + ++counter; + } + m_extensionList += newExt; + } + + connect( m_compAsMapper, SIGNAL( mapped( int ) ), SLOT( slotCompressAs( int ) ) ); +} + +void ArkMenu::slotPrepareAddToMenu() +{ + disconnect( m_addToMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotPrepareAddToMenu() ) ); + + + if ( m_extensionList.isEmpty() ) // is filled in slotPrepareCompAsMenu + slotPrepareCompAsMenu(); + + unsigned int counter = 0; + KAction * action; + m_addToMapper = new QSignalMapper( this, "addToMapper" ); + QCString actionName; + QStringList::Iterator mit; + KURL archive; + QDir dir( m_urlList.first().directory() ); + QStringList entries = dir.entryList(); + QStringList::Iterator uit = entries.begin(); + for ( ; uit != entries.end(); ++uit ) + { + for ( mit = m_extensionList.begin(); mit != m_extensionList.end(); ++mit ) + if ( (*uit).endsWith(*mit) ) + { + action = new KAction( *uit, 0, m_addToMapper, + SLOT( map() ), actionCollection() ); + m_addToMenu->insert( action ); + m_addToMapper->setMapping( action, counter ); + archive.setPath( *uit ); + m_archiveList << archive; + counter++; + break; + } + } + connect( m_addToMapper, SIGNAL( mapped( int ) ), SLOT( slotAddTo( int ) ) ); +} + +void ArkMenu::compMimeTypes() +{ + unsigned int itemCount = m_urlList.count(); + + bool havegz = false; + if ( !KStandardDirs::findExe( "gzip" ).isNull() && m_conf->readBoolEntry( "UseGz", true ) ) + { + havegz = true; + //.gz can only compress one file, not multiple + if ( itemCount == 1 ) m_archiveMimeTypes << "application/x-gzip"; + } + + bool havebz2 = false; + if ( !KStandardDirs::findExe( "bzip2" ).isNull() && m_conf->readBoolEntry( "UseBzip2", true ) ) + { + havebz2 = true; + //.bz2 can only compress one file, not multiple + if ( itemCount == 1 ) m_archiveMimeTypes << "application/x-bzip2"; + } + + bool havelzop = false; + if ( !KStandardDirs::findExe( "lzop" ).isNull() && m_conf->readBoolEntry( "UseLzop", false ) ) + { + havelzop = true; + m_archiveMimeTypes << "application/x-lzop"; + } + + if ( !KStandardDirs::findExe( "tar" ).isNull() && m_conf->readBoolEntry( "UseTar", true ) ) + { + m_archiveMimeTypes << "application/x-tar"; + if ( havegz ) + m_archiveMimeTypes << "application/x-tgz"; + if ( havebz2 ) + { + m_archiveMimeTypes << "application/x-tbz"; + m_archiveMimeTypes << "application/x-tbz2"; + } + if ( havelzop ) + m_archiveMimeTypes << "application/x-tzo"; + } + + if ( !KStandardDirs::findExe( "lha" ).isNull() && m_conf->readBoolEntry( "UseLha", false ) ) + m_archiveMimeTypes << "application/x-lha"; + + if ( !KStandardDirs::findExe( "zip" ).isNull() && m_conf->readBoolEntry( "UseZip", true ) ) + { + m_archiveMimeTypes << "application/x-zip"; + + if ( m_conf->readBoolEntry( "UseJar", false ) ) + m_archiveMimeTypes << "application/x-jar"; + } + + if ( !KStandardDirs::findExe( "rar" ).isNull() && m_conf->readBoolEntry( "UseRar", true ) ) + m_archiveMimeTypes << "application/x-rar" << "application/x-rar-compressed"; + + if ( !KStandardDirs::findExe( "7z" ).isNull() && m_conf->readBoolEntry( "Use7z", true ) ) + m_archiveMimeTypes << "application/x-7z"; + else if ( !KStandardDirs::findExe( "7za" ).isNull() && m_conf->readBoolEntry( "Use7za", true ) ) + m_archiveMimeTypes << "application/x-7z"; + else if ( !KStandardDirs::findExe( "7zr" ).isNull() && m_conf->readBoolEntry( "Use7zr", true ) ) + m_archiveMimeTypes << "application/x-7z"; + + if ( !KStandardDirs::findExe( "zoo" ).isNull() && m_conf->readBoolEntry( "UseZoo", false ) ) + m_archiveMimeTypes << "application/x-zoo"; + + if ( !KStandardDirs::findExe( "compress" ).isNull() && m_conf->readBoolEntry( "UseCompress", false ) ) + m_archiveMimeTypes << "application/x-compress"; + + if ( !KStandardDirs::findExe( "bzip" ).isNull() && m_conf->readBoolEntry( "UseBzip", false ) ) + m_archiveMimeTypes << "application/x-bzip"; + + if ( !KStandardDirs::findExe( "ar" ).isNull() && m_conf->readBoolEntry( "UseAr", false ) ) + m_archiveMimeTypes << "application/x-archive"; +} + +void ArkMenu::extMimeTypes() +{ + bool havegz = false; + if ( !KStandardDirs::findExe( "gunzip" ).isNull() ) + { + havegz = true; + m_extractMimeTypes << "application/x-gzip"; + m_extractMimeTypes << "application/x-gzpostscript"; + } + + bool havebz2 = false; + if ( !KStandardDirs::findExe( "bunzip2" ).isNull() ) + { + havebz2 = true; + m_extractMimeTypes << "application/x-bzip2"; + } + + bool havelzop = false; + if ( !KStandardDirs::findExe( "lzop" ).isNull() ) + { + havelzop = true; + m_extractMimeTypes << "application/x-lzop"; + } + + if ( !KStandardDirs::findExe( "tar" ).isNull() ) + { + m_extractMimeTypes << "application/x-tar"; + if ( havegz ) + m_extractMimeTypes << "application/x-tgz"; + if ( havebz2 ) + { + m_extractMimeTypes << "application/x-tbz"; + m_extractMimeTypes << "application/x-tbz2"; + } + if ( havelzop ) + m_extractMimeTypes << "application/x-tzo"; + } + + if ( !KStandardDirs::findExe( "lha" ).isNull() ) + m_extractMimeTypes << "application/x-lha"; + + if ( !KStandardDirs::findExe( "zip" ).isNull() ) + m_extractMimeTypes << "application/x-zip" << "application/x-jar"; + + if ( !KStandardDirs::findExe( "unrar" ).isNull() ) + m_extractMimeTypes << "application/x-rar" << "application/x-rar-compressed"; + + if ( !KStandardDirs::findExe( "7z" ).isNull() || !KStandardDirs::findExe( "7za" ).isNull() || !KStandardDirs::findExe( "7zr" ).isNull() ) + m_extractMimeTypes << "application/x-7z"; + + if ( !KStandardDirs::findExe( "zoo" ).isNull() ) + m_extractMimeTypes << "application/x-zoo"; + + if ( !KStandardDirs::findExe( "uncompress" ).isNull() ) + m_extractMimeTypes << "application/x-compress"; + + if ( !KStandardDirs::findExe( "bunzip" ).isNull() ) + m_extractMimeTypes << "application/x-bzip"; + + if ( !KStandardDirs::findExe( "ar" ).isNull() ) + m_extractMimeTypes << "application/x-archive"; +} + +void ArkMenu::stripExtension( QString & name ) +{ + QStringList patternList = KMimeType::findByPath( name )->patterns(); + QStringList::Iterator it = patternList.begin(); + QString ext; + for ( ; it != patternList.end(); ++it ) + { + ext = (*it).remove( '*' ); + if ( name.endsWith( ext ) ) + { + name = name.left( name.findRev( ext ) ) + '/'; + break; + } + } +} + +void ArkMenu::slotCompressAs( int pos ) +{ + QCString name; + QString extension, mimeType; + KURL target; + QStringList filelist( m_urlStringList ); + + //if KMimeType returns .ZIP, .7Z or .RAR. convert them to lowercase + if ( m_extensionList[ pos ].contains ( ".ZIP" ) ) + m_extensionList[ pos ] = ".zip"; + + if ( m_extensionList[ pos ].contains ( ".RAR" ) ) + m_extensionList[ pos ] = ".rar"; + + if ( m_extensionList[ pos ].contains ( ".7Z" ) ) + m_extensionList[ pos ] = ".7z"; + + if ( filelist.count() == 1) + target = filelist.first() + m_extensionList[ pos ]; + else + { + target = m_dir + i18n("Archive") + m_extensionList[ pos ]; + int i=1; + while ( KIO::NetAccess::exists(target, true, 0 ) ) + { + target = m_dir + i18n("Archive %1").arg(i) + m_extensionList[ pos ]; + i++; + } + } + compressAs( filelist, target ); + + extension = m_extensionList[ pos ]; + m_conf->setGroup( "ArkPlugin" ); + m_conf->writeEntry( "LastExtension", extension ); + + QStringList extensions; + QStringList::Iterator eit; + QStringList::Iterator mit = m_archiveMimeTypes.begin(); + bool done = false; + for ( ; mit != m_archiveMimeTypes.end() && !done; ++mit ) + { + extensions = KMimeType::mimeType(*mit)->patterns(); + eit = extensions.begin(); + for ( ; eit != extensions.end(); ++eit ) + { + (*eit).remove( '*' ); + if ( (*eit) == extension ) + { + m_conf->writeEntry( "LastMimeType", *mit ); + done = true; + break; + } + } + } + m_conf->sync(); +} + +void ArkMenu::slotCompressAsDefault() +{ + KURL name; + + if ( m_urlStringList.count() == 1) + name = m_urlStringList.first() + m_ext; + else + { + name = m_dir + i18n("Archive") + m_ext; + int i=1; + while ( KIO::NetAccess::exists(name, true, 0 ) ) + { + name = m_dir + i18n("Archive %1").arg(i) + m_ext; + i++; + } + } + compressAs( m_urlStringList, name ); +} + +// make work for URLs +void ArkMenu::compressAs( const QStringList &name, const KURL & compressed ) +{ + QStringList args; + args << "--add-to"; + args += name; + args << compressed.url(); + kapp->kdeinitExec( "ark", args ); +} + +void ArkMenu::slotAddTo( int pos ) +{ + QStringList args( m_urlStringList ); + args.prepend( "--add-to" ); + + KURL archive( m_urlStringList.first() ); + archive.setPath( archive.directory( false ) ); + archive.setFileName( m_archiveList[ pos ].fileName() ); + + args << archive.url(); + kapp->kdeinitExec( "ark", args ); +} + +void ArkMenu::slotAdd() +{ + QStringList args( m_urlStringList ); + args.prepend( "--add" ); + + kapp->kdeinitExec( "ark", args ); +} + +void ArkMenu::slotExtractHere() +{ + for ( QValueList<KURL>::ConstIterator it = m_urlList.constBegin(); + it != m_urlList.constEnd(); + ++it ) + { + QStringList args; + KURL targetDirectory = ( *it ).url(); + targetDirectory.setPath( targetDirectory.directory() ); + args << "--extract-to" << targetDirectory.url() << ( *it ).url(); + kapp->kdeinitExec( "ark", args ); + } +} + +void ArkMenu::slotExtractToSubfolders() +{ + for ( QStringList::ConstIterator it = m_urlStringList.constBegin(); + it != m_urlStringList.constEnd(); + ++it ) + { + KURL targetDir; + QString dirName; + QStringList args; + + targetDir = *it; + dirName = targetDir.path(); + stripExtension( dirName ); + targetDir.setPath( dirName ); + args << "--extract-to" << targetDir.url() << *it; + kapp->kdeinitExec( "ark", args ); + } +} + +void ArkMenu::slotExtractTo() +{ + for ( QStringList::ConstIterator it = m_urlStringList.constBegin(); + it != m_urlStringList.constEnd(); + ++it ) + { + QStringList args; + args << "--extract" << *it; + kapp->kdeinitExec( "ark", args ); + } +} + +#include "arkplugin.moc" diff --git a/konq-plugins/arkplugin/arkplugin.desktop b/konq-plugins/arkplugin/arkplugin.desktop new file mode 100644 index 0000000..7cb6d7a --- /dev/null +++ b/konq-plugins/arkplugin/arkplugin.desktop @@ -0,0 +1,59 @@ +[Desktop Entry] +Name=Compress/Extract Files with Ark +Name[bg]=Компресиране/извличане на файлове с Ark +Name[bs]=Kompresuj/ekstraktuj datoteke koristeći Ark +Name[ca]=Comprimeix/extrau fitxers amb Ark +Name[cs]=Komprimovat/rozbalit soubory pomocí Ark +Name[da]=Komprimér/Udpak filer med Ark +Name[de]=Dateien mit Ark komprimieren/extrahieren +Name[el]=Συμπίεση/Εξαγωγή αρχείων με το Ark +Name[eo]=Kunpremu/Elpaku dosierojn per Arĥivilo +Name[es]=Comprimir/Extraer archivos con Ark +Name[et]=Failide pakkimine/lahtipakkimine Arki abil +Name[eu]=Fitxategiak konprimitu/atera Ark erabiliz +Name[fa]=فشردهسازی/استخراج پروندهها توسط Ark +Name[fi]=Pakkaa/Pura tiedostoja Ark-ohjelmalla +Name[fr]=Compacter / extraire des fichiers avec Ark +Name[fy]=Triemmen ynpakke/útpakke mei Ark +Name[ga]=Comhbhrúigh/Bain Comhaid Amach le Ark +Name[gl]=Comprimir/Extrair Ficheiros con Ark +Name[he]=דחוס/פרוס קבצים עם Ark +Name[hi]=आर्क के द्वारा फ़ाइलों को संपीडित करें/निकालें +Name[hr]=Komprimiranje i izvlačenje datoteka pomoću aplikacije Ark +Name[hu]=Fájlok tömörítése és kibontása az Arkkal +Name[is]=Þjappa/taka út skrár með Ark +Name[it]=Comprimi/estrai file con Ark +Name[ja]=Ark でファイルを圧縮/展開 +Name[ka]=ფაილების Ark-ით შეკუნშვა/ამოღება +Name[kk]=Ark көмегімен файлдарды сығу/тарқату +Name[km]=បង្ហាប់/ស្រង់ចេញឯកសារដោយប្រើ Ark +Name[lt]=Suspausti/išspausti bylas naudojant Ark +Name[mk]=Компресија/отпакување датотеки со Арк +Name[ms]=Mampat/Ekstrak Fail dengan Ark +Name[nb]=Komprimer/pakk ut filer med Ark +Name[nds]=Dateien mit Ark komprimeren/utpacken +Name[ne]=आर्कबाट फाइल सङ्कुचन/निष्कर्षण गर्नुहोस् +Name[nl]=Bestanden inpakken/uitpakken met Ark +Name[nn]=Komprimer/pakk ut filer med Ark +Name[pa]=ਆਕ ਨਾਲ ਫਾਇਲਾਂ ਸਮੇਟੋ/ਖੋਲੋ +Name[pl]=Kompresja/dekompresja plików za pomocą Ark +Name[pt]=Comprimir/Extrair Ficheiros com o Ark +Name[pt_BR]=Compactar/Extrair arquivos com o Ark +Name[ru]=Сжатие/распаковка файлов в Ark +Name[sk]=Zabaliť/rozbaliť súbory pomocou Ark +Name[sl]=Stisni/Izvleci datoteke z Arkom +Name[sr]=Компресуј/извуци фајлове Ark-ом +Name[sr@Latn]=Kompresuj/izvuci fajlove Ark-om +Name[sv]=Komprimera eller packa upp filer med Ark +Name[ta]=கோப்பினை Ark உடன் சுருக்கு/எடு +Name[tg]=Фишурдан/кушодани файлҳо дар Ark +Name[tr]=Dosyaları Ark ile Sıkıştır/Ayıkla +Name[uk]=Стиснення/розпакування файлів в Ark +Name[uz]=Fayllarni Ark dasturida qisish/ajratish +Name[uz@cyrillic]=Файлларни Ark дастурида қисиш/ажратиш +Name[vi]=Nén/Giải nén tập tin bằng Ark +Name[zh_CN]=用 Ark 压缩/解压文件 +Name[zh_TW]=以 Ark 壓縮/解壓縮檔案 +Icon=ark +X-KDE-ParentApp=konqueror +#DocPath=konq-plugins/arkplugin/index.html diff --git a/konq-plugins/arkplugin/arkplugin.h b/konq-plugins/arkplugin/arkplugin.h new file mode 100644 index 0000000..8732294 --- /dev/null +++ b/konq-plugins/arkplugin/arkplugin.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE project + + Copyright (C) 2003 Georg Robbers <Georg.Robbers@urz.uni-hd.de> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _ARKPLUGIN_H_ +#define _ARKPLUGIN_H_ + +#include <konq_popupmenu.h> +#include <kfileitem.h> +#include <kconfig.h> + +class KAction; +class QSignalMapper; + +class ArkMenu : public KonqPopupMenuPlugin { + Q_OBJECT +public: + ArkMenu( KonqPopupMenu *, const char *name, const QStringList & list ); + virtual ~ArkMenu(); + +public slots: + void slotCompressAsDefault(); + void slotCompressAs( int pos ); + void slotAddTo( int pos ); + void slotAdd(); + void slotExtractHere(); + void slotExtractToSubfolders(); + void slotExtractTo(); + void slotPrepareCompAsMenu(); + void slotPrepareAddToMenu(); + +protected: + void extMimeTypes(); + void compMimeTypes(); + void compressAs( const QStringList &name, const KURL & compressed ); + + void stripExtension( QString & name ); + +private: + QString m_name, m_ext; + QValueList<KURL> m_urlList; + QStringList m_urlStringList; + KURL::List m_archiveList; + QStringList m_archiveMimeTypes; + QStringList m_extractMimeTypes; + QStringList m_extensionList; + KActionMenu * m_compAsMenu; + KActionMenu * m_addToMenu; + QSignalMapper * m_compAsMapper; + QSignalMapper * m_addToMapper; + KConfig * m_conf; + QString m_dir; //contains the currect directory +}; + +#endif + diff --git a/konq-plugins/autorefresh/Makefile.am b/konq-plugins/autorefresh/Makefile.am new file mode 100644 index 0000000..f97432b --- /dev/null +++ b/konq-plugins/autorefresh/Makefile.am @@ -0,0 +1,21 @@ +kde_module_LTLIBRARIES = libautorefresh.la + +INCLUDES = $(all_includes) + +libautorefresh_la_METASOURCES = AUTO +libautorefresh_la_SOURCES = autorefresh.cpp +libautorefresh_la_LIBADD = $(LIB_KHTML) + +libautorefresh_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +KDE_ICON = autorefresh + +autorefreshdir = $(kde_datadir)/khtml/kpartplugins +autorefresh_DATA = autorefresh.rc autorefresh.desktop + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.hh -o -name \*.H -o -name \*.hxx -o -name \*.hpp -o -name \*.cpp -o -name \*.cc -o -name \*.cxx -o -name \*.ecpp -o -name \*.C`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/autorefresh.pot; \ + fi + diff --git a/konq-plugins/autorefresh/autorefresh.cpp b/konq-plugins/autorefresh/autorefresh.cpp new file mode 100644 index 0000000..6d06ea0 --- /dev/null +++ b/konq-plugins/autorefresh/autorefresh.cpp @@ -0,0 +1,107 @@ +// -*- c++ -*- + +/* + * Copyright 2003 by Richard J. Moore, rich@kde.org + */ + + +#include <khtml_part.h> // this plugin applies to a khtml part +#include <kdebug.h> +#include "autorefresh.h" +#include <kaction.h> +#include <kinstance.h> +#include <kiconloader.h> +#include <qmessagebox.h> +#include <klocale.h> +#include <qtimer.h> +#include <kgenericfactory.h> + +AutoRefresh::AutoRefresh( QObject* parent, const char* name, const QStringList & /*args*/ ) + : Plugin( parent, name ) +{ + timer = new QTimer( this ); + connect( timer, SIGNAL( timeout() ), this, SLOT( slotRefresh() ) ); + + refresher = new KSelectAction( i18n("&Auto Refresh"), + "reload", 0, + this, SLOT(slotIntervalChanged()), + actionCollection(), "autorefresh" ); + QStringList sl; + sl << i18n("None"); + sl << i18n("Every 15 Seconds"); + sl << i18n("Every 30 Seconds"); + sl << i18n("Every Minute"); + sl << i18n("Every 5 Minutes"); + sl << i18n("Every 10 Minutes"); + sl << i18n("Every 15 Minutes"); + sl << i18n("Every 30 Minutes"); + sl << i18n("Every 60 Minutes"); + + refresher->setItems( sl ); + refresher->setCurrentItem( 0 ); +} + +AutoRefresh::~AutoRefresh() +{ +} + +void AutoRefresh::slotIntervalChanged() +{ + int idx = refresher->currentItem(); + int timeout = 0; + switch (idx) { + case 1: + timeout = ( 15*1000 ); + break; + case 2: + timeout = ( 30*1000 ); + break; + case 3: + timeout = ( 60*1000 ); + break; + case 4: + timeout = ( 5*60*1000 ); + break; + case 5: + timeout = ( 10*60*1000 ); + break; + case 6: + timeout = ( 15*60*1000 ); + break; + case 7: + timeout = ( 30*60*1000 ); + break; + case 8: + timeout = ( 60*60*1000 ); + break; + default: + break; + } + + timer->stop(); + if ( timeout ) + timer->start( timeout ); +} + +void AutoRefresh::slotRefresh() +{ + if ( !parent()->inherits("KParts::ReadOnlyPart") ) { + QString title = i18n( "Cannot Refresh Source" ); + QString text = i18n( "<qt>This plugin cannot auto-refresh the current part.</qt>" ); + + QMessageBox::warning( 0, title, text ); + } + else + { + KParts::ReadOnlyPart *part = (KParts::ReadOnlyPart *) parent(); + + // Get URL + KURL url = part->url(); + part->openURL( url ); + } +} + +K_EXPORT_COMPONENT_FACTORY( libautorefresh, KGenericFactory<AutoRefresh>( "autorefresh" ) ) + +#include "autorefresh.moc" + diff --git a/konq-plugins/autorefresh/autorefresh.desktop b/konq-plugins/autorefresh/autorefresh.desktop new file mode 100644 index 0000000..7df9332 --- /dev/null +++ b/konq-plugins/autorefresh/autorefresh.desktop @@ -0,0 +1,120 @@ +[Desktop Entry] +X-KDE-Library=autorefresh +X-KDE-PluginInfo-Author=Richard J. Moore +X-KDE-PluginInfo-Email=rich@kde.org +X-KDE-PluginInfo-Name=autorefresh +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=Auto Refresh Plugin +Name[bg]=Приставка за автоматично опресняване +Name[ca]=Connector de refresc automàtic +Name[cs]=Modul automatického obnovení +Name[da]=Plugin til autogenopfriskning +Name[de]=Aktualisierungsmodul +Name[el]=Πρόσθετο αυτόματης ανανέωσης +Name[eo]=Aŭtomata refreŝa kromaĵo +Name[es]=Complemento para actualización automática +Name[et]=Automaatse uuendamise plugin +Name[eu]=Auto Refresh plugina +Name[fa]=بازآوری خودکار وصله +Name[fi]=Automaattivirkistyssovelma +Name[fr]=Module d'auto-rafraîchissement +Name[fy]=Autoferfarskplugin +Name[gl]=Plugin de Actualización Automática +Name[he]=תוסף רענון אוטומטי +Name[hi]=स्वचालित ताज़ा करने का प्लगइन +Name[hr]=Dodatak za automatsko osvježavanje +Name[hu]=Automatikus frissítési bővítőmodul +Name[is]=Sjálfvirkt uppfærsluíforrit +Name[it]=Aggiornamento automatico +Name[ja]=自動更新プラグイン +Name[ka]=ავტო განახლების მოდული +Name[kk]=Авто жаңарту плагин модулі +Name[km]=ធ្វើឲ្យកម្មវិធីជំនួយស្រស់ដោយស្វ័យប្រវត្តិ +Name[lt]=Automatinio atnaujinimo priedas +Name[mk]=Приклучок за автоматско освежување +Name[ms]=Plugin Automuat Semula +Name[nb]=Programtillegg for auto-oppfrisking +Name[nds]=Moduul för't automaatsche Opfrischen +Name[ne]=स्वत: ताजा पार्ने प्लगइन +Name[nl]=Autoverversplugin +Name[nn]=Programtillegg for automatisk oppfrisking +Name[pa]=ਸਵੈਚਾਲਿਤ ਤਾਜ਼ਾ ਪਲੱਗਇਨ +Name[pl]=Wtyczka automatycznego odświeżania +Name[pt]='Plugin' de Actualização Automática +Name[pt_BR]=Plug-in de atualização automática +Name[ru]=Модуль автообновления +Name[sk]=Modul automatického obnovenia +Name[sl]=Vstavek za samodejno osveževanje +Name[sr]=Прикључак за аутоматско освежавање +Name[sr@Latn]=Priključak za automatsko osvežavanje +Name[sv]=Insticksprogram för automatisk uppdatering +Name[ta]=தானாகவே புதுப்பிக்கும் சொருகுப்பொருள் +Name[tg]=Худкорона аз нав кардани модул +Name[tr]=Otomatik Tazeleme Eklentisi +Name[uk]=Втулок автоматичного перезавантаження +Name[uz]=Avto-yangilash plagini +Name[uz@cyrillic]=Авто-янгилаш плагини +Name[vi]=Bổ sung tự động làm tươi +Name[zh_CN]=自动刷新插件 +Name[zh_TW]=自動刷新外掛程式 +Comment=Auto Refresh plugin +Comment[bg]=Приставка за автоматично опресняване +Comment[ca]=Connector de refresc automàtic +Comment[cs]=Modul automatického obnovení +Comment[da]=Plugin til autogenopfriskning +Comment[de]=Ein Modul zur automatischen Aktualisierung +Comment[el]=Πρόσθετο αυτόματης ανανέωσης +Comment[eo]=Aŭtomata refreŝa kromaĵo +Comment[es]=Complemento para actualización automática +Comment[et]=Automaatse uuendamise plugin +Comment[eu]=Auto Refresh plugina +Comment[fa]=بازآوری خودکار وصله +Comment[fi]=Automaattivirkistyssovelma +Comment[fr]=Module d'auto-rafraîchissement +Comment[fy]=Autoferfarskplugin +Comment[gl]=Plugin de actualización automática +Comment[he]=תוסף רענון אוטומטי +Comment[hi]=स्वचालित ताज़ा करने का प्लगइन +Comment[hr]=Dodatak za automatsko osvježavanje +Comment[hu]=Automatikus frissítési bővítőmodul +Comment[is]=Sjálfvirkt uppfærsluíforrit +Comment[it]=Plugin per l'aggiornamento automatico +Comment[ja]=自動更新プラグイン +Comment[ka]=ავტო განახლების მოდული +Comment[kk]=Авто жаңарту плагин модулі +Comment[km]=ធ្វើកម្មវិធីជំនួយឲ្យស្រស់ដោយស្វ័យប្រវត្តិ +Comment[lt]=Automatinio atnaujinimo priedas +Comment[mk]=Приклучок за автоматско освежување +Comment[ms]=Plugin AutoMuat Semula +Comment[nb]=Programtillegg for auto-oppfrisk +Comment[nds]=Moduul för't automaatsche Opfrischen +Comment[ne]=स्वत: ताजा पार्ने प्लगइन +Comment[nl]=Autoverversplugin +Comment[nn]=Programtillegg for automatisk oppfrisking +Comment[pa]=ਸਵੈ-ਚਾਲਿਤ ਤਾਜ਼ਾ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka automatycznego odświeżania +Comment[pt]='Plugin' de actualização automática +Comment[pt_BR]=Plug-in de atualização automática +Comment[ru]=Модуль автообновления +Comment[sk]=Modul automatického obnovenia +Comment[sl]=Vstavek za samodejno osveževanje +Comment[sr]=Прикључак за аутоматско освежавање +Comment[sr@Latn]=Priključak za automatsko osvežavanje +Comment[sv]=Insticksprogram för automatisk uppdatering +Comment[ta]=தானாகவே புதுப்பிக்கும் சொருகுப்பொருள் +Comment[tg]=Худкорона аз нав кардани модул +Comment[tr]=Otomatik Tazeleme Eklentisi +Comment[uk]=Втулок автоматичного перезавантаження +Comment[uz]=Veb-sahifani avto-yangilash vositasi +Comment[uz@cyrillic]=Веб-саҳифани авто-янгилаш воситаси +Comment[vi]=Bổ sung tự động làm tươi +Comment[zh_CN]=自动刷新插件 +Comment[zh_TW]=自動刷新外掛程式 +Icon=reload +X-KDE-ParentApp=konqueror + diff --git a/konq-plugins/autorefresh/autorefresh.h b/konq-plugins/autorefresh/autorefresh.h new file mode 100644 index 0000000..370e42b --- /dev/null +++ b/konq-plugins/autorefresh/autorefresh.h @@ -0,0 +1,55 @@ +// -*- c++ -*- + +/* + * Copyright 2003 by Richard J. Moore, rich@kde.org + */ + +#ifndef __plugin_autorefresh_h +#define __plugin_autorefresh_h + +#include <kparts/plugin.h> +#include <klibloader.h> + +class KURL; +class KInstance; +class QTimer; + +/** + * A plugin is the way to add actions to an existing @ref KParts application, + * or to a @ref Part. + * + * The XML of those plugins looks exactly like of the shell or parts, + * with one small difference: The document tag should have an additional + * attribute, named "library", and contain the name of the library implementing + * the plugin. + * + * If you want this plugin to be used by a part, you need to + * install the rc file under the directory + * "data" (KDEDIR/share/apps usually)+"/instancename/kpartplugins/" + * where instancename is the name of the part's instance. + **/ +class AutoRefresh : public KParts::Plugin +{ + Q_OBJECT +public: + + /** + * Construct a new KParts plugin. + */ + AutoRefresh( QObject* parent = 0, const char* name = 0, const QStringList &args = QStringList() ); + + /** + * Destructor. + */ + virtual ~AutoRefresh(); + +public slots: + void slotRefresh(); + void slotIntervalChanged(); + +private: + KSelectAction *refresher; + QTimer *timer; +}; + +#endif diff --git a/konq-plugins/autorefresh/autorefresh.rc b/konq-plugins/autorefresh/autorefresh.rc new file mode 100644 index 0000000..9226178 --- /dev/null +++ b/konq-plugins/autorefresh/autorefresh.rc @@ -0,0 +1,10 @@ +<!DOCTYPE kpartgui> + <kpartgui library="libautorefresh" name="autorefresh" version="0.1" > + <MenuBar> + <Menu name="tools"> + <Text>&Tools</Text> + <Action name="autorefresh"/> + </Menu> + </MenuBar> +</kpartgui> + diff --git a/konq-plugins/autorefresh/lo16-app-autorefresh.png b/konq-plugins/autorefresh/lo16-app-autorefresh.png Binary files differnew file mode 100644 index 0000000..e4c699a --- /dev/null +++ b/konq-plugins/autorefresh/lo16-app-autorefresh.png diff --git a/konq-plugins/babelfish/Makefile.am b/konq-plugins/babelfish/Makefile.am new file mode 100644 index 0000000..3316d68 --- /dev/null +++ b/konq-plugins/babelfish/Makefile.am @@ -0,0 +1,26 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libbabelfishplugin.la + +libbabelfishplugin_la_SOURCES = plugin_babelfish.cpp +libbabelfishplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +libbabelfishplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -no-undefined + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = plugin_babelfish.rc plugin_babelfish.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = plugin_babelfish.desktop + +install-data-local: $(srcdir)/../uninstall.desktop + $(mkinstalldirs) $(DESTDIR)$(pluginsdir) + $(INSTALL_DATA) $(srcdir)/../uninstall.desktop $(DESTDIR)$(pluginsdir)/babelfishplugin.desktop + +KDE_ICON = babelfish + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/babelfish.pot + +kde_conf_DATA = translaterc diff --git a/konq-plugins/babelfish/cr16-action-babelfish.png b/konq-plugins/babelfish/cr16-action-babelfish.png Binary files differnew file mode 100644 index 0000000..63ce64d --- /dev/null +++ b/konq-plugins/babelfish/cr16-action-babelfish.png diff --git a/konq-plugins/babelfish/cr22-action-babelfish.png b/konq-plugins/babelfish/cr22-action-babelfish.png Binary files differnew file mode 100644 index 0000000..acb9a69 --- /dev/null +++ b/konq-plugins/babelfish/cr22-action-babelfish.png diff --git a/konq-plugins/babelfish/plugin_babelfish.cpp b/konq-plugins/babelfish/plugin_babelfish.cpp new file mode 100644 index 0000000..302b71a --- /dev/null +++ b/konq-plugins/babelfish/plugin_babelfish.cpp @@ -0,0 +1,376 @@ +/* This file is part of the KDE Project + Copyright (C) 2001 Kurt Granroth <granroth@kde.org> + Original code: plugin code, connecting to Babelfish and support for selected text + Copyright (C) 2003 Rand2342 <rand2342@yahoo.com> + Submenus, KConfig file and support for other translation engines + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include "plugin_babelfish.h" + +#include <kaction.h> +#include <kinstance.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kconfig.h> +#include <kgenericfactory.h> +#include <kaboutdata.h> + +#include <khtml_part.h> + +typedef KGenericFactory<PluginBabelFish> BabelFishFactory; +static const KAboutData aboutdata("babelfish", I18N_NOOP("Translate Web Page") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY( libbabelfishplugin, BabelFishFactory( &aboutdata ) ) + +PluginBabelFish::PluginBabelFish( QObject* parent, const char* name, + const QStringList & ) + : Plugin( parent, name ) +{ + setInstance(BabelFishFactory::instance()); + + m_menu = new KActionMenu( i18n("Translate Web &Page"), "babelfish", + actionCollection(), "translatewebpage" ); + m_menu->setDelayed( false ); + + m_en = new KActionMenu( i18n("&English To"), "babelfish", + actionCollection(), "translatewebpage_en" ); + m_fr = new KActionMenu( i18n("&French To"), "babelfish", + actionCollection(), "translatewebpage_fr" ); + m_de = new KActionMenu( i18n("&German To"), "babelfish", + actionCollection(), "translatewebpage_de" ); + m_es = new KActionMenu( i18n("&Spanish To"), "babelfish", + actionCollection(), "translatewebpage_es" ); + m_pt = new KActionMenu( i18n("&Portuguese To"), "babelfish", + actionCollection(), "translatewebpage_pt" ); + m_it = new KActionMenu( i18n("&Italian To"), "babelfish", + actionCollection(), "translatewebpage_it" ); + m_nl = new KActionMenu( i18n("&Dutch To"), "babelfish", + actionCollection(), "translatewebpage_nl" ); + + m_en->insert( new KAction( i18n("&Chinese (Simplified)"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_zh") ); + m_en->insert( new KAction( i18n("Chinese (&Traditional)"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_zhTW") ); + m_en->insert( new KAction( i18n("&Dutch"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_nl") ); + m_en->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_fr") ); + m_en->insert( new KAction( i18n("&German"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_de") ); + m_en->insert( new KAction( i18n("&Italian"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_it") ); + m_en->insert( new KAction( i18n("&Japanese"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_ja") ); + m_en->insert( new KAction( i18n("&Korean"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_ko") ); + m_en->insert( new KAction( i18n("&Norwegian"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_no") ); + m_en->insert( new KAction( i18n("&Portuguese"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_pt") ); + m_en->insert( new KAction( i18n("&Russian"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_ru") ); + m_en->insert( new KAction( i18n("&Spanish"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_es") ); + m_en->insert( new KAction( i18n("T&hai"), 0, + this, SLOT(translateURL()), + actionCollection(), "en_th") ); + + m_fr->insert( new KAction( i18n("&Dutch"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_nl") ); + m_fr->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_en") ); + m_fr->insert( new KAction( i18n("&German"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_de") ); + m_fr->insert( new KAction( i18n("&Italian"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_it") ); + m_fr->insert( new KAction( i18n("&Portuguese"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_pt") ); + m_fr->insert( new KAction( i18n("&Spanish"), 0, + this, SLOT(translateURL()), + actionCollection(), "fr_es") ); + + m_de->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "de_en") ); + m_de->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "de_fr") ); + + m_es->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "es_en") ); + m_es->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "es_fr") ); + + m_pt->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "pt_en") ); + m_pt->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "pt_fr") ); + + m_it->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "it_en") ); + m_it->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "it_fr") ); + + m_nl->insert( new KAction( i18n("&English"), 0, + this, SLOT(translateURL()), + actionCollection(), "nl_en") ); + m_nl->insert( new KAction( i18n("&French"), 0, + this, SLOT(translateURL()), + actionCollection(), "nl_fr") ); + + m_menu->insert( new KAction( i18n("&Chinese (Simplified) to English"), 0, + this, SLOT(translateURL()), + actionCollection(), "zh_en") ); + m_menu->insert( new KAction( i18n("Chinese (&Traditional) to English"), 0, + this, SLOT(translateURL()), + actionCollection(), "zhTW_en") ); + m_menu->insert( m_nl ); + m_menu->insert( m_en ); + m_menu->insert( m_fr ); + m_menu->insert( m_de ); + m_menu->insert( m_it ); + m_menu->insert( new KAction( i18n("&Japanese to English"), 0, + this, SLOT(translateURL()), + actionCollection(), "ja_en") ); + m_menu->insert( new KAction( i18n("&Korean to English"), 0, + this, SLOT(translateURL()), + actionCollection(), "ko_en") ); + m_menu->insert( m_pt ); + m_menu->insert( new KAction( i18n("&Russian to English"), 0, + this, SLOT(translateURL()), + actionCollection(), "ru_en") ); + m_menu->insert( m_es ); + m_menu->setEnabled( true ); + + // TODO: we could also support plain text viewers... + if ( parent && parent->inherits( "KHTMLPart" ) ) + { + KParts::ReadOnlyPart* part = static_cast<KParts::ReadOnlyPart *>(parent); + connect( part, SIGNAL(started(KIO::Job*)), this, + SLOT(slotStarted(KIO::Job*)) ); + } +} + +PluginBabelFish::~PluginBabelFish() +{ + delete m_menu; +} + +void PluginBabelFish::slotStarted( KIO::Job* ) +{ + if ( parent()->inherits("KHTMLPart") && + // Babelfish wants http URLs only. No https. + static_cast<KParts::ReadOnlyPart *>(parent())->url().protocol().lower() == "http" ) + { + m_menu->setEnabled( true ); + } + else + { + m_menu->setEnabled( false ); + } +} + +void PluginBabelFish::translateURL() +{ + // we need the sender() for the language name + if ( !sender() ) + return; + + // The parent is assumed to be a KHTMLPart + if ( !parent()->inherits("KHTMLPart") ) + { + QString title = i18n( "Cannot Translate Source" ); + QString text = i18n( "Only web pages can be translated using " + "this plugin." ); + + KMessageBox::sorry( 0L, text, title ); + return; + } + + // Select engine + KConfig cfg( "translaterc", true ); + QString engine = cfg.readEntry( sender()->name(), "babelfish" ); + + // Get URL + KHTMLPart *part = dynamic_cast<KHTMLPart *>(parent()); + if ( !part ) + return; + + // we check if we have text selected. if so, we translate that. If + // not, we translate the url + QString totrans; + if ( part->hasSelection() ) + { + if( engine == "reverso" || engine == "tsail" ) + { + KMessageBox::sorry( 0L, + i18n( "Only full webpages can be translated for this language pair." ),i18n( "Translation Error" ) ); + return; + } + totrans = KURL::encode_string( part->selectedText() ); + } else { + KURL url = part->url(); + // Check syntax + if ( !url.isValid() ) + { + QString title = i18n( "Malformed URL" ); + QString text = i18n( "The URL you entered is not valid, please " + "correct it and try again." ); + KMessageBox::sorry( 0L, text, title ); + return; + } + totrans = KURL::encode_string( url.url() ); + } + + // Create URL + KURL result; + QString query; + if( engine == "freetranslation" ) { + query = "sequence=core&Submit=FREE Translation&language="; + if( sender()->name() == QString( "en_es" ) ) + query += "English/Spanish"; + else if( sender()->name() == QString( "en_de" ) ) + query += "English/German"; + else if( sender()->name() == QString( "en_it" ) ) + query += "English/Italian"; + else if( sender()->name() == QString( "en_nl" ) ) + query += "English/Dutch"; + else if( sender()->name() == QString( "en_pt" ) ) + query += "English/Portuguese"; + else if( sender()->name() == QString( "en_no" ) ) + query += "English/Norwegian"; + else if( sender()->name() == QString( "en_zh" ) ) + query += "English/SimplifiedChinese"; + else if( sender()->name() == QString( "en_zhTW" ) ) + query += "English/TraditionalChinese"; + else if( sender()->name() == QString( "es_en" ) ) + query += "Spanish/English"; + else if( sender()->name() == QString( "fr_en" ) ) + query += "French/English"; + else if( sender()->name() == QString( "de_en" ) ) + query += "German/English"; + else if( sender()->name() == QString( "it_en" ) ) + query += "Italian/English"; + else if( sender()->name() == QString( "nl_en" ) ) + query += "Dutch/English"; + else if( sender()->name() == QString( "pt_en" ) ) + query += "Portuguese/English"; + else // Should be en_fr + query += "English/French"; + if ( part->hasSelection() ) + { + result = KURL( "http://ets.freetranslation.com" ); + query += "&mode=html&template=results_en-us.htm&srctext="; + } else { + result = KURL( "http://www.freetranslation.com/web.asp" ); + query += "&url="; + } + query += totrans; + } else if( engine == "parsit" ) { + // Does only English -> Thai + result = KURL( "http://c3po.links.nectec.or.th/cgi-bin/Parsitcgi.exe" ); + query = "mode=test&inputtype="; + if ( part->hasSelection() ) + query += "text&TxtEng="; + else + query += "html&inputurl="; + query += totrans; + } else if( engine == "reverso" ) { + result = KURL( "http://www.reverso.net/url/frame.asp" ); + query = "autotranslate=on&templates=0&x=0&y=0&directions="; + if( sender()->name() == QString( "de_fr" ) ) + query += "524292"; + else if( sender()->name() == QString( "fr_en" ) ) + query += "65544"; + else if( sender()->name() == QString( "fr_de" ) ) + query += "262152"; + else if( sender()->name() == QString( "de_en" ) ) + query += "65540"; + else if( sender()->name() == QString( "en_de" ) ) + query += "262145"; + else if( sender()->name() == QString( "en_es" ) ) + query += "2097153"; + else if( sender()->name() == QString( "es_en" ) ) + query += "65568"; + else if( sender()->name() == QString( "fr_es" ) ) + query += "2097160"; + else // "en_fr" + query += "524289"; + query += "&url="; + query += totrans; + } else if( engine == "tsail" ) { + result = KURL( "http://www.t-mail.com/cgi-bin/tsail" ); + query = "sail=full&lp="; + if( sender()->name() == QString( "zhTW_en" ) ) + query += "tw-en"; + else if( sender()->name() == QString( "en_zhTW" ) ) + query += "en-tw"; + else + { + query += sender()->name(); + query[15] = '-'; + } + query += totrans; + } else if( engine == "voila" ) { + result = KURL( "http://trans.voila.fr/voila" ); + query = "systran_id=Voila-fr&systran_lp="; + query += sender()->name(); + if ( part->hasSelection() ) + query += "&systran_charset=utf-8&systran_text="; + else + query += "&systran_url="; + query += totrans; + } else { + // Using the altavista babelfish engine + result = KURL( "http://babelfish.altavista.com/babelfish/tr" ); + query = "lp="; + query += sender()->name(); + if ( part->hasSelection() ) + query += "&text="; + else + query += "&url="; + query += totrans; + } + + result.setQuery( query ); + + // Connect to the fish + emit part->browserExtension()->openURLRequest( result ); +} + +#include <plugin_babelfish.moc> diff --git a/konq-plugins/babelfish/plugin_babelfish.desktop b/konq-plugins/babelfish/plugin_babelfish.desktop new file mode 100644 index 0000000..b412eba --- /dev/null +++ b/konq-plugins/babelfish/plugin_babelfish.desktop @@ -0,0 +1,126 @@ +[Desktop Entry] +X-KDE-Library=babelfish +X-KDE-PluginInfo-Author=Kurt Granroth, Rand2342 +X-KDE-PluginInfo-Email=granroth@kde.org, rand2342@yahoo.com +X-KDE-PluginInfo-Name=babelfish +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Babel Plugin +Name[bg]=Приставка за Babel +Name[br]=Lugent Babel +Name[bs]=Babel plugin +Name[ca]=Connector per a Babel +Name[cs]=Modul Babel +Name[de]=Übersetzungsmodul +Name[el]=Πρόσθετο Babel +Name[eo]=Babela kromaĵo +Name[es]=Complemento babel +Name[et]=Tõlkeplugin +Name[eu]=Babelen plugina +Name[fa]=وصلۀ Babel +Name[fi]=Babel sovelma +Name[fr]=Module Babel +Name[fy]=Babel-plugin +Name[ga]=Breiseán Babel +Name[gl]=Plugin Babel +Name[he]=תוסף Babel +Name[hi]=बेबेल प्लगइन +Name[hr]=Babel dodatak +Name[hu]=Babel bővítőmodul +Name[is]=Babel íforrit +Name[it]=Plugin per Babel +Name[ja]=Babel プラグイン +Name[ka]=Babel მოდული +Name[kk]=Babel плагин модулі +Name[km]=កម្មវិធីជំនួយរបស់ Babel +Name[lt]=Babel priedas +Name[mk]=Приклучок Babel +Name[ms]=Plugin Babel +Name[nb]=Babel programtillegg +Name[nds]=Babel-Moduul +Name[ne]=बाबेल प्लगइन +Name[nl]=Babel-plugin +Name[nn]=Programtillegg for Babel +Name[pa]=ਬਬੀਲ ਪਲੱਗਇਨ +Name[pl]=Wtyczka programu Babel +Name[pt]='Plugin' Babel +Name[pt_BR]=Plug-in Babel +Name[ru]=Модуль машинного перевода +Name[sk]=Modul Babel +Name[sl]=Vstavek Babel +Name[sr]=Вавилонски прикључак +Name[sr@Latn]=Vavilonski priključak +Name[sv]=Babel-insticksprogram +Name[ta]=பாபேல் சொருகுப் பொருள் +Name[tg]=Модули тарҷумакунадаи мошинӣ +Name[tr]=Babel Eklentisi +Name[uk]=Втулок машинного перекладу +Name[vi]=Bổ sung Babel +Name[zh_CN]=Babel 插件 +Name[zh_TW]=Babel外掛程式 +Comment=Babelfish plugin +Comment[ar]=ملحق Babelfish +Comment[az]=Babelfish əlavəsi +Comment[bg]=Приставка за Babelfish +Comment[br]=Lugent Babelfish +Comment[ca]=Connector per a Babelfish +Comment[cs]=Modul Babelfish +Comment[cy]=Ategyn Babelfish +Comment[da]=Babelfish-plugin +Comment[de]=Ein Babelfish-Modul (Übersetzung) +Comment[el]=Πρόσθετο Babelfish +Comment[eo]=Babelfiŝo kromaĵo +Comment[es]=Complemento babelfish +Comment[et]=Babelfishi plugin +Comment[eu]=Babelfishen plugina +Comment[fa]=وصلۀ Babelfish +Comment[fi]=Babelfish sovelma +Comment[fo]=Babelsístingur +Comment[fr]=Module Babelfish +Comment[fy]=Babelfish-plugin +Comment[ga]=Breiseán Babelfish +Comment[gl]=Plugin de Babelfish +Comment[he]=תוסף Babelfish +Comment[hi]=बेबेलफिश प्लगइन +Comment[hr]=Dodatak za Babelfish +Comment[hu]=Babelfish-bővítőmodul +Comment[is]=Babelfish íforrit +Comment[it]=Plugin per Babelfish +Comment[ja]=Babelfish プラグイン +Comment[ka]=Babelfish მოდული +Comment[kk]=Babelfish плагин модулі +Comment[km]=កម្មវិធីជំនួយរបស់ Babelfish +Comment[lt]=Babelfish priedas +Comment[mk]=Приклучок Babelfish +Comment[ms]= Plug masuk Babelfish +Comment[nb]=Programtillegg for Babelfish +Comment[nds]=Babelfish-Moduul +Comment[ne]=बाबेलफिड प्लगइन +Comment[nl]=Babelfish-plugin +Comment[nn]=Programtillegg for Babelfish +Comment[pa]=ਬਬੀਲਫਿਸ਼ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka do programu Babelfish +Comment[pt]='Plugin' do Babelfish +Comment[pt_BR]=Plugin do Babelfish +Comment[ro]=Modul Babelfish +Comment[ru]=Модуль машинного интернет-перевода +Comment[sk]=Modul Babelfish +Comment[sl]=Vstavek za Babelfish +Comment[sr]=Прикључак за Babelfish +Comment[sr@Latn]=Priključak za Babelfish +Comment[sv]=Babelfish-insticksprogram +Comment[ta]=பேபல்பிஷ் சொருகுப்பொருள் +Comment[tg]=Модули интернет-тарҷумаи мошинӣ +Comment[tr]=Babelfish eklentisi +Comment[uk]=Втулок Babelfish +Comment[vi]=Bổ sung Babelfish +Comment[xh]=Iplagi yangaphakathi yeBabelfish +Comment[zh_CN]=Babelfish 插件 +Comment[zh_TW]=Babelfish 外掛程式 +Icon=babelfish +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/babel/index.html diff --git a/konq-plugins/babelfish/plugin_babelfish.h b/konq-plugins/babelfish/plugin_babelfish.h new file mode 100644 index 0000000..d4e8b01 --- /dev/null +++ b/konq-plugins/babelfish/plugin_babelfish.h @@ -0,0 +1,52 @@ +/* This file is part of the KDE Project + Copyright (C) 2001 Kurt Granroth <granroth@kde.org> + Copyright (C) 2003 Rand2342 <rand2342@yahoo.com> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#ifndef __plugin_babelfish_h +#define __plugin_babelfish_h + +#include <kparts/plugin.h> +#include <klibloader.h> + +class KURL; +namespace KIO { class Job; } + +class PluginBabelFish : public KParts::Plugin +{ + Q_OBJECT +public: + PluginBabelFish( QObject* parent, const char* name, + const QStringList & ); + virtual ~PluginBabelFish(); + +public slots: + void translateURL(); +protected slots: + void slotStarted( KIO::Job* ); + +private: + KActionMenu* m_menu; + KActionMenu* m_de; + KActionMenu* m_en; + KActionMenu* m_es; + KActionMenu* m_fr; + KActionMenu* m_it; + KActionMenu* m_nl; + KActionMenu* m_pt; +}; + +#endif diff --git a/konq-plugins/babelfish/plugin_babelfish.rc b/konq-plugins/babelfish/plugin_babelfish.rc new file mode 100644 index 0000000..0c1fdb4 --- /dev/null +++ b/konq-plugins/babelfish/plugin_babelfish.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="babelfish" library="libbabelfishplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="translatewebpage"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="translatewebpage"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/babelfish/translaterc b/konq-plugins/babelfish/translaterc new file mode 100644 index 0000000..a47760d --- /dev/null +++ b/konq-plugins/babelfish/translaterc @@ -0,0 +1,15 @@ +en_nl=freetranslation +en_no=freetranslation +en_ru=voila +en_th=parsit +en_zhTW=freetranslation +es_fr=voila +fr_it=voila +fr_nl=voila +fr_pt=voila +fr_es=reverso +it_fr=voila +nl_en=freetranslation +nl_fr=voila +pt_fr=voila +zhTW_en=tsail diff --git a/konq-plugins/crashes/Makefile.am b/konq-plugins/crashes/Makefile.am new file mode 100644 index 0000000..710ec6e --- /dev/null +++ b/konq-plugins/crashes/Makefile.am @@ -0,0 +1,16 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = libcrashesplugin.la +libcrashesplugin_la_SOURCES = crashesplugin.cpp +libcrashesplugin_la_LIBADD = $(LIB_KHTML) -lkonq +libcrashesplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = crashesplugin.rc crashesplugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = crashesplugin.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/crashesplugin.pot diff --git a/konq-plugins/crashes/crashesplugin.cpp b/konq-plugins/crashes/crashesplugin.cpp new file mode 100644 index 0000000..8d01553 --- /dev/null +++ b/konq-plugins/crashes/crashesplugin.cpp @@ -0,0 +1,193 @@ +/* + Copyright (c) 2002-2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kdebug.h> +#include <kaction.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kinstance.h> +#include <khtml_part.h> +#include <kgenericfactory.h> + +#include <krun.h> +#include <kservice.h> + +#include <kpopupmenu.h> +#include <kbookmarkimporter_crash.h> + +#include "crashesplugin.h" + +typedef KGenericFactory<CrashesPlugin> CrashesPluginFactory; +K_EXPORT_COMPONENT_FACTORY( libcrashesplugin, CrashesPluginFactory( "crashesplugin" ) ) + +CrashesPlugin::CrashesPlugin( QObject* parent, const char* name, const QStringList & ) +: KParts::Plugin( parent, name ) +{ + m_part = (parent && parent->inherits( "KHTMLPart" )) ? static_cast<KHTMLPart*>(parent) : 0L; + + m_pCrashesMenu = new KActionMenu( i18n("&Crashes"), "core", + actionCollection(), "crashes" ); + + m_pCrashesMenu->setDelayed( false ); + m_pCrashesMenu->setEnabled( true ); + + connect( m_pCrashesMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotAboutToShow() ) ); +} + +CrashesPlugin::~CrashesPlugin() +{ +} + +void CrashesPlugin::slotAboutToShow() +{ + m_pCrashesMenu->popupMenu()->clear(); + + KCrashBookmarkImporter importer(KCrashBookmarkImporter::crashBookmarksDir()); + + connect( &importer, SIGNAL( newBookmark( const QString &, const QCString &, const QString &) ), + SLOT( newBookmarkCallback( const QString &, const QCString &, const QString & ) ) ); + + connect( &importer, SIGNAL( endFolder() ), SLOT( endFolderCallback() ) ); + + int count = m_pCrashesMenu->popupMenu()->count(); + + m_crashesList.clear(); + m_crashRangesList.clear(); + importer.parseCrashBookmarks( false ); + + bool gotSep = true; // don't start with a sep + bool enable = true; + int firstItem = count; // item ids grow up from count + int crashGroup = INT_MAX; // group ids grow down from INT_MAX + if (m_crashesList.count() > 0) { + CrashesList::ConstIterator e = m_crashesList.begin(); + for( ; e != m_crashesList.end(); ++e ) { + if ( ((*e).first == "-") + && ((*e).second == "-") + ) { + if (!gotSep) { + if (count - firstItem > 1) + { + m_crashRangesList.append( CrashRange(firstItem, count) ); + m_pCrashesMenu->popupMenu()->insertItem( + i18n("All Pages of This Crash"), this, + SLOT(slotGroupSelected(int)), + 0, crashGroup--); + } + m_pCrashesMenu->popupMenu()->insertSeparator(); + } + gotSep = true; + firstItem = ++count; + } else { + QString str = (*e).first; + if (str.length() > 48) { + str.truncate(48); + str.append("..."); + } + m_pCrashesMenu->popupMenu()->insertItem( + str, this, + SLOT(slotItemSelected(int)), + 0, ++count ); + gotSep = false; + } + } + if (count - firstItem > 1) { + m_crashRangesList.append( CrashRange(firstItem, count) ); + m_pCrashesMenu->popupMenu()->insertItem( + i18n("All Pages of This Crash"), this, + SLOT(slotGroupSelected(int)), + 0, crashGroup--); + } + } else { + m_pCrashesMenu->popupMenu()->insertItem( + i18n("No Recovered Crashes"), this, + SLOT(slotItemSelected(int)), + 0, ++count ); + gotSep = false; + enable = false; + } + + if (!gotSep) { + // don't have an extra sep + m_pCrashesMenu->popupMenu()->insertSeparator(); + } + + int id =m_pCrashesMenu->popupMenu()->insertItem( i18n("&Clear List of Crashes"), this, + SLOT(slotClearCrashes()), + 0, ++count ); + m_pCrashesMenu->popupMenu()->setItemEnabled( id, enable); +} + +void CrashesPlugin::newBookmarkCallback( const QString & text, const QCString & url, + const QString & ) +{ + m_crashesList.prepend(qMakePair(text,url)); +} + +void CrashesPlugin::endFolderCallback( ) +{ + m_crashesList.prepend(qMakePair(QString("-"),QCString("-"))); +} + +void CrashesPlugin::slotClearCrashes() { + KCrashBookmarkImporter importer(KCrashBookmarkImporter::crashBookmarksDir()); + importer.parseCrashBookmarks( true ); + slotAboutToShow(); +} + +void CrashesPlugin::slotItemSelected( int id ) +{ + if (m_crashesList.count() == 0) + return; + KURL url( m_crashesList[id-1].second ); + if (m_part) + emit m_part->browserExtension()->openURLRequest( url ); +} + +void CrashesPlugin::slotGroupSelected( int range ) +{ + if (!m_part) + return; + + range = INT_MAX - range; + + if (m_crashesList.count() == 0 || m_crashRangesList.count() == 0) + return; + + CrashRange r = m_crashRangesList[range]; + int from = r.first; + int i = from; + + if (m_part) { + KParts::URLArgs urlargs; + urlargs.setNewTab( true ); + do { + KURL url( m_crashesList[i].second ); + // Open first one in current tab + if (i == from) + emit m_part->browserExtension()->openURLRequest( url ); + else + emit m_part->browserExtension()->createNewWindow( url, urlargs ); + } while (++i < r.second); + } +} + +#include "crashesplugin.moc" diff --git a/konq-plugins/crashes/crashesplugin.desktop b/konq-plugins/crashes/crashesplugin.desktop new file mode 100644 index 0000000..c806383 --- /dev/null +++ b/konq-plugins/crashes/crashesplugin.desktop @@ -0,0 +1,124 @@ +[Desktop Entry] +X-KDE-Library=Crashes +X-KDE-PluginInfo-Author=Alexander Kellett +X-KDE-PluginInfo-Email=lypanov@kde.org +X-KDE-PluginInfo-Name=Crashes +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=Crashes Monitor +Name[bg]=Монитор на блокирали процеси +Name[bs]=Praćenje krahova +Name[ca]=Monitor de petades +Name[cs]=Monitor pádů +Name[da]=Sammenbrudsovervågning +Name[de]=Absturzmonitor +Name[el]=Επόπτης καταρρεύσεων +Name[eo]=Kraŝa observilo +Name[es]=Monitor de bloqueos +Name[et]=Krahhide monitor +Name[eu]=Kaskraduren monitorea +Name[fa]=نمایشگر فروپاشیها +Name[fi]=Kaatumisenvalvonta +Name[fr]=Indicateur de plantages +Name[fy]=Fêstrinnersmonitor +Name[gl]=Monitor de Colgues +Name[he]=צג התרסקויות +Name[hi]=क्रैशेस मॉनीटर +Name[hr]=Nadzor padova +Name[hu]=Programhiba-figyelő +Name[is]=Hruns-eftirlit +Name[it]=Monitor dei crash +Name[ja]=クラッシュモニタ +Name[ka]=ავარიების მონიტორი +Name[kk]=Жаңылыстарды қадағалау +Name[km]=កម្មវិធីត្រួតពិនិត្យការគាំង +Name[lt]=Lūžimų stebėjimo priemonė +Name[mk]=Набљудувач на паѓања +Name[ms]=Monitor Rosak +Name[nb]=Krasjovervåker +Name[nds]=Afstörten-Kieker +Name[ne]=क्र्यास मनिटर +Name[nl]=Crash monitor +Name[nn]=Krasjovervaking +Name[pa]=ਨਸ਼ਟ ਨਿਗਰਾਨ +Name[pl]=Monitor awarii programu +Name[pt]=Monitor de Estoiros +Name[pt_BR]=Monitor de Travamentos +Name[ru]=Монитор сбоев +Name[sk]=Monitor pádov +Name[sl]=Nadzornik zrušenj +Name[sr]=Надгледање падова +Name[sr@Latn]=Nadgledanje padova +Name[sv]=Kraschövervakare +Name[ta]=திரை செயல் இழந்தது +Name[tg]=Нуқсонҳои монитор +Name[tr]=Monitörü Bozar +Name[uk]=Монітор аварій +Name[vi]=Bộ theo dõi sụp đổ +Name[zh_CN]=崩溃监视器 +Name[zh_TW]=當機監視器 +Comment=Crashes monitor +Comment[af]=Verongeluk monitor +Comment[ar]=مراقب الإنهيارات +Comment[az]=İflas izləyici +Comment[bg]=Монитор на блокирали процеси в KDE +Comment[bs]=Praćenje krahova +Comment[ca]=Monitor de petades +Comment[cs]=Monitor pádů +Comment[cy]=Gwarchodydd chwalfeydd +Comment[da]=Sammenbrudsovervåger +Comment[de]=Absturzmonitor +Comment[el]=Επόπτης καταρρεύσεων +Comment[eo]=Kraŝa observilo +Comment[es]=Monitor de bloqueos +Comment[et]=Krahhide monitor +Comment[eu]=Monitorea kraskarazten du +Comment[fa]=نمایشگر فروپاشیها +Comment[fi]=Kaatumistenvalvonta +Comment[fr]=Gestion des plantages logiciels +Comment[fy]=Fêstrinnersmonitor +Comment[gl]=Monitorea os petes das aplicacións +Comment[he]=צג התרסקויות +Comment[hi]=क्रैश मॉनीटर +Comment[hr]=Nadzor padova +Comment[hu]=Programhiba-monitor +Comment[is]=Hruns-eftirlit +Comment[it]=Monitorizza i crash +Comment[ja]=クラッシュモニタ +Comment[ka]=ავარიების მონიტორი +Comment[kk]=Жаңылыстарды қадағалау +Comment[km]=កម្មវិធីត្រួតពិនិត្យការគាំង +Comment[lt]=Lūžimų stebėtojas +Comment[mk]=Набљудувач на паѓања +Comment[ms]=Monitor rosak +Comment[nb]=Overvåker krasj +Comment[nds]=Afstörten-Kieker +Comment[ne]=मनिटर क्र्यास गर्छ +Comment[nl]=Vastlopers-monitor +Comment[nn]=Overvakar krasj +Comment[pa]=ਕਰੈਂਸ਼ ਨਿਗਰਾਨ +Comment[pl]=Monitor awarii programu +Comment[pt]=Monitor de estoiros +Comment[pt_BR]=Monitor de sistema +Comment[ro]=Program de monitorizare a prăbuşirii programelor +Comment[ru]=Монитор сбоев +Comment[sk]=Monitor pádov +Comment[sl]=Nadzornik zrušenj +Comment[sr]=Надгледање падова +Comment[sr@Latn]=Nadgledanje padova +Comment[sv]=Övervakar programkrascher +Comment[ta]=திரை செயல் இழந்தது +Comment[tg]=Нуқсонҳои монитор +Comment[tr]=Monitörü bozar +Comment[uk]=Монітор аварій +Comment[vi]=Bộ theo dõi sụp đổ +Comment[xh]=Ingqubana necebo lokubonisa +Comment[zh_CN]=崩溃监视器 +Comment[zh_TW]=當機監視器 +X-KDE-ParentApp=konqueror +Icon=core +DocPath=konq-plugins/crashes/index.html diff --git a/konq-plugins/crashes/crashesplugin.h b/konq-plugins/crashes/crashesplugin.h new file mode 100644 index 0000000..cff0831 --- /dev/null +++ b/konq-plugins/crashes/crashesplugin.h @@ -0,0 +1,70 @@ +/* + Copyright (c) 2002-2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __CRASHES_PLUGIN_H +#define __CRASHES_PLUGIN_H + +#include <qmap.h> +#include <qvaluelist.h> +#include <qstringlist.h> + +#include <kurl.h> +#include <klibloader.h> +#include <kparts/plugin.h> + +class KHTMLPart; +class KActionMenu; + +class CrashesPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + CrashesPlugin( QObject* parent, const char* name, + const QStringList & ); + ~CrashesPlugin(); + +protected slots: + void slotAboutToShow(); + void slotClearCrashes(); + void slotItemSelected(int); + void slotGroupSelected(int); + void newBookmarkCallback( const QString &, const QCString &, const QString & ); + void endFolderCallback( ); + +private: + int m_selectedItem; + + KHTMLPart* m_part; + KActionMenu* m_pCrashesMenu; + + typedef QPair<QString,QCString> Crash; + typedef QValueList<Crash> CrashesList; + + CrashesList m_crashesList; + + typedef QPair<int, int> CrashRange; + typedef QValueList<CrashRange> CrashRangesList; + + CrashRangesList m_crashRangesList; + +}; + +#endif diff --git a/konq-plugins/crashes/crashesplugin.rc b/konq-plugins/crashes/crashesplugin.rc new file mode 100644 index 0000000..35fc070 --- /dev/null +++ b/konq-plugins/crashes/crashesplugin.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartplugin> +<kpartplugin name="Crashes" library="libcrashesplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="crashes"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="crashes"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/dirfilter/Makefile.am b/konq-plugins/dirfilter/Makefile.am new file mode 100644 index 0000000..fe81189 --- /dev/null +++ b/konq-plugins/dirfilter/Makefile.am @@ -0,0 +1,19 @@ +kde_module_LTLIBRARIES = libdirfilterplugin.la + +AM_CPPFLAGS = $(all_includes) +METASOURCES = AUTO + +libdirfilterplugin_la_SOURCES = dirfilterplugin.cpp +libdirfilterplugin_la_LIBADD = -lkonq +libdirfilterplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +iconviewdir = $(kde_datadir)/konqiconview/kpartplugins +iconview_DATA = dirfilterplugin.rc dirfilterplugin.desktop +listviewdir = $(kde_datadir)/konqlistview/kpartplugins +listview_DATA = dirfilterplugin.rc dirfilterplugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = dirfilterplugin.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/dirfilterplugin.pot diff --git a/konq-plugins/dirfilter/dirfilterplugin.cpp b/konq-plugins/dirfilter/dirfilterplugin.cpp new file mode 100644 index 0000000..0966f19 --- /dev/null +++ b/konq-plugins/dirfilter/dirfilterplugin.cpp @@ -0,0 +1,492 @@ +/* + Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <unistd.h> +#include <sys/types.h> + +#include <qtimer.h> +#include <qapplication.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qhbox.h> +#include <qwhatsthis.h> +#include <qiconview.h> +#include <klistview.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kinstance.h> + +#include <kaction.h> +#include <kpopupmenu.h> +#include <kmessagebox.h> +#include <kiconloader.h> + +#include <kdirlister.h> +#include <klistviewsearchline.h> +#include <kiconviewsearchline.h> +#include <konq_dirpart.h> +#include <konq_propsview.h> +#include <kstaticdeleter.h> +#include <kgenericfactory.h> +#include <kparts/browserextension.h> + +#include "dirfilterplugin.h" + +SessionManager* SessionManager::m_self = 0; +static KStaticDeleter<SessionManager> dirfiltersd; + +SessionManager *SessionManager::self () +{ + if (!m_self) + m_self = dirfiltersd.setObject(m_self, new SessionManager); + + return m_self; +} + +SessionManager::SessionManager() +{ + m_bSettingsLoaded = false; + loadSettings (); +} + +SessionManager::~SessionManager() +{ + saveSettings(); + m_self = 0; +} + +QString SessionManager::generateKey (const KURL& url) const +{ + QString key; + + key = url.protocol (); + key += ':'; + + if (!url.host ().isEmpty ()) + { + key += url.host (); + key += ':'; + } + + key += url.path (); + key += ':'; + key += QString::number (m_pid); + + return key; +} + +QStringList SessionManager::restoreMimeFilters (const KURL& url) const +{ + QString key(generateKey(url)); + return m_filters[key]; +} + +QString SessionManager::restoreTypedFilter (const KURL& url) const +{ + QString key(generateKey(url)); + return m_typedFilter[key]; +} + +void SessionManager::save (const KURL& url, const QStringList& filters) +{ + QString key = generateKey(url); + m_filters[key] = filters; +} + +void SessionManager::save (const KURL& url, const QString& typedFilter) +{ + QString key = generateKey(url); + m_typedFilter[key] = typedFilter; +} + +void SessionManager::saveSettings() +{ + KConfig cfg ("dirfilterrc", false, false); + cfg.setGroup ("General"); + + cfg.writeEntry ("ShowCount", showCount); + cfg.writeEntry ("UseMultipleFilters", useMultipleFilters); + cfg.sync(); +} + +void SessionManager::loadSettings() +{ + if (m_bSettingsLoaded) + return; + + KConfig cfg ("dirfilterrc", false, false); + cfg.setGroup ("General"); + + showCount = cfg.readBoolEntry ("ShowCount", false); + useMultipleFilters = cfg.readBoolEntry ("UseMultipleFilters", true); + m_pid = getpid (); + m_bSettingsLoaded = true; +} + + + +DirFilterPlugin::DirFilterPlugin (QObject* parent, const char* name, + const QStringList&) + :KParts::Plugin (parent, name), + m_pFilterMenu(0), + m_searchWidget(0) +{ + m_part = ::qt_cast<KonqDirPart*>(parent); + + if ( !m_part || !m_part->scrollWidget() ) + return; + + m_pFilterMenu = new KActionMenu (i18n("View F&ilter"), "filter", + actionCollection(), "filterdir"); + m_pFilterMenu->setDelayed (false); + m_pFilterMenu->setWhatsThis(i18n("Allow to filter the currently displayed items by filetype.")); + + connect (m_pFilterMenu->popupMenu(), SIGNAL (aboutToShow()), + SLOT (slotShowPopup())); + + connect (m_part, SIGNAL (itemRemoved(const KFileItem*)), + SLOT( slotItemRemoved (const KFileItem*))); + connect (m_part, SIGNAL (itemsAdded(const KFileItemList&)), + SLOT (slotItemsAdded(const KFileItemList&))); + connect (m_part, SIGNAL (itemsFilteredByMime(const KFileItemList&)), + SLOT (slotItemsAdded(const KFileItemList&))); + connect (m_part, SIGNAL(aboutToOpenURL()), SLOT(slotOpenURL())); + + // add a searchline filter for konqis icons/list views + QHBox *hbox = new QHBox(m_part->widget()); + hbox->hide(); + + KAction *clear = new KAction(i18n("Clear Filter Field"), + QApplication::reverseLayout() ? "clear_left" : "locationbar_erase", + 0, 0, 0, actionCollection(), "clear_filter"); + + clear->setWhatsThis(i18n("Clear filter field<p>Clears the content of the filter field.")); + + if ( ::qt_cast<KListView*>(m_part->scrollWidget()) ) + { + m_searchWidget = new KListViewSearchLine(hbox); + static_cast<KListViewSearchLine*>(m_searchWidget)->setListView(static_cast<KListView*>(m_part->scrollWidget())); + } + else if ( ::qt_cast<QIconView*>(m_part->scrollWidget()) ) + { + m_searchWidget = new KIconViewSearchLine(hbox); + static_cast<KIconViewSearchLine*>(m_searchWidget)->setIconView(static_cast<QIconView*>(m_part->scrollWidget())); + } + + + if ( m_searchWidget ) + { + QWhatsThis::add(m_searchWidget, i18n("Enter here a text which an item in the view must contain anywhere to be shown.")); + connect(clear, SIGNAL(activated()), m_searchWidget, SLOT(clear())); + } + + KWidgetAction *filterAction = new KWidgetAction(hbox, i18n("Filter Field"), + 0, 0, 0, actionCollection(), "toolbar_filter_field"); + filterAction->setShortcutConfigurable(false); +} + +DirFilterPlugin::~DirFilterPlugin() +{ + delete m_pFilterMenu; +} + +void DirFilterPlugin::slotOpenURL () +{ + KURL url = m_part->url(); + + //kdDebug(90190) << "DirFilterPlugin: New URL : " << url.url() << endl; + //kdDebug(90190) << "DirFilterPlugin: Current URL: " << m_pURL.url() << endl; + + if (m_pURL != url) + { + //Clears the hidden list which is by now outdated... + if (m_searchWidget) + { + SessionManager::self()->save(m_pURL, m_searchWidget->text()); + m_searchWidget->clear(); + + QString typedFilter(SessionManager::self()->restoreTypedFilter(url)); + m_searchWidget->completionObject()->addItem(typedFilter); + m_searchWidget->setText(typedFilter); + } + + m_pURL = url; + m_pMimeInfo.clear(); + m_part->setMimeFilter (SessionManager::self()->restoreMimeFilters(url)); + } +} + +void DirFilterPlugin::slotShowPopup() +{ + if (!m_part) + { + m_pFilterMenu->setEnabled (false); + return; + } + + int id = 0; + uint enableReset = 0; + + QString label; + QStringList inodes; + + m_pFilterMenu->popupMenu()->clear(); + m_pFilterMenu->popupMenu()->insertTitle (i18n("Only Show Items of Type")); + + MimeInfoIterator it = m_pMimeInfo.begin(); + const MimeInfoIterator end = m_pMimeInfo.end(); + for (; it != end ; ++it) + { + if (it.key().startsWith("inode")) + { + inodes << it.key(); + continue; + } + + if (!SessionManager::self()->showCount) + label = it.data().mimeComment; + else + { + label = it.data().mimeComment; + label += " ("; + label += QString::number (it.data().filenames.size ()); + label += ")"; + } + + m_pMimeInfo[it.key()].id = m_pFilterMenu->popupMenu()->insertItem ( + SmallIconSet(it.data().iconName), label, + this, SLOT(slotItemSelected(int)), 0, ++id); + + if (it.data().useAsFilter) + { + m_pFilterMenu->popupMenu()->setItemChecked (id, true); + enableReset++; + } + } + + // Add all the items that have mime-type of "inode/*" here... + if (!inodes.isEmpty()) + { + m_pFilterMenu->popupMenu()->insertSeparator (); + + QStringList::Iterator it = inodes.begin(); + QStringList::Iterator end = inodes.end(); + + for (; it != end; ++it) + { + if (!SessionManager::self()->showCount) + label = m_pMimeInfo[(*it)].mimeComment; + else + { + label = m_pMimeInfo[(*it)].mimeComment; + label += " ("; + label += QString::number (m_pMimeInfo[(*it)].filenames.size ()); + label += ")"; + } + + m_pMimeInfo[(*it)].id = m_pFilterMenu->popupMenu()->insertItem ( + SmallIconSet(m_pMimeInfo[(*it)].iconName), label, + this, SLOT(slotItemSelected(int)), 0, ++id); + + if (m_pMimeInfo[(*it)].useAsFilter) + { + m_pFilterMenu->popupMenu()->setItemChecked (id, true); + enableReset ++; + } + } + } + + m_pFilterMenu->popupMenu()->insertSeparator (); + id = m_pFilterMenu->popupMenu()->insertItem (i18n("Use Multiple Filters"), + this, SLOT(slotMultipleFilters())); + m_pFilterMenu->popupMenu()->setItemEnabled (id, enableReset <= 1); + m_pFilterMenu->popupMenu()->setItemChecked (id, SessionManager::self()->useMultipleFilters); + + id = m_pFilterMenu->popupMenu()->insertItem (i18n("Show Count"), this, + SLOT(slotShowCount())); + m_pFilterMenu->popupMenu()->setItemChecked (id, SessionManager::self()->showCount); + + id = m_pFilterMenu->popupMenu()->insertItem (i18n("Reset"), this, + SLOT(slotReset())); + + m_pFilterMenu->popupMenu()->setItemEnabled (id, enableReset); +} + +void DirFilterPlugin::slotItemSelected (int id) +{ + if (!m_part) + return; + + MimeInfoIterator it = m_pMimeInfo.begin(); + while (it != m_pMimeInfo.end () && id != it.data().id) + it++; + + if (it != m_pMimeInfo.end()) + { + QStringList filters; + + if (it.data().useAsFilter) + { + it.data().useAsFilter = false; + filters = m_part->mimeFilter (); + if (filters.remove (it.key())) + m_part->setMimeFilter (filters); + } + else + { + m_pMimeInfo[it.key()].useAsFilter = true; + + if (SessionManager::self()->useMultipleFilters) + { + filters = m_part->mimeFilter (); + filters << it.key(); + } + else + { + filters << it.key(); + + MimeInfoIterator item = m_pMimeInfo.begin(); + while ( item != m_pMimeInfo.end() ) + { + if ( item != it ) + item.data().useAsFilter = false; + item++; + } + } + + m_part->setMimeFilter (filters); + } + + KURL url = m_part->url(); + m_part->openURL (url); + SessionManager::self()->save (url, filters); + } +} + +void DirFilterPlugin::slotItemsAdded (const KFileItemList& list) +{ + KURL url = m_part->url(); + + if (list.count() == 0 || !m_part || !m_part->nameFilter().isEmpty()) + { + m_pFilterMenu->setEnabled (m_part->nameFilter().isEmpty()); + return; + } + + // Make sure the filter menu is enabled once a named + // filter is removed. + if (!m_pFilterMenu->isEnabled()) + m_pFilterMenu->setEnabled (true); + + for (KFileItemListIterator it (list); it.current (); ++it) + { + QString name = it.current()->name(); + KMimeType::Ptr mime = it.current()->mimeTypePtr(); // don't resolve mimetype if unknown + if (!mime) + continue; + QString mimeType = mime->name(); + + if (!m_pMimeInfo.contains (mimeType)) + { + MimeInfo& mimeInfo = m_pMimeInfo[mimeType]; + QStringList filters = m_part->mimeFilter (); + mimeInfo.useAsFilter = (!filters.isEmpty () && + filters.contains (mimeType)); + mimeInfo.mimeComment = mime->comment(); + mimeInfo.iconName = mime->icon(KURL(), false); + mimeInfo.filenames.insert(name, false); + } + else + { + m_pMimeInfo[mimeType].filenames.insert(name, false); + } + } +} + +void DirFilterPlugin::slotItemRemoved (const KFileItem* item) +{ + if (!item || !m_part) + return; + + QString mimeType = item->mimetype().stripWhiteSpace(); + + if (m_pMimeInfo.contains (mimeType)) + { + MimeInfo info = m_pMimeInfo [mimeType]; + + if (info.filenames.size () > 1) + m_pMimeInfo [mimeType].filenames.remove (item->name ()); + else + { + if (info.useAsFilter) + { + QStringList filters = m_part->mimeFilter (); + filters.remove (mimeType); + m_part->setMimeFilter (filters); + SessionManager::self()->save (m_part->url(), filters); + QTimer::singleShot( 0, this, SLOT(slotTimeout()) ); + } + m_pMimeInfo.remove (mimeType); + } + } +} + +void DirFilterPlugin::slotReset() +{ + if (!m_part) + return; + + MimeInfoIterator it = m_pMimeInfo.begin(); + for (; it != m_pMimeInfo.end(); ++it) + it.data().useAsFilter = false; + + QStringList filters; + KURL url = m_part->url(); + + m_part->setMimeFilter (filters); + SessionManager::self()->save (url, filters); + m_part->openURL (url); +} + +void DirFilterPlugin::slotShowCount() +{ + if (SessionManager::self()->showCount) + SessionManager::self()->showCount = false; + else + SessionManager::self()->showCount = true; +} + +void DirFilterPlugin::slotMultipleFilters() +{ + if (SessionManager::self()->useMultipleFilters) + SessionManager::self()->useMultipleFilters = false; + else + SessionManager::self()->useMultipleFilters = true; +} + +void DirFilterPlugin::slotTimeout() +{ + if (m_part) + m_part->openURL (m_part->url()); +} + +typedef KGenericFactory<DirFilterPlugin> DirFilterFactory; +K_EXPORT_COMPONENT_FACTORY (libdirfilterplugin, DirFilterFactory("dirfilterplugin")) + +#include "dirfilterplugin.moc" diff --git a/konq-plugins/dirfilter/dirfilterplugin.desktop b/konq-plugins/dirfilter/dirfilterplugin.desktop new file mode 100644 index 0000000..31dfcf0 --- /dev/null +++ b/konq-plugins/dirfilter/dirfilterplugin.desktop @@ -0,0 +1,125 @@ +[Desktop Entry] +Type=Service +X-KDE-PluginInfo-Author=Dawit Alemayehu,Martin Koller +X-KDE-PluginInfo-Email=adawit@kde.org,m.koller@surfeu.at +X-KDE-PluginInfo-Name=DirFilter +X-KDE-PluginInfo-Version=3.4 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Directory Filter Plugin +Name[bg]=Приставка за филтриране на директории +Name[br]=Lugent sil ar renkelloù +Name[bs]=Plugin za filtriranje direktorija +Name[ca]=Connector filtre del directori +Name[cs]=Modul pro filtrování adresářů +Name[da]=Mappefilter-plugin +Name[de]=Ordnerfilter-Modul +Name[el]=Πρόσθετο φίλτρου καταλόγων +Name[eo]=Dosierujfiltrila kromaĵo +Name[es]=Complemento de filtrado de carpetas +Name[et]=Kataloogifiltri plugin +Name[eu]=Direktorioen iragazki plugina +Name[fa]=وصلۀ پالایۀ فهرست راهنما +Name[fi]=Hakemistosuodinsovelma +Name[fr]=Module de filtrage de dossiers +Name[fy]=Mappenfilterplugin +Name[gl]=Plugin de Filtraxe de Cartafoles +Name[he]=תוסף מסנן ספריות +Name[hi]=डिरेक्ट्री फ़िल्टर प्लगइन +Name[hr]=Dodatak filtra mapa +Name[hu]=Könyvtárszűrő bővítőmodul +Name[is]=Íforrit sem síar möppur +Name[it]=Plugin per il filtro delle directory +Name[ja]=ディレクトリ フィルタ プラグイン +Name[ka]=დირექტორიის ფილტრის მოდული +Name[kk]=Каталог сүзгісі +Name[km]=កម្មវិធីជំនួយតម្រងថត +Name[lt]=Aplanko filtro priedas +Name[mk]=Приклучок за филтирање папки +Name[ms]=Plugin Penapis Direktori +Name[nb]=Programtillegg til mappefilter +Name[nds]=Ornerfilter-Moduul +Name[ne]=डाइरेक्टरी फिल्टर प्लगइन +Name[nl]=Mappenfilterplugin +Name[nn]=Progamtillegg for katalogfilter +Name[pa]=ਡਾਇਰੈਕਟਰੀ ਫਿਲਟਰ ਪਲੱਗਇਨ +Name[pl]=Wtyczka filtrowania katalogów +Name[pt]='Plugin' de Filtragem de Directorias +Name[pt_BR]=Pasta do Plug-in de Filtro +Name[ru]=Фильтр папок +Name[sk]=Modul adresárového filtra +Name[sl]=Vstavek za filtriranje imenikov +Name[sr]=Прикључак за филтрирање директоријума +Name[sr@Latn]=Priključak za filtriranje direktorijuma +Name[sv]=Insticksprogram för katalogfilter +Name[ta]=அகராதி வடிகட்டி சொருகுப் பொருள் +Name[tg]=Филтри каталогҳо +Name[tr]=Dizin Filtre Eklentisi +Name[uk]=Втулок фільтра каталогів +Name[vi]=Bổ sung lọc thư mục +Name[zh_CN]=目录过滤器插件 +Name[zh_TW]=目錄過濾器外掛程式 +Comment=Directory filter plugin +Comment[af]=Gids filter inplak +Comment[ar]=ملحق تنقية المجلدات +Comment[az]=Qovluq filtr əlavəsi +Comment[bg]=Приставка за филтриране на директории +Comment[br]=Lugent sil ar renkelloù +Comment[bs]=Plugin za filtriranje direktorija +Comment[ca]=Connector filtre del directori +Comment[cs]=Modul pro filtrování adresářů +Comment[cy]=Ategyn hidl cyfeiriadur +Comment[da]=Mappefilter-plugin +Comment[de]=Ein Modul zum Filtern von Ordnerinhalten +Comment[el]=Πρόσθετο φίλτρου καταλόγου +Comment[eo]=Dosierujfiltrila kromaĵo +Comment[es]=Complemento de filtrado de carpetas +Comment[et]=Kataloogifiltri plugin +Comment[eu]=Direktorioen iragazki plugina +Comment[fa]=وصلۀ پالایۀ فهرست راهنما +Comment[fi]=Hakemistosuodinsovelma +Comment[fr]=Module de filtrage de dossiers +Comment[fy]=Mappenfilterplugin +Comment[gl]=Plugin de filtraxe de cartafoles +Comment[he]=תוסף מסנן ספריות +Comment[hi]=डिरेक्ट्री फ़िल्टर प्लगइन +Comment[hr]=Dodatak filtra mapa +Comment[hu]=Könyvtárszűrő modul +Comment[is]=Íforrit sem síar möppur +Comment[it]=Plugin per il filtro delle directory +Comment[ja]=ディレクトリフィルタプラグイン +Comment[ka]=დირექტორიის ფილტრის მოდული +Comment[kk]=Каталог сүзгі плагин модулі +Comment[km]=កម្មវិធីជំនួយតម្រងថត +Comment[lt]=Aplanko filtro priedas +Comment[mk]=Приклучок за филтирање папки +Comment[nb]=Programtillegg til mappefilter +Comment[nds]=Ornerfilter-Moduul +Comment[ne]=डाइरेक्टरी फिल्टर प्लगइन +Comment[nl]=Mappenfilterplugin +Comment[nn]=Progamtillegg for katalogfilter +Comment[pa]=ਡਾਇਰੈਕਟਰੀ ਫਿਲਟਰ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka filtrowania katalogów +Comment[pt]='Plugin' de filtragem de directorias +Comment[pt_BR]=Pasta de plug-in de filtragem +Comment[ro]=Modul de filtrare a directoarelor de afişat +Comment[ru]=Модуль фильтра папок +Comment[sk]=Modul adresárového filtra +Comment[sl]=Vstavek za filtriranje imenikov +Comment[sr]=Прикључак за филтрирање директоријума +Comment[sr@Latn]=Priključak za filtriranje direktorijuma +Comment[sv]=Insticksprogram för katalogfilter +Comment[ta]= அகராதி வடிகட்டி சொருகுப்பொருள் +Comment[tg]=Модули филтри каталогҳо +Comment[tr]=Dizin filtre eklentisi +Comment[uk]=Втулок фільтра каталогів +Comment[vi]=Bổ sung lọc thư mục +Comment[xh]=Isilawulo secebo lokucoca ulwelo seplagi yangaphakathi +Comment[zh_CN]=目录过滤器插件 +Comment[zh_TW]=目錄過濾器外掛程式 +Icon=filter +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/dirfilter/index.html diff --git a/konq-plugins/dirfilter/dirfilterplugin.h b/konq-plugins/dirfilter/dirfilterplugin.h new file mode 100644 index 0000000..f1c5b44 --- /dev/null +++ b/konq-plugins/dirfilter/dirfilterplugin.h @@ -0,0 +1,132 @@ +/* + Copyright (C) 2000, 2001, 2002 Dawit Alemayehu <adawit@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __DIR_FILTER_PLUGIN_H +#define __DIR_FILTER_PLUGIN_H + +#include <qmap.h> +#include <qstringlist.h> + + +#include <kurl.h> +#include <kfileitem.h> +#include <klibloader.h> +#include <kparts/plugin.h> + +class KActionMenu; +class KonqDirPart; +class KLineEdit; + + +namespace KParts +{ + struct URLArgs; +} + +namespace KIO +{ + class Job; +} + +class SessionManager +{ +public: + + ~SessionManager (); + static SessionManager* self (); + QStringList restoreMimeFilters (const KURL& url) const; + QString restoreTypedFilter(const KURL& url) const; + void save (const KURL& url, const QStringList& filters); + void save (const KURL& url, const QString& typedFilter); + + bool showCount; + bool useMultipleFilters; + +protected: + + QString generateKey (const KURL& url) const; + void loadSettings (); + void saveSettings (); + +private: + + SessionManager (); + +private: + + int m_pid; + bool m_bSettingsLoaded; + static SessionManager* m_self; + QMap<QString,QStringList> m_filters; + QMap<QString,QString> m_typedFilter; +}; + + +class DirFilterPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + + DirFilterPlugin (QObject* parent, const char* name, const QStringList &); + ~DirFilterPlugin (); + +protected: + + struct MimeInfo + { + MimeInfo() + { + id = 0; + useAsFilter = false; + } + + int id; + bool useAsFilter; + + QString mimeType; + QString iconName; + QString mimeComment; + + QMap<QString, bool> filenames; + }; + + void loadSettings(); + void saveSettings(); + +private slots: + void slotReset(); + void slotTimeout(); + void slotOpenURL(); + void slotShowPopup(); + void slotShowCount(); + void slotMultipleFilters(); + void slotItemSelected(int); + void slotItemRemoved(const KFileItem *); + void slotItemsAdded(const KFileItemList &); + +private: + KURL m_pURL; + KonqDirPart* m_part; + KActionMenu* m_pFilterMenu; + + KLineEdit *m_searchWidget; + QMap<QString,MimeInfo> m_pMimeInfo; + typedef QMap<QString,MimeInfo>::Iterator MimeInfoIterator; +}; +#endif diff --git a/konq-plugins/dirfilter/dirfilterplugin.rc b/konq-plugins/dirfilter/dirfilterplugin.rc new file mode 100644 index 0000000..80f60eb --- /dev/null +++ b/konq-plugins/dirfilter/dirfilterplugin.rc @@ -0,0 +1,13 @@ +<!DOCTYPE kpartplugin> +<kpartplugin name="DirFilter" library="libdirfilterplugin" version = "4"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="filterdir"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="filterdir"/> +</ToolBar> +<ToolBar fullWidth="true" name="locationToolBar" newline="true"><text>Filter Toolbar</text> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/domtreeviewer/Makefile.am b/konq-plugins/domtreeviewer/Makefile.am new file mode 100644 index 0000000..3dcfcc9 --- /dev/null +++ b/konq-plugins/domtreeviewer/Makefile.am @@ -0,0 +1,44 @@ +INCLUDES = $(all_includes) + +# Needed to catch DOM exceptions +KDE_CXXFLAGS = $(USE_EXCEPTIONS) +# -DKListView=DOMListView + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libdomtreeviewerplugin.la + +libdomtreeviewerplugin_la_SOURCES = plugin_domtreeviewer.cpp \ + domtreeview.cpp \ + domlistviewitem.cpp \ + domtreewindow.cpp \ + domtreecommands.cpp \ + signalreceiver.cpp \ + domtreeviewbase.ui \ + attributeeditdialog.ui \ + elementeditdialog.ui \ + texteditdialog.ui \ + messagedialog.ui +# klistview.cpp \ +# +libdomtreeviewerplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +libdomtreeviewerplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = plugin_domtreeviewer.rc plugin_domtreeviewer.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = plugin_domtreeviewer.desktop + +install-data-local: $(srcdir)/../uninstall.desktop + $(mkinstalldirs) $(DESTDIR)$(pluginsdir) + $(INSTALL_DATA) $(srcdir)/../uninstall.desktop $(DESTDIR)$(pluginsdir)/domtreeviewerplugin.desktop + +METASOURCES = AUTO +KDE_ICON = domtreeviewer + +pluginsdatadir = $(kde_datadir)/domtreeviewer +pluginsdata_DATA = domtreeviewerui.rc + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/domtreeviewer.pot + diff --git a/konq-plugins/domtreeviewer/attributeeditdialog.ui b/konq-plugins/domtreeviewer/attributeeditdialog.ui new file mode 100644 index 0000000..c77f92d --- /dev/null +++ b/konq-plugins/domtreeviewer/attributeeditdialog.ui @@ -0,0 +1,174 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>AttributeEditDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>AttributeEditDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>412</width> + <height>254</height> + </rect> + </property> + <property name="caption"> + <string>Edit Attribute</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Attribute &name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>attrName</cstring> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>attrName</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Attribute &value:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>attrValue</cstring> + </property> + </widget> + <widget class="KTextEdit"> + <property name="name"> + <cstring>attrValue</cstring> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + <property name="autoFormatting"> + <set>AutoNone</set> + </property> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>okBtn</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>121</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>cancelBtn</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>okBtn</sender> + <signal>clicked()</signal> + <receiver>AttributeEditDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>cancelBtn</sender> + <signal>clicked()</signal> + <receiver>AttributeEditDialog</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>attrValue</sender> + <signal>returnPressed()</signal> + <receiver>AttributeEditDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>attrName</sender> + <signal>returnPressed()</signal> + <receiver>AttributeEditDialog</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>ktextedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/domtreeviewer/cr16-action-domtreeviewer.png b/konq-plugins/domtreeviewer/cr16-action-domtreeviewer.png Binary files differnew file mode 100644 index 0000000..d9c99cb --- /dev/null +++ b/konq-plugins/domtreeviewer/cr16-action-domtreeviewer.png diff --git a/konq-plugins/domtreeviewer/cr22-action-domtreeviewer.png b/konq-plugins/domtreeviewer/cr22-action-domtreeviewer.png Binary files differnew file mode 100644 index 0000000..0690b3d --- /dev/null +++ b/konq-plugins/domtreeviewer/cr22-action-domtreeviewer.png diff --git a/konq-plugins/domtreeviewer/domlistviewitem.cpp b/konq-plugins/domtreeviewer/domlistviewitem.cpp new file mode 100644 index 0000000..c24df96 --- /dev/null +++ b/konq-plugins/domtreeviewer/domlistviewitem.cpp @@ -0,0 +1,73 @@ +/*************************************************************************** + domlistviewitem.cpp + ------------------- + + author : Andreas Schlapbach + email : schlpbch@iam.unibe.ch + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "domlistviewitem.h" + +#include <qpainter.h> +#include <qlistview.h> +#include <qapplication.h> + +#include <kglobalsettings.h> + +DOMListViewItem::DOMListViewItem( const DOM::Node &node, QListView *parent ) + : QListViewItem( parent ), m_node(node) +{ + init(); +} + +DOMListViewItem::DOMListViewItem( const DOM::Node &node, QListView *parent, QListViewItem *after) + : QListViewItem( parent, after ), m_node(node) +{ + init(); +} + +DOMListViewItem::DOMListViewItem( const DOM::Node &node, QListViewItem *parent ) + : QListViewItem( parent ), m_node(node) +{ + init(); +} + +DOMListViewItem::DOMListViewItem( const DOM::Node &node, QListViewItem *parent, QListViewItem *after) + : QListViewItem( parent, after ), m_node(node) +{ + init(); +} + +DOMListViewItem::~DOMListViewItem() +{ + //NOP +} + +void DOMListViewItem::init() +{ + m_color = QApplication::palette().color( QPalette::Active, QColorGroup::Text ); + m_font = KGlobalSettings::generalFont(); + clos = false; +} + +void DOMListViewItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int alignment ) +{ + QColorGroup _cg( cg ); + QColor c = _cg.text(); + + p->setFont(m_font); + _cg.setColor( QColorGroup::Text, m_color ); + QListViewItem::paintCell( p, _cg, column, width, alignment ); + _cg.setColor( QColorGroup::Text, c ); +} + + diff --git a/konq-plugins/domtreeviewer/domlistviewitem.h b/konq-plugins/domtreeviewer/domlistviewitem.h new file mode 100644 index 0000000..22f34b2 --- /dev/null +++ b/konq-plugins/domtreeviewer/domlistviewitem.h @@ -0,0 +1,57 @@ +/*************************************************************************** + domlistviewitem.h + ------------------- + + author : Andreas Schlapbach + email : schlpbch@iam.unibe.ch + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef DOMLISTVIEWITEMS_H +#define DOMLISTVIEWITEMS_H + +#include <dom/dom_node.h> + +#include <qlistview.h> +#include <qcolor.h> +#include <qfont.h> + +class DOMListViewItem : public QListViewItem +{ + + public: + DOMListViewItem( const DOM::Node &, QListView *parent ); + DOMListViewItem( const DOM::Node &, QListView *parent, QListViewItem *after ); + DOMListViewItem( const DOM::Node &, QListViewItem *parent ); + DOMListViewItem( const DOM::Node &, QListViewItem *parent, QListViewItem *after ); + virtual ~DOMListViewItem(); + + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ); + + void setColor( const QColor &color) { m_color = color; } + + void setFont( const QFont &font) { m_font = font;} + void setItalic( bool b) {m_font.setItalic(b);} + void setBold( bool b) {m_font.setBold(b);} + void setUnderline(bool b) {m_font.setUnderline(b);} + + bool isClosing() const { return clos; } + void setClosing(bool s) { clos = s; } + + DOM::Node node() const { return m_node; } + + private: + void init(); + QColor m_color; + QFont m_font; + DOM::Node m_node; + bool clos; +}; +#endif diff --git a/konq-plugins/domtreeviewer/domtreecommands.cpp b/konq-plugins/domtreeviewer/domtreecommands.cpp new file mode 100644 index 0000000..1f91cf1 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreecommands.cpp @@ -0,0 +1,562 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "domtreecommands.h" + +#include <dom/dom_doc.h> +#include <dom/dom_exception.h> + +#include <klocale.h> + +#include <qmap.h> + +using namespace domtreeviewer; + +static const char * const dom_error_msgs[] = { + I18N_NOOP("No error"), + I18N_NOOP("Index size exceeded"), + I18N_NOOP("DOMString size exceeded"), + I18N_NOOP("Hierarchy request error"), + I18N_NOOP("Wrong document"), + I18N_NOOP("Invalid character"), + I18N_NOOP("No data allowed"), + I18N_NOOP("No modification allowed"), + I18N_NOOP("Not found"), + I18N_NOOP("Not supported"), + I18N_NOOP("Attribute in use"), + I18N_NOOP("Invalid state"), + I18N_NOOP("Syntax error"), + I18N_NOOP("Invalid modification"), + I18N_NOOP("Namespace error"), + I18N_NOOP("Invalid access") +}; + +// == global functions ============================================== + +QString domtreeviewer::domErrorMessage(int dom_err) +{ + if ((unsigned)dom_err > sizeof dom_error_msgs/sizeof dom_error_msgs[0]) + return i18n("Unknown Exception %1").arg(dom_err); + else + return i18n(dom_error_msgs[dom_err]); +} + +// == ManipulationCommandSignalEmitter ============================== + +static ManipulationCommandSignalEmitter *_mcse; + +ManipulationCommandSignalEmitter::ManipulationCommandSignalEmitter() +{} +ManipulationCommandSignalEmitter::~ManipulationCommandSignalEmitter() +{} + +namespace domtreeviewer { + +ManipulationCommandSignalEmitter* ManipulationCommand::mcse() +{ + if (!_mcse) _mcse = new ManipulationCommandSignalEmitter; + return _mcse; +} + +} + +// == ChangedNodeSet ================================================ + +namespace domtreeviewer { + +// collection of nodes for which to emit the nodeChanged signal +inline static bool operator <(const DOM::Node &n1, const DOM::Node &n2) +{ + return (long)n1.handle() - (long)n2.handle() < 0; +} + +class ChangedNodeSet : public QMap<DOM::Node, bool> +{ +}; + +} + +// == ManipulationCommand =========================================== + +ManipulationCommand::ManipulationCommand() : _exception(0), changedNodes(0) + , _reapplied(false) , allow_signals(true) +{ +} + +ManipulationCommand::~ManipulationCommand() +{ +} + +void ManipulationCommand::connect(const char *signal, QObject *recv, const char *slot) +{ + QObject::connect(mcse(), signal, recv, slot); +} + +void ManipulationCommand::handleException(DOM::DOMException &ex) +{ + _exception = ex; + QString msg = name() + ": " + domErrorMessage(ex.code); + emit mcse()->error(ex.code, msg); +} + +void ManipulationCommand::checkAndEmitSignals() +{ + if (allow_signals) { + if (changedNodes) { + ChangedNodeSet::Iterator end = changedNodes->end(); + for (ChangedNodeSet::Iterator it = changedNodes->begin(); it != end; ++it) { + emit mcse()->nodeChanged(it.key()); + } + } + + if (struc_changed) emit mcse()->structureChanged(); + } + if (changedNodes) changedNodes->clear(); +} + +void ManipulationCommand::addChangedNode(const DOM::Node &node) +{ + if (!changedNodes) changedNodes = new ChangedNodeSet; + changedNodes->insert(node, true); +} + +void ManipulationCommand::execute() +{ + if (!isValid()) return; + + struc_changed = false; + + try { + if (shouldReapply()) + reapply(); + else + apply(); + + checkAndEmitSignals(); + + } catch(DOM::DOMException &ex) { + handleException(ex); + } + _reapplied = true; +} + +void ManipulationCommand::unexecute() +{ + if (!isValid()) return; + + struc_changed = false; + + try { + unapply(); + checkAndEmitSignals(); + } catch(DOM::DOMException &ex) { + handleException(ex); + } +} + +void ManipulationCommand::reapply() +{ + apply(); +} + +// == MultiCommand =========================================== + +MultiCommand::MultiCommand(const QString &desc) +: _name(desc) +{ + cmds.setAutoDelete(true); +} + +MultiCommand::~MultiCommand() +{ +} + +void MultiCommand::addCommand(ManipulationCommand *cmd) +{ + cmd->allow_signals = false; + cmds.append(cmd); +} + +void MultiCommand::apply() +{ + // apply in forward order + for (QPtrListIterator<ManipulationCommand> it = cmds; *it; ++it) { + try { + if (shouldReapply()) (*it)->reapply(); + else (*it)->apply(); + + struc_changed |= (*it)->struc_changed; + mergeChangedNodesFrom(*it); + + } catch (DOM::DOMException &) { + // rollback + for (--it; *it; --it) { + try { + (*it)->unapply(); + } catch(DOM::DOMException &) { + // ignore + } + } + throw; + } + + } +} + +void MultiCommand::unapply() +{ + // unapply in reverse order + QPtrListIterator<ManipulationCommand> it = cmds; + for (it.toLast(); *it; --it) { + try { + (*it)->unapply(); + + struc_changed |= (*it)->struc_changed; + mergeChangedNodesFrom(*it); + + } catch (DOM::DOMException &) { + // rollback + for (++it; *it; ++it) { + try { + (*it)->reapply(); + } catch(DOM::DOMException &) { + // ignore + } + } + throw; + } + + } +} + +void MultiCommand::mergeChangedNodesFrom(ManipulationCommand *cmd) +{ + if (!cmd->changedNodes) return; + + ChangedNodeSet::ConstIterator end = cmd->changedNodes->end(); + for (ChangedNodeSet::ConstIterator it = cmd->changedNodes->begin(); it != end; ++it) { + addChangedNode(it.key()); + } + + cmd->changedNodes->clear(); +} + +QString MultiCommand::name() const +{ + return _name; +} + +// == AddAttributeCommand =========================================== + +AddAttributeCommand::AddAttributeCommand(const DOM::Element &element, const QString &attrName, const QString &attrValue) +: _element(element), attrName(attrName), attrValue(attrValue) +{ + if (attrValue.isEmpty()) this->attrValue = "<dummy>"; +} + +AddAttributeCommand::~AddAttributeCommand() +{ +} + +void AddAttributeCommand::apply() +{ + _element.setAttribute(attrName, attrValue); + addChangedNode(_element); +} + +void AddAttributeCommand::unapply() +{ + _element.removeAttribute(attrName); + addChangedNode(_element); +} + +QString AddAttributeCommand::name() const +{ + return i18n("Add attribute"); +} + +// == ChangeAttributeValueCommand ==================================== + +ChangeAttributeValueCommand::ChangeAttributeValueCommand( +const DOM::Element &element, const QString &attr, const QString &value) +: _element(element), _attr(attr), new_value(value) +{ +} + +ChangeAttributeValueCommand::~ChangeAttributeValueCommand() +{ +} + +void ChangeAttributeValueCommand::apply() +{ + if (!shouldReapply()) old_value = _element.getAttribute(_attr); + _element.setAttribute(_attr, new_value); + addChangedNode(_element); +} + +void ChangeAttributeValueCommand::unapply() +{ + _element.setAttribute(_attr, old_value); + addChangedNode(_element); +} + +QString ChangeAttributeValueCommand::name() const +{ + return i18n("Change attribute value"); +} + +// == RemoveAttributeCommand ======================================== + +RemoveAttributeCommand::RemoveAttributeCommand(const DOM::Element &element, const QString &attrName) +: _element(element), attrName(attrName) +{ +} + +RemoveAttributeCommand::~RemoveAttributeCommand() +{ +} + +void RemoveAttributeCommand::apply() +{ +// kdDebug(90180) << k_funcinfo << _element.nodeName().string() << ": " << attrName.string() << endl; + if (!shouldReapply()) + oldAttrValue = _element.getAttribute(attrName); + _element.removeAttribute(attrName); + addChangedNode(_element); +} + +void RemoveAttributeCommand::unapply() +{ + _element.setAttribute(attrName, oldAttrValue); + addChangedNode(_element); +} + +QString RemoveAttributeCommand::name() const +{ + return i18n("Remove attribute"); +} + +// == RenameAttributeCommand ======================================== + +RenameAttributeCommand::RenameAttributeCommand(const DOM::Element &element, const QString &attrOldName, const QString &attrNewName) +: _element(element), attrOldName(attrOldName), attrNewName(attrNewName) +{ +} + +RenameAttributeCommand::~RenameAttributeCommand() +{ +} + +void RenameAttributeCommand::apply() +{ + if (!shouldReapply()) + attrValue = _element.getAttribute(attrOldName); + _element.removeAttribute(attrOldName); + _element.setAttribute(attrNewName, attrValue); + addChangedNode(_element); +} + +void RenameAttributeCommand::unapply() +{ + _element.removeAttribute(attrNewName); + _element.setAttribute(attrOldName, attrValue); + addChangedNode(_element); +} + +QString RenameAttributeCommand::name() const +{ + return i18n("Rename attribute"); +} + +// == ChangeCDataCommand ======================================== + +ChangeCDataCommand::ChangeCDataCommand(const DOM::CharacterData &cdata, const QString &value) +: cdata(cdata), value(value), has_newlines(false) +{ +} + +ChangeCDataCommand::~ChangeCDataCommand() +{ +} + +void ChangeCDataCommand::apply() +{ + if (!shouldReapply()) { + oldValue = cdata.data(); + has_newlines = + QConstString(value.unicode(), value.length()).string().contains('\n') + || QConstString(oldValue.unicode(), oldValue.length()).string().contains('\n'); + } + cdata.setData(value); + addChangedNode(cdata); + struc_changed = has_newlines; +} + +void ChangeCDataCommand::unapply() +{ + cdata.setData(oldValue); + addChangedNode(cdata); + struc_changed = has_newlines; +} + +QString ChangeCDataCommand::name() const +{ + return i18n("Change textual content"); +} + +// == ManipulateNodeCommand =========================================== + +ManipulateNodeCommand::ManipulateNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: _node(node), _parent(parent), _after(after) +{ +} + +ManipulateNodeCommand::~ManipulateNodeCommand() +{ +} + +void ManipulateNodeCommand::insert() +{ + _parent.insertBefore(_node, _after); +} + +void ManipulateNodeCommand::remove() +{ + DOM::DocumentFragment frag = _node; + + if (frag.isNull()) { // do a normal remove + _node = _parent.removeChild(_node); + + } else { // remove fragment nodes and recreate fragment + DOM::DocumentFragment newfrag = _parent.ownerDocument().createDocumentFragment(); + + for (DOM::Node i = frag.firstChild(); !i.isNull(); i = i.nextSibling()) { + newfrag.appendChild(_parent.removeChild(i)); + } + + _node = newfrag; + } +} + +// == InsertNodeCommand =========================================== + +InsertNodeCommand::InsertNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: ManipulateNodeCommand(node, parent, after) +{ +} + +InsertNodeCommand::~InsertNodeCommand() +{ +} + +void InsertNodeCommand::apply() +{ + insert(); + struc_changed = true; +} + +void InsertNodeCommand::unapply() +{ + remove(); + struc_changed = true; +} + +QString InsertNodeCommand::name() const +{ + return i18n("Insert node"); +} + +// == RemoveNodeCommand =========================================== + +RemoveNodeCommand::RemoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: ManipulateNodeCommand(node, parent, after) +{ +} + +RemoveNodeCommand::~RemoveNodeCommand() +{ +} + +void RemoveNodeCommand::apply() +{ + remove(); + struc_changed = true; +} + +void RemoveNodeCommand::unapply() +{ + insert(); + struc_changed = true; +} + +QString RemoveNodeCommand::name() const +{ + return i18n("Remove node"); +} + +// == MoveNodeCommand =========================================== + +MoveNodeCommand::MoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after) +: _node(node), new_parent(parent), new_after(after) +{ + old_parent = node.parentNode(); + old_after = node.nextSibling(); +} + +MoveNodeCommand::~MoveNodeCommand() +{ +} + +void MoveNodeCommand::apply() +{ + old_parent.removeChild(_node); + try { + new_parent.insertBefore(_node, new_after); + } catch (DOM::DOMException &) { + try { // rollback + old_parent.insertBefore(_node, old_after); + } catch (DOM::DOMException &) {} + throw; + } + struc_changed = true; +} + +void MoveNodeCommand::unapply() +{ + new_parent.removeChild(_node); + try { + old_parent.insertBefore(_node, old_after); + } catch (DOM::DOMException &) { + try { // rollback + new_parent.insertBefore(_node, new_after); + } catch (DOM::DOMException &) {} + throw; + } + struc_changed = true; +} + +QString MoveNodeCommand::name() const +{ + return i18n("Move node"); +} + +#include "domtreecommands.moc" + +#undef MCSE diff --git a/konq-plugins/domtreeviewer/domtreecommands.h b/konq-plugins/domtreeviewer/domtreecommands.h new file mode 100644 index 0000000..bf893dc --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreecommands.h @@ -0,0 +1,375 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef domtreecommands_H +#define domtreecommands_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dom/dom_element.h> +#include <dom/dom_exception.h> +#include <dom/dom_string.h> +#include <dom/dom_text.h> + +#include <kcommand.h> + +#include <qobject.h> +#include <qptrlist.h> + +class DOMTreeView; +class KPrinter; +class KURL; + +namespace domtreeviewer { + +class ManipulationCommandSignalEmitter; +class ChangedNodeSet; + +/** returns a localized string for the given dom exception code */ +QString domErrorMessage(int exception_code); + +/** + * Internal class for emitting signals. + * @internal + */ +class ManipulationCommandSignalEmitter : public QObject +{ + Q_OBJECT + + ManipulationCommandSignalEmitter(); + virtual ~ManipulationCommandSignalEmitter(); + +#undef signals +#define signals public +signals: +#undef signals +#define signals protected + /** emitted if the DOM structure has been changed */ + void structureChanged(); + /** emitted if a DOM node has been changed */ + void nodeChanged(const DOM::Node &changedNode); + /** emitted if an error occurred + * @param err_id DOM error id + * @param msg error message + */ + void error(int err_id, const QString &msg); + +private: // make moc not complain + friend class ManipulationCommand; +}; + +/** + * Base class of all dom tree manipulation commands. + * @author Leo Savernik + */ +class ManipulationCommand : public KCommand +{ +public: + ManipulationCommand(); + virtual ~ManipulationCommand(); + + /** returns whether this command is still valid and can be executed */ + bool isValid() const { return !_exception.code; } + /** returns the last occurred DOM exception */ + DOM::DOMException exception() const { return _exception; } + /** returns true when the next issue of execute will reapply the command */ + bool shouldReapply() const { return _reapplied; } + /** returns true if the command may emit signals */ + bool allowSignals() const { return allow_signals; } + + /** connects the given signal to a slot */ + static void connect(const char *signal, QObject *recv, const char *slot); + + /** does grunt work and calls apply()/reapply() */ + virtual void execute(); + /** does grunt work and calls unapply() */ + virtual void unexecute(); + +protected: + virtual void apply() = 0; + virtual void reapply(); + virtual void unapply() = 0; + + void handleException(DOM::DOMException &); + void checkAndEmitSignals(); + void addChangedNode(const DOM::Node &); + + static ManipulationCommandSignalEmitter *mcse(); + +protected: + DOM::DOMException _exception; + ChangedNodeSet *changedNodes; + bool _reapplied:1; + bool struc_changed:1; + +private: + bool allow_signals:1; + + friend class MultiCommand; +}; + +/** + * Combines multiple commands into a single command. + * + * Does basically the same as KMacroCommand, but inherits from + * ManipulationCommand, and supports rollback. + */ +class MultiCommand : public ManipulationCommand +{ +public: + MultiCommand(const QString &name); + virtual ~MultiCommand(); + + /** Adds a new command. Will take ownership of \c cmd */ + void addCommand(ManipulationCommand *cmd); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + + void mergeChangedNodesFrom(ManipulationCommand *cmd); + +protected: + QPtrList<ManipulationCommand> cmds; + QString _name; +}; + +/** + * Adds an attribute to a node. + * @author Leo Savernik + */ +class AddAttributeCommand : public ManipulationCommand +{ +public: + AddAttributeCommand(const DOM::Element &element, const QString &attrName, const QString &attrValue); + virtual ~AddAttributeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::Element _element; + DOM::DOMString attrName; + DOM::DOMString attrValue; +}; + +/** + * Manipulates an attribute's value. + * @author Leo Savernik + */ +class ChangeAttributeValueCommand : public ManipulationCommand +{ +public: + ChangeAttributeValueCommand(const DOM::Element &element, const QString &attr, const QString &value); + virtual ~ChangeAttributeValueCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::Element _element; + DOM::DOMString _attr; + DOM::DOMString old_value; + DOM::DOMString new_value; +}; + +/** + * Removes an attribute from a node. + * @author Leo Savernik + */ +class RemoveAttributeCommand : public ManipulationCommand +{ +public: + RemoveAttributeCommand(const DOM::Element &element, const QString &attrName); + virtual ~RemoveAttributeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::Element _element; + DOM::DOMString attrName; + DOM::DOMString oldAttrValue; +}; + +/** + * Renames an attribute. + * @author Leo Savernik + */ +class RenameAttributeCommand : public ManipulationCommand +{ +public: + RenameAttributeCommand(const DOM::Element &element, const QString &attrOldName, const QString &attrNewName); + virtual ~RenameAttributeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::Element _element; + DOM::DOMString attrOldName; + DOM::DOMString attrNewName; + DOM::DOMString attrValue; +}; + +/** + * Changes the value of a CData-node. + * @author Leo Savernik + */ +class ChangeCDataCommand : public ManipulationCommand +{ +public: + ChangeCDataCommand(const DOM::CharacterData &, const QString &value); + virtual ~ChangeCDataCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::CharacterData cdata; + DOM::DOMString value; + DOM::DOMString oldValue; + bool has_newlines; +}; + +/** + * Handles insertion and deletion primitives of nodes. + * @author Leo Savernik + */ +class ManipulateNodeCommand : public ManipulationCommand +{ +public: + /** + * Prepare command, where \c node is to be contained in \c parent, just + * before \c after. If \c after is 0, it is appended at the end. + */ + ManipulateNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after); + virtual ~ManipulateNodeCommand(); + +protected: + void insert(); + void remove(); + +protected: + DOM::Node _node; + DOM::Node _parent; + DOM::Node _after; +}; + +/** + * Inserts a node into the tree. + * + * The handed in node may be a full tree, even a document fragment. + * + * @author Leo Savernik + */ +class InsertNodeCommand : public ManipulateNodeCommand +{ +public: + /** + * Prepare insertion command, inserting \c node into \c parent, just + * before \c after. If \c after is 0, append it to the list of children. + */ + InsertNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after); + virtual ~InsertNodeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: +}; + +/** + * Removes a node from the tree. + * + * The handed in node may be a full tree, even a document fragment. + * + * @author Leo Savernik + */ +class RemoveNodeCommand : public ManipulateNodeCommand +{ +public: + /** + * Prepare insertion command, inserting \c node into \c parent, just + * before \c after. If \c after is 0, append it to the list of children. + */ + RemoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after); + virtual ~RemoveNodeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: +}; + +/** + * Moves a node. + * @author Leo Savernik + */ +class MoveNodeCommand : public ManipulationCommand +{ +public: + /** + * Move \c node from current position into \c parent, just before \c after. + * Appends if \c after is 0. + */ + MoveNodeCommand(const DOM::Node &node, const DOM::Node &parent, const DOM::Node &after); + virtual ~MoveNodeCommand(); + + virtual QString name() const; + +protected: + virtual void apply(); + virtual void unapply(); + +protected: + DOM::Node _node; + DOM::Node old_parent, old_after; + DOM::Node new_parent, new_after; +}; + +} // namespace domtreeviewer + +#endif // domtreewindow_H diff --git a/konq-plugins/domtreeviewer/domtreeview.cpp b/konq-plugins/domtreeviewer/domtreeview.cpp new file mode 100644 index 0000000..167d85a --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreeview.cpp @@ -0,0 +1,1226 @@ +/*************************************************************************** + domtreeview.cpp + ------------------- + + copyright : (C) 2001 - The Kafka Team/Andreas Schlapbach + (C) 2005 - Leo Savernik + email : kde-kafka@master.kde.org + schlpbch@iam.unibe.ch + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "domtreeview.h" +#include "domlistviewitem.h" +#include "domtreewindow.h" +#include "domtreecommands.h" + +#include "attributeeditdialog.h" +#include "elementeditdialog.h" +#include "texteditdialog.h" + +#include "signalreceiver.h" + +#include <assert.h> + +#include <qapplication.h> +#include <qcheckbox.h> +#include <qevent.h> +#include <qfont.h> +#include <qfile.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpopupmenu.h> +#include <qtextstream.h> +#include <qtimer.h> +#include <qwidgetstack.h> + +#include <dom/dom_core.h> +#include <dom/html_base.h> + +#include <kaction.h> +#include <kdebug.h> +#include <kcombobox.h> +#include <kdialog.h> +#include <keditcl.h> +#include <kfiledialog.h> +#include <kglobalsettings.h> +#include <khtml_part.h> +#include <klineedit.h> +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpushbutton.h> +#include <kshortcut.h> +#include <kstdguiitem.h> +#include <ktextedit.h> + +using namespace domtreeviewer; + +DOMTreeView::DOMTreeView(QWidget *parent, const char* name, bool /*allowSaving*/) + : DOMTreeViewBase(parent, name), m_expansionDepth(5), m_maxDepth(0), + m_bPure(true), m_bShowAttributes(true), m_bHighlightHTML(true), + m_findDialog(0), focused_child(0) +{ + part = 0; + + const QFont font(KGlobalSettings::generalFont()); + m_listView->setFont( font ); + m_listView->setSorting(-1); + m_rootListView = m_listView; + + m_pureCheckBox->setChecked(m_bPure); + connect(m_pureCheckBox, SIGNAL(toggled(bool)), this, SLOT(slotPureToggled(bool))); + + m_showAttributesCheckBox->setChecked(m_bShowAttributes); + connect(m_showAttributesCheckBox, SIGNAL(toggled(bool)), this, + SLOT(slotShowAttributesToggled(bool))); + + m_highlightHTMLCheckBox->setChecked(m_bHighlightHTML); + connect(m_highlightHTMLCheckBox, SIGNAL(toggled(bool)), this, + SLOT(slotHighlightHTMLToggled(bool))); + + connect(m_listView, SIGNAL(clicked(QListViewItem *)), this, + SLOT(slotItemClicked(QListViewItem *))); + connect(m_listView, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)), + SLOT(showDOMTreeContextMenu(QListViewItem *, const QPoint &, int))); + connect(m_listView, SIGNAL(moved(QPtrList<QListViewItem> &, QPtrList<QListViewItem> &, QPtrList<QListViewItem> &)), + SLOT(slotMovedItems(QPtrList<QListViewItem> &, QPtrList<QListViewItem> &, QPtrList<QListViewItem> &))); + + // set up message line + messageLinePane->hide(); + connect(messageHideBtn, SIGNAL(clicked()), SLOT(hideMessageLine())); + connect(messageListBtn, SIGNAL(clicked()), mainWindow(), SLOT(showMessageLog())); + + installEventFilter(m_listView); + + ManipulationCommand::connect(SIGNAL(nodeChanged(const DOM::Node &)), this, SLOT(slotRefreshNode(const DOM::Node &))); + ManipulationCommand::connect(SIGNAL(structureChanged()), this, SLOT(refresh())); + + initDOMNodeInfo(); + + installEventFilter(this); +} + +DOMTreeView::~DOMTreeView() +{ + delete m_findDialog; + disconnectFromActivePart(); +} + +void DOMTreeView::setHtmlPart(KHTMLPart *_part) +{ + KHTMLPart *oldPart = part; + part = _part; + + if (oldPart) { + // nothing here yet + } + + parentWidget()->setCaption( part ? i18n( "DOM Tree for %1" ).arg(part->url().prettyURL()) : i18n("DOM Tree") ); + + QTimer::singleShot(0, this, SLOT(slotSetHtmlPartDelayed())); +} + +DOMTreeWindow *DOMTreeView::mainWindow() const +{ + return static_cast<DOMTreeWindow *>(parentWidget()); +} + +bool DOMTreeView::eventFilter(QObject *o, QEvent *e) +{ + if (e->type() == QEvent::AccelOverride) { + QKeyEvent *ke = static_cast<QKeyEvent *>(e); + kdDebug(90180) << " acceloverride " << ke->key() << " o " << o->name() << endl; + + if (o == m_listView) { // DOM tree + KKey ks = mainWindow()->deleteNodeAction()->shortcut().seq(0).key(0); + if (ke->key() == ks.keyCodeQt()) + return true; + + } else if (o == nodeAttributes) { + KKey ks = mainWindow()->deleteAttributeAction()->shortcut().seq(0).key(0); + if (ke->key() == ks.keyCodeQt()) + return true; + + } + + } else if (e->type() == QEvent::FocusIn) { + + kdDebug(90180) << " focusin o " << o->name() << endl; + if (o != this) { + focused_child = o; + } + + } else if (e->type() == QEvent::FocusOut) { + + kdDebug(90180) << " focusout o " << o->name() << endl; + if (o != this) { + focused_child = 0; + } + + } + + return false; +} + +void DOMTreeView::activateNode(const DOM::Node &node) +{ + slotShowNode(node); + initializeOptionsFromNode(node); +} + +void DOMTreeView::slotShowNode(const DOM::Node &pNode) +{ + + if (QListViewItem *item = m_itemdict[pNode.handle()]) { + m_listView->setCurrentItem(item); + m_listView->ensureItemVisible(item); + } +} + +void DOMTreeView::slotShowTree(const DOM::Node &pNode) +{ + DOM::Node child; + + m_listView->clear(); + m_itemdict.clear(); + + try + { + child = pNode.firstChild(); + } + catch (DOM::DOMException &) + { + return; + } + + while(!child.isNull()) { + showRecursive(0, child, 0); + child = child.nextSibling(); + } + + m_maxDepth--; + //kdDebug(90180) << " Max Depth: " << m_maxDepth << endl; +} + +void DOMTreeView::showRecursive(const DOM::Node &pNode, const DOM::Node &node, uint depth) +{ + DOMListViewItem *cur_item; + DOMListViewItem *parent_item = m_itemdict[pNode.handle()]; + + if (depth > m_maxDepth) { + m_maxDepth = depth; + } + + if (depth == 0) { + cur_item = new DOMListViewItem(node, m_listView); + m_document = pNode.ownerDocument(); + } else { + cur_item = new DOMListViewItem(node, parent_item); + } + + //kdDebug(90180) << node.nodeName().string() << " [" << depth << "]" << endl; + addElement (node, cur_item, false); + cur_item->setOpen(depth < m_expansionDepth); + + if(node.handle()) { + m_itemdict.insert(node.handle(), cur_item); + } + + DOM::Node child = node.lastChild(); + if (child.isNull()) { + DOM::HTMLFrameElement frame = node; + if (!frame.isNull()) child = frame.contentDocument().documentElement(); + } + while(!child.isNull()) { + showRecursive(node, child, depth + 1); + child = child.previousSibling(); + } + + const DOM::Element element = node; + if (!m_bPure) { + if (!element.isNull() && !element.firstChild().isNull()) { + if(depth == 0) { + cur_item = new DOMListViewItem(node, m_listView, cur_item); + m_document = pNode.ownerDocument(); + } else { + cur_item = new DOMListViewItem(node, parent_item, cur_item); + } + //kdDebug(90180) << "</" << node.nodeName().string() << ">" << endl; + addElement(element, cur_item, true); +// cur_item->setOpen(depth < m_expansionDepth); + } + } +} + +void DOMTreeView::addElement ( const DOM::Node &node, DOMListViewItem *cur_item, bool isLast) +{ + cur_item->setClosing(isLast); + + const QString nodeName(node.nodeName().string()); + QString text; + const DOM::Element element = node; + if (!element.isNull()) { + if (!m_bPure) { + if (isLast) { + text ="</"; + } else { + text = "<"; + } + text += nodeName; + } else { + text = nodeName; + } + + if (m_bShowAttributes && !isLast) { + QString attributes; + DOM::Attr attr; + DOM::NamedNodeMap attrs = element.attributes(); + unsigned long lmap = attrs.length(); + for( unsigned int j=0; j<lmap; j++ ) { + attr = static_cast<DOM::Attr>(attrs.item(j)); + attributes += " " + attr.name().string() + "=\"" + attr.value().string() + "\""; + } + if (!(attributes.isEmpty())) { + text += " "; + } + text += attributes.simplifyWhiteSpace(); + } + + if (!m_bPure) { + if(element.firstChild().isNull()) { + text += "/>"; + } else { + text += ">"; + } + } + cur_item->setText(0, text); + } else { + text = "`" + node.nodeValue().string() + "'"; + + // Hacks to deal with PRE + QTextStream ts( text, IO_ReadOnly ); + while (!ts.eof()) { + const QString txt(ts.readLine()); + const QFont font(KGlobalSettings::fixedFont()); + cur_item->setFont( font ); + cur_item->setText(0, txt); + + if(node.handle()) { + m_itemdict.insert(node.handle(), cur_item); + } + + DOMListViewItem *parent; + if (cur_item->parent()) { + parent = static_cast<DOMListViewItem *>(cur_item->parent()); + } else { + parent = cur_item; + } + cur_item = new DOMListViewItem(node, parent, cur_item); + } + // This is one is too much + DOMListViewItem *notLastItem = static_cast<DOMListViewItem *>(cur_item->itemAbove()); + delete cur_item; + cur_item = notLastItem; + } + + if (m_bHighlightHTML && node.ownerDocument().isHTMLDocument()) { + highlightHTML(cur_item, nodeName); + } +} + +void DOMTreeView::highlightHTML(DOMListViewItem *cur_item, const QString &nodeName) +{ + /* This is slow. I could make it O(1) be using the tokenizer of khtml but I don't + * think it's worth it. + */ + + QColor namedColor(palette().active().text()); + QString tagName = nodeName.upper(); + if ( tagName == "HTML" ) { + namedColor = "#0000ff"; + cur_item->setBold(true); + } else if ( tagName == "HEAD" ) { + namedColor = "#0022ff"; + cur_item->setBold(true); + + } else if ( tagName == "TITLE" ) { + namedColor = "#2200ff"; + } else if ( tagName == "SCRIPT" ) { + namedColor = "#4400ff"; + } else if ( tagName == "NOSCRIPT" ) { + namedColor = "#0044ff"; + } else if ( tagName == "STYLE" ) { + namedColor = "#0066ff"; + } else if ( tagName == "LINK" ) { + namedColor = "#6600ff"; + } else if ( tagName == "META" ) { + namedColor = "#0088ff"; + + } else if ( tagName == "BODY" ) { + namedColor = "#ff0000"; + cur_item->setBold(true); + } else if ( tagName == "A") { + namedColor = "blue"; + cur_item->setUnderline(true); + } else if ( tagName == "IMG") { + namedColor = "magenta"; + cur_item->setUnderline(true); + + } else if ( tagName == "DIV" ) { + namedColor = "#ff0044"; + } else if ( tagName == "SPAN" ) { + namedColor = "#ff4400"; + } else if ( tagName == "P" ) { + namedColor = "#ff0066"; + + } else if ( tagName == "DL" || tagName == "OL"|| tagName == "UL" || tagName == "TABLE" ) { + namedColor = "#880088"; + } else if ( tagName == "LI" ) { + namedColor = "#884488"; + } else if ( tagName == "TBODY" ){ + namedColor = "#888888"; + } else if ( tagName == "TR" ) { + namedColor = "#882288"; + } else if ( tagName == "TD" ) { + namedColor = "#886688"; + + } else if ((tagName == "H1")||(tagName == "H2")||(tagName == "H3") || + (tagName == "H4")||(tagName == "H5")||(tagName == "H6")) { + namedColor = "#008800"; + } else if (tagName == "HR" ) { + namedColor = "#228822"; + + } else if ( tagName == "FRAME" || tagName == "IFRAME" ) { + namedColor = "#ff22ff"; + } else if ( tagName == "FRAMESET" ) { + namedColor = "#dd22dd"; + + } else if ( tagName == "APPLET" || tagName == "OBJECT" ) { + namedColor = "#bb22bb"; + + } else if ( tagName == "BASEFONT" || tagName == "FONT" ) { + namedColor = "#097200"; + + } else if ( tagName == "B" || tagName == "STRONG" ) { + cur_item->setBold(true); + } else if ( tagName == "I" || tagName == "EM" ) { + cur_item->setItalic(true); + } else if ( tagName == "U") { + cur_item->setUnderline(true); + } + + cur_item->setColor(namedColor); +} + +void DOMTreeView::slotItemClicked(QListViewItem *cur_item) +{ + DOMListViewItem *cur = static_cast<DOMListViewItem *>(cur_item); + if (!cur) return; + + DOM::Node handle = cur->node(); + if (!handle.isNull()) { + part->setActiveNode(handle); + } +} + +void DOMTreeView::slotFindClicked() +{ + if (m_findDialog == 0) { + m_findDialog = new KEdFind(this); + connect(m_findDialog, SIGNAL(search()), this, SLOT(slotSearch())); + } + m_findDialog->show(); +} + +void DOMTreeView::slotRefreshNode(const DOM::Node &pNode) +{ + DOMListViewItem *cur = static_cast<DOMListViewItem *>(m_itemdict[pNode.handle()]); + if (!cur) return; + + addElement(pNode, cur, false); +} + +void DOMTreeView::slotPrepareMove() +{ + DOMListViewItem *item = static_cast<DOMListViewItem *>(m_listView->currentItem()); + + if (!item) + current_node = DOM::Node(); + else + current_node = item->node(); +} + +void DOMTreeView::slotMovedItems(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &/*afterFirst*/, QPtrList<QListViewItem> &afterNow) +{ + MultiCommand *cmd = new MultiCommand(i18n("Move Nodes")); + _refreshed = false; + + QPtrList<QListViewItem>::Iterator it = items.begin(); + QPtrList<QListViewItem>::Iterator anit = afterNow.begin(); + for (; it != items.end(); ++it, ++anit) { + DOMListViewItem *item = static_cast<DOMListViewItem *>(*it); + DOMListViewItem *anitem = static_cast<DOMListViewItem *>(*anit); + DOM::Node parent = static_cast<DOMListViewItem *>(item->parent())->node(); + Q_ASSERT(!parent.isNull()); + +// kdDebug(90180) << " afternow " << anitem << " node " << (anitem ? anitem->node().nodeName().string() : QString()) << "=" << (anitem ? anitem->node().nodeValue().string() : QString()) << endl; + + cmd->addCommand(new MoveNodeCommand(item->node(), parent, + anitem ? anitem->node().nextSibling() : parent.firstChild()) + ); + } + + mainWindow()->executeAndAddCommand(cmd); + + // refresh *anyways*, otherwise consistency is disturbed + if (!_refreshed) refresh(); + + slotShowNode(current_node); +} + +void DOMTreeView::slotSearch() +{ + assert(m_findDialog); + const QString& searchText = m_findDialog->getText(); + bool caseSensitive = m_findDialog->case_sensitive(); + + searchRecursive(static_cast<DOMListViewItem*>(m_rootListView->firstChild()), + searchText, caseSensitive); + + m_findDialog->hide(); +} + +void DOMTreeView::searchRecursive(DOMListViewItem* cur_item, const QString& searchText, + bool caseSensitive) +{ + const QString text(cur_item->text(0)); + if (text.contains(searchText, caseSensitive) > 0) { + cur_item->setUnderline(true); + cur_item->setItalic(true); + m_listView->setCurrentItem(cur_item); + m_listView->ensureItemVisible(cur_item); + } else { + cur_item->setOpen(false); + } + + DOMListViewItem* child = static_cast<DOMListViewItem *>(cur_item->firstChild()); + while( child ) { + searchRecursive(child, searchText, caseSensitive); + child = static_cast<DOMListViewItem *>(child->nextSibling()); + } +} + +#if 0 +void DOMTreeView::slotSaveClicked() +{ + //kdDebug(90180) << "void KfingerCSSWidget::slotSaveAs()" << endl; + KURL url = KFileDialog::getSaveFileName( part->url().url(), "*.html", + this, i18n("Save DOM Tree as HTML") ); + if (!(url.isEmpty()) && url.isValid()) { + QFile file(url.path()); + + if (file.exists()) { + const QString title = i18n( "File Exists" ); + const QString text = i18n( "Do you really want to overwrite: \n%1?" ).arg(url.url()); + if (KMessageBox::Continue != KMessageBox::warningContinueCancel(this, text, title, i18n("Overwrite") ) ) { + return; + } + } + + if (file.open(IO_WriteOnly) ) { + kdDebug(90180) << "Opened File: " << url.url() << endl; + m_textStream = new QTextStream(&file); //(stdOut) + saveTreeAsHTML(part->document()); + file.close(); + kdDebug(90180) << "File closed " << endl; + delete m_textStream; + } else { + const QString title = i18n( "Unable to Open File" ); + const QString text = i18n( "Unable to open \n %1 \n for writing" ).arg(url.path()); + KMessageBox::sorry( this, text, title ); + } + } else { + const QString title = i18n( "Invalid URL" ); + const QString text = i18n( "This URL \n %1 \n is not valid." ).arg(url.url()); + KMessageBox::sorry( this, text, title ); + } +} + +void DOMTreeView::saveTreeAsHTML(const DOM::Node &pNode) +{ + assert(m_textStream); + + // Add a doctype + + (*m_textStream) <<"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" << endl; + if(pNode.ownerDocument().isNull()) { + saveRecursive(pNode, 0); + } else { + saveRecursive(pNode.ownerDocument(), 0); + } +} + +void DOMTreeView::saveRecursive(const DOM::Node &pNode, int indent) +{ + const QString nodeName(pNode.nodeName().string()); + QString text; + QString strIndent; + strIndent.fill(' ', indent); + const DOM::Element element = static_cast<const DOM::Element>(pNode); + + text = strIndent; + + if ( !element.isNull() ) { + if (nodeName.at(0)=='-') { + /* Don't save khtml internal tags '-konq..' + * Approximating it with <DIV> + */ + text += "<DIV> <!-- -KONG_BLOCK -->"; + } else { + text += "<" + nodeName; + + QString attributes; + DOM::Attr attr; + const DOM::NamedNodeMap attrs = element.attributes(); + unsigned long lmap = attrs.length(); + for( uint j=0; j<lmap; j++ ) { + attr = static_cast<DOM::Attr>(attrs.item(j)); + attributes += " " + attr.name().string() + "=\"" + attr.value().string() + "\""; + } + if (!(attributes.isEmpty())){ + text += " "; + } + + text += attributes.simplifyWhiteSpace(); + + if(element.firstChild().isNull()) { + text += "/>"; + } else { + text += ">"; + } + } + } else { + text = strIndent + pNode.nodeValue().string(); + } + + kdDebug(90180) << text << endl; + if (!(text.isEmpty())) { + (*m_textStream) << text << endl; + } + + DOM::Node child = pNode.firstChild(); + while(!child.isNull()) { + saveRecursive(child, indent+2); + child = child.nextSibling(); + } + + if (!(element.isNull()) && (!(element.firstChild().isNull()))) { + if (nodeName.at(0)=='-') { + text = strIndent + "</DIV> <!-- -KONG_BLOCK -->"; + } else { + text = strIndent + "</" + pNode.nodeName().string() + ">"; + } + kdDebug(90180) << text << endl; + (*m_textStream) << text << endl; + } +} +#endif + +void DOMTreeView::updateIncrDecreaseButton() +{ +#if 0 + m_decreaseButton->setEnabled((m_expansionDepth > 0)); + m_increaseButton->setEnabled((m_expansionDepth < m_maxDepth)); +#endif +} + +void DOMTreeView::refresh() +{ + if (!part) return; + scroll_ofs_x = m_listView->contentsX(); + scroll_ofs_y = m_listView->contentsY(); + + m_listView->setUpdatesEnabled(false); + slotShowTree(part->document()); + + QTimer::singleShot(0, this, SLOT(slotRestoreScrollOffset())); + _refreshed = true; +} + +void DOMTreeView::increaseExpansionDepth() +{ + if (!part) return; + if (m_expansionDepth < m_maxDepth) { + ++m_expansionDepth; + adjustDepth(); + updateIncrDecreaseButton(); + } else { + QApplication::beep(); + } +} + +void DOMTreeView::decreaseExpansionDepth() +{ + if (!part) return; + if (m_expansionDepth > 0) { + --m_expansionDepth; + adjustDepth(); + updateIncrDecreaseButton(); + } else { + QApplication::beep(); + } +} + +void DOMTreeView::adjustDepth() +{ + // get current item in a hypersmart way + DOMListViewItem *cur_node_item = m_itemdict[infoNode.handle()]; + if (!cur_node_item) + cur_node_item = static_cast<DOMListViewItem *>(m_listView->currentItem()); + + adjustDepthRecursively(m_rootListView->firstChild(), 0); + + // make current item visible again if possible + if (cur_node_item) + m_listView->ensureVisible(0, cur_node_item->itemPos()); + +} + +void DOMTreeView::adjustDepthRecursively(QListViewItem *cur_item, uint currDepth) +{ + if (!(cur_item == 0)) { + while( cur_item ) { + cur_item->setOpen( (m_expansionDepth > currDepth) ); + adjustDepthRecursively(cur_item->firstChild(), currDepth+1); + cur_item = cur_item->nextSibling(); + } + } +} + +void DOMTreeView::setMessage(const QString &msg) +{ + messageLine->setText(msg); + messageLinePane->show(); +} + +void DOMTreeView::hideMessageLine() +{ + messageLinePane->hide(); +} + +void DOMTreeView::moveToParent() +{ + // This is a hypersmart algorithm. + // If infoNode is defined, go to the parent of infoNode, otherwise, go + // to the parent of the tree view's current item. + // Hope this isn't too smart. + + DOM::Node cur = infoNode; + if (cur.isNull()) cur = static_cast<DOMListViewItem *>(m_listView->currentItem())->node(); + + if (cur.isNull()) return; + + cur = cur.parentNode(); + activateNode(cur); +} + +void DOMTreeView::showDOMTreeContextMenu(QListViewItem */*lvi*/, const QPoint &pos, int /*col*/) +{ + QPopupMenu *ctx = mainWindow()->domTreeViewContextMenu(); + Q_ASSERT(ctx); + ctx->popup(pos); +} + +void DOMTreeView::slotPureToggled(bool b) +{ + m_bPure = b; + refresh(); +} + +void DOMTreeView::slotShowAttributesToggled(bool b) +{ + m_bShowAttributes = b; + refresh(); +} + +void DOMTreeView::slotHighlightHTMLToggled(bool b) +{ + m_bHighlightHTML = b; + refresh(); +} + +void DOMTreeView::deleteNodes() +{ +// kdDebug(90180) << k_funcinfo << endl; + + DOM::Node last; + MultiCommand *cmd = new MultiCommand(i18n("Delete Nodes")); + QListViewItemIterator it(m_listView, QListViewItemIterator::Selected); + for (; *it; ++it) { + DOMListViewItem *item = static_cast<DOMListViewItem *>(*it); +// kdDebug(90180) << " item->node " << item->node().nodeName().string() << " clos " << item->isClosing() << endl; + if (item->isClosing()) continue; + + // don't regard node more than once + if (item->node() == last) continue; + + // check for selected parent + bool has_selected_parent = false; + for (QListViewItem *p = item->parent(); p; p = p->parent()) { + if (p->isSelected()) { has_selected_parent = true; break; } + } + if (has_selected_parent) continue; + +// kdDebug(90180) << " item->node " << item->node().nodeName().string() << ": schedule for removal" << endl; + // remove this node if it isn't already recursively removed by its parent + cmd->addCommand(new RemoveNodeCommand(item->node(), item->node().parentNode(), item->node().nextSibling())); + last = item->node(); + } + mainWindow()->executeAndAddCommand(cmd); +} + +void DOMTreeView::disconnectFromTornDownPart() +{ + if (!part) return; + + m_listView->clear(); + initializeOptionsFromNode(DOM::Node()); + + // remove all references to nodes + infoNode = DOM::Node(); // ### have this handled by dedicated info node panel method + current_node = DOM::Node(); + active_node_rule = DOM::CSSRule(); + stylesheet = DOM::CSSStyleSheet(); +} + +void DOMTreeView::connectToPart() +{ + if (part) { + connect(part, SIGNAL(nodeActivated(const DOM::Node &)), this, + SLOT(activateNode(const DOM::Node &))); + connect(part, SIGNAL(completed()), this, SLOT(refresh())); + + // insert a style rule to indicate activated nodes + try { +kdDebug(90180) << "(1) part.document: " << part->document().handle() << endl; + stylesheet = part->document().implementation().createCSSStyleSheet("-domtreeviewer-style", "screen"); +kdDebug(90180) << "(2)" << endl; + stylesheet.insertRule(":focus { outline: medium #f00 solid }", 0); + // ### for testing only +// stylesheet.insertRule("body { background: #f0f !important }", 1); +kdDebug(90180) << "(3)" << endl; + active_node_rule = stylesheet.cssRules().item(0); +kdDebug(90180) << "(4)" << endl; + part->document().addStyleSheet(stylesheet); +kdDebug(90180) << "(5)" << endl; + } catch (DOM::CSSException &ex) { + kdDebug(90180) << "CSS Exception " << ex.code << endl; + } catch (DOM::DOMException &ex) { + kdDebug(90180) << "DOM Exception " << ex.code << endl; + } + } + + slotShowTree(part ? (DOM::Node)part->document() : DOM::Node()); + updateIncrDecreaseButton(); +} + +void DOMTreeView::disconnectFromActivePart() +{ + if (!part) return; + + // remove style sheet + try { + part->document().removeStyleSheet(stylesheet); + } catch (DOM::CSSException &ex) { + kdDebug(90180) << "CSS Exception " << ex.code << endl; + } catch (DOM::DOMException &ex) { + kdDebug(90180) << "DOM Exception " << ex.code << endl; + } + +} + +void DOMTreeView::slotSetHtmlPartDelayed() +{ + connectToPart(); + emit htmlPartChanged(part); +} + +void DOMTreeView::slotRestoreScrollOffset() +{ + m_listView->setUpdatesEnabled(true); + m_listView->setContentsPos(scroll_ofs_x, scroll_ofs_y); +} + +void DOMTreeView::slotAddElementDlg() +{ + DOMListViewItem *item = static_cast<DOMListViewItem *>(m_listView->currentItem()); + if (!item) return; + + QString qname; + QString namespc; + SignalReceiver addBefore; + + { + ElementEditDialog dlg(this, "ElementEditDialog", true); + connect(dlg.insBeforeBtn, SIGNAL(clicked()), &addBefore, SLOT(slot())); + + // ### activate when namespaces are supported + dlg.elemNamespace->setEnabled(false); + + if (dlg.exec() != QDialog::Accepted) return; + + qname = dlg.elemName->text(); + namespc = dlg.elemNamespace->currentText(); + } + + DOM::Node curNode = item->node(); + + try { + DOM::Node parent = addBefore() ? curNode.parentNode() : curNode; + DOM::Node after = addBefore() ? curNode : 0; + + // ### take namespace into account + DOM::Node newNode = curNode.ownerDocument().createElement(qname); + + ManipulationCommand *cmd = new InsertNodeCommand(newNode, parent, after); + mainWindow()->executeAndAddCommand(cmd); + + if (cmd->isValid()) activateNode(newNode); + + } catch (DOM::DOMException &ex) { + mainWindow()->addMessage(ex.code, domErrorMessage(ex.code)); + } +} + +void DOMTreeView::slotAddTextDlg() +{ + DOMListViewItem *item = static_cast<DOMListViewItem *>(m_listView->currentItem()); + if (!item) return; + + QString text; + SignalReceiver addBefore; + + { + TextEditDialog dlg(this, "TextEditDialog", true); + connect(dlg.insBeforeBtn, SIGNAL(clicked()), &addBefore, SLOT(slot())); + + if (dlg.exec() != QDialog::Accepted) return; + + text = dlg.textPane->text(); + } + + DOM::Node curNode = item->node(); + + try { + DOM::Node parent = addBefore() ? curNode.parentNode() : curNode; + DOM::Node after = addBefore() ? curNode : 0; + + DOM::Node newNode = curNode.ownerDocument().createTextNode(text); + + ManipulationCommand *cmd = new InsertNodeCommand(newNode, parent, after); + mainWindow()->executeAndAddCommand(cmd); + + if (cmd->isValid()) activateNode(newNode); + + } catch (DOM::DOMException &ex) { + mainWindow()->addMessage(ex.code, domErrorMessage(ex.code)); + } +} + +// == DOM Node info panel ============================================= + +static QString *clickToAdd; + +/** + * List view item for attribute list. + */ +class AttributeListItem : public QListViewItem +{ + typedef QListViewItem super; + + bool _new; + +public: + AttributeListItem(QListView *parent, QListViewItem *prev) + : super(parent, prev), _new(true) + { + } + + AttributeListItem(const QString &attrName, const QString &attrValue, + QListView *parent, QListViewItem *prev) + : super(parent, prev), _new(false) + { + setText(0, attrName); + setText(1, attrValue); + } + + bool isNew() const { return _new; } + void setNew(bool s) { _new = s; } + + virtual int compare(QListViewItem *item, int column, bool ascend) const + { + return _new ? 1 : super::compare(item, column, ascend); + } + +protected: + virtual void paintCell( QPainter *p, const QColorGroup &cg, + int column, int width, int alignment ) + { + bool updates_enabled = listView()->isUpdatesEnabled(); + listView()->setUpdatesEnabled(false); + + QColor c = cg.text(); + bool text_changed = false; + QString oldText; + + if (_new) { + c = QApplication::palette().color( QPalette::Disabled, QColorGroup::Text ); + + if (!clickToAdd) clickToAdd = new QString(i18n("<Click to add>")); + oldText = text(column); + text_changed = true; + if (column == 0) setText(0, *clickToAdd); else setText(1, QString()); + } + + QColorGroup _cg( cg ); + _cg.setColor( QColorGroup::Text, c ); + super::paintCell( p, _cg, column, width, alignment ); + + if (text_changed) setText(column, oldText); + listView()->setUpdatesEnabled(updates_enabled); + } + +}; + +void DOMTreeView::initDOMNodeInfo() +{ + connect(m_listView, SIGNAL(clicked(QListViewItem *)), + SLOT(initializeOptionsFromListItem(QListViewItem *))); + + connect(nodeAttributes, SIGNAL(itemRenamed(QListViewItem *, const QString &, int)), + SLOT(slotItemRenamed(QListViewItem *, const QString &, int))); + connect(nodeAttributes, SIGNAL(executed(QListViewItem *, const QPoint &, int)), + SLOT(slotEditAttribute(QListViewItem *, const QPoint &, int))); + connect(nodeAttributes, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)), + SLOT(showInfoPanelContextMenu(QListViewItem *, const QPoint &, int))); + + connect(applyContent, SIGNAL(clicked()), SLOT(slotApplyContent())); + + ManipulationCommand::connect(SIGNAL(nodeChanged(const DOM::Node &)), this, SLOT(initializeOptionsFromNode(const DOM::Node &))); + + nodeAttributes->setRenameable(0, true); + nodeAttributes->setRenameable(1, true); + + nodeInfoStack->raiseWidget(EmptyPanel); + + installEventFilter(nodeAttributes); +} + +void DOMTreeView::initializeOptionsFromNode(const DOM::Node &node) +{ + infoNode = node; + + nodeName->clear(); + nodeType->clear(); + nodeNamespace->clear(); + nodeValue->clear(); + + if (node.isNull()) { + nodeInfoStack->raiseWidget(EmptyPanel); + return; + } + + nodeName->setText(node.nodeName().string()); + nodeType->setText(QString::number(node.nodeType())); + nodeNamespace->setText(node.namespaceURI().string()); +// nodeValue->setText(node.value().string()); + + DOM::Element element = node; + if (!element.isNull()) { + initializeOptionsFromElement(element); + return; + } + + DOM::CharacterData cdata = node; + if (!cdata.isNull()) { + initializeOptionsFromCData(cdata); + return; + } + + // Fallback + nodeInfoStack->raiseWidget(EmptyPanel); +} + +void DOMTreeView::initializeOptionsFromListItem(QListViewItem *item) +{ + const DOMListViewItem *cur_item = static_cast<const DOMListViewItem *>(item); + +// kdDebug(90180) << "cur_item: " << cur_item << endl; + initializeOptionsFromNode(cur_item ? cur_item->node() : DOM::Node()); +} + +void DOMTreeView::initializeOptionsFromElement(const DOM::Element &element) +{ + QListViewItem *last = 0; + nodeAttributes->clear(); + + DOM::NamedNodeMap attrs = element.attributes(); + unsigned long lmap = attrs.length(); + for (unsigned int j = 0; j < lmap; j++) { + DOM::Attr attr = attrs.item(j); +// kdDebug(90180) << attr.name().string() << "=" << attr.value().string() << endl; + QListViewItem *item = new AttributeListItem(attr.name().string(), + attr.value().string(), nodeAttributes, last); + last = item; + } + + // append new item + last = new AttributeListItem(nodeAttributes, last); + + nodeInfoStack->raiseWidget(ElementPanel); +} + +void DOMTreeView::initializeOptionsFromCData(const DOM::CharacterData &cdata) +{ + contentEditor->setText(cdata.data().string()); + + DOM::Text text = cdata; + contentEditor->setEnabled(!text.isNull()); + + nodeInfoStack->raiseWidget(CDataPanel); +} + +void DOMTreeView::slotItemRenamed(QListViewItem *lvi, const QString &str, int col) +{ + AttributeListItem *item = static_cast<AttributeListItem *>(lvi); + + DOM::Element element = infoNode; + if (element.isNull()) return; // Should never happen + + switch (col) { + case 0: { + ManipulationCommand *cmd; +// kdDebug(90180) << k_funcinfo << "col 0: " << element.nodeName() << " isNew: " << item->isNew() << endl; + if (item->isNew()) { + cmd = new AddAttributeCommand(element, str, item->text(1)); + item->setNew(false); + } else + cmd = new RenameAttributeCommand(element, item->text(0), str); + + mainWindow()->executeAndAddCommand(cmd); + break; + } + case 1: { + if (item->isNew()) { lvi->setText(1, QString()); break; } + + ChangeAttributeValueCommand *cmd = new ChangeAttributeValueCommand( + element, item->text(0), str); + mainWindow()->executeAndAddCommand(cmd); + break; + } + } +} + +void DOMTreeView::slotEditAttribute(QListViewItem *lvi, const QPoint &, int col) +{ + if (!lvi) return; + + QString attrName = lvi->text(0); + QString attrValue = lvi->text(1); + int res = 0; + + { + AttributeEditDialog dlg(this, "AttributeEditDialog", true); + dlg.attrName->setText(attrName); + dlg.attrValue->setText(attrValue); + + if (col == 0) { + dlg.attrName->setFocus(); + dlg.attrName->selectAll(); + } else { + dlg.attrValue->setFocus(); + dlg.attrValue->selectAll(); + } + + res = dlg.exec(); + + attrName = dlg.attrName->text(); + attrValue = dlg.attrValue->text(); + } + +// kdDebug(90180) << "name=" << attrName << " value=" << attrValue << endl; + + if (res == QDialog::Accepted) do { + if (attrName.isEmpty()) break; + + if (lvi->text(0) != attrName) { + // hack: set value to assign attribute/value pair in one go + lvi->setText(1, attrValue); + + slotItemRenamed(lvi, attrName, 0); + // Reget, item may have been changed + lvi = nodeAttributes->findItem(attrName, 0); + } + + if (lvi && lvi->text(1) != attrValue) + slotItemRenamed(lvi, attrValue, 1); + + } while(false) /*end if*/; +} + + +void DOMTreeView::slotApplyContent() +{ + DOM::CharacterData cdata = infoNode; + + if (cdata.isNull()) return; + + ManipulationCommand *cmd = new ChangeCDataCommand(cdata, contentEditor->text()); + mainWindow()->executeAndAddCommand(cmd); +} + +void DOMTreeView::showInfoPanelContextMenu(QListViewItem */*lvi*/, const QPoint &pos, int /*col*/) +{ + QPopupMenu *ctx = mainWindow()->infoPanelAttrContextMenu(); + Q_ASSERT(ctx); + ctx->popup(pos); +} + +void DOMTreeView::copyAttributes() +{ + // TODO implement me +} + +void DOMTreeView::cutAttributes() +{ + // TODO implement me +} + +void DOMTreeView::pasteAttributes() +{ + // TODO implement me +} + +void DOMTreeView::deleteAttributes() +{ + MultiCommand *cmd = new MultiCommand(i18n("Delete Attributes")); + QListViewItemIterator it(nodeAttributes, QListViewItemIterator::Selected); + for (; *it; ++it) { + AttributeListItem *item = static_cast<AttributeListItem *>(*it); + if (item->isNew()) continue; + + cmd->addCommand(new RemoveAttributeCommand(infoNode, item->text(0))); + } + mainWindow()->executeAndAddCommand(cmd); +} + +#include "domtreeview.moc" diff --git a/konq-plugins/domtreeviewer/domtreeview.h b/konq-plugins/domtreeviewer/domtreeview.h new file mode 100644 index 0000000..0e9977d --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreeview.h @@ -0,0 +1,203 @@ +/*************************************************************************** + domtreeview.h + ------------------- + + copyright : (C) 2001 - The Kafka Team/Andreas Schlapbach + (C) 2005 - Leo Savernik + email : kde-kafka@master.kde.org + schlpbch@iam.unibe.ch + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +/* $Id$ */ + +#ifndef DOMTREEVIEW_H +#define DOMTREEVIEW_H + +#include <qptrdict.h> +#include <qptrlist.h> +#include <dom/css_stylesheet.h> +#include <dom/css_rule.h> +#include <dom/dom_node.h> + +#include "domtreeviewbase.h" + +namespace DOM { + class Element; + class CharacterData; +} + +class DOMListViewItem; +class DOMTreeWindow; + +class QListViewItem; + +class KPushButton; +class KEdFind; +class KHTMLPart; + +class DOMTreeView : public DOMTreeViewBase +{ + Q_OBJECT + + public: + DOMTreeView(QWidget *parent, const char* name, bool allowSaving = true); + ~DOMTreeView(); + + KHTMLPart *htmlPart() const { return part; } + void setHtmlPart(KHTMLPart *); + + /** returns the main window */ + DOMTreeWindow *mainWindow() const; + + protected: + /* + void saveTreeAsHTML(const DOM::Node &pNode); + */ + virtual bool eventFilter(QObject *o, QEvent *e); + + signals: + /** emitted when the part has been changed. */ + void htmlPartChanged(KHTMLPart *part); + + public slots: + void refresh(); + void increaseExpansionDepth(); + void decreaseExpansionDepth(); + void setMessage(const QString &msg); + void hideMessageLine(); + + void moveToParent(); + + void activateNode(const DOM::Node &node); + void deleteNodes(); + + /** + * Takes measures to disconnect this instance from the current html + * part as long as it is active. + */ + void disconnectFromActivePart(); + + /** + * Takes measures to disconnect this instance from the current html + * part when it is being torn down. + */ + void disconnectFromTornDownPart(); + + /** + * Connects to the current html part. + */ + void connectToPart(); + + void slotFindClicked(); + void slotAddElementDlg(); + void slotAddTextDlg(); + + protected slots: + void slotShowNode(const DOM::Node &pNode); + void slotShowTree(const DOM::Node &pNode); + void slotItemClicked(QListViewItem *); + void slotRefreshNode(const DOM::Node &pNode); + void slotMovedItems(QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &afterFirst, QPtrList<QListViewItem> &afterNow); + void slotPrepareMove(); + void slotSearch(); + + // void slotSaveClicked(); + + void slotPureToggled(bool); + void slotShowAttributesToggled(bool); + void slotHighlightHTMLToggled(bool); + + void showDOMTreeContextMenu(QListViewItem *, const QPoint &, int); + + void slotSetHtmlPartDelayed(); + void slotRestoreScrollOffset(); + + private: + QPtrDict<DOMListViewItem> m_itemdict; + DOM::Node m_document; + + uint m_expansionDepth, m_maxDepth; + bool m_bPure, m_bShowAttributes, m_bHighlightHTML; + + private: + void showRecursive(const DOM::Node &pNode, const DOM::Node &node, + uint depth); + + // void saveRecursive(const DOM::Node &node, int ident); + + void searchRecursive(DOMListViewItem *cur_item, + const QString &searchText, + bool caseSensitive); + + void adjustDepth(); + void adjustDepthRecursively(QListViewItem *cur_item, uint currDepth); + void highlightHTML(DOMListViewItem *cur_item, + const QString &nodeName); + + void addElement(const DOM::Node &node, DOMListViewItem *cur_item, + bool isLast); + void updateIncrDecreaseButton(); + + private: + KEdFind* m_findDialog; + + KHTMLPart *part; + QTextStream* m_textStream; + + const KListView* m_rootListView; + + KPushButton* m_saveButton; + QObject *focused_child; + DOM::Node current_node; + DOM::CSSStyleSheet stylesheet; + DOM::CSSRule active_node_rule; + + bool _refreshed; + int scroll_ofs_x, scroll_ofs_y; + + + // == DOM Node Info panel ====================================== + + public: + // Keep in sync with the widget stack children + enum InfoPanel { ElementPanel, CDataPanel, EmptyPanel }; + + public slots: + void initializeOptionsFromNode(const DOM::Node &); + void initializeOptionsFromListItem(QListViewItem *); + + void copyAttributes(); + void cutAttributes(); + void pasteAttributes(); + void deleteAttributes(); + + private: + void initDOMNodeInfo(); + + void initializeOptionsFromElement(const DOM::Element &); + void initializeOptionsFromCData(const DOM::CharacterData &); + + private slots: + void slotItemRenamed(QListViewItem *, const QString &str, int col); + void slotEditAttribute(QListViewItem *, const QPoint &, int col); + void slotApplyContent(); + + void showInfoPanelContextMenu(QListViewItem *, const QPoint &, int); + + private: + DOM::Node infoNode; // node these infos apply to + + // == End DOM Node Info panel ================================== + +}; + +#endif diff --git a/konq-plugins/domtreeviewer/domtreeviewbase.ui b/konq-plugins/domtreeviewer/domtreeviewbase.ui new file mode 100644 index 0000000..984e435 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreeviewbase.ui @@ -0,0 +1,525 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>DOMTreeViewBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>DOMTreeViewBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>508</height> + </rect> + </property> + <property name="minimumSize"> + <size> + <width>600</width> + <height>380</height> + </size> + </property> + <property name="caption"> + <string>DOM Tree Viewer</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QFrame"> + <property name="name"> + <cstring>messageLinePane</cstring> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>170</red> + <green>0</green> + <blue>127</blue> + </color> + </property> + <property name="frameShape"> + <enum>Panel</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>1</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="KLineEdit"> + <property name="name"> + <cstring>messageLine</cstring> + </property> + <property name="paletteForegroundColor"> + <color> + <red>255</red> + <green>255</green> + <blue>127</blue> + </color> + </property> + <property name="paletteBackgroundColor"> + <color> + <red>170</red> + <green>0</green> + <blue>127</blue> + </color> + </property> + <property name="font"> + <font> + <bold>1</bold> + </font> + </property> + <property name="frame"> + <bool>false</bool> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>messageListBtn</cstring> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>&List</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>10</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KPushButton"> + <property name="name"> + <cstring>messageHideBtn</cstring> + </property> + <property name="font"> + <font> + <pointsize>10</pointsize> + </font> + </property> + <property name="text"> + <string>H&ide</string> + </property> + <property name="flat"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KListView"> + <column> + <property name="text"> + <string>DOM Tree</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>m_listView</cstring> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="selectionMode" stdset="0"> + <enum>Extended</enum> + </property> + <property name="rootIsDecorated"> + <bool>true</bool> + </property> + <property name="dragEnabled"> + <bool>true</bool> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="minimumSize"> + <size> + <width>300</width> + <height>400</height> + </size> + </property> + <property name="title"> + <string>DOM Node Info</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel1_2_3</cstring> + </property> + <property name="text"> + <string>Node &value:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nodeValue</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string>Node &type:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nodeType</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Namespace &URI:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nodeNamespace</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Node &name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>nodeName</cstring> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1"> + <property name="name"> + <cstring>nodeNamespace</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="KLineEdit" row="3" column="1"> + <property name="name"> + <cstring>nodeValue</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="KLineEdit" row="2" column="1"> + <property name="name"> + <cstring>nodeType</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + <widget class="KLineEdit" row="0" column="1"> + <property name="name"> + <cstring>nodeName</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="lineWidth"> + <number>0</number> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + </widget> + </grid> + </widget> + <widget class="QWidgetStack"> + <property name="name"> + <cstring>nodeInfoStack</cstring> + </property> + <widget class="QWidget"> + <property name="name"> + <cstring>ElementInfo</cstring> + </property> + <attribute name="id"> + <number>0</number> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="KListView"> + <column> + <property name="text"> + <string>Name</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Value</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>nodeAttributes</cstring> + </property> + <property name="focusPolicy"> + <enum>StrongFocus</enum> + </property> + <property name="selectionMode" stdset="0"> + <enum>Extended</enum> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="showSortIndicator"> + <bool>true</bool> + </property> + <property name="itemsMovable"> + <bool>false</bool> + </property> + </widget> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>CharacterData</cstring> + </property> + <attribute name="id"> + <number>1</number> + </attribute> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="KTextEdit"> + <property name="name"> + <cstring>contentEditor</cstring> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="tabChangesFocus"> + <bool>false</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>applyContent</cstring> + </property> + <property name="text"> + <string>Appl&y</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QWidget"> + <property name="name"> + <cstring>Empty</cstring> + </property> + <attribute name="id"> + <number>2</number> + </attribute> + </widget> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>DOM Tree Options</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_pureCheckBox</cstring> + </property> + <property name="text"> + <string>&Pure</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_showAttributesCheckBox</cstring> + </property> + <property name="text"> + <string>Show &attributes</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_highlightHTMLCheckBox</cstring> + </property> + <property name="text"> + <string>Highlight &HTML</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>m_listView</tabstop> + <tabstop>nodeName</tabstop> + <tabstop>nodeNamespace</tabstop> + <tabstop>nodeType</tabstop> + <tabstop>nodeValue</tabstop> + <tabstop>contentEditor</tabstop> + <tabstop>applyContent</tabstop> + <tabstop>m_pureCheckBox</tabstop> + <tabstop>m_showAttributesCheckBox</tabstop> + <tabstop>m_highlightHTMLCheckBox</tabstop> + <tabstop>nodeAttributes</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>klistview.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>klistview.h</includehint> + <includehint>ktextedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/domtreeviewer/domtreeviewerui.rc b/konq-plugins/domtreeviewer/domtreeviewerui.rc new file mode 100644 index 0000000..7249b63 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreeviewerui.rc @@ -0,0 +1,45 @@ +<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd"> +<kpartgui name="domtreeviewer" version="1"> +<MenuBar> + <Menu name="file"><text>&File</text> + </Menu> + <Menu name="edit"><text>&Edit</text> + </Menu> + <Menu name="view"><text>&View</text> + <WeakSeparator /> + <Action name="tree_inc_level" /> + <Action name="tree_dec_level" /> + <Separator /> + <Action name="show_msg_dlg" /> + </Menu> + <Menu name="go"><text>&Go</text> + <Action name="tree_up" /> + </Menu> +</MenuBar> +<ToolBar name="mainToolBar"><text>Main Toolbar</text> +</ToolBar> +<ToolBar name="treeToolBar"><text>Tree Toolbar</text> + <Action name="tree_up" /> + <Action name="view_redisplay" /> + <Separator /> + <Action name="tree_dec_level" /> + <Action name="tree_inc_level" /> +</ToolBar> +<Menu name="infopanelattr_context"> + <Action name="edit_cut" /> + <Action name="edit_copy" /> + <Action name="edit_paste" /> + <Separator /> + <Action name="attr_delete" /> +</Menu> +<Menu name="domtree_context"> + <Action name="tree_add_element" /> + <Action name="tree_add_text" /> + <Separator /> + <Action name="edit_cut" /> + <Action name="edit_copy" /> + <Action name="edit_paste" /> + <Separator /> + <Action name="tree_delete" /> +</Menu> +</kpartgui> diff --git a/konq-plugins/domtreeviewer/domtreewindow.cpp b/konq-plugins/domtreeviewer/domtreewindow.cpp new file mode 100644 index 0000000..f8b9ed5 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreewindow.cpp @@ -0,0 +1,379 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "domtreewindow.h" +#include "domtreeview.h" +#include "domtreecommands.h" +#include "messagedialog.h" +#include "plugin_domtreeviewer.h" + +#include <kaccel.h> +#include <kapplication.h> +#include <kcommand.h> +#include <kconfig.h> +#include <kdeversion.h> +#include <kglobal.h> +#include <khtml_part.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kmenubar.h> +#include <kstatusbar.h> +#include <kstandarddirs.h> +#include <ktextedit.h> +#include <kurl.h> +#include <kurldrag.h> +#include <kurlrequesterdlg.h> + +#include <kparts/partmanager.h> +#include <kparts/browserextension.h> + +#include <kedittoolbar.h> + +#include <kstdaccel.h> +#include <kaction.h> +#include <kstdaction.h> + +#include <qdatetime.h> +#include <qtimer.h> + +using domtreeviewer::ManipulationCommand; + +DOMTreeWindow::DOMTreeWindow(PluginDomtreeviewer *plugin) + : KMainWindow( 0, "DOMTreeWindow" ), + m_plugin(plugin), m_view(new DOMTreeView(this, "DOMTreeView", false)) +{ + part_manager = 0; + + // set configuration object + _config = new KConfig("domtreeviewerrc"); + + // accept dnd + setAcceptDrops(true); + + // tell the KMainWindow that this is indeed the main widget + setCentralWidget(m_view); + + // message window dialog + msgdlg = new MessageDialog(0, "MessageDialog"); + msgdlg->messagePane->setPaletteBackgroundColor(palette().active().base()); +// msgdlg->show(); + + // then, setup our actions + setupActions(); + + // Add typical actions and save size/toolbars/statusbar + setupGUI(ToolBar | Keys | StatusBar | Save | Create, + locate( "data", "domtreeviewer/domtreeviewerui.rc", instance())); + + // allow the view to change the statusbar and caption +#if 0 + connect(m_view, SIGNAL(signalChangeStatusbar(const QString&)), + this, SLOT(changeStatusbar(const QString&))); + connect(m_view, SIGNAL(signalChangeCaption(const QString&)), + this, SLOT(changeCaption(const QString&))); +#endif + connect(view(), SIGNAL(htmlPartChanged(KHTMLPart *)), + SLOT(slotHtmlPartChanged(KHTMLPart *))); + + ManipulationCommand::connect(SIGNAL(error(int, const QString &)), + this, SLOT(addMessage(int, const QString &))); + + infopanel_ctx = createInfoPanelAttrContextMenu(); + domtree_ctx = createDOMTreeViewContextMenu(); + +} + +DOMTreeWindow::~DOMTreeWindow() +{ + kdDebug(90180) << k_funcinfo << this << endl; + delete m_commandHistory; + delete msgdlg; + delete _config; +} + +void DOMTreeWindow::executeAndAddCommand(ManipulationCommand *cmd) +{ + cmd->execute(); + if (cmd->isValid()) { + m_commandHistory->addCommand(cmd, false); + view()->hideMessageLine(); + } +} + +void DOMTreeWindow::setupActions() +{ + KStdAction::close(this, SLOT(close()), actionCollection()); + + KStdAction::cut(this, SLOT(slotCut()), actionCollection())->setEnabled(false); + KStdAction::copy(this, SLOT(slotCopy()), actionCollection())->setEnabled(false); + KStdAction::paste(this, SLOT(slotPaste()), actionCollection())->setEnabled(false); + + m_commandHistory = new KCommandHistory(actionCollection()); + + KStdAction::find(this, SLOT(slotFind()), actionCollection()); + + KStdAction::redisplay(m_view, SLOT(refresh()), actionCollection()); + + // toggle manipulation dialog + KAction *showMsgDlg = new KAction(i18n("Show Message Log"), + CTRL+Key_E, actionCollection(), "show_msg_dlg"); + connect(showMsgDlg, SIGNAL(activated()), SLOT(showMessageLog())); + +// KAction *custom = new KAction(i18n("Cus&tom Menuitem"), 0, +// this, SLOT(optionsPreferences()), +// actionCollection(), "custom_action"); + + // actions for the dom tree list view toolbar + KStdAction::up(view(), SLOT(moveToParent()), actionCollection(), "tree_up"); + KAction *tree_inc_level = new KAction(i18n("Expand"), + "1rightarrow", CTRL+Key_Greater, view(), + SLOT(increaseExpansionDepth()), actionCollection(), + "tree_inc_level"); + tree_inc_level->setToolTip(i18n("Increase expansion level")); + KAction *tree_dec_level = new KAction(i18n("Collapse"), + "1leftarrow", CTRL+Key_Less, view(), + SLOT(decreaseExpansionDepth()), actionCollection(), + "tree_dec_level"); + tree_dec_level->setToolTip(i18n("Decrease expansion level")); + + // actions for the dom tree list view context menu + + del_tree = new KAction(i18n("&Delete"), "editdelete", + Key_Delete, view(), SLOT(deleteNodes()), + actionCollection(), "tree_delete"); + del_tree->setToolTip(i18n("Delete nodes")); + /*KAction *new_elem = */new KAction(i18n("New &Element ..."), + "bookmark", KShortcut(), view(), + SLOT(slotAddElementDlg()), actionCollection(), + "tree_add_element"); + /*KAction *new_text = */new KAction(i18n("New &Text Node ..."), + "text", KShortcut(), view(), SLOT(slotAddTextDlg()), + actionCollection(), "tree_add_text"); + + // actions for the info panel attribute list context menu + del_attr = new KAction(i18n("&Delete"), "editdelete", + Key_Delete, view(), SLOT(deleteAttributes()), + actionCollection(), "attr_delete"); + del_attr->setToolTip(i18n("Delete attributes")); + +} + +QPopupMenu *DOMTreeWindow::createInfoPanelAttrContextMenu() +{ + QWidget *w = factory()->container("infopanelattr_context", this); + Q_ASSERT(w); + return static_cast<QPopupMenu *>(w); +} + +QPopupMenu *DOMTreeWindow::createDOMTreeViewContextMenu() +{ + QWidget *w = factory()->container("domtree_context", this); + Q_ASSERT(w); + return static_cast<QPopupMenu *>(w); +} + +void DOMTreeWindow::saveProperties(KConfig *config) +{ + // the 'config' object points to the session managed + // config file. anything you write here will be available + // later when this app is restored + +#if 0 + if (!m_view->currentURL().isNull()) { +#if KDE_IS_VERSION(3,1,3) + config->writePathEntry("lastURL", m_view->currentURL()); +#else + config->writeEntry("lastURL", m_view->currentURL()); +#endif + } +#endif +} + +void DOMTreeWindow::readProperties(KConfig *config) +{ + // the 'config' object points to the session managed + // config file. this function is automatically called whenever + // the app is being restored. read in here whatever you wrote + // in 'saveProperties' + +#if 0 + QString url = config->readPathEntry("lastURL"); + + if (!url.isEmpty()) + m_view->openURL(KURL::fromPathOrURL(url)); +#endif +} + +void DOMTreeWindow::dragEnterEvent(QDragEnterEvent *event) +{ + // accept uri drops only + event->accept(KURLDrag::canDecode(event)); +} + +void DOMTreeWindow::dropEvent(QDropEvent *event) +{ + // this is a very simplistic implementation of a drop event. we + // will only accept a dropped URL. the Qt dnd code can do *much* + // much more, so please read the docs there + KURL::List urls; + + // see if we can decode a URI.. if not, just ignore it + if (KURLDrag::decode(event, urls) && !urls.isEmpty()) + { + // okay, we have a URI.. process it + const KURL &url = urls.first(); +#if 0 + // load in the file + load(url); +#endif + } +} + +void DOMTreeWindow::addMessage(int msg_id, const QString &msg) +{ + QDateTime t(QDateTime::currentDateTime()); + QString fullmsg = t.toString(); + fullmsg += ":"; + + if (msg_id != 0) + fullmsg += " (" + QString::number(msg_id) + ") "; + fullmsg += msg; + + if (msgdlg) msgdlg->addMessage(fullmsg); + view()->setMessage(msg); + kdWarning() << fullmsg << endl; +} +void DOMTreeWindow::slotCut() +{ + // TODO implement +} + +void DOMTreeWindow::slotCopy() +{ + // TODO implement +} + +void DOMTreeWindow::slotPaste() +{ + // TODO implement +} + +void DOMTreeWindow::slotFind() +{ + view()->slotFindClicked(); +} + +void DOMTreeWindow::showMessageLog() +{ + msgdlg->show(); + msgdlg->raise(); + msgdlg->setActiveWindow(); +} + +void DOMTreeWindow::optionsConfigureToolbars() +{ + // use the standard toolbar editor + saveMainWindowSettings( config(), autoSaveGroup() ); + KEditToolbar dlg(actionCollection()); + connect(&dlg, SIGNAL(newToolbarConfig()), this, SLOT(newToolbarConfig())); + dlg.exec(); +} + +void DOMTreeWindow::newToolbarConfig() +{ + // this slot is called when user clicks "Ok" or "Apply" in the toolbar editor. + // recreate our GUI, and re-apply the settings (e.g. "text under icons", etc.) + createGUI(locate( "data", "domtreeviewer/domtreeviewerui.rc", instance())); + applyMainWindowSettings( config(), autoSaveGroup() ); +} + +void DOMTreeWindow::optionsPreferences() +{ +#if 0 + // popup some sort of preference dialog, here + DOMTreeWindowPreferences dlg; + if (dlg.exec()) + { + // redo your settings + } +#endif +} + +void DOMTreeWindow::changeStatusbar(const QString& text) +{ + // display the text on the statusbar + statusBar()->message(text); +} + +void DOMTreeWindow::changeCaption(const QString& text) +{ + // display the text on the caption + setCaption(text); +} + +void DOMTreeWindow::slotHtmlPartChanged(KHTMLPart *p) +{ + kdDebug(90180) << k_funcinfo << p << endl; + + if (p) { + // set up manager connections + if ( part_manager ) + disconnect(part_manager); + + part_manager = p->manager(); + + connect(part_manager, SIGNAL(activePartChanged(KParts::Part *)), + SLOT(slotActivePartChanged(KParts::Part *))); + connect(part_manager, SIGNAL(partRemoved(KParts::Part *)), + SLOT(slotPartRemoved(KParts::Part *))); + + // set up browser extension connections + connect(p, SIGNAL(docCreated()), SLOT(slotClosePart())); + } +} + +void DOMTreeWindow::slotActivePartChanged(KParts::Part *p) +{ + kdDebug(90180) << k_funcinfo << p << endl; + Q_ASSERT(p != view()->htmlPart()); + + m_commandHistory->clear(); + view()->disconnectFromTornDownPart(); + view()->setHtmlPart(::qt_cast<KHTMLPart *>(p)); +} + +void DOMTreeWindow::slotPartRemoved(KParts::Part *p) +{ + kdDebug(90180) << k_funcinfo << p << endl; + if (p != view()->htmlPart()) return; + + m_commandHistory->clear(); + view()->disconnectFromTornDownPart(); + view()->setHtmlPart(0); +} + +void DOMTreeWindow::slotClosePart() +{ + kdDebug(90180) << k_funcinfo << endl; + view()->disconnectFromTornDownPart(); + view()->connectToPart(); +} + +#include "domtreewindow.moc" diff --git a/konq-plugins/domtreeviewer/domtreewindow.h b/konq-plugins/domtreeviewer/domtreewindow.h new file mode 100644 index 0000000..f942798 --- /dev/null +++ b/konq-plugins/domtreeviewer/domtreewindow.h @@ -0,0 +1,194 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef domtreewindow_H +#define domtreewindow_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <kmainwindow.h> + +#include <qguardedptr.h> + +namespace domtreeviewer { + class ManipulationCommand; +} + +namespace KParts { + class Part; + class PartManager; +} + +class DOMTreeView; +class PluginDomtreeviewer; + +class KAction; +class KConfig; +class KPrinter; +class KURL; +class KCommandHistory; +class KHTMLPart; +class MessageDialog; + +class QPopupMenu; + +/** + * This class serves as the main window for DOM Tree Viewer. It handles the + * menus, toolbars, and status bars. + * + * @short Main window class + * @author Leo Savernik + */ +class DOMTreeWindow : public KMainWindow +{ + Q_OBJECT +public: + /** + * Default Constructor + */ + DOMTreeWindow(PluginDomtreeviewer *plugin); + + /** + * Default Destructor + */ + virtual ~DOMTreeWindow(); + + /** + * returns the dom tree view + */ + DOMTreeView *view() const { return m_view; } + + /** + * returns the command history + */ + KCommandHistory *commandHistory() const { return m_commandHistory; } + + /** + * creates and returns the context menu for the list info panel + */ + QPopupMenu *createInfoPanelAttrContextMenu(); + + /** + * returns the context menu for the list info panel + */ + QPopupMenu *infoPanelAttrContextMenu() { return infopanel_ctx; } + + /** + * creates and returns the context menu for the DOM tree view + */ + QPopupMenu *createDOMTreeViewContextMenu(); + + /** + * returns the context menu for the DOM tree view + */ + QPopupMenu *domTreeViewContextMenu() { return domtree_ctx; } + + /** + * Executes the given command and adds it to the history. + * + * If the command could not be executed, it will not be added. + */ + void executeAndAddCommand(domtreeviewer::ManipulationCommand *); + + /** + * Returns the config object for this plugin. + */ + KConfig *config() const { return _config; } + + /** returns the attribute delete action */ + KAction *deleteAttributeAction() const { return del_attr; } + /** returns the node delete action */ + KAction *deleteNodeAction() const { return del_tree; } + +public slots: + /** + * Adds a log message + * @param id message id + * @param msg message text + */ + void addMessage(int id, const QString &msg); + + /** + * Displays the message log window. + */ + void showMessageLog(); + +protected: + /** + * Overridden virtuals for Qt drag 'n drop (XDND) + */ + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); +protected: + /** + * This function is called when it is time for the app to save its + * properties for session management purposes. + */ + void saveProperties(KConfig *); + + /** + * This function is called when this app is restored. The KConfig + * object points to the session management config file that was saved + * with @ref saveProperties + */ + void readProperties(KConfig *); + + +private slots: + void slotCut(); + void slotCopy(); + void slotPaste(); + //void slotUndo(); + //void slotRedo(); + void slotFind(); + void optionsConfigureToolbars(); + void optionsPreferences(); + void newToolbarConfig(); + + void changeStatusbar(const QString& text); + void changeCaption(const QString& text); + + void slotHtmlPartChanged(KHTMLPart *); + void slotActivePartChanged(KParts::Part *); + void slotPartRemoved(KParts::Part *); + void slotClosePart(); + +private: + void setupAccel(); + void setupActions(); + +private: + PluginDomtreeviewer *m_plugin; + DOMTreeView *m_view; + MessageDialog *msgdlg; + + KCommandHistory *m_commandHistory; + QPopupMenu *infopanel_ctx; + QPopupMenu *domtree_ctx; + KConfig *_config; + + KAction *del_tree, *del_attr; + + QGuardedPtr<KParts::PartManager> part_manager; +}; + +#endif // domtreewindow_H diff --git a/konq-plugins/domtreeviewer/elementeditdialog.ui b/konq-plugins/domtreeviewer/elementeditdialog.ui new file mode 100644 index 0000000..8705250 --- /dev/null +++ b/konq-plugins/domtreeviewer/elementeditdialog.ui @@ -0,0 +1,201 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ElementEditDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>ElementEditDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>469</width> + <height>113</height> + </rect> + </property> + <property name="caption"> + <string>Edit Element</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Element &name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>elemName</cstring> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>elemName</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Element &namespace:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>elemNamespace</cstring> + </property> + </widget> + <widget class="KComboBox"> + <property name="name"> + <cstring>elemNamespace</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="editable"> + <bool>true</bool> + </property> + <property name="autoCompletion"> + <bool>true</bool> + </property> + <property name="duplicatesEnabled"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>insChildBtn</cstring> + </property> + <property name="text"> + <string>&Append as Child</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>insBeforeBtn</cstring> + </property> + <property name="text"> + <string>Insert &Before Current</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>60</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>cancelBtn</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>insChildBtn</sender> + <signal>clicked()</signal> + <receiver>ElementEditDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>cancelBtn</sender> + <signal>clicked()</signal> + <receiver>ElementEditDialog</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>elemName</sender> + <signal>returnPressed()</signal> + <receiver>ElementEditDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>insBeforeBtn</sender> + <signal>clicked()</signal> + <receiver>ElementEditDialog</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/domtreeviewer/messagedialog.ui b/konq-plugins/domtreeviewer/messagedialog.ui new file mode 100644 index 0000000..3ef4a75 --- /dev/null +++ b/konq-plugins/domtreeviewer/messagedialog.ui @@ -0,0 +1,117 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MessageDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>MessageDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>511</width> + <height>282</height> + </rect> + </property> + <property name="caption"> + <string>Message Log</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KTextEdit"> + <property name="name"> + <cstring>messagePane</cstring> + </property> + <property name="textFormat"> + <enum>LogText</enum> + </property> + <property name="wordWrap"> + <enum>FixedColumnWidth</enum> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="undoRedoEnabled"> + <bool>false</bool> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnClear</cstring> + </property> + <property name="text"> + <string>C&lear</string> + </property> + <property name="autoDefault"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>300</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnClose</cstring> + </property> + <property name="text"> + <string>&Close</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>btnClose</sender> + <signal>clicked()</signal> + <receiver>MessageDialog</receiver> + <slot>close()</slot> + </connection> + <connection> + <sender>btnClear</sender> + <signal>clicked()</signal> + <receiver>messagePane</receiver> + <slot>clear()</slot> + </connection> +</connections> +<includes> + <include location="local" impldecl="in implementation">messagedialog.ui.h</include> +</includes> +<slots> + <slot specifier="non virtual">addMessage( const QString & msg )</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ktextedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/domtreeviewer/messagedialog.ui.h b/konq-plugins/domtreeviewer/messagedialog.ui.h new file mode 100644 index 0000000..dcb6609 --- /dev/null +++ b/konq-plugins/domtreeviewer/messagedialog.ui.h @@ -0,0 +1,20 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + +#include <kdebug.h> + +#include <qdatetime.h> + +void MessageDialog::addMessage( const QString &msg ) +{ + messagePane->append(msg); +} diff --git a/konq-plugins/domtreeviewer/plugin_domtreeviewer.cpp b/konq-plugins/domtreeviewer/plugin_domtreeviewer.cpp new file mode 100644 index 0000000..3555a84 --- /dev/null +++ b/konq-plugins/domtreeviewer/plugin_domtreeviewer.cpp @@ -0,0 +1,56 @@ +#include "plugin_domtreeviewer.h" +#include "domtreewindow.h" +#include "domtreeview.h" + +#include <kaction.h> +#include <kinstance.h> +#include <klibloader.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kgenericfactory.h> + +#include <khtml_part.h> + +typedef KGenericFactory<PluginDomtreeviewer> DomtreeviewerFactory; +K_EXPORT_COMPONENT_FACTORY( libdomtreeviewerplugin, DomtreeviewerFactory( "domtreeviewer" ) ) + +PluginDomtreeviewer::PluginDomtreeviewer( QObject* parent, const char* name, + const QStringList & ) + : Plugin( parent, name ), m_dialog( 0 ) +{ + (void) new KAction( i18n("Show &DOM Tree"), + "domtreeviewer", 0, + this, SLOT(slotShowDOMTree()), + actionCollection(), "viewdomtree" ); +} + +PluginDomtreeviewer::~PluginDomtreeviewer() +{ + kdDebug(90180) << k_funcinfo << endl; + delete m_dialog; +} + +void PluginDomtreeviewer::slotShowDOMTree() +{ + if ( m_dialog ) + { + delete m_dialog; + Q_ASSERT((DOMTreeWindow *)m_dialog == (DOMTreeWindow *)0); + } + if (KHTMLPart *part = ::qt_cast<KHTMLPart *>(parent())) + { + m_dialog = new DOMTreeWindow(this); + connect( m_dialog, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + m_dialog->view()->setHtmlPart(part); + m_dialog->show(); + } +} + +void PluginDomtreeviewer::slotDestroyed() +{ + kdDebug(90180) << k_funcinfo << endl; + m_dialog = 0; +} + +#include <plugin_domtreeviewer.moc> diff --git a/konq-plugins/domtreeviewer/plugin_domtreeviewer.desktop b/konq-plugins/domtreeviewer/plugin_domtreeviewer.desktop new file mode 100644 index 0000000..780947a --- /dev/null +++ b/konq-plugins/domtreeviewer/plugin_domtreeviewer.desktop @@ -0,0 +1,128 @@ +[Desktop Entry] +X-KDE-Library=domtreeviewer +X-KDE-PluginInfo-Author=The Kafka Team, Andreas Schlapbach +X-KDE-PluginInfo-Email=kde-kafka@master.kde.org, schlpbch@iam.unibe.ch +X-KDE-PluginInfo-Name=domtreeviewer +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=DOM Tree Viewer +Name[bg]=Преглед на DOM +Name[br]=Gweler ar wwezenn DOM +Name[bs]=Preglednik DOM stabla +Name[ca]=Visor de l'arbre DOM +Name[cs]=Prohlížeč DOM stromu +Name[da]=DOM-trævisning +Name[de]=DOM-Baumansicht +Name[el]=Προβολέας δέντρου DOM +Name[eo]=DOM-a arba rigardilo +Name[es]=Visor del árbol DOM +Name[et]=DOM puu vaataja +Name[eu]=DOM arbolaren ikustailea +Name[fa]=مشاهدهگر درخت DOM +Name[fi]=DOM-puun näyttäjä +Name[fr]=Visualiseur d'arborescence DOM +Name[fy]=DOM tree-werjefteprogramma +Name[ga]=Amharcán Crainn DOM +Name[gl]=Visor da Árbore DOM +Name[he]=מציג עץ DOM +Name[hi]=डॉम ट्री प्रदर्शक +Name[hr]=DOM preglednik stabla +Name[hu]=A DOM-fastruktúra megjelenítése +Name[is]=DOM Trjáasýn +Name[it]=Visualizzatore DOM tree +Name[ja]=DOM ツリービューア +Name[ka]=DOM ხის მხილველი +Name[kk]=DOM бұтақтары +Name[km]=កម្មវិធីមើលមែកធាង DOM +Name[lt]=DOM medžio žiūryklė +Name[mk]=Прегледувач на DOM-стебло +Name[ms]=Pelihat Pepohon DOM +Name[nb]=DOM-trevisning +Name[nds]=DOM-Boom-Kieker +Name[ne]=डीओएम ट्री दर्शक +Name[nl]=DOM tree-weergaveprogramma +Name[nn]=DOM-trevising +Name[pa]=DOM ਟਰੀ ਦਰਸ਼ਕ +Name[pl]=Przeglądarka drzewa DOM +Name[pt]=Visualizador da Árvore DOM +Name[pt_BR]=Visão em Árvore DOM +Name[ru]=Дерево DOM +Name[sk]=Prehliadač pre strom DOM +Name[sl]=Drevesni pogled DOM +Name[sr]=Приказивач DOM стабла +Name[sr@Latn]=Prikazivač DOM stabla +Name[sv]=DOM-trädvisaren +Name[ta]=DOM மரக் காட்சியமைப்பு +Name[tg]=Дарахти DOM +Name[tr]=DOM Ağaç Görünümü +Name[uk]=Переглядач дерева DOM +Name[vi]=Bộ xem cây DOM +Name[zh_CN]=DOM 树形视图查看器 +Name[zh_TW]=DOM 樹檢視器 +Comment=DOM tree viewer +Comment[af]=Dom boom aansig +Comment[ar]=مستعرض شجرة DOM +Comment[az]=DOM ağac nümayişçisi +Comment[bg]=Преглед структурата на DOM +Comment[br]=Gweler gwezenn DOM +Comment[bs]=Preglednik DOM stabla +Comment[ca]=Visor de l'arbre DOM +Comment[cs]=Prohlížeč DOM stromu +Comment[cy]=Gwelydd coeden DOM +Comment[da]=DOM-trævisning +Comment[de]=DOM-Baumansicht +Comment[el]=Προβολέας δέντρου DOM +Comment[eo]=DOM-a arba rigardilo +Comment[es]=Visor del árbol DOM +Comment[et]=DOM puu vaataja +Comment[eu]=DOM arbolaren ikustailea +Comment[fa]=مشاهدهگر درخت DOM +Comment[fi]=DOM-puun näyttäjä +Comment[fr]=Afficheur d'arborescence de modèle orienté document +Comment[fy]=DOM tree-werjefteprogramma +Comment[ga]=Amharcán crainn DOM +Comment[gl]=Visor da árbore DOM +Comment[he]=מציג עץ DOM +Comment[hi]=डॉम ट्री प्रदर्शक +Comment[hr]=DOM preglednik stabla +Comment[hu]=DOM-nézegető +Comment[is]=DOM Trjáasýn +Comment[it]=Visualizzatore DOM tree +Comment[ja]=DOM ツリービューア +Comment[ka]=DOM ხის მხილველი +Comment[kk]=DOM бұтақтарын қарау құралы +Comment[km]=កម្មវិធីមើលមែកធាង DOM +Comment[lt]=DOM medžio žiūriklis +Comment[mk]=Прегледувач на DOM-стебло +Comment[ms]=Pelihat pepohon DOM +Comment[nb]=DOM tre-fremviser +Comment[nds]=DOM-Boom-Kieker +Comment[ne]=डीओएम ट्री हेराई +Comment[nl]=DOM tree-weergaveprogramma +Comment[nn]=Framvising av DOM-tre +Comment[pa]=DOM ਲੜੀ ਦਰਸ਼ਕ +Comment[pl]=Widok drzewa DOM +Comment[pt]=Visualizador da árvore DOM +Comment[pt_BR]=Visão em Árvore DOM +Comment[ro]=Afişează o structură arborescentă DOM a documentelor XML/HTML +Comment[ru]=Модуль для просмотра дерева DOM +Comment[sk]=DOM prehliadač +Comment[sl]=Pregledovalnik dreves DOM +Comment[sr]=Приказивач DOM стабла +Comment[sr@Latn]=Prikazivač DOM stabla +Comment[sv]=DOM-trädvisare +Comment[ta]=DOM மரக்காட்சியாளர் +Comment[tg]=Модул барои аз назар гузаронидани дарахти DOM +Comment[tr]=DOM ağaç görünümü +Comment[uk]=Переглядач дерева DOM +Comment[vi]=Bộ xem cây DOM +Comment[xh]=Umbukeli womthi weDOM +Comment[zh_CN]=DOM 树形视图查看器 +Comment[zh_TW]=DOM 樹檢視器 +Icon=domtreeviewer +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/domtreeviewer/index.html diff --git a/konq-plugins/domtreeviewer/plugin_domtreeviewer.h b/konq-plugins/domtreeviewer/plugin_domtreeviewer.h new file mode 100644 index 0000000..ba380a9 --- /dev/null +++ b/konq-plugins/domtreeviewer/plugin_domtreeviewer.h @@ -0,0 +1,27 @@ +/* $Id$ */ + +#ifndef __plugin_domtreeviewer_h +#define __plugin_domtreeviewer_h + +#include <kparts/plugin.h> +// #include <klibloader.h> + +class DOMTreeWindow; +class KURL; + +class PluginDomtreeviewer : public KParts::Plugin +{ + Q_OBJECT +public: + PluginDomtreeviewer( QObject* parent, const char* name, + const QStringList & ); + virtual ~PluginDomtreeviewer(); + +public slots: + void slotShowDOMTree(); + void slotDestroyed(); +private: + DOMTreeWindow* m_dialog; +}; + +#endif diff --git a/konq-plugins/domtreeviewer/plugin_domtreeviewer.rc b/konq-plugins/domtreeviewer/plugin_domtreeviewer.rc new file mode 100644 index 0000000..2216b99 --- /dev/null +++ b/konq-plugins/domtreeviewer/plugin_domtreeviewer.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="domtreeviewer" library="libdomtreeviewerplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="viewdomtree"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="viewdomtree"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/domtreeviewer/signalreceiver.cpp b/konq-plugins/domtreeviewer/signalreceiver.cpp new file mode 100644 index 0000000..f928036 --- /dev/null +++ b/konq-plugins/domtreeviewer/signalreceiver.cpp @@ -0,0 +1,37 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "signalreceiver.h" + +SignalReceiver::SignalReceiver(QObject *parent, const char *name) +: QObject(parent, name), rcvd(false) +{ +} + +SignalReceiver::~SignalReceiver() +{ +} + +void SignalReceiver::slot() +{ + rcvd = true; +} + +#include "signalreceiver.moc" diff --git a/konq-plugins/domtreeviewer/signalreceiver.h b/konq-plugins/domtreeviewer/signalreceiver.h new file mode 100644 index 0000000..8c0f5d9 --- /dev/null +++ b/konq-plugins/domtreeviewer/signalreceiver.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + * + * Copyright (C) 2005 Leo Savernik <l.savernik@aon.at> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef SIGNALCATCHER_H +#define SIGNALCATCHER_H + +#include <qobject.h> + +/** + * \brief Class for receiving signals. + * + * This is a convenience class for receiving signals when it is not worth + * the effort, or overly complicated to introduce a dedicated slot. + * + * Use as follows: + * \code + * SignalReceiver sr; + * sr.connect(some_obj, SIGNAL(someSignal()), SLOT(slot())); + * <do something with some_obj> ... + * if (sr.receivedSignal()) { // yes, signal was received + * } + * \endcode + * + * It is not possible to discriminate between different signals. Hence, + * use different signal receiver instances for different signals. + * @autor Leo Savernik + */ +class SignalReceiver : public QObject +{ + Q_OBJECT + +public: + SignalReceiver(QObject *parent = 0, const char *name = 0); + virtual ~SignalReceiver(); + + /** returns true if any signal has been received */ + bool signalReceived() const { return rcvd; } + + /** returns true if any signal has been received */ + bool operator ()() const { return rcvd; } + +public slots: + /** connect a signal to this slot to receive it */ + void slot(); + +private: + bool rcvd; +}; + +#endif // SIGNALCATCHER_H diff --git a/konq-plugins/domtreeviewer/texteditdialog.ui b/konq-plugins/domtreeviewer/texteditdialog.ui new file mode 100644 index 0000000..96980e2 --- /dev/null +++ b/konq-plugins/domtreeviewer/texteditdialog.ui @@ -0,0 +1,149 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>TextEditDialog</class> +<widget class="QDialog"> + <property name="name"> + <cstring>TextEditDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>469</width> + <height>211</height> + </rect> + </property> + <property name="caption"> + <string>Edit Text</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Edit &text for text node:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>textPane</cstring> + </property> + </widget> + <widget class="KTextEdit"> + <property name="name"> + <cstring>textPane</cstring> + </property> + <property name="acceptDrops"> + <bool>true</bool> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="tabChangesFocus"> + <bool>true</bool> + </property> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>HLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>insChildBtn</cstring> + </property> + <property name="text"> + <string>&Append as Child</string> + </property> + <property name="default"> + <bool>true</bool> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>insBeforeBtn</cstring> + </property> + <property name="text"> + <string>Insert &Before Current</string> + </property> + <property name="flat"> + <bool>false</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>60</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>cancelBtn</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>insChildBtn</sender> + <signal>clicked()</signal> + <receiver>TextEditDialog</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>cancelBtn</sender> + <signal>clicked()</signal> + <receiver>TextEditDialog</receiver> + <slot>reject()</slot> + </connection> + <connection> + <sender>insBeforeBtn</sender> + <signal>clicked()</signal> + <receiver>TextEditDialog</receiver> + <slot>accept()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ktextedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/fsview/Makefile.am b/konq-plugins/fsview/Makefile.am new file mode 100644 index 0000000..a400096 --- /dev/null +++ b/konq-plugins/fsview/Makefile.am @@ -0,0 +1,51 @@ +INCLUDES= $(all_includes) +METASOURCES = AUTO + +KDE_ICON = fsview + +EXTRA_DIST = main.cpp fsview.cpp fsview.h scan.cpp scan.h scantest.cpp \ + inode.h inode.cpp \ + fsview.desktop hi32-app-fsview.png + +#xdg_apps_DATA = fsview.desktop + +messages: rc.cpp + LIST=`find . -name \*.h -o -name \*.cpp`; \ + if test -n "$$LIST"; then \ + $(XGETTEXT) $$LIST -o $(podir)/fsview.pot; \ + fi + +# Used both by application and KPart + +noinst_LTLIBRARIES = libfsview.la +libfsview_la_SOURCES = treemap.cpp fsview.cpp scan.cpp inode.cpp + +# Application + +bin_PROGRAMS = fsview + +fsview_LDFLAGS = $(all_libraries) $(KDE_RPATH) +fsview_SOURCES = main.cpp +fsview_LDADD = libfsview.la $(LIB_KIO) $(LIB_KDECORE) $(LIB_QT) + +check_PROGRAMS = scantest + +scantest_LDFLAGS = $(all_libraries) $(KDE_RPATH) +scantest_SOURCES = scantest.cpp +scantest_LDADD = libfsview.la $(LIB_KIO) $(LIB_KDECORE) $(LIB_QT) + +# The KPart + +kde_module_LTLIBRARIES = libfsviewpart.la +libfsviewpart_la_SOURCES = fsview_part.cpp +libfsviewpart_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +libfsviewpart_la_LIBADD = libfsview.la $(LIB_KPARTS) $(LIB_KIO) -lkonq + +partdesktopdir = $(kde_servicesdir) +partdesktop_DATA = fsview_part.desktop + +rcdir = $(kde_datadir)/fsview +rc_DATA = fsview_part.rc + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = fsview.desktop diff --git a/konq-plugins/fsview/README b/konq-plugins/fsview/README new file mode 100644 index 0000000..faf1c44 --- /dev/null +++ b/konq-plugins/fsview/README @@ -0,0 +1,29 @@ +What's this? +============ + +Josef Weidendorfer +Josef.Weidendorfer@gmx.de + +FSView is a tool for showing disc utilization in a graphical form, much +like the UNIX command 'du'. The visualisation type choosen is a treemap. +Treemaps allow for showing metrics of objects in nested structures, like +sizes of files and directories on your hard disc, where the the size of +directories is defined to be the sum of the size of its children. +Each object is represented by a rectangle which area is proportional to +its metric. The metric must have the property that the sum of the +children's metric of some object is equal or smaller than the objects +metric. This holds true for the file/directory sizes in the use case of +FSView. + +It's provided both as a Konqueror KPart plugin for the mime type +inode/directory, and a standalone executable. + +This was meant as a small test application and usage tutorial for +the TreeMap widget developed within KCachegrind. As it's quite cool +and small, it is now provided as a Konqueror addon in KDE. + +For a full featured graphical 'du', see KDirStat. It's quite similar +to FSView, but allows for lot of cleanup actions. + +Happy space hunting, +Josef diff --git a/konq-plugins/fsview/fsview.cpp b/konq-plugins/fsview/fsview.cpp new file mode 100644 index 0000000..b0c82d8 --- /dev/null +++ b/konq-plugins/fsview/fsview.cpp @@ -0,0 +1,540 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialisaton of TreeMap classes. + */ + + +#include <qdir.h> +#include <qpopupmenu.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <kurl.h> + +#include <kio/global.h> + +#include "fsview.h" + + +// FSView + +QMap<QString, MetricEntry> FSView::_dirMetric; + +FSView::FSView(Inode* base, QWidget* parent, const char* name) + : TreeMapWidget(base, parent, name) +{ + setFieldType(0, i18n("Name")); + setFieldType(1, i18n("Size")); + setFieldType(2, i18n("File Count")); + setFieldType(3, i18n("Directory Count")); + setFieldType(4, i18n("Last Modified")); + setFieldType(5, i18n("Owner")); + setFieldType(6, i18n("Group")); + setFieldType(7, i18n("Mime Type")); + + // defaults + setVisibleWidth(4, true); + setSplitMode(TreeMapItem::Rows); + setFieldForced(0, true); // show directory names + setFieldForced(1, true); // show directory sizes + setSelectionMode(TreeMapWidget::Extended); + + _colorMode = Depth; + _pathDepth = 0; + _allowRefresh = true; + + _progressPhase = 0; + _chunkData1 = 0; + _chunkData2 = 0; + _chunkData3 = 0; + _chunkSize1 = 0; + _chunkSize2 = 0; + _chunkSize3 = 0; + _progressSize = 0; + _progress = 0; + _dirsFinished = 0; + _lastDir = 0; + + _config = new KConfig("fsviewrc"); + + // restore TreeMap visualization options of last execution + KConfigGroup tmconfig(_config, QCString("TreeMap")); + restoreOptions(&tmconfig); + QString str = tmconfig.readEntry("ColorMode"); + if (!str.isEmpty()) setColorMode(str); + + if (_dirMetric.count() == 0) { + // restore metric cache + KConfigGroup cconfig(_config, QCString("MetricCache")); + int ccount = cconfig.readNumEntry("Count", 0); + int i, f, d; + double s; + QString str; + for (i=1;i<=ccount;i++) { + str = QString("Dir%1").arg(i); + if (!cconfig.hasKey(str)) continue; + str = cconfig.readPathEntry(str); + s = cconfig.readDoubleNumEntry(QString("Size%1").arg(i), 0.0); + f = cconfig.readNumEntry(QString("Files%1").arg(i), 0); + d = cconfig.readNumEntry(QString("Dirs%1").arg(i), 0); + if (s==0.0 || f==0 || d==0) continue; + setDirMetric(str, s, f, d); + } + } + + _sm.setListener(this); +} + +FSView::~FSView() +{ + delete _config; +} + +void FSView::stop() +{ + _sm.stopScan(); +} + +void FSView::setPath(QString p) +{ + Inode* b = (Inode*)base(); + if (!b) return; + + //kdDebug(90100) << "FSView::setPath " << p << endl; + + // stop any previous updating + stop(); + + QFileInfo fi(p); + _path = fi.absFilePath(); + if (!fi.isDir()) { + _path = fi.dirPath(true); + } + _pathDepth = _path.contains('/'); + + KURL u; + u.setPath(_path); + if (!kapp->authorizeURLAction("list", KURL(), u)) + { + QString msg = KIO::buildErrorString(KIO::ERR_ACCESS_DENIED, u.prettyURL()); + KMessageBox::queuedMessageBox(this, KMessageBox::Sorry, msg); + } + + ScanDir* d = _sm.setTop(_path); + + b->setPeer(d); + + setCaption(QString("%1 - FSView").arg(_path)); + requestUpdate(b); +} + +KURL::List FSView::selectedUrls() +{ + TreeMapItemList s = selection(); + TreeMapItem* i; + KURL::List urls; + + for(i=s.first();i;i=s.next()) { + KURL u; + u.setPath( ((Inode*)i)->path() ); + urls.append(u); + } + return urls; +} + +bool FSView::getDirMetric(const QString& k, + double& s, unsigned int& f, unsigned int& d) +{ + QMap<QString, MetricEntry>::iterator it; + + it = _dirMetric.find(k); + if (it == _dirMetric.end()) return false; + + s = (*it).size; + f = (*it).fileCount; + d = (*it).dirCount; + + if (0) kdDebug(90100) << "getDirMetric " << k << endl; + if (0) kdDebug(90100) << " - got size " << s << ", files " << f << endl; + + return true; +} + +void FSView::setDirMetric(const QString& k, + double s, unsigned int f, unsigned int d) +{ + if (0) kdDebug(90100) << "setDirMetric '" << k << "': size " + << s << ", files " << f << ", dirs " << d << endl; + _dirMetric.insert(k, MetricEntry(s, f, d)); +} + +void FSView::requestUpdate(Inode* i) +{ + if (0) kdDebug(90100) << "FSView::requestUpdate(" << i->path() + << ")" << endl; + + ScanDir* peer = i->dirPeer(); + if (!peer) return; + + peer->clear(); + i->clear(); + + if (!_sm.scanRunning()) { + QTimer::singleShot(0, this, SLOT(doUpdate())); + QTimer::singleShot(100, this, SLOT(doRedraw())); + + /* start new progress chunk */ + _progressPhase = 1; + _chunkData1 += 3; + _chunkData2 = _chunkData1 + 1; + _chunkData3 = _chunkData1 + 2; + _chunkSize1 = 0; + _chunkSize2 = 0; + _chunkSize3 = 0; + peer->setData(_chunkData1); + + _progressSize = 0; + _progress = 0; + _dirsFinished = 0; + _lastDir = 0; + emit started(); + } + + _sm.startScan(peer); +} + +void FSView::scanFinished(ScanDir* d) +{ + /* if finished directory was from last progress chunk, increment */ + int data = d->data(); + switch(_progressPhase) { + case 1: + if (data == _chunkData1) _chunkSize1--; + break; + case 2: + if (data == _chunkData1) _progress++; + if (data == _chunkData2) _chunkSize2--; + break; + case 3: + if ((data == _chunkData1) || + (data == _chunkData2)) _progress++; + if (data == _chunkData3) _chunkSize3--; + break; + case 4: + if ((data == _chunkData1) || + (data == _chunkData2) || + (data == _chunkData3)) _progress++; + break; + default: + break; + } + + _lastDir = d; + _dirsFinished++; + + if (0) kdDebug(90100) << "FSFiew::scanFinished: " << d->path() + << ", Data " << data + << ", Progress " << _progress << "/" + << _progressSize << endl; +} + +void FSView::selected(TreeMapItem* i) +{ + setPath(((Inode*)i)->path()); +} + +void FSView::contextMenu(TreeMapItem* i, const QPoint& p) +{ + QPopupMenu popup; + + QPopupMenu* spopup = new QPopupMenu(); + QPopupMenu* dpopup = new QPopupMenu(); + QPopupMenu* apopup = new QPopupMenu(); + QPopupMenu* fpopup = new QPopupMenu(); + + // choosing from the selection menu will give a selectionChanged() signal + addSelectionItems(spopup, 901, i); + popup.insertItem(i18n("Go To"), spopup, 900); + + popup.insertItem(i18n("Go Up"), 2); + popup.insertSeparator(); + popup.insertItem(i18n("Stop Refresh"), 3); + popup.setItemEnabled(3, _sm.scanRunning()); + popup.insertItem(i18n("Refresh"), 5); + popup.setItemEnabled(5, !_sm.scanRunning()); + + if (i) popup.insertItem(i18n("Refresh '%1'").arg(i->text(0)), 4); + popup.insertSeparator(); + addDepthStopItems(dpopup, 1001, i); + popup.insertItem(i18n("Stop at Depth"), dpopup, 1000); + addAreaStopItems(apopup, 1101, i); + popup.insertItem(i18n("Stop at Area"), apopup, 1100); + addFieldStopItems(fpopup, 1201, i); + popup.insertItem(i18n("Stop at Name"), fpopup, 1200); + + popup.insertSeparator(); + + QPopupMenu* cpopup = new QPopupMenu(); + addColorItems(cpopup, 1401); + popup.insertItem(i18n("Color Mode"), cpopup, 1400); + QPopupMenu* vpopup = new QPopupMenu(); + addVisualizationItems(vpopup, 1301); + popup.insertItem(i18n("Visualization"), vpopup, 1300); + + _allowRefresh = false; + int r = popup.exec(mapToGlobal(p)); + _allowRefresh = true; + + if (r==1) + selected(i); + else if (r==2) { + Inode* i = (Inode*) base(); + if (i) setPath(i->path()+"/.."); + } + else if (r==3) + stop(); + else if (r==4) { + //((Inode*)i)->refresh(); + requestUpdate( (Inode*)i ); + } + else if (r==5) { + Inode* i = (Inode*) base(); + if (i) requestUpdate(i); + } +} + +void FSView::saveMetric(KConfigGroup* g) +{ + QMap<QString, MetricEntry>::iterator it; + int c = 1; + for (it=_dirMetric.begin();it!=_dirMetric.end();++it) { + g->writePathEntry(QString("Dir%1").arg(c), it.key()); + g->writeEntry(QString("Size%1").arg(c), (*it).size); + g->writeEntry(QString("Files%1").arg(c), (*it).fileCount); + g->writeEntry(QString("Dirs%1").arg(c), (*it).dirCount); + c++; + } + g->writeEntry("Count", c-1); +} + +void FSView::setColorMode(FSView::ColorMode cm) +{ + if (_colorMode == cm) return; + + _colorMode = cm; + redraw(); +} + +bool FSView::setColorMode(QString mode) +{ + if (mode == "None") setColorMode(None); + else if (mode == "Depth") setColorMode(Depth); + else if (mode == "Name") setColorMode(Name); + else if (mode == "Owner") setColorMode(Owner); + else if (mode == "Group") setColorMode(Group); + else if (mode == "Mime") setColorMode(Mime); + else return false; + + return true; +} + +QString FSView::colorModeString() const +{ + QString mode; + switch(_colorMode) { + case None: mode = "None"; break; + case Depth: mode = "Depth"; break; + case Name: mode = "Name"; break; + case Owner: mode = "Owner"; break; + case Group: mode = "Group"; break; + case Mime: mode = "Mime"; break; + default: mode = "Unknown"; break; + } + return mode; +} + +void FSView::addColorItems(QPopupMenu* popup, int id) +{ + _colorID = id; + popup->setCheckable(true); + + connect(popup, SIGNAL(activated(int)), + this, SLOT(colorActivated(int))); + + popup->insertItem(i18n("None"), id); + popup->insertItem(i18n("Depth"), id+1); + popup->insertItem(i18n("Name"), id+2); + popup->insertItem(i18n("Owner"), id+3); + popup->insertItem(i18n("Group"), id+4); + popup->insertItem(i18n("Mime Type"), id+5); + + switch(colorMode()) { + case None: popup->setItemChecked(id,true); break; + case Depth: popup->setItemChecked(id+1,true); break; + case Name: popup->setItemChecked(id+2,true); break; + case Owner: popup->setItemChecked(id+3,true); break; + case Group: popup->setItemChecked(id+4,true); break; + case Mime: popup->setItemChecked(id+5,true); break; + default: break; + } +} + +void FSView::colorActivated(int id) +{ + if (id == _colorID) setColorMode(None); + else if (id == _colorID+1) setColorMode(Depth); + else if (id == _colorID+2) setColorMode(Name); + else if (id == _colorID+3) setColorMode(Owner); + else if (id == _colorID+4) setColorMode(Group); + else if (id == _colorID+5) setColorMode(Mime); +} + +void FSView::saveFSOptions() +{ + KConfigGroup tmconfig(_config, QCString("TreeMap")); + saveOptions(&tmconfig); + tmconfig.writeEntry("ColorMode", colorModeString()); + + KConfigGroup gconfig(_config, QCString("General")); + gconfig.writeEntry("Path", _path); + + KConfigGroup cconfig(_config, QCString("MetricCache")); + saveMetric(&cconfig); +} + +void FSView::quit() +{ + saveFSOptions(); + KApplication::kApplication()->quit(); +} + +void FSView::doRedraw() +{ + // we update progress every 1/4 second, and redraw every second + static int redrawCounter = 0; + + bool redo = _sm.scanRunning(); + if (!redo) redrawCounter = 0; + + if ((_progress>0) && (_progressSize>0) && _lastDir) { + int percent = _progress * 100 / _progressSize; + if (0) kdDebug(90100) << "FSView::progress " + << _progress << "/" << _progressSize + << "= " << percent << "%, " + << _dirsFinished << " dirs read, in " + << _lastDir->path() << endl; + emit progress(percent, _dirsFinished, _lastDir->path()); + } + + + if (_allowRefresh && ((redrawCounter%4)==0)) { + if (0) kdDebug(90100) << "doRedraw " << _sm.scanLength() << endl; + redraw(); + } + else + redo = true; + + if (redo) { + QTimer::singleShot(500, this, SLOT(doRedraw())); + redrawCounter++; + } +} + + +void FSView::doUpdate() +{ + for(int i=0;i<5;i++) { + switch(_progressPhase) { + case 1: + _chunkSize1 += _sm.scan(_chunkData1); + if (_chunkSize1 > 100) { + _progressPhase = 2; + + /* Go to maximally 33% by scaling with 3 */ + _progressSize = 3 * _chunkSize1; + + if (1) kdDebug(90100) << "Phase 2: CSize " << _chunkSize1 << endl; + } + break; + + case 2: + /* progress phase 2 */ + _chunkSize2 += _sm.scan(_chunkData2); + /* switch to Phase 3 if we reach 80 % of Phase 2 */ + if (_progress * 3 > _progressSize * 8/10) { + _progressPhase = 3; + + /* Goal: Keep percentage equal from phase 2 to 3 */ + double percent = (double)_progress / _progressSize; + /* We scale by factor 2/3 aferwards */ + percent = percent * 3/2; + + int todo = _chunkSize2 + (_progressSize/3 - _progress); + _progressSize = (int) ((double)todo / (1.0 - percent)); + _progress = _progressSize - todo; + + /* Go to maximally 66% by scaling with 1.5 */ + _progressSize = _progressSize *3/2; + + if (1) kdDebug(90100) << "Phase 3: CSize " << _chunkSize2 + << ", Todo " << todo + << ", Progress " << _progress + << "/" << _progressSize << endl; + } + break; + + case 3: + /* progress phase 3 */ + _chunkSize3 += _sm.scan(_chunkData3); + /* switch to Phase 4 if we reach 80 % of Phase 3 */ + if (_progress * 3/2 > _progressSize * 8/10) { + _progressPhase = 4; + + /* Goal: Keep percentage equal from phase 2 to 3 */ + double percent = (double)_progress / _progressSize; + int todo = _chunkSize3 + (_progressSize*2/3 - _progress); + _progressSize = (int)((double)todo / (1.0 - percent) + .5); + _progress = _progressSize - todo; + + if (1) kdDebug(90100) << "Phase 4: CSize " << _chunkSize3 + << ", Todo " << todo + << ", Progress " << _progress + << "/" << _progressSize << endl; + } + + default: + _sm.scan(-1); + break; + } + } + + if (_sm.scanRunning()) + QTimer::singleShot(0, this, SLOT(doUpdate())); + else + emit completed(_dirsFinished); +} + +#include "fsview.moc" diff --git a/konq-plugins/fsview/fsview.desktop b/konq-plugins/fsview/fsview.desktop new file mode 100644 index 0000000..6f7f163 --- /dev/null +++ b/konq-plugins/fsview/fsview.desktop @@ -0,0 +1,120 @@ +# KDE Config File +[Desktop Entry] +Type=Application +Exec=fsview -caption "%c" %i %m %u +MimeType=inode/directory +Icon=fsview +DocPath=konq-plugins/fsview/index.html +Terminal=false +Name=File Size Viewer +Name[bg]=Преглед на файловия размер +Name[bs]=Preglednik veličine datoteka +Name[ca]=Visor de mides de fitxers +Name[cs]=Prohlížeč velikostí souborů +Name[da]=Filstørrelses fremviser +Name[de]=Dateigrößenbetrachter +Name[el]=Προβολέας μεγέθους αρχείων +Name[eo]=Dosiergrandeca rigardilo +Name[es]=Visor del tamaño del archivo +Name[et]=Failisuuruse näitaja +Name[eu]=Fitxategi neurrien ikustailea +Name[fa]=مشاهدهگر اندازۀ پرونده +Name[fi]=Tiedostokoon näyttäjä +Name[fr]=Afficheur de taille de fichiers +Name[fy]=werjefte ôfbyldingsgrutte +Name[gl]=Visor do Tamaño de Ficheiros +Name[he]=מציג גדלי קבצים +Name[hi]=फ़ाइल आकार प्रदर्शक +Name[hr]=Preglednik veličine datoteka +Name[hu]=Fájlméret-megtekintő +Name[is]=Skoða stærð skráa +Name[it]=Visualizzatore della dimensione dei file +Name[ja]=ファイルサイズビューア +Name[ka]=ფაილის ზომის მხილველი +Name[kk]=Файл көлемін қарау +Name[km]=កម្មវិធីមើលទំហំឯកសារ +Name[lt]=Bylų dydžio stebėjimo priemonė +Name[mk]=Прегледувач на големина на датотеки +Name[ms]=Pelihat Saiz Fail +Name[nb]=Filstørrelseviser +Name[nds]=Dateigrött-Kieker +Name[ne]=फाइल साइज दर्शक +Name[nl]=Afbeeldinggrootteweergave +Name[nn]=Filstorleikvisar +Name[pa]=ਫਾਇਲ ਅਕਾਰ ਦਰਸ਼ਕ +Name[pl]=Przeglądarka rozmiaru plików +Name[pt]=Visualizador do Tamanho de Ficheiros +Name[pt_BR]=Visão do Tam. do arquivo +Name[ru]=Размер файла +Name[sk]=Prehliadač veľkosti súborov +Name[sl]=Pregledovalnik velikosti datotek +Name[sr]=Приказивач величине фајла +Name[sr@Latn]=Prikazivač veličine fajla +Name[sv]=Filstorleksvisning +Name[ta]=கோப்பு அளவு காட்சியாளன் +Name[tg]=Андозаи файл +Name[tr]=Dosya Boyut Göstericisi +Name[uk]=Переглядач розміру файлів +Name[uz]=Fayl hajmini koʻruvchi +Name[uz@cyrillic]=Файл ҳажмини кўрувчи +Name[vi]=Bộ xem kích cỡ tập tin +Name[zh_CN]=文件大小查看器 +Name[zh_TW]=檔案大小檢視器 +Comment=View your filesystem as a TreeMap +Comment[ar]=عرض لنظام الملفات بنمط شجري +Comment[bg]=Преглед на файловата система +Comment[bs]=Prikazuje vaš datotečni sistem kao mapu stabla +Comment[ca]=Visualitza el vostre sistema de fitxers com a un mapa arbrolat +Comment[cs]=Zobrazení souborového systému ve stylu stromové mapy +Comment[cy]=Gweld eich cysawd ffeiliau fel MapCoeden +Comment[da]=Vis dit filsystem som et trækort +Comment[de]=Dateisystem als Hierarchiestruktur betrachten +Comment[el]=Προβολή του συστήματος αρχείων σας σαν δενδρική δομή +Comment[eo]=Vidu vian dosiersistemon kiel ArbMapo +Comment[es]=Ver su sistema de archivos en forma árbol +Comment[et]=Võimalus vaadata failisüsteemi puukujulisena +Comment[eu]=Ikusi zure fitxategi sistema arbola balitz lez +Comment[fa]=سیستم پروندهتان را به عنوان یک TreeMap مشاهده کنید +Comment[fi]=Katsele tiedostojärjestelmääsi puukarttana +Comment[fr]=Afficher votre système de fichiers sous la forme d'une arborescence +Comment[fy]=Besjoch jo triemsysteem as beamstruktuer +Comment[gl]=Ver o sistema de ficheiros como unha árbore-mapa +Comment[he]=תצוגת הקבצים שלך בתור עץ +Comment[hi]=आपके फ़ाइल-सिस्टम को एक ट्री-मैप में दिखाए +Comment[hr]=Prikazuje datotečni sustav u obliku stabla +Comment[hu]=A fájlrendszer áttekintése fastruktúraként +Comment[is]=Flakka um skráarkerfið í tráarham +Comment[it]=Visualizza il tuo filesystem come una mappa ad albero +Comment[ja]=ツリーマップでファイルシステムを表示 +Comment[ka]=ფაილური სისტემის ხის სახით ხილვა +Comment[kk]=Файлдар жүйесінің бұтақтарын қарау +Comment[km]=មើលប្រព័ន្ធឯកសាររបស់អ្នកជាផែនទីមែកធាង +Comment[lt]=Peržiūrėti bylų sistemą kaip medžio tipo žemėlapį +Comment[mk]=Прегледајте го Вашиот датотечен систем како мапа на стебло +Comment[ms]=Lihat sistem fail anda sebagai TreeMap +Comment[nb]=Se filsystemet som et tre-kart +Comment[nds]=Dien Dateisysteem as Boomkoort +Comment[ne]=ट्री मानचित्रका रुपमा तपाईँको फाइल प्रणाली हेर्नुहोस् +Comment[nl]=Bekijk uw bestandssysteem als boomstructuur +Comment[nn]=Viser filsystemet som eit trekart +Comment[pa]=ਆਪਣੇ ਫਾਇਲ ਸਿਸਟਮ ਨੂੰ ਲੜੀ-ਖਾਕੇ ਦੇ ਰੂਪ ਵਿੱਚ ਵੇਖੋ +Comment[pl]=Przedstawia system plików jako drzewo +Comment[pt]=Ver o sistema de ficheiros como uma árvore-mapa +Comment[pt_BR]=Vê seu sistema de arquivos como um Mapa em Árvore +Comment[ro]=Afişează sistemul de fişiere ca pe o hartă arborescentă +Comment[ru]=Просмотр дерева папок +Comment[sk]=Zobrazenie vášho systému súborov ako stromová mapa +Comment[sl]=Prikaz datotečnega sistema kot drevesa +Comment[sr]=Прикажите ваш систем фајлова као стаблолику мапу +Comment[sr@Latn]=Prikažite vaš sistem fajlova kao stabloliku mapu +Comment[sv]=Visa filsystemet som en trädkarta +Comment[ta]=உங்கள் கோப்பு அமைப்பை மர வரைபடமாக பார்வையிடு +Comment[tg]=Аз назар гузаронидани дарахти каталогҳо +Comment[tr]=Dosya sistemini ağaç şeklinde görüntüle +Comment[uk]=Перегляд вашої файлової системи як дерева +Comment[vi]=Xem hệ thống tập tin dạng Sơ Đồ Cây +Comment[zh_CN]=以树形图查看您的文件系统 +Comment[zh_TW]=將您的作業系統以樹狀圖檢視 +X-DCOP-ServiceType=Multi +Categories=Qt;KDE;Utility; +X-KDE-ParentApp=konqueror diff --git a/konq-plugins/fsview/fsview.h b/konq-plugins/fsview/fsview.h new file mode 100644 index 0000000..17d926f --- /dev/null +++ b/konq-plugins/fsview/fsview.h @@ -0,0 +1,136 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialisaton of TreeMap classes. + */ + +#ifndef FSVIEW_H +#define FSVIEW_H + +#include <qmap.h> +#include <qptrlist.h> +#include <qfileinfo.h> +#include <qstring.h> + +#include <kmimetype.h> + +#include "treemap.h" +#include "inode.h" +#include "scan.h" + +class KConfig; + +/* Cached Metric info config */ +class MetricEntry +{ + public: + MetricEntry() + { size = 0.0; fileCount = 0; dirCount = 0; } + MetricEntry(double s, unsigned int f, unsigned int d) + { size = s; fileCount = f; dirCount = d; } + + double size; + unsigned int fileCount, dirCount; +}; + +/** + * The root object for the treemap. + * + * Does context menu handling and + * asynchronous file size update + */ +class FSView : public TreeMapWidget, public ScanListener +{ + Q_OBJECT + +public: + enum ColorMode { None = 0, Depth, Name, Owner, Group, Mime }; + + FSView(Inode*, QWidget* parent=0, const char* name=0); + ~FSView(); + + KConfig* config() { return _config; } + + void setPath(QString); + QString path() { return _path; } + int pathDepth() { return _pathDepth; } + + void setColorMode(FSView::ColorMode cm); + FSView::ColorMode colorMode() const { return _colorMode; } + // returns true if string was recognized + bool setColorMode(QString); + QString colorModeString() const; + + void requestUpdate(Inode*); + + /* Implementation of listener interface of ScanManager. + * Used to calculate progress info */ + void scanFinished(ScanDir*); + + void stop(); + + static bool getDirMetric(const QString&, double&, unsigned int&, unsigned int&); + static void setDirMetric(const QString&, double, unsigned int, unsigned int); + void saveMetric(KConfigGroup*); + void saveFSOptions(); + + // for color mode + void addColorItems(QPopupMenu*, int); + + KURL::List selectedUrls(); + +public slots: + void selected(TreeMapItem*); + void contextMenu(TreeMapItem*, const QPoint &); + void quit(); + void doUpdate(); + void doRedraw(); + void colorActivated(int); + + signals: + void started(); + void progress(int percent, int dirs, const QString& lastDir); + void completed(int dirs); + + private: + KConfig* _config; + ScanManager _sm; + + // when a contextMenu is shown, we don't allow async. refreshs + bool _allowRefresh; + // a cache for directory sizes with long lasting updates + static QMap<QString, MetricEntry> _dirMetric; + + // current root path + int _pathDepth; + QString _path; + + // for progress info + int _progressPhase; + int _chunkData1, _chunkData2, _chunkData3; + int _chunkSize1, _chunkSize2, _chunkSize3; + int _progress, _progressSize, _dirsFinished; + ScanDir* _lastDir; + + ColorMode _colorMode; + int _colorID; +}; + +#endif // FSVIEW_H + diff --git a/konq-plugins/fsview/fsview_part.cpp b/konq-plugins/fsview/fsview_part.cpp new file mode 100644 index 0000000..745cb63 --- /dev/null +++ b/konq-plugins/fsview/fsview_part.cpp @@ -0,0 +1,413 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * The KPart embedding the FSView widget + */ + +#include <qclipboard.h> +#include <qtimer.h> +#include <qwhatsthis.h> + +#include <kinstance.h> +#include <kfiledialog.h> +#include <kfileitem.h> +#include <kparts/genericfactory.h> +#include <kapplication.h> +#include <kaboutdata.h> +#include <klocale.h> +#include <kaction.h> +#include <kpopupmenu.h> +#include <kglobalsettings.h> +#include <kprotocolinfo.h> +#include <kio/job.h> +#include <kmessagebox.h> + +// from kdebase/libkonq... +#include <konq_operations.h> +#include <konq_drag.h> + +#include "fsview_part.h" + + + + +typedef KParts::GenericFactory<FSViewPart> FSViewPartFactory; +K_EXPORT_COMPONENT_FACTORY( libfsviewpart, FSViewPartFactory ) + + +// FSJob, for progress + +FSJob::FSJob(FSView* v) + : KIO::Job(false) +{ + _view = v; + QObject::connect(v, SIGNAL(progress(int,int,const QString&)), + this, SLOT(progressSlot(int,int,const QString&))); +} + +void FSJob::kill(bool quietly) +{ + _view->stop(); + + Job::kill(quietly); +} + +void FSJob::progressSlot(int percent, int dirs, const QString& cDir) +{ + if (percent<100) { + emitPercent(percent, 100); + slotInfoMessage(this, i18n("Read 1 folder, in %1", + "Read %n folders, in %1", + dirs ).arg(cDir)); + } + else + slotInfoMessage(this, i18n("1 folder", "%n folders", dirs)); +} + + +// FSViewPart + +KAboutData* FSViewPart::createAboutData() +{ + KAboutData* aboutData; + aboutData = new KAboutData("fsview", I18N_NOOP("FSView"), "0.1.1", + I18N_NOOP("Filesystem Utilization Viewer"), + KAboutData::License_GPL, + I18N_NOOP("(c) 2003-2005, Josef Weidendorfer")); + return aboutData; +} + +FSViewPart::FSViewPart(QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, + const QStringList& /* args */) + : KParts::ReadOnlyPart(parent, name) +{ + // we need an instance + setInstance( FSViewPartFactory::instance() ); + + _view = new FSView(new Inode(), parentWidget, widgetName); + QWhatsThis::add(_view, i18n("<p>This is the FSView plugin, a graphical " + "browsing mode showing filesystem utilization " + "by using a tree map visualization.</p>" + "<p>Note that in this mode, automatic updating " + "when filesystem changes are made " + "is intentionally <b>not</b> done.</p>" + "<p>For details on usage and options available, " + "see the online help under " + "menu 'Help/FSView Manual'.</p>")); + + _view->show(); + setWidget(_view); + + _ext = new FSViewBrowserExtension(this); + _job = 0; + + _areaMenu = new KActionMenu (i18n("Stop at Area"), + actionCollection(), "treemap_areadir"); + _depthMenu = new KActionMenu (i18n("Stop at Depth"), + actionCollection(), "treemap_depthdir"); + _visMenu = new KActionMenu (i18n("Visualization"), + actionCollection(), "treemap_visdir"); + _colorMenu = new KActionMenu (i18n("Color Mode"), + actionCollection(), "treemap_colordir"); + + KAction* action; + action = new KAction( i18n( "&FSView Manual" ), "fsview", + KShortcut(), this, SLOT(showHelp()), + actionCollection(), "help_fsview" ); + action->setToolTip(i18n("Show FSView manual")); + action->setWhatsThis(i18n("Opens the help browser with the " + "FSView documentation")); + + QObject::connect (_visMenu->popupMenu(), SIGNAL (aboutToShow()), + SLOT (slotShowVisMenu())); + QObject::connect (_areaMenu->popupMenu(), SIGNAL (aboutToShow()), + SLOT (slotShowAreaMenu())); + QObject::connect (_depthMenu->popupMenu(), SIGNAL (aboutToShow()), + SLOT (slotShowDepthMenu())); + QObject::connect (_colorMenu->popupMenu(), SIGNAL (aboutToShow()), + SLOT (slotShowColorMenu())); + + slotSettingsChanged(KApplication::SETTINGS_MOUSE); + if (kapp) + connect( kapp, SIGNAL( settingsChanged(int) ), + SLOT( slotSettingsChanged(int) ) ); + + QObject::connect(_view,SIGNAL(returnPressed(TreeMapItem*)), + _ext,SLOT(selected(TreeMapItem*))); + QObject::connect(_view,SIGNAL(selectionChanged()), + _ext,SLOT(updateActions())); + QObject::connect(_view, + SIGNAL(contextMenuRequested(TreeMapItem*,const QPoint&)), + _ext, + SLOT(contextMenu(TreeMapItem*, const QPoint&))); + + QObject::connect(_view, SIGNAL(started()), this, SLOT(startedSlot())); + QObject::connect(_view, SIGNAL(completed(int)), + this, SLOT(completedSlot(int))); + + QTimer::singleShot(1, this, SLOT(showInfo())); + + setXMLFile( "fsview_part.rc" ); +} + + +FSViewPart::~FSViewPart() +{ + kdDebug(90100) << "FSViewPart Destructor" << endl; + + delete _job; + _view->saveFSOptions(); +} + +void FSViewPart::slotSettingsChanged(int category) +{ + if (category != KApplication::SETTINGS_MOUSE) return; + + QObject::disconnect(_view,SIGNAL(clicked(TreeMapItem*)), + _ext,SLOT(selected(TreeMapItem*))); + QObject::disconnect(_view,SIGNAL(doubleClicked(TreeMapItem*)), + _ext,SLOT(selected(TreeMapItem*))); + + if (KGlobalSettings::singleClick()) + QObject::connect(_view,SIGNAL(clicked(TreeMapItem*)), + _ext,SLOT(selected(TreeMapItem*))); + else + QObject::connect(_view,SIGNAL(doubleClicked(TreeMapItem*)), + _ext,SLOT(selected(TreeMapItem*))); +} + +void FSViewPart::showInfo() +{ + QString info; + info = i18n("FSView intentionally does not support automatic updates " + "when changes are made to files or directories, " + "currently visible in FSView, from the outside.\n" + "For details, see the 'Help/FSView Manual'."); + + KMessageBox::information( _view, info, QString::null, "ShowFSViewInfo"); +} + +void FSViewPart::showHelp() +{ + KApplication::startServiceByDesktopName("khelpcenter", + QString("help:/konq-plugins/fsview/index.html")); +} + +void FSViewPart::startedSlot() +{ + _job = new FSJob(_view); + emit started(_job); +} + +void FSViewPart::completedSlot(int dirs) +{ + if (_job) { + _job->progressSlot(100, dirs, QString::null); + delete _job; + _job = 0; + } + + KConfigGroup cconfig(_view->config(), QCString("MetricCache")); + _view->saveMetric(&cconfig); + + emit completed(); +} + +void FSViewPart::slotShowVisMenu() +{ + _visMenu->popupMenu()->clear(); + _view->addVisualizationItems(_visMenu->popupMenu(), 1301); +} + +void FSViewPart::slotShowAreaMenu() +{ + _areaMenu->popupMenu()->clear(); + _view->addAreaStopItems(_areaMenu->popupMenu(), 1001, 0); +} + +void FSViewPart::slotShowDepthMenu() +{ + _depthMenu->popupMenu()->clear(); + _view->addDepthStopItems(_depthMenu->popupMenu(), 1501, 0); +} + +void FSViewPart::slotShowColorMenu() +{ + _colorMenu->popupMenu()->clear(); + _view->addColorItems(_colorMenu->popupMenu(), 1401); +} + +bool FSViewPart::openFile() // never called since openURL is reimplemented +{ + kdDebug(90100) << "FSViewPart::openFile " << m_file << endl; + _view->setPath(m_file); + + return true; +} + +bool FSViewPart::openURL(const KURL &url) +{ + kdDebug(90100) << "FSViewPart::openURL " << url.path() << endl; + + if (!url.isValid()) return false; + if (!url.isLocalFile()) return false; + + m_url = url; + emit setWindowCaption( m_url.prettyURL() ); + + _view->setPath(url.path()); + + return true; +} + +bool FSViewPart::closeURL() +{ + kdDebug(90100) << "FSViewPart::closeURL " << endl; + + _view->stop(); + + return true; +} + +// FSViewBrowserExtension + +FSViewBrowserExtension::FSViewBrowserExtension(FSViewPart* viewPart, + const char *name) + :KParts::BrowserExtension(viewPart, name) +{ + _view = viewPart->view(); +} + +FSViewBrowserExtension::~FSViewBrowserExtension() +{} + +void FSViewBrowserExtension::updateActions() +{ + TreeMapItemList s = _view->selection(); + TreeMapItem* i; + int canDel = 0, canCopy = 0; + KURL::List urls; + + for(i=s.first();i;i=s.next()) { + KURL u; + u.setPath( ((Inode*)i)->path() ); + urls.append(u); + canCopy++; + if ( KProtocolInfo::supportsDeleting( u ) ) canDel++; + } + emit enableAction( "copy", canCopy > 0 ); + emit enableAction( "cut", canDel > 0 ); + emit enableAction( "trash", canDel > 0); + emit enableAction( "del", canDel > 0 ); + emit enableAction( "editMimeType", ( s.count() == 1 ) ); + + emit selectionInfo(urls); + + kdDebug(90100) << "FSViewPart::updateActions, deletable " << canDel << endl; +} + + +void FSViewBrowserExtension::del() +{ + KonqOperations::del(_view, KonqOperations::DEL, _view->selectedUrls()); + // How to get notified of end of delete operation? + // - search for the KonqOperations child of _view (name "KonqOperations") + // - connect to destroyed signal + KonqOperations* o = (KonqOperations*) _view->child("KonqOperations"); + if (o) connect(o, SIGNAL(destroyed()), SLOT(refresh())); +} + +void FSViewBrowserExtension::trash() +{ + KonqOperations::del(_view, KonqOperations::TRASH, _view->selectedUrls()); + KonqOperations* o = (KonqOperations*) _view->child("KonqOperations"); + if (o) connect(o, SIGNAL(destroyed()), SLOT(refresh())); +} + +void FSViewBrowserExtension::copySelection( bool move ) +{ + KonqDrag *urlData = KonqDrag::newDrag( _view->selectedUrls(), move ); + QApplication::clipboard()->setData( urlData ); +} + +void FSViewBrowserExtension::editMimeType() +{ + Inode* i = (Inode*) _view->selection().first(); + if (i) + KonqOperations::editMimeType( i->mimeType()->name() ); +} + + +// refresh treemap at end of KIO jobs +void FSViewBrowserExtension::refresh() +{ + // only need to refresh common ancestor for all selected items + TreeMapItemList s = _view->selection(); + TreeMapItem *i, *commonParent = s.first(); + if (!commonParent) return; + while( (i=s.next()) ) + commonParent = commonParent->commonParent(i); + + /* if commonParent is a file, update parent directory */ + if ( !((Inode*)commonParent)->isDir() ) { + commonParent = commonParent->parent(); + if (!commonParent) return; + } + + kdDebug(90100) << "FSViewPart::refreshing " + << ((Inode*)commonParent)->path() << endl; + + _view->requestUpdate( (Inode*)commonParent ); +} + +void FSViewBrowserExtension::selected(TreeMapItem* i) +{ + if (!i) return; + + KURL url; + url.setPath( ((Inode*)i)->path() ); + emit openURLRequest(url); +} + +void FSViewBrowserExtension::contextMenu(TreeMapItem* /*item*/,const QPoint& p) +{ + TreeMapItemList s = _view->selection(); + TreeMapItem* i; + KFileItemList items; + items.setAutoDelete(true); + + for(i=s.first();i;i=s.next()) { + KURL u; + u.setPath( ((Inode*)i)->path() ); + QString mimetype = ((Inode*)i)->mimeType()->name(); + const QFileInfo& info = ((Inode*)i)->fileInfo(); + mode_t mode = + info.isFile() ? S_IFREG : + info.isDir() ? S_IFDIR : + info.isSymLink() ? S_IFLNK : (mode_t)-1; + items.append(new KFileItem(u, mimetype, mode)); + } + + if (items.count()>0) + emit popupMenu(_view->mapToGlobal(p), items); +} + + +#include "fsview_part.moc" diff --git a/konq-plugins/fsview/fsview_part.desktop b/konq-plugins/fsview/fsview_part.desktop new file mode 100644 index 0000000..d282178 --- /dev/null +++ b/konq-plugins/fsview/fsview_part.desktop @@ -0,0 +1,58 @@ +[Desktop Entry] +Name=File Size View +Name[bg]=Преглед на файловия размер +Name[bs]=Pogled veličine datoteka +Name[ca]=Vista de mides de fitxers +Name[cs]=Prohlížeč velikostí souborů +Name[da]=Fremvisning af filstørrelse +Name[de]=Dateigrößen-Ansicht +Name[el]=Προβολή Μεγέθους αρχείων +Name[eo]=Dosiergrandeca rigardo +Name[es]=Vista del tamaño del archivo +Name[et]=Failisuuruse vaade +Name[eu]=Fitxategien neurriaren ikuspegia +Name[fa]=نمای اندازۀ پرونده +Name[fr]=Afficheur de taille de fichiers +Name[gl]=Vista de Tamaño de Ficheiros +Name[he]=מציג גדלי קבצים +Name[hi]=फ़ाइल आकार दृश्य +Name[hr]=Prikaz veličine datoteke +Name[hu]=Fájlméret-nézet +Name[is]=Skoða skráarstærð +Name[it]=Visualizza dimensione file +Name[ja]=ファイルサイズ表示 +Name[ka]=ფაილის ზომის ხილვა +Name[kk]=Файл көлемдердің қарау +Name[km]=មើលទំហំឯកសារ +Name[lt]=Bylų dydžio vaizdas +Name[mk]=Преглед на големина на датотеки +Name[ms]=Pandangan Saiz Fail +Name[nb]=Filstørrelsevisning +Name[nds]=Dateigrött-Ansicht +Name[ne]=फाइल साइज दृश्य +Name[nn]=Filstorleikvisar +Name[pa]=ਫਾਇਲ ਅਕਾਰ ਵੇਖੋ +Name[pl]=Widok rozmiaru plików +Name[pt]=Vista de Tamanho de Ficheiros +Name[pt_BR]=Visão do Tam. do arquivo +Name[ru]=Размер файла +Name[sk]=Veľkosť súborov +Name[sl]=Pregledovalnik velikosti datotek +Name[sr]=Приказ величине фајла +Name[sr@Latn]=Prikaz veličine fajla +Name[sv]=Filstorleksvisning +Name[ta]=கோப்பு அளவு காட்சி +Name[tg]=Андозаи файл +Name[tr]=Dosya Boyut Görüntüleme +Name[uk]=Перегляд розміру файлів +Name[uz]=Fayl hajmini koʻrish +Name[uz@cyrillic]=Файл ҳажмини кўриш +Name[vi]=Xem cỡ tập tin +Name[zh_CN]=文件大小查看 +Name[zh_TW]=檔案大小檢視器 +MimeType=inode/directory +ServiceTypes=KParts/ReadOnlyPart +X-KDE-Library=libfsviewpart +Type=Service +Icon=fsview +DocPath=konq-plugins/fsview/index.html diff --git a/konq-plugins/fsview/fsview_part.h b/konq-plugins/fsview/fsview_part.h new file mode 100644 index 0000000..4f2c734 --- /dev/null +++ b/konq-plugins/fsview/fsview_part.h @@ -0,0 +1,122 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * The KPart embedding the FSView widget + */ + +#ifndef FSVIEW_PART_H +#define FSVIEW_PART_H + +#include <kparts/part.h> +#include <kparts/browserextension.h> +#include <kio/jobclasses.h> + +#include "fsview.h" + +class KAboutData; +class KActionMenu; + +class FSViewPart; + +class FSViewBrowserExtension : public KParts::BrowserExtension +{ + Q_OBJECT + +public: + FSViewBrowserExtension(FSViewPart *viewPart, const char *name=0L); + ~FSViewBrowserExtension(); + +protected slots: + void selected(TreeMapItem*); + void contextMenu(TreeMapItem*,const QPoint&); + + void updateActions(); + void refresh(); + + void copy() { copySelection( false ); } + void cut() { copySelection( true ); } + void trash(); + void del(); + void editMimeType(); + +private: + void copySelection( bool move ); + + FSView* _view; +}; + +class FSJob: public KIO::Job +{ + Q_OBJECT + +public: + FSJob(FSView*); + + virtual void kill( bool quietly = true ); + +public slots: + void progressSlot(int percent, int dirs, const QString& lastDir); + +private: + FSView* _view; +}; + + +class FSViewPart : public KParts::ReadOnlyPart +{ + Q_OBJECT + Q_PROPERTY( bool supportsUndo READ supportsUndo ) +public: + FSViewPart(QWidget *parentWidget, const char *widgetName, + QObject *parent, const char *name, const QStringList &args); + + virtual ~FSViewPart(); + + bool supportsUndo() const { return false; } + + static KAboutData* createAboutData(); + FSView* view() const { return _view; } + +public slots: + void showInfo(); + void showHelp(); + void startedSlot(); + void completedSlot(int dirs); + void slotShowVisMenu(); + void slotShowAreaMenu(); + void slotShowDepthMenu(); + void slotShowColorMenu(); + void slotSettingsChanged(int); + +protected: + /** + * This must be implemented by each part + */ + virtual bool openFile(); + virtual bool openURL(const KURL &url); + virtual bool closeURL(); + +private: + FSView* _view; + FSJob* _job; + FSViewBrowserExtension* _ext; + KActionMenu *_visMenu, *_areaMenu, *_depthMenu, *_colorMenu; +}; + +#endif // FSVIEW_PART_H diff --git a/konq-plugins/fsview/fsview_part.rc b/konq-plugins/fsview/fsview_part.rc new file mode 100644 index 0000000..c8df3df --- /dev/null +++ b/konq-plugins/fsview/fsview_part.rc @@ -0,0 +1,15 @@ +<!DOCTYPE kpartplugin> +<kpartplugin name="FSViewPart" library="libfsviewpart" version = "1"> +<MenuBar> + <Menu name="view"><Text>&View</Text> + <Separator/> + <Action name="treemap_visdir"/> + <Action name="treemap_colordir"/> + <Action name="treemap_areadir"/> + <Action name="treemap_depthdir"/> + </Menu> + <Menu name="help"><text>&Help</text> + <Action name="help_fsview"/> + </Menu> +</MenuBar> +</kpartplugin> diff --git a/konq-plugins/fsview/hi22-app-fsview.png b/konq-plugins/fsview/hi22-app-fsview.png Binary files differnew file mode 100644 index 0000000..efdcdcb --- /dev/null +++ b/konq-plugins/fsview/hi22-app-fsview.png diff --git a/konq-plugins/fsview/hi32-app-fsview.png b/konq-plugins/fsview/hi32-app-fsview.png Binary files differnew file mode 100644 index 0000000..6e22f8b --- /dev/null +++ b/konq-plugins/fsview/hi32-app-fsview.png diff --git a/konq-plugins/fsview/inode.cpp b/konq-plugins/fsview/inode.cpp new file mode 100644 index 0000000..0411d3a --- /dev/null +++ b/konq-plugins/fsview/inode.cpp @@ -0,0 +1,385 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialisaton of TreeMapItem class. + */ + + +#include <kurl.h> +#include <kmimetype.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> + +#include "inode.h" +#include "scan.h" +#include "fsview.h" + +// Inode + +Inode::Inode() +{ + _dirPeer = 0; + _filePeer = 0; + init(""); +} + +Inode::Inode(ScanDir* d, Inode* parent) + : TreeMapItem(parent) +{ + QString absPath; + if (parent) { + absPath = parent->path(); + if (!absPath.endsWith("/")) absPath += "/"; + } + absPath += d->name(); + + _dirPeer = d; + _filePeer = 0; + + init(absPath); +} + +Inode::Inode(ScanFile* f, Inode* parent) + : TreeMapItem(parent) +{ + QString absPath; + if (parent) + absPath = parent->path() + "/"; + absPath += f->name(); + + _dirPeer = 0; + _filePeer = f; + + init(absPath); +} + +Inode::~Inode() +{ + if (0) kdDebug(90100) << "~Inode [" << path() + << "]" << endl; + + /* reset Listener of old Peer */ + if (_dirPeer) + _dirPeer->setListener(0); + if (_filePeer) + _filePeer->setListener(0); +} + +void Inode::setPeer(ScanDir* d) +{ + /* reset Listener of old Peer */ + if (_dirPeer) + _dirPeer->setListener(0); + if (_filePeer) + _filePeer->setListener(0); + + _dirPeer = d; + _filePeer = 0; + init(d->name()); +} + +QString Inode::path() const +{ + return _info.absFilePath(); +} + +void Inode::init(const QString& path) +{ + if (0) kdDebug(90100) << "Inode::init [" << path + << "]" << endl; + + _info = QFileInfo(path); + + if (!FSView::getDirMetric(path, _sizeEstimation, + _fileCountEstimation, + _dirCountEstimation)) { + _sizeEstimation = 0.0; + _fileCountEstimation = 0; + _dirCountEstimation = 0; + } + + _mimeSet = false; + _mimePixmapSet = false; + _resortNeeded = false; + + clear(); + + /* we want to get notifications about dir changes */ + if (_dirPeer) + _dirPeer->setListener(this); + if (_filePeer) + _filePeer->setListener(this); + + if (_dirPeer && _dirPeer->scanFinished()) + scanFinished(_dirPeer); +} + +/* ScanListener interface */ +void Inode::sizeChanged(ScanDir* d) +{ + if (0) kdDebug(90100) << "Inode::sizeChanged [" << path() << "] in " + << d->name() << ": size " << d->size() << endl; + + _resortNeeded = true; +} + +void Inode::scanFinished(ScanDir* d) +{ + if (0) kdDebug(90100) << "Inode::scanFinished [" << path() << "] in " + << d->name() << ": size " << d->size() << endl; + + _resortNeeded = true; + + /* no estimation any longer */ + _sizeEstimation = 0.0; + _fileCountEstimation = 0; + _dirCountEstimation = 0; + + // cache metrics if "important" (for "/usr" is dd==3) + int dd = ((FSView*)widget())->pathDepth() + depth(); + int files = d->fileCount(); + int dirs = d->dirCount(); + + if ((files < 500) && (dirs < 50)) { + if (dd>4 && (files < 50) && (dirs < 5)) return; + } + + FSView::setDirMetric(path(), d->size(), files, dirs); +} + +void Inode::destroyed(ScanDir* d) +{ + if (_dirPeer == d) _dirPeer = 0; + + // remove children + clear(); +} + +void Inode::destroyed(ScanFile* f) +{ + if (_filePeer == f) _filePeer = 0; +} + + + +TreeMapItemList* Inode::children() +{ + if (!_dirPeer) return 0; + + if (!_children) { + if (!_dirPeer->scanStarted()) return 0; + + _children = new TreeMapItemList; + _children->setAutoDelete(true); + + setSorting(-1); + + ScanFileVector& files = _dirPeer->files(); + if (files.count()>0) { + ScanFileVector::iterator it; + for( it = files.begin(); it != files.end(); ++it ) + new Inode( &(*it), this); + } + + ScanDirVector& dirs = _dirPeer->dirs(); + if (dirs.count()>0) { + ScanDirVector::iterator it; + for( it = dirs.begin(); it != dirs.end(); ++it ) { + new Inode( &(*it), this); + } + } + + setSorting(-2); + _resortNeeded = false; + } + + if (_resortNeeded) { + resort(); + _resortNeeded = false; + } + + return _children; +} + + + +double Inode::size() const +{ + // sizes of files are always correct + if (_filePeer) return _filePeer->size(); + if (!_dirPeer) return 0; + + double size = _dirPeer->size(); + return (_sizeEstimation > size) ? _sizeEstimation : size; +} + +double Inode::value() const +{ + return size(); +} + +unsigned int Inode::fileCount() const +{ + unsigned int fileCount = 1; + + if (_dirPeer) fileCount = _dirPeer->fileCount(); + + if (_fileCountEstimation > fileCount) + fileCount = _fileCountEstimation; + + return fileCount; +} + +unsigned int Inode::dirCount() const +{ + unsigned int dirCount = 0; + + if (_dirPeer) dirCount = _dirPeer->dirCount(); + + if (_dirCountEstimation > dirCount) + dirCount = _dirCountEstimation; + + return dirCount; +} + + +QColor Inode::backColor() const +{ + QString n; + int id = 0; + + switch( ((FSView*)widget())->colorMode() ) { + case FSView::Depth: + { + int d = ((FSView*)widget())->pathDepth() + depth(); + return QColor((100*d)%360, 192,128, QColor::Hsv); + } + + case FSView::Name: n = text(0); break; + case FSView::Owner: id = _info.ownerId(); break; + case FSView::Group: id = _info.groupId(); break; + case FSView::Mime: n = text(7); break; + + default: + break; + } + + if (id>0) n = QString::number(id); + + if (n.isEmpty()) + return widget()->colorGroup().button(); + + const char* str = n.ascii(); + int h = 0, s = 100; + while (*str) { + h = (h * 37 + s* (unsigned)*str) % 256; + s = (s * 17 + h* (unsigned)*str) % 192; + str++; + } + return QColor(h, 64+s, 192, QColor::Hsv); +} + +KMimeType::Ptr Inode::mimeType() const +{ + if (!_mimeSet) { + KURL u; + u.setPath(path()); + _mimeType = KMimeType::findByURL( u, 0, true, false ); + + _mimeSet = true; + } + return _mimeType; +} + +QString Inode::text(int i) const +{ + if (i==0) { + QString name; + if (_dirPeer) { + name = _dirPeer->name(); + if (!name.endsWith("/")) name += "/"; + } + else if (_filePeer) name = _filePeer->name(); + + return name; + } + if (i==1) { + QString text; + double s = size(); + + if (s < 1000) + text = QString("%1 B").arg((int)(s+.5)); + else if (s < 10 * 1024) + text = QString("%1 kB").arg(KGlobal::locale()->formatNumber(s/1024+.005,2)); + else if (s < 100 * 1024) + text = QString("%1 kB").arg(KGlobal::locale()->formatNumber(s/1024+.05,1)); + else if (s < 1000 * 1024) + text = QString("%1 kB").arg((int)(s/1024+.5)); + else if (s < 10 * 1024 * 1024) + text = QString("%1 MB").arg(KGlobal::locale()->formatNumber(s/1024/1024+.005,2)); + else if (s < 100 * 1024 * 1024) + text = QString("%1 MB").arg(KGlobal::locale()->formatNumber(s/1024/1024+.05,1)); + else if (s < 1000 * 1024 * 1024) + text = QString("%1 MB").arg((int)(s/1024/1024+.5)); + else + text = QString("%1 GB").arg(KGlobal::locale()->formatNumber(s/1024/1024/1024+.005,2)); + + if (_sizeEstimation>0) text += "+"; + return text; + } + + if ((i==2) || (i==3)) { + /* file/dir count makes no sense for files */ + if (_filePeer) return QString(); + + QString text; + unsigned int f = (i==2) ? fileCount() : dirCount(); + + if (f>0) { + while (f>1000) { + text = QString("%1 %2").arg(QString::number(f).right(3)).arg(text); + f /= 1000; + } + text = QString("%1 %2").arg(QString::number(f)).arg(text); + if (_fileCountEstimation>0) text += "+"; + } + return text; + } + + if (i==4) return _info.lastModified().toString(); + if (i==5) return _info.owner(); + if (i==6) return _info.group(); + if (i==7) return mimeType()->comment(); + return QString(); +} + +QPixmap Inode::pixmap(int i) const +{ + if (i!=0) return QPixmap(); + + if (!_mimePixmapSet) { + KURL u; + u.setPath(path()); + _mimePixmap = mimeType()->pixmap(u, KIcon::Small); + + _mimePixmapSet = true; + } + return _mimePixmap; +} diff --git a/konq-plugins/fsview/inode.h b/konq-plugins/fsview/inode.h new file mode 100644 index 0000000..8289f6b --- /dev/null +++ b/konq-plugins/fsview/inode.h @@ -0,0 +1,97 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * FSView specialisaton of TreeMapItem class. + */ + +#ifndef INODE_H +#define INODE_H + +#include <qmap.h> +#include <qptrlist.h> +#include <qfileinfo.h> +#include <qstring.h> + +#include <kmimetype.h> + +#include "treemap.h" +#include "scan.h" + + +/** + * A specialized version of a TreeMapItem + * for representation of an Directory or File. + * + * These are dynamically created on drawing. + * The real breadth-first scanning of the filesystem + * uses ScanDir:scan. + */ +class Inode: public TreeMapItem, public ScanListener +{ +public: + Inode(); + Inode(ScanDir*, Inode*); + Inode(ScanFile*, Inode*); + ~Inode(); + void init(const QString&); + + void setPeer(ScanDir*); + + TreeMapItemList* children(); + + double value() const; + double size() const; + unsigned int fileCount() const; + unsigned int dirCount() const; + QString path() const; + QString text(int i) const; + QPixmap pixmap(int i) const; + QColor backColor() const; + KMimeType::Ptr mimeType() const; + + const QFileInfo& fileInfo() const { return _info; } + ScanDir* dirPeer() { return _dirPeer; } + ScanFile* filePeer() { return _filePeer; } + bool isDir() { return (_dirPeer != 0); } + + void sizeChanged(ScanDir*); + void scanFinished(ScanDir*); + void destroyed(ScanDir*); + void destroyed(ScanFile*); + +private: + void setMetrics(double, unsigned int); + + QFileInfo _info; + ScanDir* _dirPeer; + ScanFile* _filePeer; + + double _sizeEstimation; + unsigned int _fileCountEstimation, _dirCountEstimation; + + bool _resortNeeded; + + // Cached values, calculated lazy. + // This means a change even in const methods, thus has to be "mutable" + mutable bool _mimeSet, _mimePixmapSet; + mutable KMimeType::Ptr _mimeType; + mutable QPixmap _mimePixmap; +}; + +#endif diff --git a/konq-plugins/fsview/main.cpp b/konq-plugins/fsview/main.cpp new file mode 100644 index 0000000..da18dcf --- /dev/null +++ b/konq-plugins/fsview/main.cpp @@ -0,0 +1,56 @@ +/***************************************************** + * FSView, a simple TreeMap application + * + * (C) 2002, Josef Weidendorfer + */ + +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kaboutdata.h> +#include <klocale.h> +#include <kglobal.h> +#include <kconfig.h> + +#include "fsview.h" + + +static KCmdLineOptions options[] = +{ + { "+[folder]", I18N_NOOP("View filesystem starting from this folder"), 0 }, + KCmdLineLastOption // End of options. +}; + +int main(int argc, char* argv[]) +{ + // KDE compliant startup + KAboutData aboutData("fsview", I18N_NOOP("FSView"), "0.1", + I18N_NOOP("Filesystem Viewer"), + KAboutData::License_GPL, + I18N_NOOP("(c) 2002, Josef Weidendorfer")); + KCmdLineArgs::init(argc, argv, &aboutData); + KCmdLineArgs::addCmdLineOptions(options); + KApplication a; + + KConfigGroup gconfig(KGlobal::config(), QCString("General")); + QString path = gconfig.readPathEntry("Path", "."); + + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + if (args->count()>0) path = args->arg(0); + + // TreeMap Widget as toplevel window + FSView w(new Inode()); + + QObject::connect(&w,SIGNAL(clicked(TreeMapItem*)), + &w,SLOT(selected(TreeMapItem*))); + QObject::connect(&w,SIGNAL(returnPressed(TreeMapItem*)), + &w,SLOT(selected(TreeMapItem*))); + QObject::connect(&w, + SIGNAL(contextMenuRequested(TreeMapItem*,const QPoint&)), + &w,SLOT(contextMenu(TreeMapItem*, const QPoint&))); + + w.setPath(path); + w.show(); + + a.connect( &a, SIGNAL( lastWindowClosed() ), &w, SLOT( quit() ) ); + return a.exec(); +} diff --git a/konq-plugins/fsview/scan.cpp b/konq-plugins/fsview/scan.cpp new file mode 100644 index 0000000..ed691e3 --- /dev/null +++ b/konq-plugins/fsview/scan.cpp @@ -0,0 +1,362 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qdir.h> +#include <qstringlist.h> + +#include <kapplication.h> +#include <kdebug.h> + +#include "scan.h" +#include "inode.h" + + +// ScanManager + +ScanManager::ScanManager() +{ + _topDir = 0; + _listener = 0; +} + +ScanManager::ScanManager(const QString& path) +{ + _topDir = 0; + _listener = 0; + setTop(path); +} + +ScanManager::~ScanManager() +{ + stopScan(); + if (_topDir) delete _topDir; +} + +void ScanManager::setListener(ScanListener* l) +{ + _listener = l; +} + +ScanDir* ScanManager::setTop(const QString& path, int data) +{ + stopScan(); + if (_topDir) { + delete _topDir; + _topDir = 0; + } + if (!path.isEmpty()) { + _topDir = new ScanDir(path, this, 0, data); + } + return _topDir; +} + +bool ScanManager::scanRunning() +{ + if (!_topDir) return false; + + return _topDir->scanRunning(); +} + +void ScanManager::startScan(ScanDir* from) +{ + if (!_topDir) return; + if (!from) from = _topDir; + + if (scanRunning()) stopScan(); + + from->clear(); + if (from->parent()) + from->parent()->setupChildRescan(); + + _list.append(new ScanItem(from->path(),from)); +} + +void ScanManager::stopScan() +{ + if (!_topDir) return; + + if (0) kdDebug(90100) << "ScanManager::stopScan, scanLength " + << _list.count() << endl; + + ScanItem* si; + while( (si=_list.take(0))!=0 ) { + si->dir->finish(); + delete si; + } +} + +int ScanManager::scan(int data) +{ + ScanItem* si = _list.take(0); + if (!si) return false; + + int newCount = si->dir->scan(si, _list, data); + delete si; + + return newCount; +} + + +// ScanFile + +ScanFile::ScanFile() +{ + _size = 0; + _listener = 0; +} + +ScanFile::ScanFile(const QString& n, KIO::fileoffset_t s) +{ + _name = n; + _size = s; + _listener = 0; +} + +ScanFile::~ScanFile() +{ + if (_listener) _listener->destroyed(this); +} + +// ScanDir + +ScanDir::ScanDir() +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _parent = 0; + _manager = 0; + _listener = 0; + _data = 0; +} + +ScanDir::ScanDir(const QString& n, ScanManager* m, + ScanDir* p, int data) + : _name(n) +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _parent = p; + _manager = m; + _listener = 0; + _data = data; +} + +ScanDir::~ScanDir() +{ + if (_listener) _listener->destroyed(this); +} + +void ScanDir::setListener(ScanListener* l) +{ + _listener = l; +} + +QString ScanDir::path() +{ + if (_parent) { + QString p = _parent->path(); + if (!p.endsWith("/")) p += "/"; + return p + _name; + } + + return _name; +} + +void ScanDir::clear() +{ + _dirty = true; + _dirsFinished = -1; /* scan not started */ + + _files.clear(); + _dirs.clear(); +} + +void ScanDir::update() +{ + if (!_dirty) return; + _dirty = false; + + _fileCount = 0; + _dirCount = 0; + _size = 0; + + if (_dirsFinished == -1) return; + + if (_files.count()>0) { + _fileCount += _files.count(); + _size = _fileSize; + } + if (_dirs.count()>0) { + _dirCount += _dirs.count(); + ScanDirVector::iterator it; + for( it = _dirs.begin(); it != _dirs.end(); ++it ) { + (*it).update(); + _fileCount += (*it)._fileCount; + _dirCount += (*it)._dirCount; + _size += (*it)._size; + } + } +} + +int ScanDir::scan(ScanItem* si, ScanItemList& list, int data) +{ + clear(); + _dirsFinished = 0; + _fileSize = 0; + _dirty = true; + + KURL u; + u.setPath(si->absPath); + if (!kapp->authorizeURLAction("list", KURL(), u)) { + if (_parent) + _parent->subScanFinished(); + + return 0; + } + + QDir d(si->absPath); + QStringList fileList = d.entryList( QDir::Files | + QDir::Hidden | QDir::NoSymLinks ); + + if (fileList.count()>0) { + KDE_struct_stat buff; + + _files.reserve(fileList.count()); + + QStringList::Iterator it; + for (it = fileList.begin(); it != fileList.end(); ++it ) { + KDE_lstat( QFile::encodeName(si->absPath + "/" + (*it)), &buff ); + _files.append( ScanFile(*it, buff.st_size) ); + _fileSize += buff.st_size; + } + } + + QStringList dirList = d.entryList( QDir::Dirs | + QDir::Hidden | QDir::NoSymLinks ); + + if (dirList.count()>2) { + _dirs.reserve(dirList.count()-2); + + QStringList::Iterator it; + for (it = dirList.begin(); it != dirList.end(); ++it ) { + if ( ((*it) == "..") || ((*it) == ".") ) continue; + _dirs.append( ScanDir(*it, _manager, this, data) ); + list.append( new ScanItem( si->absPath + "/" + (*it), + &(_dirs.last()) )); + } + _dirCount += _dirs.count(); + } + + callScanStarted(); + callSizeChanged(); + + if (_dirs.count() == 0) { + callScanFinished(); + + if (_parent) + _parent->subScanFinished(); + } + + return _dirs.count(); +} + +void ScanDir::subScanFinished() +{ + _dirsFinished++; + callSizeChanged(); + + if (0) kdDebug(90100) << "ScanDir::subScanFinished [" << path() + << "]: " << _dirsFinished << "/" << _dirs.count() << endl; + + + + if (_dirsFinished < (int)_dirs.count()) return; + + /* all subdirs read */ + callScanFinished(); + + if (_parent) + _parent->subScanFinished(); +} + +void ScanDir::finish() +{ + if (scanRunning()) { + _dirsFinished = (int)_dirs.count(); + callScanFinished(); + } + + if (_parent) + _parent->finish(); +} + +void ScanDir::setupChildRescan() +{ + if (_dirs.count() == 0) return; + + _dirsFinished = 0; + ScanDirVector::iterator it; + for( it = _dirs.begin(); it != _dirs.end(); ++it ) + if ((*it).scanFinished()) _dirsFinished++; + + if (_parent && + (_dirsFinished < (int)_dirs.count()) ) + _parent->setupChildRescan(); + + callScanStarted(); +} + +void ScanDir::callScanStarted() +{ + if (0) kdDebug(90100) << "ScanDir:Started [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + ScanListener* mListener = _manager ? _manager->listener() : 0; + + if (_listener) _listener->scanStarted(this); + if (mListener) mListener->scanStarted(this); +} + +void ScanDir::callSizeChanged() +{ + if (0) kdDebug(90100) << ". [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + _dirty = true; + + if (_parent) _parent->callSizeChanged(); + + ScanListener* mListener = _manager ? _manager->listener() : 0; + + if (_listener) _listener->sizeChanged(this); + if (mListener) mListener->sizeChanged(this); +} + +void ScanDir::callScanFinished() +{ + if (0) kdDebug(90100) << "ScanDir:Finished [" << path() + << "]: size " << size() << ", files " << fileCount() << endl; + + ScanListener* mListener = _manager ? _manager->listener() : 0; + + if (_listener) _listener->scanFinished(this); + if (mListener) mListener->scanFinished(this); +} + diff --git a/konq-plugins/fsview/scan.h b/konq-plugins/fsview/scan.h new file mode 100644 index 0000000..38b015c --- /dev/null +++ b/konq-plugins/fsview/scan.h @@ -0,0 +1,230 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * Classes for breadth-first search in local filesystem + */ + +#ifndef FSDIR_H +#define FSDIR_H + +#include <qptrlist.h> +#include <qvaluevector.h> +#include <qfile.h> + +/* Use KDE_lstat and KIO::fileoffset_t for 64-bit sizes */ +#include <klargefile.h> +#include <kio/global.h> + +class ScanDir; +class ScanFile; + +class ScanItem +{ + public: + ScanItem(const QString& p, ScanDir* d) + { absPath = p; dir = d; } + + QString absPath; + ScanDir* dir; +}; + +typedef QPtrList<ScanItem> ScanItemList; + + +/** + * Listener for events from directory scanning. + * + * You can register a listener for the ScanManager to get + * all scan events and a listener for every ScanDir for + * directory specific scan events. + * + * sizeChanged is called when a scan of a subdirectory + * finished. + */ +class ScanListener +{ + public: + virtual void scanStarted(ScanDir*) {} + virtual void sizeChanged(ScanDir*) {} + virtual void scanFinished(ScanDir*) {} + // destroyed events are not delivered to listeners of ScanManager + virtual void destroyed(ScanDir*) {} + virtual void destroyed(ScanFile*) {} +}; + + + +/** + * ScanManager + * + * Start/Stop/Restart Scans. Example: + * + * ScanManager m("/opt"); + * m.startScan(); + * while(m.scan()); + */ +class ScanManager +{ + public: + ScanManager(); + ScanManager(const QString& path); + ~ScanManager(); + + /** Set the top path for scanning + * The ScanDir object created gets attribute data. + */ + ScanDir* setTop(const QString& path, int data = 0); + ScanDir* top() { return _topDir; } + + bool scanRunning(); + unsigned int scanLength() { return _list.count(); } + + /** + * Starts the scan. Stop previous scan if running. + * For the actual scan to happen, you have to call + * scan() peridically. + * + * If from !=0, restart scan at given position; from must + * be from the previous scan of this manager. + */ + void startScan(ScanDir* from = 0); + + /** Stop a current running scan. + * Make all directories to finish their scan. + */ + void stopScan(); + + /** + * Scan first directory from todo list. + * Directories added to the todo list are attributed with data. + * Returns the number of new subdirectories created for scanning. + */ + int scan(int data); + + /* set listener to get a callbacks from this ScanDir */ + void setListener(ScanListener*); + ScanListener* listener() { return _listener; } + + private: + ScanItemList _list; + ScanDir* _topDir; + ScanListener* _listener; +}; + +class ScanFile +{ + public: + ScanFile(); + ScanFile(const QString& n, KIO::fileoffset_t s); + ~ScanFile(); + + const QString& name() { return _name; } + KIO::fileoffset_t size() { return _size; } + + /* set listener to get callbacks from this ScanDir */ + void setListener(ScanListener* l) { _listener = l; } + ScanListener* listener() { return _listener; } + + private: + QString _name; + KIO::fileoffset_t _size; + ScanListener* _listener; +}; + +typedef QValueVector<ScanFile> ScanFileVector; +typedef QValueVector<ScanDir> ScanDirVector; + +/** + * A directory to scan. + * You can attribute a directory to scan with a + * integer data attribute. + */ +class ScanDir +{ + public: + ScanDir(); + ScanDir(const QString& n, ScanManager* m, + ScanDir* p = 0, int data = 0); + ~ScanDir(); + + /* Get items of this directory + * and append subdirectories to todo list. + * + * Directories added to the todo list are attributed with data. + * Returns the number of new subdirectories created for scanning. + */ + int scan(ScanItem* si, ScanItemList& list, int data); + + /* clear scan objects below */ + void clear(); + + /* + * Setup for child rescan + */ + void setupChildRescan(); + + /* Absolute path. Warning: Slow, loops to top parent. */ + QString path(); + + /* get integer data attribute */ + int data() { return _data; } + void setData(int d) { _data = d; } + + ScanFileVector& files() { return _files; } + ScanDirVector& dirs() { return _dirs; } + const QString& name() { return _name; } + KIO::fileoffset_t size() { update(); return _size; } + unsigned int fileCount() { update(); return _fileCount; } + unsigned int dirCount() { update(); return _dirCount; } + ScanDir* parent() { return _parent; } + bool scanStarted() { return (_dirsFinished >= 0); } + bool scanFinished() { return (_dirsFinished == (int)_dirs.count()); } + bool scanRunning() { return scanStarted() && !scanFinished(); } + + /* set listener to get a callbacks from this ScanDir */ + void setListener(ScanListener*); + ScanListener* listener() { return _listener; } + ScanManager* manager() { return _manager; } + + /* force current scan to be finished */ + void finish(); + + private: + void update(); + + /* this propagates file count and size to upper dirs */ + void subScanFinished(); + void callScanStarted(); + void callSizeChanged(); + void callScanFinished(); + + ScanFileVector _files; + ScanDirVector _dirs; + + QString _name; + bool _dirty; /* needs a call to update() */ + KIO::fileoffset_t _size, _fileSize; + unsigned int _fileCount, _dirCount; + int _dirsFinished, _data; + ScanDir* _parent; + ScanListener* _listener; + ScanManager* _manager; +}; + +#endif diff --git a/konq-plugins/fsview/scantest.cpp b/konq-plugins/fsview/scantest.cpp new file mode 100644 index 0000000..e1319a9 --- /dev/null +++ b/konq-plugins/fsview/scantest.cpp @@ -0,0 +1,56 @@ +/* This file is part of FSView. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* Test Directory Scanning. Usually not build. */ + +#include <stdio.h> +#include <unistd.h> + +#include "scan.h" + +class MyListener: public ScanListener +{ +public: + void scanStarted(ScanDir* d) + { + printf("Started Scan on %s\n", d->name().latin1()); + }; + + void sizeChanged(ScanDir* d) + { + printf("Change in %s: Dirs %d, Files %d", + d->name().latin1(), + d->dirCount(), d->fileCount()); + printf("Size %llu\n", (unsigned long long int)d->size()); + } + + void scanFinished(ScanDir* d) + { + printf("Finished Scan on %s\n", d->name().latin1()); + } +}; + +int main(int argc, char* argv[]) +{ + ScanManager m("/opt"); + if (argc>1) m.setTop(argv[1]); + + m.setListener(new MyListener()); + m.startScan(); + while(m.scan(1)); +} diff --git a/konq-plugins/fsview/treemap.cpp b/konq-plugins/fsview/treemap.cpp new file mode 100644 index 0000000..8de5c01 --- /dev/null +++ b/konq-plugins/fsview/treemap.cpp @@ -0,0 +1,3199 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/* + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + */ + +#include <math.h> + +#include <qpainter.h> +#include <qtooltip.h> +#include <qregexp.h> +#include <qstyle.h> +#include <qpopupmenu.h> + +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> + +#include "treemap.h" + + +// set this to 1 to enable debug output +#define DEBUG_DRAWING 0 +#define MAX_FIELD 12 + + +// +// StoredDrawParams +// +StoredDrawParams::StoredDrawParams() +{ + _selected = false; + _current = false; + _shaded = true; + _rotated = false; + + _backColor = Qt::white; + + // field array has size 0 +} + +StoredDrawParams::StoredDrawParams(QColor c, + bool selected, bool current) +{ + _backColor = c; + + _selected = selected; + _current = current; + _shaded = true; + _rotated = false; + + // field array has size 0 +} + +QString StoredDrawParams::text(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return QString::null; + + return _field[f].text; +} + +QPixmap StoredDrawParams::pixmap(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return QPixmap(); + + return _field[f].pix; +} + +DrawParams::Position StoredDrawParams::position(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return Default; + + return _field[f].pos; +} + +int StoredDrawParams::maxLines(int f) const +{ + if ((f<0) || (f >= (int)_field.size())) + return 0; + + return _field[f].maxLines; +} + +const QFont& StoredDrawParams::font() const +{ + static QFont* f = 0; + if (!f) f = new QFont(QApplication::font()); + + return *f; +} + +void StoredDrawParams::ensureField(int f) +{ + static Field* def = 0; + if (!def) { + def = new Field(); + def->pos = Default; + def->maxLines = 0; + } + + if (f<0 || f>=MAX_FIELD) return; + + if ((int)_field.size() < f+1) _field.resize(f+1, *def); +} + + +void StoredDrawParams::setField(int f, const QString& t, QPixmap pm, + Position p, int maxLines) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].text = t; + _field[f].pix = pm; + _field[f].pos = p; + _field[f].maxLines = maxLines; +} + +void StoredDrawParams::setText(int f, const QString& t) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].text = t; +} + +void StoredDrawParams::setPixmap(int f, const QPixmap& pm) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].pix = pm; +} + +void StoredDrawParams::setPosition(int f, Position p) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].pos = p; +} + +void StoredDrawParams::setMaxLines(int f, int m) +{ + if (f<0 || f>=MAX_FIELD) return; + ensureField(f); + + _field[f].maxLines = m; +} + + + +// +// RectDrawing +// + +RectDrawing::RectDrawing(QRect r) +{ + _fm = 0; + _dp = 0; + setRect(r); +} + + +RectDrawing::~RectDrawing() +{ + delete _fm; + delete _dp; +} + +DrawParams* RectDrawing::drawParams() +{ + if (!_dp) + _dp = new StoredDrawParams(); + + return _dp; +} + + +void RectDrawing::setDrawParams(DrawParams* dp) +{ + if (_dp) delete _dp; + _dp = dp; +} + +void RectDrawing::setRect(QRect r) +{ + _rect = r; + + _usedTopLeft = 0; + _usedTopCenter = 0; + _usedTopRight = 0; + _usedBottomLeft = 0; + _usedBottomCenter = 0; + _usedBottomRight = 0; + + _fontHeight = 0; +} + +QRect RectDrawing::remainingRect(DrawParams* dp) +{ + if (!dp) dp = drawParams(); + + if ((_usedTopLeft >0) || + (_usedTopCenter >0) || + (_usedTopRight >0)) { + if (dp->rotated()) + _rect.setLeft(_rect.left() + _fontHeight); + else + _rect.setTop(_rect.top() + _fontHeight); + } + + if ((_usedBottomLeft >0) || + (_usedBottomCenter >0) || + (_usedBottomRight >0)) { + if (dp->rotated()) + _rect.setRight(_rect.right() - _fontHeight); + else + _rect.setBottom(_rect.bottom() - _fontHeight); + } + return _rect; +} + + +void RectDrawing::drawBack(QPainter* p, DrawParams* dp) +{ + if (!dp) dp = drawParams(); + if (_rect.width()<=0 || _rect.height()<=0) return; + + QRect r = _rect; + QColor normal = dp->backColor(); + if (dp->selected()) normal = normal.light(); + bool isCurrent = dp->current(); + + // 3D raised/sunken frame effect... + QColor high = normal.light(); + QColor low = normal.dark(); + p->setPen( isCurrent ? low:high); + p->drawLine(r.left(), r.top(), r.right(), r.top()); + p->drawLine(r.left(), r.top(), r.left(), r.bottom()); + p->setPen( isCurrent ? high:low); + p->drawLine(r.right(), r.top(), r.right(), r.bottom()); + p->drawLine(r.left(), r.bottom(), r.right(), r.bottom()); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + + if (dp->shaded()) { + // some shading + bool goDark = qGray(normal.rgb())>128; + int rBase, gBase, bBase; + normal.rgb(&rBase, &gBase, &bBase); + p->setBrush(QBrush::NoBrush); + + // shade parameters: + int d = 7; + float factor = 0.1, forth=0.7, back1 =0.9, toBack2 = .7, back2 = 0.97; + + // coefficient corrections because of rectangle size + int s = r.width(); + if (s > r.height()) s = r.height(); + if (s<100) { + forth -= .3 * (100-s)/100; + back1 -= .2 * (100-s)/100; + back2 -= .02 * (100-s)/100; + } + + + // maximal color difference + int rDiff = goDark ? -rBase/d : (255-rBase)/d; + int gDiff = goDark ? -gBase/d : (255-gBase)/d; + int bDiff = goDark ? -bBase/d : (255-bBase)/d; + + QColor shadeColor; + while (factor<.95) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + factor = 1.0 - ((1.0 - factor) * forth); + } + + // and back (1st half) + while (factor>toBack2) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + factor = 1.0 - ((1.0 - factor) / back1); + } + + // and back (2nd half) + while ( factor>.01) { + shadeColor.setRgb((int)(rBase+factor*rDiff+.5), + (int)(gBase+factor*gDiff+.5), + (int)(bBase+factor*bDiff+.5)); + p->setPen(shadeColor); + p->drawRect(r); + r.setRect(r.x()+1, r.y()+1, r.width()-2, r.height()-2); + if (r.width()<=0 || r.height()<=0) return; + + factor = factor * back2; + } + } + + // fill inside + p->setPen(QPen::NoPen); + p->setBrush(normal); + p->drawRect(r); +} + + +bool RectDrawing::drawField(QPainter* p, int f, DrawParams* dp) +{ + if (!dp) dp = drawParams(); + + if (!_fm) { + _fm = new QFontMetrics(dp->font()); + _fontHeight = _fm->height(); + } + + QRect r = _rect; + + if (0) kdDebug(90100) << "DrawField: Rect " << r.x() << "/" << r.y() + << " - " << r.width() << "x" << r.height() << endl; + + int h = _fontHeight; + bool rotate = dp->rotated(); + int width = (rotate ? r.height() : r.width()) -4; + int height = (rotate ? r.width() : r.height()); + int lines = height / h; + + // stop if we have no space available + if (lines<1) return false; + + // calculate free space in first line (<unused>) + int pos = dp->position(f); + if (pos == DrawParams::Default) { + switch(f%4) { + case 0: pos = DrawParams::TopLeft; break; + case 1: pos = DrawParams::TopRight; break; + case 2: pos = DrawParams::BottomRight; break; + case 3: pos = DrawParams::BottomLeft; break; + } + } + + int unused = 0; + bool isBottom = false; + bool isCenter = false; + bool isRight = false; + int* used = 0; + switch(pos) { + case DrawParams::TopLeft: + used = &_usedTopLeft; + if (_usedTopLeft == 0) { + if (_usedTopCenter) + unused = (width - _usedTopCenter)/2; + else + unused = width - _usedTopRight; + } + break; + + case DrawParams::TopCenter: + isCenter = true; + used = &_usedTopCenter; + if (_usedTopCenter == 0) { + if (_usedTopLeft > _usedTopRight) + unused = width - 2 * _usedTopLeft; + else + unused = width - 2 * _usedTopRight; + } + break; + + case DrawParams::TopRight: + isRight = true; + used = &_usedTopRight; + if (_usedTopRight == 0) { + if (_usedTopCenter) + unused = (width - _usedTopCenter)/2; + else + unused = width - _usedTopLeft; + } + break; + + case DrawParams::BottomLeft: + isBottom = true; + used = &_usedBottomLeft; + if (_usedBottomLeft == 0) { + if (_usedBottomCenter) + unused = (width - _usedBottomCenter)/2; + else + unused = width - _usedBottomRight; + } + break; + + case DrawParams::BottomCenter: + isCenter = true; + isBottom = true; + used = &_usedBottomCenter; + if (_usedBottomCenter == 0) { + if (_usedBottomLeft > _usedBottomRight) + unused = width - 2 * _usedBottomLeft; + else + unused = width - 2 * _usedBottomRight; + } + break; + + case DrawParams::BottomRight: + isRight = true; + isBottom = true; + used = &_usedBottomRight; + if (_usedBottomRight == 0) { + if (_usedBottomCenter) + unused = (width - _usedBottomCenter)/2; + else + unused = width - _usedBottomLeft; + } + break; + } + + if (isBottom) { + if ((_usedTopLeft >0) || + (_usedTopCenter >0) || + (_usedTopRight >0)) + lines--; + } + else if (!isBottom) { + if ((_usedBottomLeft >0) || + (_usedBottomCenter >0) || + (_usedBottomRight >0)) + lines--; + } + if (lines<1) return false; + + + int y = isBottom ? height - h : 0; + + if (unused < 0) unused = 0; + if (unused == 0) { + // no space available in last line at this position + y = isBottom ? (y-h) : (y+h); + lines--; + + if (lines<1) return false; + + // new line: reset used space + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + + unused = width; + } + + // stop as soon as possible when there's no space for "..." + static int dotW = 0; + if (!dotW) dotW = _fm->width("..."); + if (width < dotW) return false; + + // get text and pixmap now, only if we need to, because it is possible + // that they are calculated on demand (and this can take some time) + QString name = dp->text(f); + if (name.isEmpty()) return 0; + QPixmap pix = dp->pixmap(f); + + // check if pixmap can be drawn + int pixW = pix.width(); + int pixH = pix.height(); + int pixY = 0; + bool pixDrawn = true; + if (pixW>0) { + pixW += 2; // X distance from pix + if ((width < pixW + dotW) || (height < pixH)) { + // don't draw + pixW = 0; + } + else + pixDrawn = false; + } + + // width of text and pixmap to be drawn + int w = pixW + _fm->width(name); + + if (0) kdDebug(90100) << " For '" << name << "': Unused " << unused + << ", StrW " << w << ", Width " << width << endl; + + // if we have limited space at 1st line: + // use it only if whole name does fit in last line... + if ((unused < width) && (w > unused)) { + y = isBottom ? (y-h) : (y+h); + lines--; + + if (lines<1) return false; + + // new line: reset used space + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + + p->save(); + p->setPen( (qGray(dp->backColor().rgb())>100) ? Qt::black : Qt::white); + p->setFont(dp->font()); + if (rotate) { + //p->translate(r.x()+2, r.y()+r.height()); + p->translate(r.x(), r.y()+r.height()-2); + p->rotate(270); + } + else + p->translate(r.x()+2, r.y()); + + + // adjust available lines according to maxLines + int max = dp->maxLines(f); + if ((max > 0) && (lines>max)) lines = max; + + /* loop over name parts to break up string depending on available width. + * every char category change is supposed a possible break, + * with the exception Uppercase=>Lowercase. + * It's good enough for numbers, Symbols... + * + * If the text is to be written at the bottom, we start with the + * end of the string (so everything is reverted) + */ + QString remaining; + int origLines = lines; + while (lines>0) { + + if (w>width && lines>1) { + int lastBreakPos = name.length(), lastWidth = w; + int len = name.length(); + QChar::Category caOld, ca; + + if (!isBottom) { + // start with comparing categories of last 2 chars + caOld = name[len-1].category(); + while (len>2) { + len--; + ca = name[len-1].category(); + if (ca != caOld) { + // "Aa" has no break between... + if (ca == QChar::Letter_Uppercase && + caOld == QChar::Letter_Lowercase) { + caOld = ca; + continue; + } + caOld = ca; + lastBreakPos = len; + w = pixW + _fm->width(name, len); + lastWidth = w; + if (w <= width) break; + } + } + w = lastWidth; + remaining = name.mid(lastBreakPos); + // remove space on break point + if (name[lastBreakPos-1].category() == QChar::Separator_Space) + name = name.left(lastBreakPos-1); + else + name = name.left(lastBreakPos); + } + else { // bottom + int l = len; + caOld = name[l-len].category(); + while (len>2) { + len--; + ca = name[l-len].category(); + + if (ca != caOld) { + // "Aa" has no break between... + if (caOld == QChar::Letter_Uppercase && + ca == QChar::Letter_Lowercase) { + caOld = ca; + continue; + } + caOld = ca; + lastBreakPos = len; + w = pixW + _fm->width(name.right(len)); + lastWidth = w; + if (w <= width) break; + } + } + w = lastWidth; + remaining = name.left(l-lastBreakPos); + // remove space on break point + if (name[l-lastBreakPos].category() == QChar::Separator_Space) + name = name.right(lastBreakPos-1); + else + name = name.right(lastBreakPos); + } + } + else + remaining = QString::null; + + /* truncate and add ... if needed */ + if (w>width) { + int len = name.length(); + w += dotW; + while (len>2 && (w > width)) { + len--; + w = pixW + _fm->width(name, len) + dotW; + } + // stop drawing: we cannot draw 2 chars + "..." + if (w>width) break; + + name = name.left(len) + "..."; + } + + int x = 0; + if (isCenter) + x = (width - w)/2; + else if (isRight) + x = width - w; + + if (!pixDrawn) { + pixY = y+(h-pixH)/2; // default: center vertically + if (pixH > h) pixY = isBottom ? y-(pixH-h) : y; + + p->drawPixmap( x, pixY, pix); + + // for distance to next text + pixY = isBottom ? (pixY - h - 2) : (pixY + pixH + 2); + pixDrawn = true; + } + + + if (0) kdDebug(90100) << " Drawing '" << name << "' at " + << x+pixW << "/" << y << endl; + + p->drawText( x+pixW, y, + width - pixW, h, + Qt::AlignLeft, name); + y = isBottom ? (y-h) : (y+h); + lines--; + + if (remaining.isEmpty()) break; + name = remaining; + w = pixW + _fm->width(name); + } + + // make sure the pix stays visible + if (pixDrawn && (pixY>0)) { + if (isBottom && (pixY<y)) y = pixY; + if (!isBottom && (pixY>y)) y = pixY; + } + + if (origLines > lines) { + // if only 1 line written, don't reset _used* vars + if (lines - origLines >1) { + if (isBottom) + _usedBottomLeft = _usedBottomCenter = _usedBottomRight = 0; + else + _usedTopLeft = _usedTopCenter = _usedTopRight = 0; + } + + // take back one line + y = isBottom ? (y+h) : (y-h); + if (used) *used = w; + } + + // update free space + if (!isBottom) { + if (rotate) + _rect.setRect(r.x()+y, r.y(), r.width()-y, r.height()); + else + _rect.setRect(r.x(), r.y()+y, r.width(), r.height()-y); + } + else { + if (rotate) + _rect.setRect(r.x(), r.y(), y+h, r.height()); + else + _rect.setRect(r.x(), r.y(), r.width(), y+h); + } + + p->restore(); + + return true; +} + + + + + + +// +// TreeMapItemList +// + +int TreeMapItemList::compareItems ( Item item1, Item item2 ) +{ + bool ascending; + int result; + + TreeMapItem* parent = ((TreeMapItem*)item1)->parent(); + // shouldn't happen + if (!parent) return 0; + + int textNo = parent->sorting(&ascending); + + if (textNo < 0) { + double diff = ((TreeMapItem*)item1)->value() - + ((TreeMapItem*)item2)->value(); + result = (diff < -.9) ? -1 : (diff > .9) ? 1 : 0; + } + else + result = (((TreeMapItem*)item1)->text(textNo) < + ((TreeMapItem*)item2)->text(textNo)) ? -1 : 1; + + return ascending ? result : -result; +} + + +TreeMapItem* TreeMapItemList::commonParent() +{ + TreeMapItem* parent, *item; + parent = first(); + if (parent) + while( (item = next()) != 0) + parent = parent->commonParent(item); + + return parent; +} + + +// TreeMapItem + +TreeMapItem::TreeMapItem(TreeMapItem* parent, double value) +{ + _value = value; + _parent = parent; + + _sum = 0; + _children = 0; + _widget = 0; + _index = -1; + _depth = -1; // not set + _unused_self = 0; + _freeRects = 0; + + if (_parent) { + // take sorting from parent + _sortTextNo = _parent->sorting(&_sortAscending); + _parent->addItem(this); + } + else { + _sortAscending = false; + _sortTextNo = -1; // default: no sorting + } +} + + +TreeMapItem::TreeMapItem(TreeMapItem* parent, double value, + QString text1, QString text2, + QString text3, QString text4) +{ + _value = value; + _parent = parent; + + // this resizes the text vector only if needed + if (!text4.isEmpty()) setText(3, text4); + if (!text3.isEmpty()) setText(2, text3); + if (!text2.isEmpty()) setText(1, text2); + setText(0, text1); + + _sum = 0; + _children = 0; + _widget = 0; + _index = -1; + _depth = -1; // not set + _unused_self = 0; + _freeRects = 0; + + if (_parent) _parent->addItem(this); +} + +TreeMapItem::~TreeMapItem() +{ + if (_children) delete _children; + if (_freeRects) delete _freeRects; + + // finally, notify widget about deletion + if (_widget) _widget->deletingItem(this); +} + +void TreeMapItem::setParent(TreeMapItem* p) +{ + _parent = p; + if (p) _widget = p->_widget; +} + +bool TreeMapItem::isChildOf(TreeMapItem* item) +{ + if (!item) return false; + + TreeMapItem* i = this; + while (i) { + if (item == i) return true; + i = i->_parent; + } + return false; +} + +TreeMapItem* TreeMapItem::commonParent(TreeMapItem* item) +{ + while (item && !isChildOf(item)) { + item = item->parent(); + } + return item; +} + +void TreeMapItem::redraw() +{ + if (_widget) + _widget->redraw(this); +} + +void TreeMapItem::clear() +{ + if (_children) { + // delete selected items below this item from selection + if (_widget) _widget->clearSelection(this); + + delete _children; + _children = 0; + } +} + + +// invalidates current children and forces redraw +// this is only usefull when children are created on demand in items() +void TreeMapItem::refresh() +{ + clear(); + redraw(); +} + + +QStringList TreeMapItem::path(int textNo) const +{ + QStringList list(text(textNo)); + + TreeMapItem* i = _parent; + while (i) { + QString text = i->text(textNo); + if (!text.isEmpty()) + list.prepend(i->text(textNo)); + i = i->_parent; + } + return list; +} + +int TreeMapItem::depth() const +{ + if (_depth>0) return _depth; + + if (_parent) + return _parent->depth() + 1; + return 1; +} + + +bool TreeMapItem::initialized() +{ + if (!_children) { + _children = new TreeMapItemList; + _children->setAutoDelete(true); + return false; + } + return true; +} + +void TreeMapItem::addItem(TreeMapItem* i) +{ + if (!i) return; + + if (!_children) { + _children = new TreeMapItemList; + _children->setAutoDelete(true); + } + i->setParent(this); + + if (sorting(0) == -1) + _children->append(i); // preserve insertion order + else + _children->inSort(i); +} + + +// default implementations of virtual functions + +double TreeMapItem::value() const +{ + return _value; +} + +double TreeMapItem::sum() const +{ + return _sum; +} + +DrawParams::Position TreeMapItem::position(int f) const +{ + Position p = StoredDrawParams::position(f); + if (_widget && (p == Default)) + p = _widget->fieldPosition(f); + + return p; +} + +// use widget font +const QFont& TreeMapItem::font() const +{ + return _widget->currentFont(); +} + + +bool TreeMapItem::isMarked(int) const +{ + return false; +} + + +int TreeMapItem::borderWidth() const +{ + if (_widget) + return _widget->borderWidth(); + + return 2; +} + +int TreeMapItem::sorting(bool* ascending) const +{ + if (ascending) *ascending = _sortAscending; + return _sortTextNo; +} + +// do *not* set sorting recursively +void TreeMapItem::setSorting(int textNo, bool ascending) +{ + if (_sortTextNo == textNo) { + if(_sortAscending == ascending) return; + if (textNo == -1) { + // when no sorting is done, order change doesn't do anything + _sortAscending = ascending; + return; + } + } + _sortAscending = ascending; + _sortTextNo = textNo; + + if (_children && _sortTextNo != -1) _children->sort(); +} + +void TreeMapItem::resort(bool recursive) +{ + if (!_children) return; + + if (_sortTextNo != -1) _children->sort(); + + if (recursive) + for (TreeMapItem* i=_children->first(); i; i=_children->next()) + i->resort(recursive); +} + + +TreeMapItem::SplitMode TreeMapItem::splitMode() const +{ + if (_widget) + return _widget->splitMode(); + + return Best; +} + +int TreeMapItem::rtti() const +{ + return 0; +} + +TreeMapItemList* TreeMapItem::children() +{ + if (!_children) { + _children = new TreeMapItemList; + _children->setAutoDelete(true); + } + return _children; +} + +void TreeMapItem::clearItemRect() +{ + _rect = QRect(); + clearFreeRects(); +} + +void TreeMapItem::clearFreeRects() +{ + if (_freeRects) _freeRects->clear(); +} + +void TreeMapItem::addFreeRect(const QRect& r) +{ + // don't add invalid rects + if ((r.width() < 1) || (r.height() < 1)) return; + + if (!_freeRects) { + _freeRects = new QPtrList<QRect>; + _freeRects->setAutoDelete(true); + } + + if (0) kdDebug(90100) << "addFree(" << path(0).join("/") << ", " + << r.x() << "/" << r.y() << "-" + << r.width() << "x" << r.height() << ")" << endl; + + QRect* last = _freeRects->last(); + if (!last) { + _freeRects->append(new QRect(r)); + return; + } + + // join rect with last rect if possible + // this saves memory and doesn't make the tooltip flicker + + bool replaced = false; + if ((last->left() == r.left()) && (last->width() == r.width())) { + if ((last->bottom()+1 == r.top()) || (r.bottom()+1 == last->top())) { + *last |= r; + replaced = true; + } + } + else if ((last->top() == r.top()) && (last->height() == r.height())) { + if ((last->right()+1 == r.left()) || (r.right()+1 == last->left())) { + *last |= r; + replaced = true; + } + } + + if (!replaced) { + _freeRects->append(new QRect(r)); + return; + } + + if (0) kdDebug(90100) << " united with last to (" + << last->x() << "/" << last->y() << "-" + << last->width() << "x" << last->height() << ")" << endl; +} + + +// Tooltips for TreeMapWidget + +class TreeMapTip: public QToolTip +{ +public: + TreeMapTip( QWidget* p ):QToolTip(p) {} + +protected: + void maybeTip( const QPoint & ); +}; + +void TreeMapTip::maybeTip( const QPoint& pos ) +{ + if ( !parentWidget()->inherits( "TreeMapWidget" ) ) + return; + + TreeMapWidget* p = (TreeMapWidget*)parentWidget(); + TreeMapItem* i; + i = p->item(pos.x(), pos.y()); + QPtrList<QRect>* rList = i ? i->freeRects() : 0; + if (rList) { + QRect* r; + for(r=rList->first();r;r=rList->next()) + if (r->contains(pos)) + tip(*r, p->tipString(i)); + } +} + + + +// TreeMapWidget + +TreeMapWidget::TreeMapWidget(TreeMapItem* base, + QWidget* parent, const char* name) + : QWidget(parent, name) +{ + _base = base; + _base->setWidget(this); + + _font = font(); + _fontHeight = fontMetrics().height(); + + + // default behaviour + _selectionMode = Single; + _splitMode = TreeMapItem::AlwaysBest; + _visibleWidth = 2; + _reuseSpace = false; + _skipIncorrectBorder = false; + _drawSeparators = false; + _allowRotation = true; + _borderWidth = 2; + _shading = true; // beautiful is default! + _maxSelectDepth = -1; // unlimited + _maxDrawingDepth = -1; // unlimited + _minimalArea = -1; // unlimited + _markNo = 0; + + // _stopAtText will be unset on resizing (per default) + // _textVisible will be true on resizing (per default) + // _forceText will be false on resizing (per default) + + // start state: _selection is an empty list + _current = 0; + _oldCurrent = 0; + _pressed = 0; + _lastOver = 0; + _needsRefresh = _base; + + setBackgroundMode(Qt::NoBackground); + setFocusPolicy(QWidget::StrongFocus); + _tip = new TreeMapTip(this); +} + +TreeMapWidget::~TreeMapWidget() +{ +} + +const QFont& TreeMapWidget::currentFont() const +{ + return _font; +} + +void TreeMapWidget::setSplitMode(TreeMapItem::SplitMode m) +{ + if (_splitMode == m) return; + + _splitMode = m; + redraw(); +} + +TreeMapItem::SplitMode TreeMapWidget::splitMode() const +{ + return _splitMode; +} + +bool TreeMapWidget::setSplitMode(QString mode) +{ + if (mode == "Bisection") setSplitMode(TreeMapItem::Bisection); + else if (mode == "Columns") setSplitMode(TreeMapItem::Columns); + else if (mode == "Rows") setSplitMode(TreeMapItem::Rows); + else if (mode == "AlwaysBest") setSplitMode(TreeMapItem::AlwaysBest); + else if (mode == "Best") setSplitMode(TreeMapItem::Best); + else if (mode == "HAlternate") setSplitMode(TreeMapItem::HAlternate); + else if (mode == "VAlternate") setSplitMode(TreeMapItem::VAlternate); + else if (mode == "Horizontal") setSplitMode(TreeMapItem::Horizontal); + else if (mode == "Vertical") setSplitMode(TreeMapItem::Vertical); + else return false; + + return true; +} + +QString TreeMapWidget::splitModeString() const +{ + QString mode; + switch(splitMode()) { + case TreeMapItem::Bisection: mode = "Bisection"; break; + case TreeMapItem::Columns: mode = "Columns"; break; + case TreeMapItem::Rows: mode = "Rows"; break; + case TreeMapItem::AlwaysBest: mode = "AlwaysBest"; break; + case TreeMapItem::Best: mode = "Best"; break; + case TreeMapItem::HAlternate: mode = "HAlternate"; break; + case TreeMapItem::VAlternate: mode = "VAlternate"; break; + case TreeMapItem::Horizontal: mode = "Horizontal"; break; + case TreeMapItem::Vertical: mode = "Vertical"; break; + default: mode = "Unknown"; break; + } + return mode; +} + + +void TreeMapWidget::setShadingEnabled(bool s) +{ + if (_shading == s) return; + + _shading = s; + redraw(); +} + +void TreeMapWidget::setAllowRotation(bool enable) +{ + if (_allowRotation == enable) return; + + _allowRotation = enable; + redraw(); +} + +void TreeMapWidget::setVisibleWidth(int width, bool reuseSpace) +{ + if (_visibleWidth == width && _reuseSpace == reuseSpace) return; + + _visibleWidth = width; + _reuseSpace = reuseSpace; + redraw(); +} + +void TreeMapWidget::setSkipIncorrectBorder(bool enable) +{ + if (_skipIncorrectBorder == enable) return; + + _skipIncorrectBorder = enable; + redraw(); +} + +void TreeMapWidget::setBorderWidth(int w) +{ + if (_borderWidth == w) return; + + _borderWidth = w; + redraw(); +} + +void TreeMapWidget::setMaxDrawingDepth(int d) +{ + if (_maxDrawingDepth == d) return; + + _maxDrawingDepth = d; + redraw(); +} + +QString TreeMapWidget::defaultFieldType(int f) const +{ + return i18n("Text %1").arg(f+1); +} + +QString TreeMapWidget::defaultFieldStop(int) const +{ + return QString(); +} + +bool TreeMapWidget::defaultFieldVisible(int f) const +{ + return (f<2); +} + +bool TreeMapWidget::defaultFieldForced(int) const +{ + return false; +} + +DrawParams::Position TreeMapWidget::defaultFieldPosition(int f) const +{ + switch(f%4) { + case 0: return DrawParams::TopLeft; + case 1: return DrawParams::TopRight; + case 2: return DrawParams::BottomRight; + case 3: return DrawParams::BottomLeft; + default:break; + } + return DrawParams::TopLeft; +} + +bool TreeMapWidget::resizeAttr(int size) +{ + if (size<0 || size>=MAX_FIELD) return false; + + if (size>(int)_attr.size()) { + struct FieldAttr a; + int oldSize = _attr.size(); + _attr.resize(size, a); + while (oldSize<size) { + _attr[oldSize].type = defaultFieldType(oldSize); + _attr[oldSize].stop = defaultFieldStop(oldSize); + _attr[oldSize].visible = defaultFieldVisible(oldSize); + _attr[oldSize].forced = defaultFieldForced(oldSize); + _attr[oldSize].pos = defaultFieldPosition(oldSize); + oldSize++; + } + } + return true; +} + +void TreeMapWidget::setFieldType(int f, QString type) +{ + if (((int)_attr.size() < f+1) && + (type == defaultFieldType(f))) return; + if (resizeAttr(f+1)) _attr[f].type = type; + + // no need to redraw: the type string is not visible in the TreeMap +} + +QString TreeMapWidget::fieldType(int f) const +{ + if (f<0 || (int)_attr.size()<f+1) return defaultFieldType(f); + return _attr[f].type; +} + +void TreeMapWidget::setFieldStop(int f, QString stop) +{ + if (((int)_attr.size() < f+1) && + (stop == defaultFieldStop(f))) return; + if (resizeAttr(f+1)) { + _attr[f].stop = stop; + redraw(); + } +} + +QString TreeMapWidget::fieldStop(int f) const +{ + if (f<0 || (int)_attr.size()<f+1) return defaultFieldStop(f); + return _attr[f].stop; +} + +void TreeMapWidget::setFieldVisible(int f, bool enable) +{ + if (((int)_attr.size() < f+1) && + (enable == defaultFieldVisible(f))) return; + + if (resizeAttr(f+1)) { + _attr[f].visible = enable; + redraw(); + } +} + +bool TreeMapWidget::fieldVisible(int f) const +{ + if (f<0 || (int)_attr.size()<f+1) + return defaultFieldVisible(f); + + return _attr[f].visible; +} + +void TreeMapWidget::setFieldForced(int f, bool enable) +{ + if (((int)_attr.size() < f+1) && + (enable == defaultFieldForced(f))) return; + + if (resizeAttr(f+1)) { + _attr[f].forced = enable; + if (_attr[f].visible) redraw(); + } +} + +bool TreeMapWidget::fieldForced(int f) const +{ + if (f<0 || (int)_attr.size()<f+1) + return defaultFieldForced(f); + + return _attr[f].forced; +} + +void TreeMapWidget::setFieldPosition(int f, TreeMapItem::Position pos) +{ + if (((int)_attr.size() < f+1) && + (pos == defaultFieldPosition(f))) return; + + if (resizeAttr(f+1)) { + _attr[f].pos = pos; + if (_attr[f].visible) redraw(); + } +} + +DrawParams::Position TreeMapWidget::fieldPosition(int f) const +{ + if (f<0 || (int)_attr.size()<f+1) + return defaultFieldPosition(f); + + return _attr[f].pos; +} + +void TreeMapWidget::setFieldPosition(int f, QString pos) +{ + if (pos == "TopLeft") + setFieldPosition(f, DrawParams::TopLeft); + else if (pos == "TopCenter") + setFieldPosition(f, DrawParams::TopCenter); + else if (pos == "TopRight") + setFieldPosition(f, DrawParams::TopRight); + else if (pos == "BottomLeft") + setFieldPosition(f, DrawParams::BottomLeft); + else if (pos == "BottomCenter") + setFieldPosition(f, DrawParams::BottomCenter); + else if (pos == "BottomRight") + setFieldPosition(f, DrawParams::BottomRight); + else if (pos == "Default") + setFieldPosition(f, DrawParams::Default); +} + +QString TreeMapWidget::fieldPositionString(int f) const +{ + TreeMapItem::Position pos = fieldPosition(f); + if (pos == DrawParams::TopLeft) return QString("TopLeft"); + if (pos == DrawParams::TopCenter) return QString("TopCenter"); + if (pos == DrawParams::TopRight) return QString("TopRight"); + if (pos == DrawParams::BottomLeft) return QString("BottomLeft"); + if (pos == DrawParams::BottomCenter) return QString("BottomCenter"); + if (pos == DrawParams::BottomRight) return QString("BottomRight"); + if (pos == DrawParams::Default) return QString("Default"); + return QString("unknown"); +} + +void TreeMapWidget::setMinimalArea(int area) +{ + if (_minimalArea == area) return; + + _minimalArea = area; + redraw(); +} + + +void TreeMapWidget::deletingItem(TreeMapItem* i) +{ + // remove any references to the item to be deleted + while(_selection.findRef(i) > -1) + _selection.remove(); + + while(_tmpSelection.findRef(i) > -1) + _tmpSelection.remove(); + + if (_current == i) _current = 0; + if (_oldCurrent == i) _oldCurrent = 0; + if (_pressed == i) _pressed = 0; + if (_lastOver == i) _lastOver = 0; + + // don't redraw a deleted item + if (_needsRefresh == i) { + // we can savely redraw the parent, as deleting order is + // from child to parent; i.e. i->parent() is existing. + _needsRefresh = i->parent(); + } +} + + +QString TreeMapWidget::tipString(TreeMapItem* i) const +{ + QString tip, itemTip; + + while (i) { + if (!i->text(0).isEmpty()) { + itemTip = i->text(0); + if (!i->text(1).isEmpty()) + itemTip += " (" + i->text(1) + ")"; + + if (!tip.isEmpty()) + tip += "\n"; + + tip += itemTip; + } + i = i->parent(); + } + return tip; +} + +TreeMapItem* TreeMapWidget::item(int x, int y) const +{ + TreeMapItem* p = _base; + TreeMapItem* i; + + if (!rect().contains(x, y)) return 0; + if (DEBUG_DRAWING) kdDebug(90100) << "item(" << x << "," << y << "):" << endl; + + while (1) { + TreeMapItemList* list = p->children(); + if (!list) + i = 0; + else { + int idx=0; + for (i=list->first();i;i=list->next(),idx++) { + + if (DEBUG_DRAWING) + kdDebug(90100) << " Checking " << i->path(0).join("/") << " (" + << i->itemRect().x() << "/" << i->itemRect().y() + << "-" << i->itemRect().width() + << "x" << i->itemRect().height() << ")" << endl; + + if (i->itemRect().contains(x, y)) { + + if (DEBUG_DRAWING) kdDebug(90100) << " .. Got. Index " << idx << endl; + + p->setIndex(idx); + break; + } + } + } + + if (!i) { + static TreeMapItem* last = 0; + if (p != last) { + last = p; + + if (DEBUG_DRAWING) + kdDebug(90100) << "item(" << x << "," << y << "): Got " + << p->path(0).join("/") << " (Size " + << p->itemRect().width() << "x" << p->itemRect().height() + << ", Val " << p->value() << ")" << endl; + } + + return p; + } + p = i; + } + return 0; +} + +TreeMapItem* TreeMapWidget::possibleSelection(TreeMapItem* i) const +{ + if (i) { + if (_maxSelectDepth>=0) { + int depth = i->depth(); + while(i && depth > _maxSelectDepth) { + i = i->parent(); + depth--; + } + } + } + return i; +} + +TreeMapItem* TreeMapWidget::visibleItem(TreeMapItem* i) const +{ + if (i) { + /* Must have a visible area */ + while(i && ((i->itemRect().width() <1) || + (i->itemRect().height() <1))) { + TreeMapItem* p = i->parent(); + if (!p) break; + int idx = p->children()->findRef(i); + idx--; + if (idx<0) + i = p; + else + i = p->children()->at(idx); + } + } + return i; +} + +void TreeMapWidget::setSelected(TreeMapItem* item, bool selected) +{ + item = possibleSelection(item); + setCurrent(item); + + TreeMapItem* changed = setTmpSelected(item, selected); + if (!changed) return; + + _selection = _tmpSelection; + if (_selectionMode == Single) + emit selectionChanged(item); + emit selectionChanged(); + redraw(changed); + + if (0) kdDebug(90100) << (selected ? "S":"Des") << "elected Item " + << (item ? item->path(0).join("") : QString("(null)")) + << " (depth " << (item ? item->depth() : -1) + << ")" << endl; +} + +void TreeMapWidget::setMarked(int markNo, bool redrawWidget) +{ + // if there's no marking, return + if ((_markNo == 0) && (markNo == 0)) return; + + _markNo = markNo; + if (!clearSelection() && redrawWidget) redraw(); +} + +/* Returns all items which appear only in one of the given lists */ +TreeMapItemList TreeMapWidget::diff(TreeMapItemList& l1, + TreeMapItemList& l2) +{ + TreeMapItemList l; + TreeMapItemListIterator it1(l1), it2(l2); + + TreeMapItem* item; + while ( (item = it1.current()) != 0 ) { + ++it1; + if (l2.containsRef(item) > 0) continue; + l.append(item); + } + while ( (item = it2.current()) != 0 ) { + ++it2; + if (l1.containsRef(item) > 0) continue; + l.append(item); + } + + return l; +} + +/* Only modifies _tmpSelection. + * Returns 0 when no change happened, otherwise the TreeMapItem that has + * to be redrawn for all changes. + */ +TreeMapItem* TreeMapWidget::setTmpSelected(TreeMapItem* item, bool selected) +{ + if (!item) return 0; + if (_selectionMode == NoSelection) return 0; + + TreeMapItemList old = _tmpSelection; + + if (_selectionMode == Single) { + _tmpSelection.clear(); + if (selected) _tmpSelection.append(item); + } + else { + if (selected) { + TreeMapItem* i=_tmpSelection.first(); + while (i) { + if (i->isChildOf(item) || item->isChildOf(i)) { + _tmpSelection.remove(); + i = _tmpSelection.current(); + } + else + i = _tmpSelection.next(); + } + _tmpSelection.append(item); + } + else + _tmpSelection.removeRef(item); + } + + return diff(old, _tmpSelection).commonParent(); +} + + +bool TreeMapWidget::clearSelection(TreeMapItem* parent) +{ + TreeMapItemList old = _selection; + + TreeMapItem* i=_selection.first(); + while (i) { + if (i->isChildOf(parent)) { + _selection.remove(); + i = _selection.current(); + } + else + i = _selection.next(); + } + + TreeMapItem* changed = diff(old, _selection).commonParent(); + if (changed) { + changed->redraw(); + emit selectionChanged(); + } + return (changed != 0); +} + +bool TreeMapWidget::isSelected(TreeMapItem* i) const +{ + return _selection.containsRef(i)>0; +} + +bool TreeMapWidget::isTmpSelected(TreeMapItem* i) +{ + return _tmpSelection.containsRef(i)>0; +} + + +void TreeMapWidget::setCurrent(TreeMapItem* i, bool kbd) +{ + TreeMapItem* old = _current; + _current = i; + + if (_markNo >0) { + // remove mark + _markNo = 0; + + if (1) kdDebug(90100) << "setCurrent(" << i->path(0).join("/") + << ") - mark removed" << endl; + + // always complete redraw needed to remove mark + redraw(); + + if (old == _current) return; + } + else { + if (old == _current) return; + + if (old) old->redraw(); + if (i) i->redraw(); + } + + //kdDebug(90100) << "Current Item " << (i ? i->path().ascii() : "(null)") << endl; + + emit currentChanged(i, kbd); +} + +void TreeMapWidget::setRangeSelection(TreeMapItem* i1, + TreeMapItem* i2, bool selected) +{ + i1 = possibleSelection(i1); + i2 = possibleSelection(i2); + setCurrent(i2); + + TreeMapItem* changed = setTmpRangeSelection(i1, i2, selected); + if (!changed) return; + + _selection = _tmpSelection; + if (_selectionMode == Single) + emit selectionChanged(i2); + emit selectionChanged(); + redraw(changed); +} + +TreeMapItem* TreeMapWidget::setTmpRangeSelection(TreeMapItem* i1, + TreeMapItem* i2, + bool selected) +{ + if ((i1 == 0) && (i2 == 0)) return 0; + if ((i1 == 0) || i1->isChildOf(i2)) return setTmpSelected(i2, selected); + if ((i2 == 0) || i2->isChildOf(i1)) return setTmpSelected(i1, selected); + + TreeMapItem* changed = setTmpSelected(i1, selected); + TreeMapItem* changed2 = setTmpSelected(i2, selected); + if (changed2) changed = changed2->commonParent(changed); + + TreeMapItem* commonParent = i1; + while (commonParent && !i2->isChildOf(commonParent)) { + i1 = commonParent; + commonParent = commonParent->parent(); + } + if (!commonParent) return changed; + while (i2 && i2->parent() != commonParent) + i2 = i2->parent(); + if (!i2) return changed; + + TreeMapItemList* list = commonParent->children(); + if (!list) return changed; + + TreeMapItem* i = list->first(); + bool between = false; + while (i) { + if (between) { + if (i==i1 || i==i2) break; + changed2 = setTmpSelected(i, selected); + if (changed2) changed = changed2->commonParent(changed); + } + else if (i==i1 || i==i2) + between = true; + i = list->next(); + } + + return changed; +} + +void TreeMapWidget::contextMenuEvent( QContextMenuEvent* e ) +{ + //kdDebug(90100) << "TreeMapWidget::contextMenuEvent" << endl; + + if ( receivers( SIGNAL(contextMenuRequested(TreeMapItem*, const QPoint &)) ) ) + e->accept(); + + if ( e->reason() == QContextMenuEvent::Keyboard ) { + QRect r = (_current) ? _current->itemRect() : _base->itemRect(); + QPoint p = QPoint(r.left() + r.width()/2, r.top() + r.height()/2); + emit contextMenuRequested(_current, p); + } + else { + TreeMapItem* i = item(e->x(), e->y()); + emit contextMenuRequested(i, e->pos()); + } +} + + +void TreeMapWidget::mousePressEvent( QMouseEvent* e ) +{ + //kdDebug(90100) << "TreeMapWidget::mousePressEvent" << endl; + + _oldCurrent = _current; + + TreeMapItem* i = item(e->x(), e->y()); + + _pressed = i; + + _inShiftDrag = e->state() & ShiftButton; + _inControlDrag = e->state() & ControlButton; + _lastOver = _pressed; + + TreeMapItem* changed = 0; + TreeMapItem* item = possibleSelection(_pressed); + + switch(_selectionMode) { + case Single: + changed = setTmpSelected(item, true); + break; + case Multi: + changed = setTmpSelected(item, !isTmpSelected(item)); + break; + case Extended: + if (_inControlDrag) + changed = setTmpSelected(item, !isTmpSelected(item)); + else if (_inShiftDrag) { + TreeMapItem* sCurrent = possibleSelection(_current); + changed = setTmpRangeSelection(sCurrent, item, + !isTmpSelected(item)); + } + else { + _selectionMode = Single; + changed = setTmpSelected(item, true); + _selectionMode = Extended; + } + break; + default: + break; + } + + // item under mouse always selected on right button press + if (e->button() == RightButton) { + TreeMapItem* changed2 = setTmpSelected(item, true); + if (changed2) changed = changed2->commonParent(changed); + } + + setCurrent(_pressed); + + if (changed) + redraw(changed); + + if (e->button() == RightButton) { + + // emit selection change + if (! (_tmpSelection == _selection)) { + _selection = _tmpSelection; + if (_selectionMode == Single) + emit selectionChanged(_lastOver); + emit selectionChanged(); + } + _pressed = 0; + _lastOver = 0; + emit rightButtonPressed(i, e->pos()); + } +} + +void TreeMapWidget::mouseMoveEvent( QMouseEvent* e ) +{ + //kdDebug(90100) << "TreeMapWidget::mouseMoveEvent" << endl; + + if (!_pressed) return; + TreeMapItem* over = item(e->x(), e->y()); + if (_lastOver == over) return; + + setCurrent(over); + if (over == 0) { + _lastOver = 0; + return; + } + + TreeMapItem* changed = 0; + TreeMapItem* item = possibleSelection(over); + + switch(_selectionMode) { + case Single: + changed = setTmpSelected(item, true); + break; + case Multi: + changed = setTmpSelected(item, !isTmpSelected(item)); + break; + case Extended: + if (_inControlDrag) + changed = setTmpSelected(item, !isTmpSelected(item)); + else { + TreeMapItem* sLast = possibleSelection(_lastOver); + changed = setTmpRangeSelection(sLast, item, true); + } + break; + + default: + break; + } + + _lastOver = over; + + if (changed) + redraw(changed); +} + +void TreeMapWidget::mouseReleaseEvent( QMouseEvent* ) +{ + //kdDebug(90100) << "TreeMapWidget::mouseReleaseEvent" << endl; + + if (!_pressed) return; + + if (!_lastOver) { + // take back + setCurrent(_oldCurrent); + TreeMapItem* changed = diff(_tmpSelection, _selection).commonParent(); + _tmpSelection = _selection; + if (changed) + redraw(changed); + } + else { + if (! (_tmpSelection == _selection)) { + _selection = _tmpSelection; + if (_selectionMode == Single) + emit selectionChanged(_lastOver); + emit selectionChanged(); + } + if (!_inControlDrag && !_inShiftDrag && (_pressed == _lastOver)) + emit clicked(_lastOver); + } + + _pressed = 0; + _lastOver = 0; +} + + +void TreeMapWidget::mouseDoubleClickEvent( QMouseEvent* e ) +{ + TreeMapItem* over = item(e->x(), e->y()); + + emit doubleClicked(over); +} + + +/* returns -1 if nothing visible found */ +int nextVisible(TreeMapItem* i) +{ + TreeMapItem* p = i->parent(); + if (!p || p->itemRect().isEmpty()) return -1; + + int idx = p->children()->findRef(i); + if (idx<0) return -1; + + while (idx < (int)p->children()->count()-1) { + idx++; + QRect r = p->children()->at(idx)->itemRect(); + if (r.width()>1 && r.height()>1) + return idx; + } + return -1; +} + +/* returns -1 if nothing visible found */ +int prevVisible(TreeMapItem* i) +{ + TreeMapItem* p = i->parent(); + if (!p || p->itemRect().isEmpty()) return -1; + + int idx = p->children()->findRef(i); + if (idx<0) return -1; + + while (idx > 0) { + idx--; + QRect r = p->children()->at(idx)->itemRect(); + if (r.width()>1 && r.height()>1) + return idx; + } + return -1; +} + + + + +void TreeMapWidget::keyPressEvent( QKeyEvent* e ) +{ + if (e->key() == Key_Escape && _pressed) { + + // take back + if (_oldCurrent != _lastOver) + setCurrent(_oldCurrent); + if (! (_tmpSelection == _selection)) { + TreeMapItem* changed = diff(_tmpSelection, _selection).commonParent(); + _tmpSelection = _selection; + if (changed) + redraw(changed); + } + _pressed = 0; + _lastOver = 0; + } + + if ((e->key() == Key_Space) || + (e->key() == Key_Return)) { + + switch(_selectionMode) { + case NoSelection: + break; + case Single: + setSelected(_current, true); + break; + case Multi: + setSelected(_current, !isSelected(_current)); + break; + case Extended: + if ((e->state() & ControlButton) || (e->state() & ShiftButton)) + setSelected(_current, !isSelected(_current)); + else { + _selectionMode = Single; + setSelected(_current, true); + _selectionMode = Extended; + } + } + + if (_current && (e->key() == Key_Return)) + emit returnPressed(_current); + + return; + } + + if (!_current) { + if (e->key() == Key_Down) { + setCurrent(_base, true); + } + return; + } + + TreeMapItem* old = _current, *newItem; + TreeMapItem* p = _current->parent(); + + bool goBack; + if (_current->sorting(&goBack) == -1) { + // noSorting + goBack = false; + } + + + if ((e->key() == Key_Backspace) || + (e->key() == Key_Up)) { + newItem = visibleItem(p); + setCurrent(newItem, true); + } + else if (e->key() == Key_Left) { + int newIdx = goBack ? nextVisible(_current) : prevVisible(_current); + if (p && newIdx>=0) { + p->setIndex(newIdx); + setCurrent(p->children()->at(newIdx), true); + } + } + else if (e->key() == Key_Right) { + int newIdx = goBack ? prevVisible(_current) : nextVisible(_current); + if (p && newIdx>=0) { + p->setIndex(newIdx); + setCurrent(p->children()->at(newIdx), true); + } + } + else if (e->key() == Key_Down) { + if (_current->children() && _current->children()->count()>0) { + int newIdx = _current->index(); + if (newIdx<0) + newIdx = goBack ? (_current->children()->count()-1) : 0; + if (newIdx>=(int)_current->children()->count()) + newIdx = _current->children()->count()-1; + newItem = visibleItem(_current->children()->at(newIdx)); + setCurrent(newItem, true); + } + } + + if (old == _current) return; + if (! (e->state() & ControlButton)) return; + if (! (e->state() & ShiftButton)) return; + + switch(_selectionMode) { + case NoSelection: + break; + case Single: + setSelected(_current, true); + break; + case Multi: + setSelected(_current, !isSelected(_current)); + break; + case Extended: + if (e->state() & ControlButton) + setSelected(_current, !isSelected(_current)); + else + setSelected(_current, isSelected(old)); + } +} + +void TreeMapWidget::fontChange( const QFont& ) +{ + redraw(); +} + + +void TreeMapWidget::resizeEvent( QResizeEvent * ) +{ + // this automatically redraws (as size is changed) + drawTreeMap(); +} + +void TreeMapWidget::paintEvent( QPaintEvent * ) +{ + drawTreeMap(); +} + +void TreeMapWidget::showEvent( QShowEvent * ) +{ + // refresh only if needed + drawTreeMap(); +} + +// Updates screen from shadow buffer, +// but redraws before if needed +void TreeMapWidget::drawTreeMap() +{ + // no need to draw if hidden + if (!isVisible()) return; + + if (_pixmap.size() != size()) + _needsRefresh = _base; + + if (_needsRefresh) { + + if (DEBUG_DRAWING) + kdDebug(90100) << "Redrawing " << _needsRefresh->path(0).join("/") << endl; + + if (_needsRefresh == _base) { + // redraw whole widget + _pixmap = QPixmap(size()); + _pixmap.fill(backgroundColor()); + } + QPainter p(&_pixmap); + if (_needsRefresh == _base) { + p.setPen(black); + p.drawRect(QRect(2, 2, QWidget::width()-4, QWidget::height()-4)); + _base->setItemRect(QRect(3, 3, QWidget::width()-6, QWidget::height()-6)); + } + else { + // only subitem + if (!_needsRefresh->itemRect().isValid()) return; + } + + // reset cached font object; it could have been changed + _font = font(); + _fontHeight = fontMetrics().height(); + + drawItems(&p, _needsRefresh); + _needsRefresh = 0; + } + + bitBlt( this, 0, 0, &_pixmap, 0, 0, + QWidget::width(), QWidget::height(), CopyROP, true); + + if (hasFocus()) { + QPainter p(this); + style().drawPrimitive( QStyle::PE_FocusRect, &p, + QRect(0, 0, QWidget::width(), QWidget::height()), + colorGroup() ); + } +} + + + +void TreeMapWidget::redraw(TreeMapItem* i) +{ + if (!i) return; + + if (!_needsRefresh) + _needsRefresh = i; + else { + if (!i->isChildOf(_needsRefresh)) + _needsRefresh = _needsRefresh->commonParent(i); + } + + if (isVisible()) { + // delayed drawing if we have multiple redraw requests + update(); + } +} + +void TreeMapWidget::drawItem(QPainter* p, + TreeMapItem* item) +{ + bool isSelected = false; + TreeMapItem* i; + + if (_markNo>0) { + for(i = item;i;i=i->parent()) + if (i->isMarked(_markNo)) break; + + isSelected = (i!=0); + } + else { + for (i=_tmpSelection.first();i;i=_tmpSelection.next()) + if (item->isChildOf(i)) break; + + isSelected = (i!=0); + } + + bool isCurrent = _current && item->isChildOf(_current); + + RectDrawing d(item->itemRect()); + item->setSelected(isSelected); + item->setCurrent(isCurrent); + item->setShaded(_shading); + d.drawBack(p, item); +} + + +bool TreeMapWidget::horizontal(TreeMapItem* i, const QRect& r) +{ + switch(i->splitMode()) { + case TreeMapItem::HAlternate: + return (i->depth()%2)==1; + case TreeMapItem::VAlternate: + return (i->depth()%2)==0; + case TreeMapItem::Horizontal: + return true; + case TreeMapItem::Vertical: + return false; + default: + return r.width() > r.height(); + } + return false; +} + + +/** + * Draw TreeMapItems recursive, starting from item + */ +void TreeMapWidget::drawItems(QPainter* p, + TreeMapItem* item) +{ + if (DEBUG_DRAWING) + kdDebug(90100) << "+drawItems(" << item->path(0).join("/") << ", " + << item->itemRect().x() << "/" << item->itemRect().y() + << "-" << item->itemRect().width() << "x" + << item->itemRect().height() << "), Val " << item->value() + << ", Sum " << item->sum() << endl; + + drawItem(p, item); + item->clearFreeRects(); + + QRect origRect = item->itemRect(); + int bw = item->borderWidth(); + QRect r = QRect(origRect.x()+bw, origRect.y()+bw, + origRect.width()-2*bw, origRect.height()-2*bw); + + TreeMapItemList* list = item->children(); + TreeMapItem* i; + + bool stopDrawing = false; + + // only subdivide if there are children + if (!list || list->count()==0) + stopDrawing = true; + + // only subdivide if there is enough space + if (!stopDrawing && (r.width()<=0 || r.height()<=0)) + stopDrawing = true; + + // stop drawing if maximum depth is reached + if (!stopDrawing && + (_maxDrawingDepth>=0 && item->depth()>=_maxDrawingDepth)) + stopDrawing = true; + + // stop drawing if stopAtText is reached + if (!stopDrawing) + for (int no=0;no<(int)_attr.size();no++) { + QString stopAt = fieldStop(no); + if (!stopAt.isEmpty() && (item->text(no) == stopAt)) { + stopDrawing = true; + break; + } + } + + // area size is checked later... +#if 0 + // stop drawing if minimal area size is reached + if (!stopDrawing && + (_minimalArea > 0) && + (r.width() * r.height() < _minimalArea)) stopDrawing = true; +#endif + + if (stopDrawing) { + if (list) { + // invalidate rects + for (i=list->first();i;i=list->next()) + i->clearItemRect(); + } + // tooltip apears on whole item rect + item->addFreeRect(item->itemRect()); + + // if we have space for text... + if ((r.height() < _fontHeight) || (r.width() < _fontHeight)) return; + + RectDrawing d(r); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no=0;no<(int)_attr.size();no++) { + if (!fieldVisible(no)) continue; + d.drawField(p, no, item); + } + r = d.remainingRect(item); + + if (DEBUG_DRAWING) + kdDebug(90100) << "-drawItems(" << item->path(0).join("/") << ")" << endl; + return; + } + + double user_sum, child_sum, self; + + // user supplied sum + user_sum = item->sum(); + + // own sum + child_sum = 0; + for (i=list->first();i;i=list->next()) { + child_sum += i->value(); + if (DEBUG_DRAWING) + kdDebug(90100) << " child: " << i->text(0) << ", value " + << i->value() << endl; + } + + QRect orig = r; + + // if we have space for text... + if ((r.height() >= _fontHeight) && (r.width() >= _fontHeight)) { + + RectDrawing d(r); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no=0;no<(int)_attr.size();no++) { + if (!fieldVisible(no)) continue; + if (!fieldForced(no)) continue; + d.drawField(p, no, item); + } + r = d.remainingRect(item); + } + + if (orig.x() == r.x()) { + // Strings on top + item->addFreeRect(QRect(orig.x(), orig.y(), + orig.width(), orig.height()-r.height())); + } + else { + // Strings on the left + item->addFreeRect(QRect(orig.x(), orig.y(), + orig.width()-r.width(), orig.height())); + } + + if (user_sum == 0) { + // user didn't supply any sum + user_sum = child_sum; + self = 0; + } + else { + self = user_sum - child_sum; + + if (user_sum < child_sum) { + //kdDebug(90100) << "TreeMWidget " << + // item->path() << ": User sum " << user_sum << " < Child Items sum " << child_sum << endl; + + // invalid user supplied sum: ignore and use calculate sum + user_sum = child_sum; + self = 0.0; + } + else { + // Try to put the border waste in self + // percent of wasted space on border... + float borderArea = origRect.width() * origRect.height(); + borderArea = (borderArea - r.width()*r.height())/borderArea; + unsigned borderValue = (unsigned)(borderArea * user_sum); + + if (borderValue > self) { + if (_skipIncorrectBorder) { + r = origRect; + // should add my self to nested self and set my self =0 + } + else + self = 0.0; + } + else + self -= borderValue; + + user_sum = child_sum + self; + } + } + + bool rotate = (_allowRotation && (r.height() > r.width())); + int self_length = (int)( ((rotate) ? r.width() : r.height()) * + self / user_sum + .5); + if (self_length > 0) { + // take space for self cost + QRect sr = r; + if (rotate) { + sr.setWidth( self_length ); + r.setRect(r.x()+sr.width(), r.y(), r.width()-sr.width(), r.height()); + } + else { + sr.setHeight( self_length ); + r.setRect(r.x(), r.y()+sr.height(), r.width(), r.height()-sr.height()); + } + + // set selfRect (not occupied by children) for tooltip + item->addFreeRect(sr); + + if (0) kdDebug(90100) << "Item " << item->path(0).join("/") << ": SelfR " + << sr.x() << "/" << sr.y() << "-" << sr.width() + << "/" << sr.height() << ", self " << self << "/" + << user_sum << endl; + + if ((sr.height() >= _fontHeight) && (sr.width() >= _fontHeight)) { + + RectDrawing d(sr); + item->setRotated(_allowRotation && (r.height() > r.width())); + for (int no=0;no<(int)_attr.size();no++) { + if (!fieldVisible(no)) continue; + if (fieldForced(no)) continue; + d.drawField(p, no, item); + } + } + + user_sum -= self; + } + + bool goBack; + if (item->sorting(&goBack) == -1) { + // noSorting + goBack = false; + } + + TreeMapItemListIterator it(*list); + if (goBack) it.toLast(); + + if (item->splitMode() == TreeMapItem::Columns) { + int len = list->count(); + bool drawDetails = true; + + while (len>0 && user_sum>0) { + TreeMapItemListIterator first = it; + double valSum = 0; + int lenLeft = len; + int columns = (int)(sqrt((double)len * r.width()/r.height())+.5); + if (columns==0) columns = 1; //should never be needed + + while (lenLeft>0 && ((double)valSum*(len-lenLeft) < + (double)len*user_sum/columns/columns)) { + valSum += it.current()->value(); + if (goBack) --it; else ++it; + lenLeft--; + } + + // we always split horizontally + int nextPos = (int)((double)r.width() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), nextPos, r.height()); + + if (nextPos < _visibleWidth) { + if (item->sorting(0) == -1) { + // fill current rect with hash pattern + drawFill(item, p, firstRect); + } + else { + // fill rest with hash pattern + drawFill(item, p, r, first, len, goBack); + break; + } + } + else { + drawDetails = drawItemArray(p, item, firstRect, + valSum, first, len-lenLeft, goBack); + } + r.setRect(r.x()+nextPos, r.y(), r.width()-nextPos, r.height()); + user_sum -= valSum; + len = lenLeft; + + if (!drawDetails) { + if (item->sorting(0) == -1) + drawDetails = true; + else { + drawFill(item, p, r, it, len, goBack); + break; + } + } + } + } + else if (item->splitMode() == TreeMapItem::Rows) { + int len = list->count(); + bool drawDetails = true; + + while (len>0 && user_sum>0) { + TreeMapItemListIterator first = it; + double valSum = 0; + int lenLeft = len; + int rows = (int)(sqrt((double)len * r.height()/r.width())+.5); + if (rows==0) rows = 1; //should never be needed + + while (lenLeft>0 && ((double)valSum*(len-lenLeft) < + (double)len*user_sum/rows/rows)) { + valSum += it.current()->value(); + if (goBack) --it; else ++it; + lenLeft--; + } + + // we always split horizontally + int nextPos = (int)((double)r.height() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), r.width(), nextPos); + + if (nextPos < _visibleWidth) { + if (item->sorting(0) == -1) { + drawFill(item, p, firstRect); + } + else { + drawFill(item, p, r, first, len, goBack); + break; + } + } + else { + drawDetails = drawItemArray(p, item, firstRect, + valSum, first, len-lenLeft, goBack); + } + r.setRect(r.x(), r.y()+nextPos, r.width(), r.height()-nextPos); + user_sum -= valSum; + len = lenLeft; + + if (!drawDetails) { + if (item->sorting(0) == -1) + drawDetails = true; + else { + drawFill(item, p, r, it, len, goBack); + break; + } + } + } + } + else + drawItemArray(p, item, r, user_sum, it, list->count(), goBack); + + if (DEBUG_DRAWING) + kdDebug(90100) << "-drawItems(" << item->path(0).join("/") << ")" << endl; +} + +// fills area with a pattern if to small to draw children +void TreeMapWidget::drawFill(TreeMapItem* i, QPainter* p, QRect& r) +{ + p->setBrush(Qt::Dense4Pattern); + p->setPen(Qt::NoPen); + p->drawRect(r); + i->addFreeRect(r); +} + +// fills area with a pattern if to small to draw children +void TreeMapWidget::drawFill(TreeMapItem* i, QPainter* p, QRect& r, + TreeMapItemListIterator it, int len, bool goBack) +{ + if (DEBUG_DRAWING) + kdDebug(90100) << " +drawFill(" << r.x() << "/" << r.y() + << "-" << r.width() << "x" << r.height() + << ", len " << len << ")" << endl; + + p->setBrush(Qt::Dense4Pattern); + p->setPen(Qt::NoPen); + p->drawRect(r); + i->addFreeRect(r); + + // reset rects + while (len>0 && it.current()) { + + if (DEBUG_DRAWING) + kdDebug(90100) << " Reset Rect " << (*it)->path(0).join("/") << endl; + + (*it)->clearItemRect(); + if (goBack) --it; else ++it; + len--; + } + if (DEBUG_DRAWING) + kdDebug(90100) << " -drawFill(" << r.x() << "/" << r.y() + << "-" << r.width() << "x" << r.height() + << ", len " << len << ")" << endl; +} + +// returns false if rect gets to small +bool TreeMapWidget::drawItemArray(QPainter* p, TreeMapItem* item, + QRect& r, double user_sum, + TreeMapItemListIterator it, int len, + bool goBack) +{ + if (user_sum == 0) return false; + + static bool b2t = true; + + // stop recursive bisection for small rectangles + if (((r.height() < _visibleWidth) && + (r.width() < _visibleWidth)) || + ((_minimalArea > 0) && + (r.width() * r.height() < _minimalArea))) { + + drawFill(item, p, r, it, len, goBack); + return false; + } + + if (DEBUG_DRAWING) + kdDebug(90100) << " +drawItemArray(" << item->path(0).join("/") + << ", " << r.x() << "/" << r.y() << "-" << r.width() + << "x" << r.height() << ")" << endl; + + if (len>2 && (item->splitMode() == TreeMapItem::Bisection)) { + + TreeMapItemListIterator first = it; + double valSum = 0; + int lenLeft = len; + //while (lenLeft>0 && valSum<user_sum/2) { + while (lenLeft>len/2) { + valSum += it.current()->value(); + if (goBack) --it; else ++it; + lenLeft--; + } + + // draw first half... + bool drawOn; + + if (r.width() > r.height()) { + int halfPos = (int)((double)r.width() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), halfPos, r.height()); + drawOn = drawItemArray(p, item, firstRect, + valSum, first, len-lenLeft, goBack); + r.setRect(r.x()+halfPos, r.y(), r.width()-halfPos, r.height()); + } + else { + int halfPos = (int)((double)r.height() * valSum / user_sum); + QRect firstRect = QRect(r.x(), r.y(), r.width(), halfPos); + drawOn = drawItemArray(p, item, firstRect, + valSum, first, len-lenLeft, goBack); + r.setRect(r.x(), r.y()+halfPos, r.width(), r.height()-halfPos); + } + + // if no sorting, don't stop drawing + if (item->sorting(0) == -1) drawOn = true; + + // second half + if (drawOn) + drawOn = drawItemArray(p, item, r, user_sum - valSum, + it, lenLeft, goBack); + else { + drawFill(item, p, r, it, len, goBack); + } + + if (DEBUG_DRAWING) + kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/") + << ")" << endl; + + return drawOn; + } + + bool hor = horizontal(item,r); + + TreeMapItem* i; + while (len>0) { + i = it.current(); + if (user_sum <= 0) { + + if (DEBUG_DRAWING) + kdDebug(90100) << "drawItemArray: Reset " << i->path(0).join("/") << endl; + + i->clearItemRect(); + if (goBack) --it; else ++it; + len--; + continue; + } + + // stop drawing for small rectangles + if (((r.height() < _visibleWidth) && + (r.width() < _visibleWidth)) || + ((_minimalArea > 0) && + (r.width() * r.height() < _minimalArea))) { + + drawFill(item, p, r, it, len, goBack); + if (DEBUG_DRAWING) + kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/") + << "): Stop" << endl; + return false; + } + + if (i->splitMode() == TreeMapItem::AlwaysBest) + hor = r.width() > r.height(); + + int lastPos = hor ? r.width() : r.height(); + double val = i->value(); + int nextPos = (user_sum <= 0.0) ? 0: (int)(lastPos * val / user_sum +.5); + if (nextPos>lastPos) nextPos = lastPos; + + if ((item->sorting(0) != -1) && (nextPos < _visibleWidth)) { + drawFill(item, p, r, it, len, goBack); + if (DEBUG_DRAWING) + kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/") + << "): Stop" << endl; + return false; + } + + QRect currRect = r; + + if (hor) + currRect.setWidth(nextPos); + else { + if (b2t) + currRect.setRect(r.x(), r.bottom()-nextPos+1, r.width(), nextPos); + else + currRect.setHeight(nextPos); + } + + // don't draw very small rectangles: + if (nextPos >= _visibleWidth) { + i->setItemRect(currRect); + drawItems(p, i); + } + else { + i->clearItemRect(); + drawFill(item, p, currRect); + } + + // draw Separator + if (_drawSeparators && (nextPos<lastPos)) { + p->setPen(black); + if (hor) { + if (r.top()<=r.bottom()) + p->drawLine(r.x() + nextPos, r.top(), r.x() + nextPos, r.bottom()); + } + else { + if (r.left()<=r.right()) + p->drawLine(r.left(), r.y() + nextPos, r.right(), r.y() + nextPos); + } + nextPos++; + } + + if (hor) + r.setRect(r.x() + nextPos, r.y(), lastPos-nextPos, r.height()); + else { + if (b2t) + r.setRect(r.x(), r.y(), r.width(), lastPos-nextPos); + else + r.setRect(r.x(), r.y() + nextPos, r.width(), lastPos-nextPos); + } + + user_sum -= val; + if (goBack) --it; else ++it; + len--; + } + + if (DEBUG_DRAWING) + kdDebug(90100) << " -drawItemArray(" << item->path(0).join("/") + << "): Continue" << endl; + + return true; +} + + +/*---------------------------------------------------------------- + * Popup menus for option setting + */ + +void TreeMapWidget::splitActivated(int id) +{ + if (id == _splitID) setSplitMode(TreeMapItem::Bisection); + else if (id == _splitID+1) setSplitMode(TreeMapItem::Columns); + else if (id == _splitID+2) setSplitMode(TreeMapItem::Rows); + else if (id == _splitID+3) setSplitMode(TreeMapItem::AlwaysBest); + else if (id == _splitID+4) setSplitMode(TreeMapItem::Best); + else if (id == _splitID+5) setSplitMode(TreeMapItem::VAlternate); + else if (id == _splitID+6) setSplitMode(TreeMapItem::HAlternate); + else if (id == _splitID+7) setSplitMode(TreeMapItem::Horizontal); + else if (id == _splitID+8) setSplitMode(TreeMapItem::Vertical); +} + + +void TreeMapWidget::addSplitDirectionItems(QPopupMenu* popup, int id) +{ + _splitID = id; + popup->setCheckable(true); + + connect(popup, SIGNAL(activated(int)), + this, SLOT(splitActivated(int))); + + popup->insertItem(i18n("Recursive Bisection"), id); + popup->insertItem(i18n("Columns"), id+1); + popup->insertItem(i18n("Rows"), id+2); + popup->insertItem(i18n("Always Best"), id+3); + popup->insertItem(i18n("Best"), id+4); + popup->insertItem(i18n("Alternate (V)"), id+5); + popup->insertItem(i18n("Alternate (H)"), id+6); + popup->insertItem(i18n("Horizontal"), id+7); + popup->insertItem(i18n("Vertical"), id+8); + + switch(splitMode()) { + case TreeMapItem::Bisection: popup->setItemChecked(id,true); break; + case TreeMapItem::Columns: popup->setItemChecked(id+1,true); break; + case TreeMapItem::Rows: popup->setItemChecked(id+2,true); break; + case TreeMapItem::AlwaysBest: popup->setItemChecked(id+3,true); break; + case TreeMapItem::Best: popup->setItemChecked(id+4,true); break; + case TreeMapItem::VAlternate: popup->setItemChecked(id+5,true); break; + case TreeMapItem::HAlternate: popup->setItemChecked(id+6,true); break; + case TreeMapItem::Horizontal: popup->setItemChecked(id+7,true); break; + case TreeMapItem::Vertical: popup->setItemChecked(id+8,true); break; + default: break; + } +} + +void TreeMapWidget::visualizationActivated(int id) +{ + if (id == _visID+2) setSkipIncorrectBorder(!skipIncorrectBorder()); + else if (id == _visID+3) setBorderWidth(0); + else if (id == _visID+4) setBorderWidth(1); + else if (id == _visID+5) setBorderWidth(2); + else if (id == _visID+6) setBorderWidth(3); + else if (id == _visID+10) setAllowRotation(!allowRotation()); + else if (id == _visID+11) setShadingEnabled(!isShadingEnabled()); + else if (id<_visID+19 || id>_visID+100) return; + + id -= 20+_visID; + int f = id/10; + if ((id%10) == 1) setFieldVisible(f, !fieldVisible(f)); + else if ((id%10) == 2) setFieldForced(f, !fieldForced(f)); + else if ((id%10) == 3) setFieldPosition(f, DrawParams::TopLeft); + else if ((id%10) == 4) setFieldPosition(f, DrawParams::TopCenter); + else if ((id%10) == 5) setFieldPosition(f, DrawParams::TopRight); + else if ((id%10) == 6) setFieldPosition(f, DrawParams::BottomLeft); + else if ((id%10) == 7) setFieldPosition(f, DrawParams::BottomCenter); + else if ((id%10) == 8) setFieldPosition(f, DrawParams::BottomRight); +} + +void TreeMapWidget::addVisualizationItems(QPopupMenu* popup, int id) +{ + _visID = id; + + popup->setCheckable(true); + + QPopupMenu* bpopup = new QPopupMenu(); + bpopup->setCheckable(true); + + connect(popup, SIGNAL(activated(int)), + this, SLOT(visualizationActivated(int))); + connect(bpopup, SIGNAL(activated(int)), + this, SLOT(visualizationActivated(int))); + + QPopupMenu* spopup = new QPopupMenu(); + addSplitDirectionItems(spopup, id+100); + popup->insertItem(i18n("Nesting"), spopup, id); + + popup->insertItem(i18n("Border"), bpopup, id+1); + bpopup->insertItem(i18n("Correct Borders Only"), id+2); + bpopup->insertSeparator(); + bpopup->insertItem(i18n("Width %1").arg(0), id+3); + bpopup->insertItem(i18n("Width %1").arg(1), id+4); + bpopup->insertItem(i18n("Width %1").arg(2), id+5); + bpopup->insertItem(i18n("Width %1").arg(3), id+6); + bpopup->setItemChecked(id+2, skipIncorrectBorder()); + bpopup->setItemChecked(id+3, borderWidth()==0); + bpopup->setItemChecked(id+4, borderWidth()==1); + bpopup->setItemChecked(id+5, borderWidth()==2); + bpopup->setItemChecked(id+6, borderWidth()==3); + + popup->insertItem(i18n("Allow Rotation"), id+10); + popup->setItemChecked(id+10,allowRotation()); + popup->insertItem(i18n("Shading"), id+11); + popup->setItemChecked(id+11,isShadingEnabled()); + + if (_attr.size() ==0) return; + + popup->insertSeparator(); + int f; + QPopupMenu* tpopup; + id += 20; + for (f=0;f<(int)_attr.size();f++, id+=10) { + tpopup = new QPopupMenu(); + tpopup->setCheckable(true); + popup->insertItem(_attr[f].type, tpopup, id); + tpopup->insertItem(i18n("Visible"), id+1); + tpopup->insertItem(i18n("Take Space From Children"), id+2); + tpopup->insertSeparator(); + tpopup->insertItem(i18n("Top Left"), id+3); + tpopup->insertItem(i18n("Top Center"), id+4); + tpopup->insertItem(i18n("Top Right"), id+5); + tpopup->insertItem(i18n("Bottom Left"), id+6); + tpopup->insertItem(i18n("Bottom Center"), id+7); + tpopup->insertItem(i18n("Bottom Right"), id+8); + + tpopup->setItemChecked(id+1,_attr[f].visible); + tpopup->setItemEnabled(id+2,_attr[f].visible); + tpopup->setItemEnabled(id+3,_attr[f].visible); + tpopup->setItemEnabled(id+4,_attr[f].visible); + tpopup->setItemEnabled(id+5,_attr[f].visible); + tpopup->setItemEnabled(id+6,_attr[f].visible); + tpopup->setItemEnabled(id+7,_attr[f].visible); + tpopup->setItemEnabled(id+8,_attr[f].visible); + tpopup->setItemChecked(id+2,_attr[f].forced); + tpopup->setItemChecked(id+3,_attr[f].pos == DrawParams::TopLeft); + tpopup->setItemChecked(id+4,_attr[f].pos == DrawParams::TopCenter); + tpopup->setItemChecked(id+5,_attr[f].pos == DrawParams::TopRight); + tpopup->setItemChecked(id+6,_attr[f].pos == DrawParams::BottomLeft); + tpopup->setItemChecked(id+7,_attr[f].pos == DrawParams::BottomCenter); + tpopup->setItemChecked(id+8,_attr[f].pos == DrawParams::BottomRight); + + connect(tpopup, SIGNAL(activated(int)), + this, SLOT(visualizationActivated(int))); + } +} + +void TreeMapWidget::selectionActivated(int id) +{ + TreeMapItem* i = _menuItem; + id -= _selectionID; + while (id>0 && i) { + i=i->parent(); + id--; + } + if (i) + setSelected(i, true); +} + +void TreeMapWidget::addSelectionItems(QPopupMenu* popup, + int id, TreeMapItem* i) +{ + if (!i) return; + + _selectionID = id; + _menuItem = i; + + connect(popup, SIGNAL(activated(int)), + this, SLOT(selectionActivated(int))); + + while (i) { + QString name = i->text(0); + if (name.isEmpty()) break; + popup->insertItem(i->text(0), id++); + i = i->parent(); + } +} + +void TreeMapWidget::fieldStopActivated(int id) +{ + if (id == _fieldStopID) setFieldStop(0, QString::null); + else { + TreeMapItem* i = _menuItem; + id -= _fieldStopID+1; + while (id>0 && i) { + i=i->parent(); + id--; + } + if (i) + setFieldStop(0, i->text(0)); + } +} + +void TreeMapWidget::addFieldStopItems(QPopupMenu* popup, + int id, TreeMapItem* i) +{ + _fieldStopID = id; + + connect(popup, SIGNAL(activated(int)), + this, SLOT(fieldStopActivated(int))); + + popup->insertItem(i18n("No %1 Limit").arg(fieldType(0)), id); + popup->setItemChecked(id, fieldStop(0).isEmpty()); + _menuItem = i; + bool foundFieldStop = false; + if (i) { + popup->insertSeparator(); + + while (i) { + id++; + QString name = i->text(0); + if (name.isEmpty()) break; + popup->insertItem(i->text(0), id); + if (fieldStop(0) == i->text(0)) { + popup->setItemChecked(id, true); + foundFieldStop = true; + } + i = i->parent(); + } + } + + if (!foundFieldStop && !fieldStop(0).isEmpty()) { + popup->insertSeparator(); + popup->insertItem(fieldStop(0), id+1); + popup->setItemChecked(id+1, true); + } +} + +void TreeMapWidget::areaStopActivated(int id) +{ + if (id == _areaStopID) setMinimalArea(-1); + else if (id == _areaStopID+1) { + int area = _menuItem ? (_menuItem->width() * _menuItem->height()) : -1; + setMinimalArea(area); + } + else if (id == _areaStopID+2) setMinimalArea(100); + else if (id == _areaStopID+3) setMinimalArea(400); + else if (id == _areaStopID+4) setMinimalArea(1000); + else if (id == _areaStopID+5) setMinimalArea(minimalArea()*2); + else if (id == _areaStopID+6) setMinimalArea(minimalArea()/2); +} + +void TreeMapWidget::addAreaStopItems(QPopupMenu* popup, + int id, TreeMapItem* i) +{ + _areaStopID = id; + _menuItem = i; + + connect(popup, SIGNAL(activated(int)), + this, SLOT(areaStopActivated(int))); + + bool foundArea = false; + + popup->insertItem(i18n("No Area Limit"), id); + popup->setItemChecked(id, minimalArea() == -1); + + if (i) { + int area = i->width() * i->height(); + popup->insertSeparator(); + popup->insertItem(i18n("Area of '%1' (%2)") + .arg(i->text(0)).arg(area), id+1); + if (area == minimalArea()) { + popup->setItemChecked(id+1, true); + foundArea = true; + } + } + + popup->insertSeparator(); + int area = 100, count; + for (count=0;count<3;count++) { + popup->insertItem(i18n("1 Pixel", "%n Pixels", area), id+2+count); + if (area == minimalArea()) { + popup->setItemChecked(id+2+count, true); + foundArea = true; + } + area = (area==100) ? 400 : (area==400) ? 1000 : 4000; + } + + if (minimalArea()>0) { + popup->insertSeparator(); + if (!foundArea) { + popup->insertItem(i18n("1 Pixel", "%n Pixels", minimalArea()), id+10); + popup->setItemChecked(id+10, true); + } + + popup->insertItem(i18n("Double Area Limit (to %1)") + .arg(minimalArea()*2), id+5); + popup->insertItem(i18n("Halve Area Limit (to %1)") + .arg(minimalArea()/2), id+6); + } +} + + +void TreeMapWidget::depthStopActivated(int id) +{ + if (id == _depthStopID) setMaxDrawingDepth(-1); + else if (id == _depthStopID+1) { + int d = _menuItem ? _menuItem->depth() : -1; + setMaxDrawingDepth(d); + } + else if (id == _depthStopID+2) setMaxDrawingDepth(maxDrawingDepth()-1); + else if (id == _depthStopID+3) setMaxDrawingDepth(maxDrawingDepth()+1); + else if (id == _depthStopID+4) setMaxDrawingDepth(2); + else if (id == _depthStopID+5) setMaxDrawingDepth(4); + else if (id == _depthStopID+6) setMaxDrawingDepth(6); +} + +void TreeMapWidget::addDepthStopItems(QPopupMenu* popup, + int id, TreeMapItem* i) +{ + _depthStopID = id; + _menuItem = i; + + connect(popup, SIGNAL(activated(int)), + this, SLOT(depthStopActivated(int))); + + bool foundDepth = false; + + popup->insertItem(i18n("No Depth Limit"), id); + popup->setItemChecked(id, maxDrawingDepth() == -1); + + if (i) { + int d = i->depth(); + popup->insertSeparator(); + popup->insertItem(i18n("Depth of '%1' (%2)") + .arg(i->text(0)).arg(d), id+1); + if (d == maxDrawingDepth()) { + popup->setItemChecked(id+1, true); + foundDepth = true; + } + } + + popup->insertSeparator(); + int depth = 2, count; + for (count=0;count<3;count++) { + popup->insertItem(i18n("Depth %1").arg(depth), id+4+count); + if (depth == maxDrawingDepth()) { + popup->setItemChecked(id+4+count, true); + foundDepth = true; + } + depth = (depth==2) ? 4 : 6; + } + + if (maxDrawingDepth()>1) { + popup->insertSeparator(); + if (!foundDepth) { + popup->insertItem(i18n("Depth %1").arg(maxDrawingDepth()), id+10); + popup->setItemChecked(id+10, true); + } + + popup->insertItem(i18n("Decrement (to %1)") + .arg(maxDrawingDepth()-1), id+2); + popup->insertItem(i18n("Increment (to %1)") + .arg(maxDrawingDepth()+1), id+3); + } +} + + + +/*---------------------------------------------------------------- + * Option saving/restoring + */ + +void TreeMapWidget::saveOptions(KConfigGroup* config, QString prefix) +{ + config->writeEntry(prefix+"Nesting", splitModeString()); + config->writeEntry(prefix+"AllowRotation", allowRotation()); + config->writeEntry(prefix+"ShadingEnabled", isShadingEnabled()); + config->writeEntry(prefix+"OnlyCorrectBorder", skipIncorrectBorder()); + config->writeEntry(prefix+"BorderWidth", borderWidth()); + config->writeEntry(prefix+"MaxDepth", maxDrawingDepth()); + config->writeEntry(prefix+"MinimalArea", minimalArea()); + + int f, fCount = _attr.size(); + config->writeEntry(prefix+"FieldCount", fCount); + for (f=0;f<fCount;f++) { + config->writeEntry(QString(prefix+"FieldVisible%1").arg(f), + _attr[f].visible); + config->writeEntry(QString(prefix+"FieldForced%1").arg(f), + _attr[f].forced); + config->writeEntry(QString(prefix+"FieldStop%1").arg(f), + _attr[f].stop); + config->writeEntry(QString(prefix+"FieldPosition%1").arg(f), + fieldPositionString(f)); + } +} + + +void TreeMapWidget::restoreOptions(KConfigGroup* config, QString prefix) +{ + bool enabled; + int num; + QString str; + + str = config->readEntry(prefix+"Nesting"); + if (!str.isEmpty()) setSplitMode(str); + + if (config->hasKey(prefix+"AllowRotation")) { + enabled = config->readBoolEntry(prefix+"AllowRotation", true); + setAllowRotation(enabled); + } + + if (config->hasKey(prefix+"ShadingEnabled")) { + enabled = config->readBoolEntry(prefix+"ShadingEnabled", true); + setShadingEnabled(enabled); + } + + if (config->hasKey(prefix+"OnlyCorrectBorder")) { + enabled = config->readBoolEntry(prefix+"OnlyCorrectBorder", false); + setSkipIncorrectBorder(enabled); + } + + num = config->readNumEntry(prefix+"BorderWidth", -2); + if (num!=-2) setBorderWidth(num); + + num = config->readNumEntry(prefix+"MaxDepth", -2); + if (num!=-2) setMaxDrawingDepth(num); + + num = config->readNumEntry(prefix+"MinimalArea", -2); + if (num!=-2) setMinimalArea(num); + + num = config->readNumEntry(prefix+"FieldCount", -2); + if (num<=0 || num>MAX_FIELD) return; + + int f; + for (f=0;f<num;f++) { + str = QString(prefix+"FieldVisible%1").arg(f); + if (config->hasKey(str)) + setFieldVisible(f, config->readBoolEntry(str)); + + str = QString(prefix+"FieldForced%1").arg(f); + if (config->hasKey(str)) + setFieldForced(f, config->readBoolEntry(str)); + + str = config->readEntry(QString(prefix+"FieldStop%1").arg(f)); + setFieldStop(f, str); + + str = config->readEntry(QString(prefix+"FieldPosition%1").arg(f)); + if (!str.isEmpty()) setFieldPosition(f, str); + } +} + +#include "treemap.moc" diff --git a/konq-plugins/fsview/treemap.h b/konq-plugins/fsview/treemap.h new file mode 100644 index 0000000..a834d23 --- /dev/null +++ b/konq-plugins/fsview/treemap.h @@ -0,0 +1,742 @@ +/* This file is part of KCachegrind. + Copyright (C) 2002, 2003 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> + + KCachegrind is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation, version 2. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +/** + * A Widget for visualizing hierarchical metrics as areas. + * The API is similar to QListView. + * + * This file defines the following classes: + * DrawParams, RectDrawing, TreeMapItem, TreeMapWidget + * + * DrawParams/RectDrawing allows reusing of TreeMap drawing + * functions in other widgets. + */ + +#ifndef TREEMAP_H +#define TREEMAP_H + +#include <qstring.h> +#include <qwidget.h> +#include <qpixmap.h> +#include <qptrlist.h> +#include <qvaluevector.h> +#include <qcolor.h> +#include <qapplication.h> +#include <qstringlist.h> + +class QPopupMenu; +class TreeMapTip; +class TreeMapWidget; +class TreeMapItem; +class TreeMapItemList; +class QString; + +class KConfigGroup; + + +/** + * Drawing parameters for an object. + * A Helper Interface for RectDrawing. + */ +class DrawParams +{ +public: + /** + * Positions for drawing into a rectangle. + * + * The specified position assumes no rotation. + * If there is more than one text for one position, it is put + * nearer to the center of the item. + * + * Drawing at top positions cuts free space from top, + * drawing at bottom positions cuts from bottom. + * Default usually gives positions clockwise according to field number. + */ + enum Position { TopLeft, TopCenter, TopRight, + BottomLeft, BottomCenter, BottomRight, + Default, Unknown}; + + // no constructor as this is an abstract class + virtual ~DrawParams() {} + + virtual QString text(int) const = 0; + virtual QPixmap pixmap(int) const = 0; + virtual Position position(int) const = 0; + // 0: no limit, negative: leave at least -maxLines() free + virtual int maxLines(int) const { return 0; } + virtual int fieldCount() const { return 0; } + + virtual QColor backColor() const { return Qt::white; } + virtual const QFont& font() const = 0; + + virtual bool selected() const { return false; } + virtual bool current() const { return false; } + virtual bool shaded() const { return true; } + virtual bool rotated() const { return false; } +}; + + +/* + * DrawParam with attributes stored + */ +class StoredDrawParams: public DrawParams +{ +public: + StoredDrawParams(); + StoredDrawParams(QColor c, + bool selected = false, bool current = false); + + // getters + QString text(int) const; + QPixmap pixmap(int) const; + Position position(int) const; + int maxLines(int) const; + int fieldCount() const { return _field.size(); } + + QColor backColor() const { return _backColor; } + bool selected() const { return _selected; } + bool current() const { return _current; } + bool shaded() const { return _shaded; } + bool rotated() const { return _rotated; } + + const QFont& font() const; + + // attribute setters + void setField(int f, const QString& t, QPixmap pm = QPixmap(), + Position p = Default, int maxLines = 0); + void setText(int f, const QString&); + void setPixmap(int f, const QPixmap&); + void setPosition(int f, Position); + void setMaxLines(int f, int); + void setBackColor(const QColor& c) { _backColor = c; } + void setSelected(bool b) { _selected = b; } + void setCurrent(bool b) { _current = b; } + void setShaded(bool b) { _shaded = b; } + void setRotated(bool b) { _rotated = b; } + +protected: + QColor _backColor; + bool _selected, _current, _shaded, _rotated; + +private: + // resize field array if needed to allow to access field <f> + void ensureField(int f); + + struct Field { + QString text; + QPixmap pix; + Position pos; + int maxLines; + }; + + QValueVector<Field> _field; +}; + + +/* State for drawing on a rectangle. + * + * Following drawing functions are provided: + * - background drawing with shading and 3D frame + * - successive pixmap/text drawing at various positions with wrap-around + * optimized for minimal space usage (e.g. if a text is drawn at top right + * after text on top left, the same line is used if space allows) + * + */ +class RectDrawing +{ +public: + RectDrawing(QRect); + ~RectDrawing(); + + // The default DrawParams object used. + DrawParams* drawParams(); + // we take control over the given object (i.e. delete at destruction) + void setDrawParams(DrawParams*); + + // draw on a given QPainter, use this class as info provider per default + void drawBack(QPainter*, DrawParams* dp = 0); + /* Draw field at position() from pixmap()/text() with maxLines(). + * Returns true if something was drawn + */ + bool drawField(QPainter*, int f, DrawParams* dp = 0); + + // resets rectangle for free space + void setRect(QRect); + + // Returns the rectangle area still free of text/pixmaps after + // a number of drawText() calls. + QRect remainingRect(DrawParams* dp = 0); + +private: + int _usedTopLeft, _usedTopCenter, _usedTopRight; + int _usedBottomLeft, _usedBottomCenter, _usedBottomRight; + QRect _rect; + + // temporary + int _fontHeight; + QFontMetrics* _fm; + DrawParams* _dp; +}; + + +class TreeMapItemList: public QPtrList<TreeMapItem> +{ +public: + TreeMapItem* commonParent(); +protected: + int compareItems ( Item item1, Item item2 ); +}; + +typedef QPtrListIterator<TreeMapItem> TreeMapItemListIterator; + + +/** + * Base class of items in TreeMap. + * + * This class supports an arbitrary number of text() strings + * positioned counterclock-wise starting at TopLeft. Each item + * has its own static value(), sum() and sorting(). The + * splitMode() and borderWidth() is taken from a TreeMapWidget. + * + * If you want more flexibility, reimplement TreeMapItem and + * override the corresponding methods. For dynamic creation of child + * items on demand, reimplement children(). + */ +class TreeMapItem: public StoredDrawParams +{ +public: + + /** + * Split direction for nested areas: + * AlwaysBest: Choose split direction for every subitem according to + * longest side of rectangle left for drawing + * Best: Choose split direction for all subitems of an area + * depending on longest side + * HAlternate: Horizontal at top; alternate direction on depth step + * VAlternate: Vertical at top; alternate direction on depth step + * Horizontal: Always horizontal split direction + * Vertical: Always vertical split direction + */ + enum SplitMode { Bisection, Columns, Rows, + AlwaysBest, Best, + HAlternate, VAlternate, + Horizontal, Vertical }; + + TreeMapItem(TreeMapItem* parent = 0, double value = 1.0 ); + TreeMapItem(TreeMapItem* parent, double value, + QString text1, QString text2 = QString::null, + QString text3 = QString::null, QString text4 = QString::null); + virtual ~TreeMapItem(); + + bool isChildOf(TreeMapItem*); + + TreeMapItem* commonParent(TreeMapItem* item); + + // force a redraw of this item + void redraw(); + + // delete all children + void clear(); + + // force new child generation & refresh + void refresh(); + + // call in a reimplemented items() method to check if already called + // after a clear(), this will return false + bool initialized(); + + /** + * Adds an item to a parent. + * When no sorting is used, the item is appended (drawn at bottom). + * This is only needed if the parent was not already specified in the + * construction of the item. + */ + void addItem(TreeMapItem*); + + /** + * Returns a list of text strings of specified text number, + * from root up to this item. + */ + QStringList path(int) const; + + /** + * Depth of this item. This is the distance to root. + */ + int depth() const; + + /** + * Parent Item + */ + TreeMapItem* parent() const { return _parent; } + + /** + * Temporary rectangle used for drawing this item the last time. + * This is internally used to map from a point to an item. + */ + void setItemRect(const QRect& r) { _rect = r; } + void clearItemRect(); + const QRect& itemRect() const { return _rect; } + int width() const { return _rect.width(); } + int height() const { return _rect.height(); } + + /** + * Temporary rectangle list of free space of this item. + * Used internally to enable tooltip. + */ + void clearFreeRects(); + QPtrList<QRect>* freeRects() const { return _freeRects; } + void addFreeRect(const QRect& r); + + /** + * Temporary child item index of the child that was current() recently. + */ + int index() const { return _index; } + void setIndex(int i) { _index = i; } + + + /** + * TreeMap widget this item is put in. + */ + TreeMapWidget* widget() const { return _widget; } + + void setParent(TreeMapItem* p); + void setWidget(TreeMapWidget* w) { _widget = w; } + void setSum(double s) { _sum = s; } + void setValue(double s) { _value = s; } + + virtual double sum() const; + virtual double value() const; + // replace "Default" position with setting from TreeMapWidget + virtual Position position(int) const; + virtual const QFont& font() const; + virtual bool isMarked(int) const; + + virtual int borderWidth() const; + + /** + * Returns the text number after that sorting is done or + * -1 for no sorting, -2 for value() sorting (default). + * If ascending != 0, a bool value is written at that location + * to indicate if sorting should be ascending. + */ + virtual int sorting(bool* ascending) const; + + /** + * Set the sorting for child drawing. + * + * Default is no sorting: <textNo> = -1 + * For value() sorting, use <textNo> = -2 + * + * For fast sorting, set this to -1 before child insertions and call + * again after inserting all children. + */ + void setSorting(int textNo, bool ascending = true); + + /** + * Resort according to the already set sorting. + * + * This has to be done if the sorting base changes (e.g. text or values + * change). If this is only true for the children of this item, you can + * set the recursive parameter to false. + */ + void resort(bool recursive = true); + + virtual SplitMode splitMode() const; + virtual int rtti() const; + // not const as this can create children on demand + virtual TreeMapItemList* children(); + +protected: + TreeMapItemList* _children; + double _sum, _value; + +private: + TreeMapWidget* _widget; + TreeMapItem* _parent; + + int _sortTextNo; + bool _sortAscending; + + // temporary layout + QRect _rect; + QPtrList<QRect>* _freeRects; + int _depth; + + // temporary self value (when using level skipping) + double _unused_self; + + // index of last active subitem + int _index; +}; + + +/** + * Class for visualisation of a metric of hierarchically + * nested items as 2D areas. + */ +class TreeMapWidget: public QWidget +{ + Q_OBJECT + +public: + + /** + * Same as in QListBox/QListView + */ + enum SelectionMode { Single, Multi, Extended, NoSelection }; + + TreeMapWidget(TreeMapItem* base, QWidget* parent=0, const char* name=0); + ~TreeMapWidget(); + + /** + * Returns the TreeMapItem filling out the widget space + */ + TreeMapItem* base() const { return _base; } + + /** + * Returns a reference to the current widget font. + */ + const QFont& currentFont() const; + + /** + * Returns the area item at position x/y, independent from any + * maxSelectDepth setting. + */ + TreeMapItem* item(int x, int y) const; + + /** + * Returns the nearest item with a visible area; this + * can be the given item itself. + */ + TreeMapItem* visibleItem(TreeMapItem*) const; + + /** + * Returns the item possible for selection. this returns the + * given item itself or a parent thereof, + * depending on setting of maxSelectDepth(). + */ + TreeMapItem* possibleSelection(TreeMapItem*) const; + + /** + * Selects or unselects an item. + * In multiselection mode, the constrain that a selected item + * has no selected children or parents stays true. + */ + void setSelected(TreeMapItem*, bool selected = true); + + /** + * Switches on the marking <markNo>. Marking 0 switches off marking. + * This is mutually exclusive to selection, and is automatically + * switched off when selection is changed (also by the user). + * Marking is visually the same as selection, and is based on + * TreeMapItem::isMarked(<markNo>). + * This enables to programmatically show multiple selected items + * at once even in single selection mode. + */ + void setMarked(int markNo = 1, bool redraw = true); + + /** + * Clear selection of all selected items which are children of + * parent. When parent == 0, clears whole selection + * Returns true if selection changed. + */ + bool clearSelection(TreeMapItem* parent = 0); + + /** + * Selects or unselects items in a range. + * This is needed internally for Shift-Click in Extented mode. + * Range means for a hierarchical widget: + * - select/unselect i1 and i2 according selected + * - search common parent of i1 and i2, and select/unselect the + * range of direct children between but excluding the child + * leading to i1 and the child leading to i2. + */ + void setRangeSelection(TreeMapItem* i1, + TreeMapItem* i2, bool selected); + + /** + * Sets the current item. + * The current item is mainly used for keyboard navigation. + */ + void setCurrent(TreeMapItem*, bool kbd=false); + + /** + * Set the maximal depth a selected item can have. + * If you try to select a item with higher depth, the ancestor holding + * this condition is used. + * + * See also possibleSelection(). + */ + void setMaxSelectDepth(int d) { _maxSelectDepth = d; } + + + void setSelectionMode(SelectionMode m) { _selectionMode = m; } + + /** + * for setting/getting global split direction + */ + void setSplitMode(TreeMapItem::SplitMode m); + TreeMapItem::SplitMode splitMode() const; + // returns true if string was recognized + bool setSplitMode(QString); + QString splitModeString() const; + + + /* + * Shading of rectangles enabled ? + */ + void setShadingEnabled(bool s); + bool isShadingEnabled() const { return _shading; } + + + /** + * Items usually have a size proportional to their value(). + * With <width>, you can give the minimum width + * of the resulting rectangle to still be drawn. + * For space not used because of to small items, you can specify + * with <reuseSpace> if the background should shine through or + * the space will be used to enlarge the next item to be drawn + * at this level. + */ + void setVisibleWidth(int width, bool reuseSpace = false); + + /** + * If a children value() is almost the parents sum(), + * it can happen that the border to be drawn for visibilty of + * nesting relations takes to much space, and the + * parent/child size relation can not be mapped to a correct + * area size relation. + * + * Either + * (1) Ignore the incorrect drawing, or + * (2) Skip drawing of the parent level alltogether. + */ + void setSkipIncorrectBorder(bool enable = true); + bool skipIncorrectBorder() const { return _skipIncorrectBorder; } + + /** + * Maximal nesting depth + */ + void setMaxDrawingDepth(int d); + int maxDrawingDepth() const { return _maxDrawingDepth; } + + /** + * Minimal area for rectangles to draw + */ + void setMinimalArea(int area); + int minimalArea() const { return _minimalArea; } + + /* defaults for text attributes */ + QString defaultFieldType(int) const; + QString defaultFieldStop(int) const; + bool defaultFieldVisible(int) const; + bool defaultFieldForced(int) const; + DrawParams::Position defaultFieldPosition(int) const; + + /** + * Set the type name of a field. + * This is important for the visualization menu generated + * with visualizationMenu() + */ + void setFieldType(int, QString); + QString fieldType(int) const; + + /** + * Stop drawing at item with name + */ + void setFieldStop(int, QString); + QString fieldStop(int) const; + + /** + * Should the text with number textNo be visible? + * This is only done if remaining space is enough to allow for + * proportional size constrains. + */ + void setFieldVisible(int, bool); + bool fieldVisible(int) const; + + /** + * Should the drawing of the name into the rectangle be forced? + * This enables drawing of the name before drawing subitems, and + * thus destroys proportional constrains. + */ + void setFieldForced(int, bool); + bool fieldForced(int) const; + + /** + * Set the field position in the area. See TreeMapItem::Position + */ + void setFieldPosition(int, DrawParams::Position); + DrawParams::Position fieldPosition(int) const; + void setFieldPosition(int, QString); + QString fieldPositionString(int) const; + + /** + * Do we allow the texts to be rotated by 90 degrees for better fitting? + */ + void setAllowRotation(bool); + bool allowRotation() const { return _allowRotation; } + + void setBorderWidth(int w); + int borderWidth() const { return _borderWidth; } + + /** + * Save/restore options. + */ + void saveOptions(KConfigGroup*, QString prefix = QString::null); + void restoreOptions(KConfigGroup*, QString prefix = QString::null); + + /** + * These functions populate given popup menus. + * The added items are already connected to handlers. + * + * The int is the menu id where to start for the items (100 IDs reserved). + */ + void addSplitDirectionItems(QPopupMenu*, int); + void addSelectionItems(QPopupMenu*, int, TreeMapItem*); + void addFieldStopItems(QPopupMenu*, int, TreeMapItem*); + void addAreaStopItems(QPopupMenu*, int, TreeMapItem*); + void addDepthStopItems(QPopupMenu*, int, TreeMapItem*); + void addVisualizationItems(QPopupMenu*, int); + + TreeMapWidget* widget() { return this; } + TreeMapItem* current() const { return _current; } + TreeMapItemList selection() const { return _selection; } + bool isSelected(TreeMapItem* i) const; + int maxSelectDepth() const { return _maxSelectDepth; } + SelectionMode selectionMode() const { return _selectionMode; } + + /** + * Return tooltip string to show for a item (can be rich text) + * Default implementation gives lines with "text0 (text1)" going to root. + */ + virtual QString tipString(TreeMapItem* i) const; + + /** + * Redraws an item with all children. + * This takes changed values(), sums(), colors() and text() into account. + */ + void redraw(TreeMapItem*); + void redraw() { redraw(_base); } + + /** + * Resort all TreeMapItems. See TreeMapItem::resort(). + */ + void resort() { _base->resort(true); } + + // internal + void drawTreeMap(); + + // used internally when items are destroyed + void deletingItem(TreeMapItem*); + +protected slots: + void splitActivated(int); + void selectionActivated(int); + void fieldStopActivated(int); + void areaStopActivated(int); + void depthStopActivated(int); + void visualizationActivated(int); + +signals: + void selectionChanged(); + void selectionChanged(TreeMapItem*); + + /** + * This signal is emitted if the current item changes. + * If the change is done because of keyboard navigation, + * the <kbd> is set to true + */ + void currentChanged(TreeMapItem*, bool keyboard); + void clicked(TreeMapItem*); + void returnPressed(TreeMapItem*); + void doubleClicked(TreeMapItem*); + void rightButtonPressed(TreeMapItem*, const QPoint &); + void contextMenuRequested(TreeMapItem*, const QPoint &); + +protected: + void mousePressEvent( QMouseEvent * ); + void contextMenuEvent( QContextMenuEvent * ); + void mouseReleaseEvent( QMouseEvent * ); + void mouseMoveEvent( QMouseEvent * ); + void mouseDoubleClickEvent( QMouseEvent * ); + void keyPressEvent( QKeyEvent* ); + void paintEvent( QPaintEvent * ); + void resizeEvent( QResizeEvent * ); + void showEvent( QShowEvent * ); + void fontChange( const QFont& ); + +private: + TreeMapItemList diff(TreeMapItemList&, TreeMapItemList&); + // returns true if selection changed + TreeMapItem* setTmpSelected(TreeMapItem*, bool selected = true); + TreeMapItem* setTmpRangeSelection(TreeMapItem* i1, + TreeMapItem* i2, bool selected); + bool isTmpSelected(TreeMapItem* i); + + void drawItem(QPainter* p, TreeMapItem*); + void drawItems(QPainter* p, TreeMapItem*); + bool horizontal(TreeMapItem* i, const QRect& r); + void drawFill(TreeMapItem*,QPainter* p, QRect& r); + void drawFill(TreeMapItem*,QPainter* p, QRect& r, + TreeMapItemListIterator it, int len, bool goBack); + bool drawItemArray(QPainter* p, TreeMapItem*, QRect& r, double, + TreeMapItemListIterator it, int len, bool); + bool resizeAttr(int); + + TreeMapItem* _base; + TreeMapItem *_current, *_pressed, *_lastOver, *_oldCurrent; + TreeMapTip* _tip; + int _maxSelectDepth, _maxDrawingDepth; + + // attributes for field, per textNo + struct FieldAttr { + QString type, stop; + bool visible, forced; + DrawParams::Position pos; + }; + QValueVector<FieldAttr> _attr; + + SelectionMode _selectionMode; + TreeMapItem::SplitMode _splitMode; + int _visibleWidth, _stopArea, _minimalArea, _borderWidth; + bool _reuseSpace, _skipIncorrectBorder, _drawSeparators, _shading; + bool _allowRotation; + TreeMapItem * _needsRefresh; + TreeMapItemList _selection; + int _markNo; + + // for the context menus: start IDs + int _splitID, _selectionID, _visID; + int _fieldStopID, _areaStopID, _depthStopID; + TreeMapItem* _menuItem; + + // temporary selection while dragging, used for drawing + // most of the time, _selection == _tmpSelection + TreeMapItemList _tmpSelection; + bool _inShiftDrag, _inControlDrag; + + // temporary widget font metrics while drawing + QFont _font; + int _fontHeight; + + // back buffer pixmap + QPixmap _pixmap; +}; + +#endif diff --git a/konq-plugins/imagerotation/Makefile.am b/konq-plugins/imagerotation/Makefile.am new file mode 100644 index 0000000..f0686ad --- /dev/null +++ b/konq-plugins/imagerotation/Makefile.am @@ -0,0 +1,7 @@ +progdir = $(kde_datadir)/imagerotation +prog_SCRIPTS = exif.py orient.py + +bin_SCRIPTS = jpegorient + +desktop_DATA = jpegorient.desktop imageconverter.desktop +desktopdir = $(kde_datadir)/konqueror/servicemenus diff --git a/konq-plugins/imagerotation/exif.py b/konq-plugins/imagerotation/exif.py new file mode 100755 index 0000000..309df47 --- /dev/null +++ b/konq-plugins/imagerotation/exif.py @@ -0,0 +1,1079 @@ +#! /usr/bin/env python +# Library to extract EXIF information in digital camera image files +# +# Contains code from "exifdump.py" originally written by Thierry Bousch +# <bousch@topo.math.u-psud.fr> and released into the public domain. +# +# Updated and turned into general-purpose library by Gene Cash +# <gcash@cfl.rr.com> +# +# NOTE: This version has been modified by Leif Jensen +# +# This copyright license is intended to be similar to the FreeBSD license. +# +# Copyright 2002 Gene Cash All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the +# distribution. +# +# THIS SOFTWARE IS PROVIDED BY GENE CASH ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# This means you may do anything you want with this code, except claim you +# wrote it. Also, if it breaks you get to keep both pieces. +# +# 21-AUG-99 TB Last update by Thierry Bousch to his code. +# 17-JAN-02 CEC Discovered code on web. +# Commented everything. +# Made small code improvements. +# Reformatted for readability. +# 19-JAN-02 CEC Added ability to read TIFFs and JFIF-format JPEGs. +# Added ability to extract JPEG formatted thumbnail. +# Added ability to read GPS IFD (not tested). +# Converted IFD data structure to dictionaries indexed by +# tag name. +# Factored into library returning dictionary of IFDs plus +# thumbnail, if any. +# 20-JAN-02 CEC Added MakerNote processing logic. +# Added Olympus MakerNote. +# Converted data structure to single-level dictionary, avoiding +# tag name collisions by prefixing with IFD name. This makes +# it much easier to use. +# 23-JAN-02 CEC Trimmed nulls from end of string values. +# 25-JAN-02 CEC Discovered JPEG thumbnail in Olympus TIFF MakerNote. +# 26-JAN-02 CEC Added ability to extract TIFF thumbnails. +# Added Nikon, Fujifilm, Casio MakerNotes. +# +# To do: +# * Finish Canon MakerNote format +# * Better printing of ratios + +# field type descriptions as (length, abbreviation, full name) tuples +FIELD_TYPES=( + (0, 'X', 'Dummy'), # no such type + (1, 'B', 'Byte'), + (1, 'A', 'ASCII'), + (2, 'S', 'Short'), + (4, 'L', 'Long'), + (8, 'R', 'Ratio'), + (1, 'SB', 'Signed Byte'), + (1, 'U', 'Undefined'), + (2, 'SS', 'Signed Short'), + (4, 'SL', 'Signed Long'), + (8, 'SR', 'Signed Ratio') + ) + +# dictionary of main EXIF tag names +# first element of tuple is tag name, optional second element is +# another dictionary giving names to values +EXIF_TAGS={ + 0x0100: ('ImageWidth', ), + 0x0101: ('ImageLength', ), + 0x0102: ('BitsPerSample', ), + 0x0103: ('Compression', + {1: 'Uncompressed TIFF', + 6: 'JPEG Compressed'}), + 0x0106: ('PhotometricInterpretation', ), + 0x010A: ('FillOrder', ), + 0x010D: ('DocumentName', ), + 0x010E: ('ImageDescription', ), + 0x010F: ('Make', ), + 0x0110: ('Model', ), + 0x0111: ('StripOffsets', ), + 0x0112: ('Orientation', ), + 0x0115: ('SamplesPerPixel', ), + 0x0116: ('RowsPerStrip', ), + 0x0117: ('StripByteCounts', ), + 0x011A: ('XResolution', ), + 0x011B: ('YResolution', ), + 0x011C: ('PlanarConfiguration', ), + 0x0128: ('ResolutionUnit', + {1: 'Not Absolute', + 2: 'Pixels/Inch', + 3: 'Pixels/Centimeter'}), + 0x012D: ('TransferFunction', ), + 0x0131: ('Software', ), + 0x0132: ('DateTime', ), + 0x013B: ('Artist', ), + 0x013E: ('WhitePoint', ), + 0x013F: ('PrimaryChromaticities', ), + 0x0156: ('TransferRange', ), + 0x0200: ('JPEGProc', ), + 0x0201: ('JPEGInterchangeFormat', ), + 0x0202: ('JPEGInterchangeFormatLength', ), + 0x0211: ('YCbCrCoefficients', ), + 0x0212: ('YCbCrSubSampling', ), + 0x0213: ('YCbCrPositioning', ), + 0x0214: ('ReferenceBlackWhite', ), + 0x828D: ('CFARepeatPatternDim', ), + 0x828E: ('CFAPattern', ), + 0x828F: ('BatteryLevel', ), + 0x8298: ('Copyright', ), + 0x829A: ('ExposureTime', ), + 0x829D: ('FNumber', ), + 0x83BB: ('IPTC/NAA', ), + 0x8769: ('ExifOffset', ), + 0x8773: ('InterColorProfile', ), + 0x8822: ('ExposureProgram', + {0: 'Unidentified', + 1: 'Manual', + 2: 'Program Normal', + 3: 'Aperture Priority', + 4: 'Shutter Priority', + 5: 'Program Creative', + 6: 'Program Action', + 7: 'Portrait Mode', + 8: 'Landscape Mode'}), + 0x8824: ('SpectralSensitivity', ), + 0x8825: ('GPSInfo', ), + 0x8827: ('ISOSpeedRatings', ), + 0x8828: ('OECF', ), + 0x9000: ('ExifVersion', ), + 0x9003: ('DateTimeOriginal', ), + 0x9004: ('DateTimeDigitized', ), + 0x9101: ('ComponentsConfiguration', + {0: '', + 1: 'Y', + 2: 'Cb', + 3: 'Cr', + 4: 'Red', + 5: 'Green', + 6: 'Blue'}), + 0x9102: ('CompressedBitsPerPixel', ), + 0x9201: ('ShutterSpeedValue', ), + 0x9202: ('ApertureValue', ), + 0x9203: ('BrightnessValue', ), + 0x9204: ('ExposureBiasValue', ), + 0x9205: ('MaxApertureValue', ), + 0x9206: ('SubjectDistance', ), + 0x9207: ('MeteringMode', + {0: 'Unidentified', + 1: 'Average', + 2: 'CenterWeightedAverage', + 3: 'Spot', + 4: 'MultiSpot'}), + 0x9208: ('LightSource', + {0: 'Unknown', + 1: 'Daylight', + 2: 'Fluorescent', + 3: 'Tungsten', + 10: 'Flash', + 17: 'Standard Light A', + 18: 'Standard Light B', + 19: 'Standard Light C', + 20: 'D55', + 21: 'D65', + 22: 'D75', + 255: 'Other'}), + 0x9209: ('Flash', {0: 'No', + 1: 'Fired', + 5: 'Fired (?)', # no return sensed + 7: 'Fired (!)', # return sensed + 9: 'Fill Fired', + 13: 'Fill Fired (?)', + 15: 'Fill Fired (!)', + 16: 'Off', + 24: 'Auto Off', + 25: 'Auto Fired', + 29: 'Auto Fired (?)', + 31: 'Auto Fired (!)', + 32: 'Not Available'}), + 0x920A: ('FocalLength', ), + 0x927C: ('MakerNote', ), + 0x9286: ('UserComment', ), + 0x9290: ('SubSecTime', ), + 0x9291: ('SubSecTimeOriginal', ), + 0x9292: ('SubSecTimeDigitized', ), + 0xA000: ('FlashPixVersion', ), + 0xA001: ('ColorSpace', ), + 0xA002: ('ExifImageWidth', ), + 0xA003: ('ExifImageLength', ), + 0xA005: ('InteroperabilityOffset', ), + 0xA20B: ('FlashEnergy', ), # 0x920B in TIFF/EP + 0xA20C: ('SpatialFrequencyResponse', ), # 0x920C - - + 0xA20E: ('FocalPlaneXResolution', ), # 0x920E - - + 0xA20F: ('FocalPlaneYResolution', ), # 0x920F - - + 0xA210: ('FocalPlaneResolutionUnit', ), # 0x9210 - - + 0xA214: ('SubjectLocation', ), # 0x9214 - - + 0xA215: ('ExposureIndex', ), # 0x9215 - - + 0xA217: ('SensingMethod', ), # 0x9217 - - + 0xA300: ('FileSource', + {3: 'Digital Camera'}), + 0xA301: ('SceneType', + {1: 'Directly Photographed'}), + } + +# interoperability tags +INTR_TAGS={ + 0x0001: ('InteroperabilityIndex', ), + 0x0002: ('InteroperabilityVersion', ), + 0x1000: ('RelatedImageFileFormat', ), + 0x1001: ('RelatedImageWidth', ), + 0x1002: ('RelatedImageLength', ), + } + +# GPS tags (not used yet, haven't seen camera with GPS) +GPS_TAGS={ + 0x0000: ('GPSVersionID', ), + 0x0001: ('GPSLatitudeRef', ), + 0x0002: ('GPSLatitude', ), + 0x0003: ('GPSLongitudeRef', ), + 0x0004: ('GPSLongitude', ), + 0x0005: ('GPSAltitudeRef', ), + 0x0006: ('GPSAltitude', ), + 0x0007: ('GPSTimeStamp', ), + 0x0008: ('GPSSatellites', ), + 0x0009: ('GPSStatus', ), + 0x000A: ('GPSMeasureMode', ), + 0x000B: ('GPSDOP', ), + 0x000C: ('GPSSpeedRef', ), + 0x000D: ('GPSSpeed', ), + 0x000E: ('GPSTrackRef', ), + 0x000F: ('GPSTrack', ), + 0x0010: ('GPSImgDirectionRef', ), + 0x0011: ('GPSImgDirection', ), + 0x0012: ('GPSMapDatum', ), + 0x0013: ('GPSDestLatitudeRef', ), + 0x0014: ('GPSDestLatitude', ), + 0x0015: ('GPSDestLongitudeRef', ), + 0x0016: ('GPSDestLongitude', ), + 0x0017: ('GPSDestBearingRef', ), + 0x0018: ('GPSDestBearing', ), + 0x0019: ('GPSDestDistanceRef', ), + 0x001A: ('GPSDestDistance', ) + } + +# Nikon E99x MakerNote Tags +# http://members.tripod.com/~tawba/990exif.htm +MAKERNOTE_NIKON_NEWER_TAGS={ + 0x0002: ('ISOSetting', ), + 0x0003: ('ColorMode', ), + 0x0004: ('Quality', ), + 0x0005: ('Whitebalance', ), + 0x0006: ('ImageSharpening', ), + 0x0007: ('FocusMode', ), + 0x0008: ('FlashSetting', ), + 0x000F: ('ISOSelection', ), + 0x0080: ('ImageAdjustment', ), + 0x0082: ('AuxiliaryLens', ), + 0x0085: ('ManualFocusDistance', ), + 0x0086: ('DigitalZoomFactor', ), + 0x0088: ('AFFocusPosition', + {0x0000: 'Center', + 0x0100: 'Top', + 0x0200: 'Bottom', + 0x0300: 'Left', + 0x0400: 'Right'}), + 0x0094: ('Saturation', + {-3: 'B&W', + -2: '-2', + -1: '-1', + 0: '0', + 1: '1', + 2: '2'}), + 0x0095: ('NoiseReduction', ), + 0x0010: ('DataDump', ) + } + +MAKERNOTE_NIKON_OLDER_TAGS={ + 0x0003: ('Quality', + {1: 'VGA Basic', + 2: 'VGA Normal', + 3: 'VGA Fine', + 4: 'SXGA Basic', + 5: 'SXGA Normal', + 6: 'SXGA Fine'}), + 0x0004: ('ColorMode', + {1: 'Color', + 2: 'Monochrome'}), + 0x0005: ('ImageAdjustment', + {0: 'Normal', + 1: 'Bright+', + 2: 'Bright-', + 3: 'Contrast+', + 4: 'Contrast-'}), + 0x0006: ('CCDSpeed', + {0: 'ISO 80', + 2: 'ISO 160', + 4: 'ISO 320', + 5: 'ISO 100'}), + 0x0007: ('WhiteBalance', + {0: 'Auto', + 1: 'Preset', + 2: 'Daylight', + 3: 'Incandescent', + 4: 'Fluorescent', + 5: 'Cloudy', + 6: 'Speed Light'}) + } + +# decode Olympus SpecialMode tag in MakerNote +def olympus_special_mode(v): + a={ + 0: 'Normal', + 1: 'Unknown', + 2: 'Fast', + 3: 'Panorama'} + b={ + 0: 'Non-panoramic', + 1: 'Left to right', + 2: 'Right to left', + 3: 'Bottom to top', + 4: 'Top to bottom'} + return '%s - sequence %d - %s' % (a[v[0]], v[1], b[v[2]]) + +MAKERNOTE_OLYMPUS_TAGS={ + # ah HAH! those sneeeeeaky bastids! this is how they get past the fact + # that a JPEG thumbnail is not allowed in an uncompressed TIFF file + 0x0100: ('JPEGThumbnail', ), + 0x0200: ('SpecialMode', olympus_special_mode), + 0x0201: ('JPEGQual', + {1: 'SQ', + 2: 'HQ', + 3: 'SHQ'}), + 0x0202: ('Macro', + {0: 'Normal', + 1: 'Macro'}), + 0x0204: ('DigitalZoom', ), + 0x0207: ('SoftwareRelease', ), + 0x0208: ('PictureInfo', ), + # print as string + 0x0209: ('CameraID', lambda x: ''.join(map(chr, x))), + 0x0F00: ('DataDump', ) + } + +MAKERNOTE_CASIO_TAGS={ + 0x0001: ('RecordingMode', + {1: 'Single Shutter', + 2: 'Panorama', + 3: 'Night Scene', + 4: 'Portrait', + 5: 'Landscape'}), + 0x0002: ('Quality', + {1: 'Economy', + 2: 'Normal', + 3: 'Fine'}), + 0x0003: ('FocusingMode', + {2: 'Macro', + 3: 'Auto Focus', + 4: 'Manual Focus', + 5: 'Infinity'}), + 0x0004: ('FlashMode', + {1: 'Auto', + 2: 'On', + 3: 'Off', + 4: 'Red Eye Reduction'}), + 0x0005: ('FlashIntensity', + {11: 'Weak', + 13: 'Normal', + 15: 'Strong'}), + 0x0006: ('Object Distance', ), + 0x0007: ('WhiteBalance', + {1: 'Auto', + 2: 'Tungsten', + 3: 'Daylight', + 4: 'Fluorescent', + 5: 'Shade', + 129: 'Manual'}), + 0x000B: ('Sharpness', + {0: 'Normal', + 1: 'Soft', + 2: 'Hard'}), + 0x000C: ('Contrast', + {0: 'Normal', + 1: 'Low', + 2: 'High'}), + 0x000D: ('Saturation', + {0: 'Normal', + 1: 'Low', + 2: 'High'}), + 0x0014: ('CCDSpeed', + {64: 'Normal', + 80: 'Normal', + 100: 'High', + 125: '+1.0', + 244: '+3.0', + 250: '+2.0',}) + } + +MAKERNOTE_FUJIFILM_TAGS={ + 0x0000: ('NoteVersion', lambda x: ''.join(map(chr, x))), + 0x1000: ('Quality', ), + 0x1001: ('Sharpness', + {1: 'Soft', + 2: 'Soft', + 3: 'Normal', + 4: 'Hard', + 5: 'Hard'}), + 0x1002: ('WhiteBalance', + {0: 'Auto', + 256: 'Daylight', + 512: 'Cloudy', + 768: 'DaylightColor-Fluorescent', + 769: 'DaywhiteColor-Fluorescent', + 770: 'White-Fluorescent', + 1024: 'Incandescent', + 3840: 'Custom'}), + 0x1003: ('Color', + {0: 'Normal', + 256: 'High', + 512: 'Low'}), + 0x1004: ('Tone', + {0: 'Normal', + 256: 'High', + 512: 'Low'}), + 0x1010: ('FlashMode', + {0: 'Auto', + 1: 'On', + 2: 'Off', + 3: 'Red Eye Reduction'}), + 0x1011: ('FlashStrength', ), + 0x1020: ('Macro', + {0: 'Off', + 1: 'On'}), + 0x1021: ('FocusMode', + {0: 'Auto', + 1: 'Manual'}), + 0x1030: ('SlowSync', + {0: 'Off', + 1: 'On'}), + 0x1031: ('PictureMode', + {0: 'Auto', + 1: 'Portrait', + 2: 'Landscape', + 4: 'Sports', + 5: 'Night', + 6: 'Program AE', + 256: 'Aperture Priority AE', + 512: 'Shutter Priority AE', + 768: 'Manual Exposure'}), + 0x1100: ('MotorOrBracket', + {0: 'Off', + 1: 'On'}), + 0x1300: ('BlurWarning', + {0: 'Off', + 1: 'On'}), + 0x1301: ('FocusWarning', + {0: 'Off', + 1: 'On'}), + 0x1302: ('AEWarning', + {0: 'Off', + 1: 'On'}) + } + +MAKERNOTE_CANON_TAGS={ + 0x0006: ('ImageType', ), + 0x0007: ('FirmwareVersion', ), + 0x0008: ('ImageNumber', ), + 0x0009: ('OwnerName', ) + } + +# see http://www.burren.cx/david/canon.html by David Burren +# this is in element offset, name, optional value dictionary format +MAKERNOTE_CANON_TAG_0x001={ + 1: ('Macromode', + {1: 'Macro', + 2: 'Normal'}), + 2: ('SelfTimer', ), + 3: ('Quality', + {2: 'Normal', + 3: 'Fine', + 5: 'Superfine'}), + 4: ('FlashMode', + {0: 'Flash Not Fired', + 1: 'Auto', + 2: 'On', + 3: 'Red-Eye Reduction', + 4: 'Slow Synchro', + 5: 'Auto + Red-Eye Reduction', + 6: 'On + Red-Eye Reduction', + 16: 'external flash'}), + 5: ('ContinuousDriveMode', + {0: 'Single Or Timer', + 1: 'Continuous'}), + 7: ('FocusMode', + {0: 'One-Shot', + 1: 'AI Servo', + 2: 'AI Focus', + 3: 'MF', + 4: 'Single', + 5: 'Continuous', + 6: 'MF'}), + 10: ('ImageSize', + {0: 'Large', + 1: 'Medium', + 2: 'Small'}), + 11: ('EasyShootingMode', + {0: 'Full Auto', + 1: 'Manual', + 2: 'Landscape', + 3: 'Fast Shutter', + 4: 'Slow Shutter', + 5: 'Night', + 6: 'B&W', + 7: 'Sepia', + 8: 'Portrait', + 9: 'Sports', + 10: 'Macro/Close-Up', + 11: 'Pan Focus'}), + 12: ('DigitalZoom', + {0: 'None', + 1: '2x', + 2: '4x'}), + 13: ('Contrast', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 14: ('Saturation', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 15: ('Sharpness', + {0xFFFF: 'Low', + 0: 'Normal', + 1: 'High'}), + 16: ('ISO', + {0: 'See ISOSpeedRatings Tag', + 15: 'Auto', + 16: '50', + 17: '100', + 18: '200', + 19: '400'}), + 17: ('MeteringMode', + {3: 'Evaluative', + 4: 'Partial', + 5: 'Center-weighted'}), + 18: ('FocusType', + {0: 'Manual', + 1: 'Auto', + 3: 'Close-Up (Macro)', + 8: 'Locked (Pan Mode)'}), + 19: ('AFPointSelected', + {0x3000: 'None (MF)', + 0x3001: 'Auto-Selected', + 0x3002: 'Right', + 0x3003: 'Center', + 0x3004: 'Left'}), + 20: ('ExposureMode', + {0: 'Easy Shooting', + 1: 'Program', + 2: 'Tv-priority', + 3: 'Av-priority', + 4: 'Manual', + 5: 'A-DEP'}), + 23: ('LongFocalLengthOfLensInFocalUnits', ), + 24: ('ShortFocalLengthOfLensInFocalUnits', ), + 25: ('FocalUnitsPerMM', ), + 28: ('FlashActivity', + {0: 'Did Not Fire', + 1: 'Fired'}), + 29: ('FlashDetails', + {14: 'External E-TTL', + 13: 'Internal Flash', + 11: 'FP Sync Used', + 7: '2nd("Rear")-Curtain Sync Used', + 4: 'FP Sync Enabled'}), + 32: ('FocusMode', + {0: 'Single', + 1: 'Continuous'}) + } + +MAKERNOTE_CANON_TAG_0x004={ + 7: ('WhiteBalance', + {0: 'Auto', + 1: 'Sunny', + 2: 'Cloudy', + 3: 'Tungsten', + 4: 'Fluorescent', + 5: 'Flash', + 6: 'Custom'}), + 9: ('SequenceNumber', ), + 14: ('AFPointUsed', ), + 15: ('FlashBias', + {0XFFC0: '-2 EV', + 0XFFCC: '-1.67 EV', + 0XFFD0: '-1.50 EV', + 0XFFD4: '-1.33 EV', + 0XFFE0: '-1 EV', + 0XFFEC: '-0.67 EV', + 0XFFF0: '-0.50 EV', + 0XFFF4: '-0.33 EV', + 0X0000: '0 EV', + 0X000C: '0.33 EV', + 0X0010: '0.50 EV', + 0X0014: '0.67 EV', + 0X0020: '1 EV', + 0X002C: '1.33 EV', + 0X0030: '1.50 EV', + 0X0034: '1.67 EV', + 0X0040: '2 EV'}), + 19: ('SubjectDistance', ) + } + +# extract multibyte integer in Motorola format (little endian) +def s2n_motorola(str): + x=0 + for c in str: + x=(long(x) << 8) | ord(c) + return x + +# extract multibyte integer in Intel format (big endian) +def s2n_intel(str): + x=0 + y=0 + for c in str: + x=x | (ord(c) << y) + y=y+8 + return x + +# ratio object that eventually will be able to reduce itself to lowest +# common denominator for printing +def gcd(a, b): + if b == 0: + return a + else: + return gcd(b, a % b) + +class Ratio: + def __init__(self, num, den): + self.num=num + self.den=den + + def __repr__(self): +# self.reduce() # ugh, 259/250 worse 1036/1000 + if self.den == 1: + return str(self.num) + return '%d/%d' % (self.num, self.den) + + def reduce(self): + div=gcd(self.num, self.den) + if div > 1: + self.num=self.num/div + self.den=self.den/div + +# for ease of dealing with tags +class IFD_Tag: + def __init__(self, printable, tag, field_type, values, field_offset, + field_length): + self.printable=printable + self.tag=tag + self.field_type=field_type + self.field_offset=field_offset + self.field_length=field_length + self.values=values + + def __str__(self): + return self.printable + + def __repr__(self): + return '(0x%04X) %s=%s @ %d' % (self.tag, + FIELD_TYPES[self.field_type][2], + self.printable, + self.field_offset) + +# class that handles an EXIF header +class EXIF_header: + def __init__(self, file, endian, offset, debug=0): + self.file=file + self.endian=endian + self.offset=offset + self.debug=debug + self.tags={} + + # convert slice to integer, based on sign and endian flags + def s2n(self, offset, length, signed=0): + self.file.seek(self.offset+offset) + slice=self.file.read(length) + if self.endian == 'I': + val=s2n_intel(slice) + else: + val=s2n_motorola(slice) + # Sign extension ? + if signed: + msb=1L << (8*length-1) + if val & msb: + val=val-(msb << 1) + return val + + # convert offset to string + def n2s(self, offset, length): + s='' + for i in range(length): + if self.endian == 'I': + s=s+chr(offset & 0xFF) + else: + s=chr(offset & 0xFF)+s + offset=offset >> 8 + return s + + # return first IFD + def first_IFD(self): + return self.s2n(4, 4) + + # return pointer to next IFD + def next_IFD(self, ifd): + entries=self.s2n(ifd, 2) + return self.s2n(ifd+2+12*entries, 4) + + # return list of IFDs in header + def list_IFDs(self): + i=self.first_IFD() + a=[] + while i: + a.append(i) + i=self.next_IFD(i) + return a + + # return list of entries in this IFD + def dump_IFD(self, ifd, ifd_name, dict=EXIF_TAGS): + entries=self.s2n(ifd, 2) + for i in range(entries): + entry=ifd+2+12*i + tag=self.s2n(entry, 2) + field_type=self.s2n(entry+2, 2) + if not 0 < field_type < len(FIELD_TYPES): + # unknown field type + raise ValueError, \ + 'unknown type %d in tag 0x%04X' % (field_type, tag) + typelen=FIELD_TYPES[field_type][0] + count=self.s2n(entry+4, 4) + offset=entry+8 + if count*typelen > 4: + # not the value, it's a pointer to the value + offset=self.s2n(offset, 4) + field_offset=offset + if field_type == 2: + # special case: null-terminated ASCII string + if count != 0: + self.file.seek(self.offset+offset) + values=self.file.read(count).strip().replace('\x00','') + else: + values='' + elif tag == 0x927C or tag == 0x9286: # MakerNote or UserComment +# elif tag == 0x9286: # UserComment + values=[] + else: + values=[] + signed=(field_type in [6, 8, 9, 10]) + for j in range(count): + if field_type in (5, 10): + # a ratio + value_j=Ratio(self.s2n(offset, 4, signed), + self.s2n(offset+4, 4, signed)) + else: + value_j=self.s2n(offset, typelen, signed) + values.append(value_j) + offset=offset+typelen + # now "values" is either a string or an array + if count == 1 and field_type != 2: + printable=str(values[0]) + else: + printable=str(values) + # figure out tag name + tag_entry=dict.get(tag) + if tag_entry: + tag_name=tag_entry[0] + if len(tag_entry) != 1: + # optional 2nd tag element is present + if callable(tag_entry[1]): + # call mapping function + printable=tag_entry[1](values) + else: + printable='' + for i in values: + # use LUT for this tag + printable+=tag_entry[1].get(i, repr(i)) + else: + tag_name='Tag 0x%04X' % tag + self.tags[ifd_name+' '+tag_name]=IFD_Tag(printable, tag, + field_type, + values, field_offset, + count*typelen) + if self.debug: + print ' %s: %s' % (tag_name, + repr(self.tags[ifd_name+' '+tag_name])) + + # extract uncompressed TIFF thumbnail (like pulling teeth) + # we take advantage of the pre-existing layout in the thumbnail IFD as + # much as possible + def extract_TIFF_thumbnail(self, thumb_ifd): + entries=self.s2n(thumb_ifd, 2) + # this is header plus offset to IFD ... + if self.endian == 'M': + tiff='MM\x00*\x00\x00\x00\x08' + else: + tiff='II*\x00\x08\x00\x00\x00' + # ... plus thumbnail IFD data plus a null "next IFD" pointer + self.file.seek(self.offset+thumb_ifd) + tiff+=self.file.read(entries*12+2)+'\x00\x00\x00\x00' + + # fix up large value offset pointers into data area + for i in range(entries): + entry=thumb_ifd+2+12*i + tag=self.s2n(entry, 2) + field_type=self.s2n(entry+2, 2) + typelen=FIELD_TYPES[field_type][0] + count=self.s2n(entry+4, 4) + oldoff=self.s2n(entry+8, 4) + # start of the 4-byte pointer area in entry + ptr=i*12+18 + # remember strip offsets location + if tag == 0x0111: + strip_off=ptr + strip_len=count*typelen + # is it in the data area? + if count*typelen > 4: + # update offset pointer (nasty "strings are immutable" crap) + # should be able to say "tiff[ptr:ptr+4]=newoff" + newoff=len(tiff) + tiff=tiff[:ptr]+self.n2s(newoff, 4)+tiff[ptr+4:] + # remember strip offsets location + if tag == 0x0111: + strip_off=newoff + strip_len=4 + # get original data and store it + self.file.seek(self.offset+oldoff) + tiff+=self.file.read(count*typelen) + + # add pixel strips and update strip offset info + old_offsets=self.tags['Thumbnail StripOffsets'].values + old_counts=self.tags['Thumbnail StripByteCounts'].values + for i in range(len(old_offsets)): + # update offset pointer (more nasty "strings are immutable" crap) + offset=self.n2s(len(tiff), strip_len) + tiff=tiff[:strip_off]+offset+tiff[strip_off+strip_len:] + strip_off+=strip_len + # add pixel strip to end + self.file.seek(self.offset+old_offsets[i]) + tiff+=self.file.read(old_counts[i]) + + self.tags['TIFFThumbnail']=tiff + + # decode all the camera-specific MakerNote formats + def decode_maker_note(self): + note=self.tags['EXIF MakerNote'] + make=self.tags['Image Make'].printable + model=self.tags['Image Model'].printable + + # Nikon + if make == 'NIKON': + if note.values[0:5] == [78, 105, 107, 111, 110]: # "Nikon" + # older model + self.dump_IFD(note.field_offset+8, 'MakerNote', + dict=MAKERNOTE_NIKON_OLDER_TAGS) + else: + # newer model (E99x or D1) + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_NIKON_NEWER_TAGS) + return + + # Olympus + if make[:7] == 'OLYMPUS': + self.dump_IFD(note.field_offset+8, 'MakerNote', + dict=MAKERNOTE_OLYMPUS_TAGS) + return + + # Casio + if make == 'Casio': + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_CASIO_TAGS) + return + + # Fujifilm + if make == 'FUJIFILM': + # bug: everything else is "Motorola" endian, but the MakerNote + # is "Intel" endian + endian=self.endian + self.endian='I' + # bug: IFD offsets are from beginning of MakerNote, not + # beginning of file header + offset=self.offset + self.offset+=note.field_offset + # process note with bogus values (note is actually at offset 12) + self.dump_IFD(12, 'MakerNote', dict=MAKERNOTE_FUJIFILM_TAGS) + # reset to correct values + self.endian=endian + self.offset=offset + return + + # Canon + if make == 'Canon': + self.dump_IFD(note.field_offset, 'MakerNote', + dict=MAKERNOTE_CANON_TAGS) + for i in (('MakerNote Tag 0x0001', MAKERNOTE_CANON_TAG_0x001), + ('MakerNote Tag 0x0004', MAKERNOTE_CANON_TAG_0x004)): + if self.debug: + print ' SubMakerNote BitSet for ' +i[0] + self.canon_decode_tag(self.tags[i[0]].values, i[1]) + return + + # decode Canon MakerNote tag based on offset within tag + # see http://www.burren.cx/david/canon.html by David Burren + def canon_decode_tag(self, value, dict): + for i in range(1, len(value)): + x=dict.get(i, ('Unknown', )) +# if self.debug: +# print i, x + name=x[0] + if len(x) > 1: + val=x[1].get(value[i], 'Unknown') + else: + val=value[i] + if self.debug: + print ' '+name+':', val + self.tags['MakerNote '+name]=val + +# process an image file (expects an open file object) +# this is the function that has to deal with all the arbitrary nasty bits +# of the EXIF standard +def process_file(file, debug=0, noclose=0): + # determine whether it's a JPEG or TIFF + data=file.read(12) + if data[0:4] in ['II*\x00', 'MM\x00*']: + # it's a TIFF file + file.seek(0) + endian=file.read(1) + file.read(1) + offset=0 + elif data[0:2] == '\xFF\xD8': + # it's a JPEG file + # skip JFIF style header(s) + while data[2] == '\xFF' and data[6:10] in ('JFIF', 'JFXX', 'OLYM'): + length=ord(data[4])*256+ord(data[5]) + file.read(length-8) + # fake an EXIF beginning of file + data='\xFF\x00'+file.read(10) + if data[2] == '\xFF' and data[6:10] == 'Exif': + # detected EXIF header + offset=file.tell() + endian=file.read(1) + else: + # no EXIF information + return {} + else: + # file format not recognized + return {} + + # deal with the EXIF info we found + if debug: + print {'I': 'Intel', 'M': 'Motorola'}[endian], 'format' + hdr=EXIF_header(file, endian, offset, debug) + ifd_list=hdr.list_IFDs() + ctr=0 + for i in ifd_list: + if ctr == 0: + IFD_name='Image' + elif ctr == 1: + IFD_name='Thumbnail' + thumb_ifd=i + else: + IFD_name='IFD %d' % ctr + if debug: + print ' IFD %d (%s) at offset %d:' % (ctr, IFD_name, i) + hdr.tags['Exif Offset'] = offset + hdr.tags['Exif Endian'] = endian + hdr.tags[IFD_name+' IFDOffset'] = i + hdr.dump_IFD(i, IFD_name) + # EXIF IFD + exif_off=hdr.tags.get(IFD_name+' ExifOffset') + if exif_off: + if debug: + print ' EXIF SubIFD at offset %d:' % exif_off.values[0] + hdr.dump_IFD(exif_off.values[0], 'EXIF') + # Interoperability IFD contained in EXIF IFD + #intr_off=hdr.tags.get('EXIF SubIFD InteroperabilityOffset') + intr_off=hdr.tags.get('EXIF InteroperabilityOffset') + if intr_off: + if debug: + print ' EXIF Interoperability SubSubIFD at offset %d:' \ + % intr_off.values[0] + hdr.dump_IFD(intr_off.values[0], 'EXIF Interoperability', + dict=INTR_TAGS) + # deal with MakerNote contained in EXIF IFD + if hdr.tags.has_key('EXIF MakerNote'): + if debug: + print ' EXIF MakerNote SubSubIFD at offset %d:' \ + % intr_off.values[0] + hdr.decode_maker_note() + # GPS IFD + gps_off=hdr.tags.get(IFD_name+' GPSInfoOffset') + if gps_off: + if debug: + print ' GPS SubIFD at offset %d:' % gps_off.values[0] + hdr.dump_IFD(gps_off.values[0], 'GPS', dict=GPS_TAGS) + ctr+=1 + + + # extract uncompressed TIFF thumbnail + thumb=hdr.tags.get('Thumbnail Compression') + if thumb and thumb.printable == 'Uncompressed TIFF': + hdr.extract_TIFF_thumbnail(thumb_ifd) + + # JPEG thumbnail (thankfully the JPEG data is stored as a unit) + thumb_off=hdr.tags.get('Thumbnail JPEGInterchangeFormat') + if thumb_off: + file.seek(offset+thumb_off.values[0]) + size=hdr.tags['Thumbnail JPEGInterchangeFormatLength'].values[0] + hdr.tags['JPEGThumbnail']=file.read(size) + + # Sometimes in a TIFF file, a JPEG thumbnail is hidden in the MakerNote + # since it's not allowed in a uncompressed TIFF IFD + if not hdr.tags.has_key('JPEGThumbnail'): + thumb_off=hdr.tags.get('MakerNote JPEGThumbnail') + if thumb_off: + file.seek(offset+thumb_off.values[0]) + hdr.tags['JPEGThumbnail']=file.read(thumb_off.field_length) + + if noclose == 0: + file.close() + return hdr.tags + +# library test/debug function (dump given files) +if __name__ == '__main__': + import sys + + if len(sys.argv) < 2: + print 'Usage: %s files...\n' % sys.argv[0] + sys.exit(0) + + for filename in sys.argv[1:]: + try: + file=open(filename, 'rb') + except: + print filename, 'unreadable' + print + continue + print filename+':' + # data=process_file(file, 1) # with debug info + data=process_file(file, 1) + if not data: + print 'No EXIF information found' + continue + +# x=data.keys() +# x.sort() +# for i in x: +# if i in ('JPEGThumbnail', 'TIFFThumbnail'): +# continue +# print ' %s (%s): %s' % \ +# (i, FIELD_TYPES[data[i].field_type][2], data[i].printable) +# if data.has_key('JPEGThumbnail'): +# print 'File has JPEG thumbnail' +# print diff --git a/konq-plugins/imagerotation/imageconverter.desktop b/konq-plugins/imagerotation/imageconverter.desktop new file mode 100644 index 0000000..07cb700 --- /dev/null +++ b/konq-plugins/imagerotation/imageconverter.desktop @@ -0,0 +1,83 @@ +# +# Servicemenu image converter, by Jens Benecke <jens-kde@spamfreemail.de>. +# Released under the same license as the KDE core distribution (GPL 2.0). +# +[Desktop Entry] +ServiceTypes=image/* +Actions=convToJPEG;convToPNG;convToGIF;convToTIF; +X-KDE-Submenu=Convert To +X-KDE-Submenu[bg]=Конвертиране в +X-KDE-Submenu[ca]=Converteix a +X-KDE-Submenu[cs]=Převést na +X-KDE-Submenu[da]=Konvertér til +X-KDE-Submenu[de]=Konvertieren in +X-KDE-Submenu[el]=Μετατροπή σε +X-KDE-Submenu[eo]=Konvertu al +X-KDE-Submenu[es]=Convertir a +X-KDE-Submenu[et]=Teisendamine +X-KDE-Submenu[eu]=Bihurtu honetara +X-KDE-Submenu[fa]=تبدیل به +X-KDE-Submenu[fi]=Muunna +X-KDE-Submenu[fr]=Convertir en +X-KDE-Submenu[fy]=Konvertearje nei +X-KDE-Submenu[ga]=Tiontaigh Go +X-KDE-Submenu[gl]=Converter En +X-KDE-Submenu[hr]=Pretvori u +X-KDE-Submenu[hu]=Átalakítás +X-KDE-Submenu[is]=Umbreyta í +X-KDE-Submenu[it]=Converti in +X-KDE-Submenu[ja]=変換 +X-KDE-Submenu[ka]=კონვერტაცია +X-KDE-Submenu[kk]=Мынаған айналдыру +X-KDE-Submenu[km]=បម្លែងទៅជា +X-KDE-Submenu[lt]=Konvertuoti į +X-KDE-Submenu[mk]=Претвори во +X-KDE-Submenu[nb]=Konverter til +X-KDE-Submenu[nds]=Ümwanneln na +X-KDE-Submenu[ne]=यसमा बदल्नुहोस् +X-KDE-Submenu[nl]=Converteren naar +X-KDE-Submenu[nn]=Konverter til +X-KDE-Submenu[pl]=Konwertuj do +X-KDE-Submenu[pt]=Converter Para +X-KDE-Submenu[pt_BR]=Converter Para +X-KDE-Submenu[ru]=Сохранить как +X-KDE-Submenu[sk]=Konvertovať na +X-KDE-Submenu[sl]=Pretvori v +X-KDE-Submenu[sr]=Претвори у +X-KDE-Submenu[sr@Latn]=Pretvori u +X-KDE-Submenu[sv]=Konvertera till +X-KDE-Submenu[tr]=Dönüştür +X-KDE-Submenu[uk]=Перетворити в +X-KDE-Submenu[vi]=Chuyển đổi sang +X-KDE-Submenu[zh_CN]=转换为 +X-KDE-Submenu[zh_TW]=轉換為 +TryExec=convert + +[Desktop Action convToJPEG] +Name=JPEG +Name[hi]=जेपीईजी +Name[ne]=जेपीईजी +Icon=image +Exec=convert %f "`echo %f | perl -pe 's/\.[^.]+$//'`.jpg" + +[Desktop Action convToPNG] +Name=PNG +Name[hi]=पीएनजी +Name[ne]=पीएनजी +Icon=image +Exec=convert %f "`echo %f | perl -pe 's/\.[^.]+$//'`.png" + +[Desktop Action convToTIF] +Name=TIF +Name[hi]=टिफ़ +Name[ne]=टीआईएफ +Icon=image +Exec=convert %f "`echo %f | perl -pe 's/\.[^.]+$//'`.tif" + +[Desktop Action convToGIF] +Name=GIF +Name[hi]=जिफ़ +Name[ne]=जीआईएफ +Icon=image +Exec=convert %f "`echo %f | perl -pe 's/\.[^.]+$//'`.gif" + diff --git a/konq-plugins/imagerotation/jpegorient b/konq-plugins/imagerotation/jpegorient new file mode 100755 index 0000000..6323289 --- /dev/null +++ b/konq-plugins/imagerotation/jpegorient @@ -0,0 +1,89 @@ +#!/bin/sh + +if test "$#" -lt 2; then + echo "Usage: $0 '##|v|h' jpegs" + exit 2 +fi + +die() { + echo "$@"; exit 1 +} + +notify() { + case "$1" in + /*) url=file:"$1" ;; + *) url=file:"$PWD"/"$1" ;; + esac + + konq=`dcop konqueror-\*` + for k in $konq; do + notify=`dcop $k KDirNotify-\*` + for n in $notify; do + dcop $k $n FilesChanged [ "$url" ] # $1 must be a url + done + done +} + +IFS=: +for path in `kde-config --path data --expandvars`; do + PATH=$path/imagerotation:$PATH +done +export PATH +unset IFS + +action=$1 + +case $action in +[1-8]|+[1-8]) o=$action ;; +90|[+-]90) o=+6 ;; # Use + for all these +270|[+-]270) o=+8 ;; +180|[+-]180) o=+3 ;; +v|-v) o=+4 ;; +h|-h) o=+2 ;; +*) die cannot understand transformation "$action" ;; +esac + +shift + +for file in "$@"; do + +if orient.py $o "$file" | grep 'orientation changed' >/dev/null 2>&1; then + notify "$file" + continue +fi + +### try jpegtran instead +if which jpegtran-mmx >/dev/null 2>&1; then + JPEGTRAN=jpegtran-mmx +else + if which jpegtran >/dev/null 2>&1; then + JPEGTRAN=jpegtran + else + die could not change orientation + fi +fi + +case $action in +v|-v) c='-flip vertical' ;; +h|-h) c='-flip horizontal' ;; +*90) c='-rotate 90' ;; +*180) c='-rotate 180' ;; +*270) c='-rotate 270' ;; ++5) c='-transpose' ;; ++7) c='-transverse' ;; +*) die cannot understand transformation "$action" using jpegtran ;; +esac # others could be emulated, but ... + +tmp="$file.a.$$" + +cleandie() { + mv -i "$tmp" $"2" </dev/null 2>/dev/null; die "$@" +} + +mv -i "$file" "$tmp" </dev/null 2>/dev/null || die unable to move temp files +$JPEGTRAN -copy all -outfile "$file" $c "$tmp" || cleandie error using jpegtran +rm "$tmp" +notify "$file" + +done + diff --git a/konq-plugins/imagerotation/jpegorient.desktop b/konq-plugins/imagerotation/jpegorient.desktop new file mode 100644 index 0000000..3f5b26c --- /dev/null +++ b/konq-plugins/imagerotation/jpegorient.desktop @@ -0,0 +1,307 @@ +[Desktop Entry] +ServiceTypes=image/jpeg +Actions=jpegRot90;jpegRot270;jpegFlipV;jpegFlipH; +X-KDE-Submenu=Transform Image +X-KDE-Submenu[bg]=Конвертиране на изображението +X-KDE-Submenu[ca]=Transforma la imatge +X-KDE-Submenu[cs]=Převést obrázek +X-KDE-Submenu[da]=Transformér billede +X-KDE-Submenu[de]=Bild transformieren +X-KDE-Submenu[el]=Μετασχηματισμός εικόνας +X-KDE-Submenu[eo]=Transformu bildon +X-KDE-Submenu[es]=Transformar imagen +X-KDE-Submenu[et]=Pildi muutmine +X-KDE-Submenu[eu]=Irudia eraldatu +X-KDE-Submenu[fa]=تبدیل تصویر +X-KDE-Submenu[fi]=Muuta kuva +X-KDE-Submenu[fr]=Transformer l'image +X-KDE-Submenu[fy]=Ofbyld transformearje +X-KDE-Submenu[ga]=Trasfhoirmigh Íomhá +X-KDE-Submenu[gl]=Transformar a Imaxe +X-KDE-Submenu[hr]=Pretvaranje slike +X-KDE-Submenu[hu]=Képátalakítás +X-KDE-Submenu[is]=Ummynda +X-KDE-Submenu[it]=Trasforma immagine +X-KDE-Submenu[ja]=画像を変換 +X-KDE-Submenu[ka]=გამოსახულებათა ტრანსფორმაცია +X-KDE-Submenu[kk]=Кескінді түрлендіру +X-KDE-Submenu[km]=ប្លែងរូបភាព +X-KDE-Submenu[lt]=Transformuoti paveikslėlį +X-KDE-Submenu[mk]=Трансформирај слика +X-KDE-Submenu[nb]=Transformer bilde +X-KDE-Submenu[nds]=Bild ännern +X-KDE-Submenu[ne]=छवि रुपान्तरण गर्नुहोस् +X-KDE-Submenu[nl]=Afbeelding transformeren +X-KDE-Submenu[nn]=Forvandla bilete +X-KDE-Submenu[pl]=Przekształć obrazek +X-KDE-Submenu[pt]=Transformar a Imagem +X-KDE-Submenu[pt_BR]=Transformar Imagem +X-KDE-Submenu[ru]=Преобразовать +X-KDE-Submenu[sk]=Transformovať obrázok +X-KDE-Submenu[sl]=Preoblikuj sliko +X-KDE-Submenu[sr]=Трансформиши слику +X-KDE-Submenu[sr@Latn]=Transformiši sliku +X-KDE-Submenu[sv]=Ändra bild +X-KDE-Submenu[tr]=Resmi Döndür +X-KDE-Submenu[uk]=Перетворити зображення +X-KDE-Submenu[vi]=Chuyển đổi ảnh +X-KDE-Submenu[zh_CN]=图像变形 +X-KDE-Submenu[zh_TW]=轉換影像 +X-KDE-Require=Write + +[Desktop Action jpegRot90] +Name=Rotate Clockwise +Name[ar]=تدوير في اتجاه الساعة +Name[az]=Saat Əqrəbi İstiqamətində Fırlat +Name[bg]=Завъртане по посока на часов. стрелка +Name[bs]=Rotiraj u smjeru kazaljke +Name[ca]=Gira 90 graus +Name[cs]=Rotovat ve směru hod. ručiček +Name[cy]=Cylchdroi yn Glocwedd +Name[da]=Rotér med uret +Name[de]=Im Uhrzeigersinn drehen (nach rechts) +Name[el]=Περιστροφή δεξιόστροφα +Name[eo]=Turnu laŭhorloĝe +Name[es]=Girar en el sentido de las agujas del reloj +Name[et]=Pööra päripäeva +Name[eu]=Biratu erloju orratzen norabidean +Name[fa]=چرخش در جهت ساعت +Name[fi]=Käännä myötäpäivään +Name[fr]=Tourner en sens horaire +Name[fy]=Mei de wizers fan'e klok mei draaie +Name[ga]=Rothlaigh go Deisealach +Name[gl]=Xirar en Sentido Horário +Name[he]=סובב עם כיוון השעון +Name[hi]=घड़ी की दिशा में घुमाएँ +Name[hr]=Okret udesno +Name[hu]=Forgatás jobbra +Name[is]=Snúa réttsælis +Name[it]=Ruota in senso orario +Name[ja]=右回転 +Name[ka]=საათის ისრის მიმართულებით მოტრიალება +Name[kk]=Сағаттың тіліне сәйкес айналдыру +Name[km]=បង្វិលស្របទ្រនិចនាឡិកា +Name[lt]=Sukti pagal laikrodžio rodyklę +Name[mk]=Ротирај кон стрелката на часовникот +Name[ms]=Putar Ikut Jam +Name[nb]=Roter medurs +Name[nds]=Na rechts dreihen +Name[ne]=घडिको दिशामा घुमाउनुहोस् +Name[nl]=Klokgewijs draaien +Name[nn]=Roter med klokka +Name[pa]=ਸੱਜਾ ਦਾਅ ਘੁੰਮਾਉ +Name[pl]=Obróć zgodnie z ruchem wskazówek zegara +Name[pt]=Rodar no Sentido Horário +Name[pt_BR]=Rodar Relógio Sentido Horário +Name[ro]=Roteşte la dreapta +Name[ru]=Повернуть по часовой стрелке +Name[sk]=Otočiť v smere hodinových ručičiek +Name[sl]=Zasuči v smeri urinega kazalca +Name[sr]=Ротирај у смеру казаљке на часовнику +Name[sr@Latn]=Rotiraj u smeru kazaljke na časovniku +Name[sv]=Rotera medurs +Name[ta]=வலதுபுறமாக சுழற்று +Name[tg]=Чархиш бо ақрабаки соат +Name[tr]=Saat Yönünde Döndür +Name[uk]=Обернути за годинниковою стрілкою +Name[uz]=Soat koʻrsatgichi boʻyicha burish +Name[uz@cyrillic]=Соат кўрсатгичи бўйича буриш +Name[vi]=Xoay xuôi chiều +Name[zh_CN]=顺时针旋转 +Name[zh_TW]=順時針旋轉 +Icon=rotate_cw +Exec=jpegorient +90 %F + +[Desktop Action jpegRot270] +Name=Rotate Counter-Clockwise +Name[ar]=تدوير عكس اتجاه الساعة +Name[az]=Saat Əqrəbinə Tərs İstiqamətdə Fırlat +Name[bg]=Завъртане обратно на часов. стрелка +Name[bs]=Rotiraj u smjeru suprotnom od kazaljke +Name[ca]=Gira 270 graus +Name[cs]=Rotovat proti směru hod. ručiček +Name[cy]=Cylchdroi yn Wrthglocwedd +Name[da]=Rotér mod uret +Name[de]=Gegen den Uhrzeigersinn drehen (nach links) +Name[el]=Περιστροφή αριστερόστροφα +Name[en_GB]=Rotate Anti-Clockwise +Name[eo]=Turnu kontraŭhorloĝe +Name[es]=Girar en el sentido contrario a las agujas del reloj +Name[et]=Pööra vastupäeva +Name[eu]=Biratu erloju orratzen aurkako norabidean +Name[fa]=چرخش در خلاف جهت ساعت +Name[fi]=Käännä vastapäivään +Name[fr]=Tourner en sens anti-horaire +Name[fy]=Tsjin'e wizers fan de klok yn draaie +Name[ga]=Rothlaigh go Tuathalach +Name[gl]=Xirar en Sentido Antiorário +Name[he]=סובב נגד כיוון השעון +Name[hi]=घड़ी की उलटी दिशा में घुमाएँ +Name[hr]=Okret ulijevo +Name[hu]=Forgatás balra +Name[is]=Snúa rangsælis +Name[it]=Ruota in senso anti-orario +Name[ja]=左回転 +Name[ka]=საათის ისრის მიმართულებით მოტრიალება +Name[kk]=Сағаттың тіліне қарсы айналдыру +Name[km]=បង្វិលច្រាសទ្រនិចនាឡិកា +Name[lt]=Sukti prieš laikrodžio rodyklę +Name[mk]=Ротирај обратно од стрелката на часовникот +Name[ms]=Putar Lawan Jam +Name[nb]=Roter moturs +Name[nds]=Na links dreihen +Name[ne]=घडिको विपरित दिशामा घुमाउनुहोस् +Name[nl]=Anti-klokgewijs draaien +Name[nn]=Roter mot klokka +Name[pa]=ਖੱਬੇ ਦਾਅ ਘੁੰਮਾਓ +Name[pl]=Obróć przeciwnie do ruchu wskazówek zegara +Name[pt]=Rodar no Sentido Anti-Horário +Name[pt_BR]=Rodar Contador de Relógio +Name[ro]=Roteşte la stînga +Name[ru]=Повернуть против часовой стрелки +Name[sk]=Otočiť proti smeru hodinových ručičiek +Name[sl]=Zasuči v nasportni smeri urinega kazalca +Name[sr]=Ротирај супротно смеру казаљке на часовнику +Name[sr@Latn]=Rotiraj suprotno smeru kazaljke na časovniku +Name[sv]=Rotera moturs +Name[ta]=கடிகார ஓட்டத்திற்கெதிராக சுழற்று +Name[tg]=Чархиш ба муқобили ақрабаки соат +Name[tr]=Saat Yönünün Tesine Döndür +Name[uk]=Обернути проти годинникової стрілки +Name[uz]=Soat koʻrsatgichiga qarshi burish +Name[uz@cyrillic]=Соат кўрсатгичига қарши буриш +Name[vi]=Xoay ngược chiều +Name[zh_CN]=逆时针旋转 +Name[zh_TW]=逆時針旋轉 +Icon=rotate_ccw +Exec=jpegorient +270 %F + +#[Desktop Action jpegRot180] +#Name=Rotate 180 +#Icon=misc +#Exec=jpegorient +180 %F + +[Desktop Action jpegFlipV] +Name=Flip Vertically +Name[ar]=تدوير رأسي +Name[az]=Şaquli Olaraq Çevir +Name[bg]=Вертикално обръщане +Name[bs]=Obrni vertikalno +Name[ca]=Torna vertical +Name[cs]=Převrátit svisle +Name[cy]=Troi Drosodd yn Fertigol +Name[da]=Flip lodret +Name[de]=Vertikal kippen +Name[el]=Αναστροφή κατακόρυφα +Name[eo]=Inversigu vertikale +Name[es]=Reflejar verticalmente +Name[et]=Keera ümber vertikaalselt +Name[eu]=Buruz behera ipini +Name[fa]=قرینۀ عمودی +Name[fi]=Käännä pystysuorassa +Name[fr]=Retourner verticalement +Name[fy]=Fertikaal omdraaie +Name[ga]=Smeach go hIngearach +Name[gl]=Inverter Verticalmente +Name[he]=שקף אנכית +Name[hi]=खड़ा पलटें +Name[hr]=Prevrni uspravno +Name[hu]=Tükrözés függőlegesen +Name[is]=Snúa við um miðju lóðrétt +Name[it]=Fletti verticalmente +Name[ja]=上下反転 +Name[ka]=ვერტიკალურად შეტრიალება +Name[kk]=Тігінен терістеу +Name[km]=ត្រឡប់បញ្ឈរ +Name[lt]=Versti vertikaliai +Name[mk]=Преврти вертикално +Name[nb]=Speilvend loddrett +Name[nds]=Pielliek ümdreihen +Name[ne]=ठाडो गरी फ्लिप गर्नुहोस् +Name[nl]=Verticaal omdraaien +Name[nn]=Snu loddrett +Name[pa]=ਲੰਬਕਾਰੀ ਝਟਕੋ +Name[pl]=Odwróć pionowo +Name[pt]=Inverter Verticalmente +Name[pt_BR]=Refletir Verticalmente +Name[ro]=Întoarce pe verticală +Name[ru]=Отразить вертикально +Name[sk]=Preklopiť vertikálne +Name[sl]=Obrni navpično +Name[sr]=Преврни усправно +Name[sr@Latn]=Prevrni uspravno +Name[sv]=Vänd vertikalt +Name[ta]=மேல்கீழாக திருப்பு +Name[tg]=Баргардондан ба амудӣ +Name[tr]=Dik Olarak Dağıt +Name[uk]=Перекинути вертикально +Name[uz]=Eni boʻyicha burish +Name[uz@cyrillic]=Эни бўйича буриш +Name[vi]=Lật dọc +Name[zh_CN]=上下翻转 +Name[zh_TW]=垂直翻轉 +Icon=2uparrow +Exec=jpegorient v %F + +[Desktop Action jpegFlipH] +Name=Flip Horizontally +Name[ar]=تدوير أفقي +Name[az]=Üfüqi Olaraq Çevir +Name[bg]=Хоризонтално обръщане +Name[bs]=Obrni horizontalno +Name[ca]=Torna horitzontal +Name[cs]=Převrátit vodorovně +Name[cy]=Troi Drosodd yn Llorweddol +Name[da]=Flip vandret +Name[de]=Horizontal kippen +Name[el]=Αναστροφή οριζόντια +Name[eo]=Inversigu horizontale +Name[es]=Reflejar horizontalmente +Name[et]=Keera ümber horisontaalselt +Name[eu]=Biratu horizontalki +Name[fa]=قرینۀ افقی +Name[fi]=Käännä vaakasuorassa +Name[fr]=Retourner horizontalement +Name[fy]=Horizontaal omdraaie +Name[ga]=Smeach go Cothrománach +Name[gl]=Inverter Horizontalmente +Name[he]=שקף אופקית +Name[hi]=आड़ा पलटें +Name[hr]=Prevrni vodoravno +Name[hu]=Tükrözés vízszintesen +Name[is]=Snúa við um miðju lárétt +Name[it]=Fletti orizzontalmente +Name[ja]=左右反転 +Name[ka]=ჰორიზონტალურად შეტრიალება +Name[kk]=Төңкеру +Name[km]=ត្រឡប់ផ្ដេក +Name[lt]=Versti horizontaliai +Name[mk]=Преврти хоризонтално +Name[ms]=Balikkan Melintang +Name[nb]=Speilvend vannrett +Name[nds]=Waagrecht ümdreihen +Name[ne]=तेर्सो गरी फ्लिप गर्नुहोस् +Name[nl]=Horizontaal omdraaien +Name[nn]=Snu vassrett +Name[pa]=ਖਿਤਿਜੀ ਝਟਕੋ +Name[pl]=Odwróć poziomo +Name[pt]=Inverter Horizontalmente +Name[pt_BR]=Refletir Horizontalmente +Name[ro]=Întoarce pe orizontală +Name[ru]=Отразить горизонтально +Name[sk]=Preklopiť horizontálne +Name[sl]=Obrni vodoravno +Name[sr]=Преврни водоравно +Name[sr@Latn]=Prevrni vodoravno +Name[sv]=Vänd horisontellt +Name[ta]=இடம்வலமாக திருப்புக +Name[tg]=Баргардондан ба уфуқӣ +Name[tr]=Yatay Olarak Dağıt +Name[uk]=Перекинути горизонтально +Name[uz]=Boʻyi boʻyicha burish +Name[uz@cyrillic]=Бўйи бўйича буриш +Name[vi]=Lật ngang +Name[zh_CN]=左右翻转 +Name[zh_TW]=水平翻轉 +Icon=2rightarrow +Exec=jpegorient h %F diff --git a/konq-plugins/imagerotation/orient.py b/konq-plugins/imagerotation/orient.py new file mode 100755 index 0000000..0671876 --- /dev/null +++ b/konq-plugins/imagerotation/orient.py @@ -0,0 +1,104 @@ +#! /usr/bin/env python +import os +import sys +import exif + +def compose(delta, old): + map=[0, 4, 2, 6, 5, 1, 7, 3] + unmap=[1, 6, 3, 8, 2, 5, 4, 7] + x = map[delta-1] + y = map[old-1] + z = ((x^y)&4) + ((y+(x&3)*(((y&4)>>1)+1))&3) + return unmap[z] + +def deg2o(d): + map={90:6, 270:8, 180:3} + if map.has_key(d): + return map[d] + else: + return 0 + +if len(sys.argv) < 2: + print 'Usage: %s [[+]orientnum] file\n' % sys.argv[0] + sys.exit(1) +try: + if len(sys.argv) == 2: + filename=sys.argv[1] + file=open(filename, "r"); + else: + filename=sys.argv[2] + mod=sys.argv[1] + fd = os.open(filename, os.O_RDWR) + file=os.fdopen(fd,'r') + # check file exists and is readable + file.read(1) + file.seek(0,0) +except: + print 'Cannot open', filename + sys.exit(1) + +tags=exif.process_file(file,0,1) +if not tags: + print 'no EXIF information in', filename + sys.exit(1) +if not tags.has_key('Exif Offset') \ + or not tags.has_key('Image Orientation'): + print 'cannot get orientation info in', filename + sys.exit(1) + +exifp = tags['Exif Offset'] +endian = tags['Exif Endian'] +tagp = tags['Image Orientation'].field_offset + +orientp = exifp + tagp + +if endian == 'M': # MM byte order + orientp += 1 + +file.seek(orientp) +o = ord(file.read(1)) + +if o < 1 or o > 8: + print 'orientation out of range', o + sys.exit(1) + +if len(sys.argv) == 2: + print 'orientation is', o + sys.exit(0) + +try: + if mod[0] == '+': + deltao = int(mod) + if 1 <= deltao and deltao <= 8: + newo = compose(deltao, o) + elif deg2o(deltao) != 0: + newo = compose(deg2o(deltao), o) + else: + print 'cannot understand orientation modification', mod + sys.exit(1) # it will still hit the except ... how to fix? + else: + newo = int(mod) +except: + print 'expected numeric orientation and got',mod + sys.exit(1) + +if newo < 1 or newo > 8: + newo = deg2o(newo) + if newo == 0: + print 'cannot understand orientation', deltao + sys.exit(1) + +os.lseek(fd,orientp,0) +os.write(fd,chr(newo)) + +# Thumbnail orientation : +thumb_ifdp = 0 +if tags.has_key('Thumbnail Orientation'): + thumb_tagp = tags['Thumbnail Orientation'].field_offset + thumb_orientp = exifp + thumb_tagp + if endian == 'M': # MM byte order + thumb_orientp += 1 + os.lseek(fd,thumb_orientp,0) + os.write(fd,chr(newo)) + +print 'orientation changed from', o, 'to', newo diff --git a/konq-plugins/khtmlsettingsplugin/Makefile.am b/konq-plugins/khtmlsettingsplugin/Makefile.am new file mode 100644 index 0000000..1c98400 --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/Makefile.am @@ -0,0 +1,18 @@ +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = libkhtmlsettingsplugin.la + +libkhtmlsettingsplugin_la_SOURCES = settingsplugin.cpp +libkhtmlsettingsplugin_la_LIBADD = $(LIB_KHTML) +libkhtmlsettingsplugin_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = khtmlsettingsplugin.rc khtmlsettingsplugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = khtmlsettingsplugin.desktop + +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/khtmlsettingsplugin.pot diff --git a/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop new file mode 100644 index 0000000..94ff35a --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.desktop @@ -0,0 +1,136 @@ +[Desktop Entry] +X-KDE-Library=khtmlsettingsplugin +X-KDE-PluginInfo-Author=Carsten Pfeiffer +X-KDE-PluginInfo-Email=pfeiffer@kde.org +X-KDE-PluginInfo-Name=khtmlsettingsplugin +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=KHTML Settings +Name[af]=Khtml Instellings +Name[ar]=اعدادات KHTML +Name[az]=KHTML Qurğuları +Name[bg]=Настройки на KHTML +Name[br]=Dibarzhoù KHTML +Name[bs]=KHTML postavke +Name[ca]=Preferències KHTML +Name[cs]=Nastavení KHTML +Name[cy]=Gosodiadau KHTML +Name[da]=KHTML-opsætning +Name[de]=KHTML-Einstellungen +Name[el]=Ρυθμίσεις KHTML +Name[eo]=KHTML-agordo +Name[es]=Preferencias de KHTML +Name[et]=KHTML seadistused +Name[eu]=KHTMLren ezarpenak +Name[fa]=تنظیمات KHTML +Name[fi]=KHTML-asetukset +Name[fo]=KHTML-uppseting +Name[fr]=Réglages KHTML +Name[fy]=KHTML-ynstellingen +Name[ga]=Socruithe KHTML +Name[gl]=Configuración de KHTML +Name[he]=הגדרות KHTML +Name[hi]=के-एचटीएमएल विन्यास +Name[hr]=KHTML postavke +Name[hu]=KHTML-beállítások +Name[it]=Impostazioni KHTML +Name[ja]=KHTML 設定 +Name[ka]=KHTML პარამეტრები +Name[kk]=KHTML параметрлері +Name[km]=ការកំណត់ KHTML +Name[lt]=KHTML nustatymai +Name[mk]=Поставувања за KHTML +Name[ms]=Seting KHTML +Name[nb]=KHTML-innstillinger +Name[nds]=KHTML-Instellen +Name[ne]=केएचटीएमएल सेटिङ +Name[nl]=KHTML-instellingen +Name[nn]=KHTML-innstillingar +Name[pa]=KHTML ਸਥਾਪਨ +Name[pl]=Ustawienia KHTML +Name[pt]=Configuração do KHTML +Name[pt_BR]=Configurações KHTML +Name[ro]=Setări KHTML +Name[ru]=Параметры KHTML +Name[sk]=KHTML nastavenia +Name[sl]=Nastavitve KHTML +Name[sr]=Подешавања KHTML-а +Name[sr@Latn]=Podešavanja KHTML-a +Name[sv]=KHTML-inställningar +Name[ta]=KHTML அமைப்புகள் +Name[tg]=Танзимотҳои KHTML +Name[tr]=KHTML Ayarları +Name[uk]=Параметри KHTML +Name[uz]=KHTML moslamalari +Name[uz@cyrillic]=KHTML мосламалари +Name[vi]=Thiết lập KHTML +Name[xh]=Ucwangciso lwe KHTML +Name[zh_CN]=KHTML 设置 +Name[zh_TW]=KHTML 設定 +Comment=Fast way to change the KHTML settings +Comment[af]=Vinnige weg na verander die Khtml instellings +Comment[ar]=طريقة سهلة لتغيير اعدادات KHTML +Comment[az]=KHTML qurğularını dəyişdirmənin sür'ətli yolu +Comment[bg]=Бърз начин да се променят някои от най-важните настройки на KHTML +Comment[bs]=Brz način za mijenjanje KHTML postavki +Comment[ca]=Per a canviar ràpidament les preferències de KHTML +Comment[cs]=Rychlé přepínání nastavení KHTML +Comment[cy]=Ffordd cyflym o newid y gosodiadau KHTML +Comment[da]=Hurtig måde at ændre KHTML-opsætningen på +Comment[de]=Schnelle Möglichkeiten zur Änderung der KHTML-Einstellungen +Comment[el]=Γρήγορος τρόπος αλλαγής των ρυθμίσεων του KHTML +Comment[eo]=Rapida kielo por ŝanĝi la KHTML-agordon +Comment[es]=Una forma rápida de cambiar las preferencias de KHTML +Comment[et]=Kiirmeetod muuta KHTML seadistusi +Comment[eu]=KHTMLren ezarpenak aldatzeko bide azkarra +Comment[fa]=روش سریع تغییر تنظیمات KHTML +Comment[fi]=Nopea tapa muuttaa KHTML asetuksia +Comment[fo]=Snarvegur uppsetingin av KHTML +Comment[fr]=Méthode rapide pour configurer les réglages KHTML +Comment[fy]=Snelle manier om de ynstellingen fan KHTML te wizigjen +Comment[gl]=Unha forma rápida de alterar a configuración de KHTML +Comment[he]=דרך מהירה לשנות את ההגדרות של KHTML +Comment[hi]=के-एचटीएमएल विन्यास बदलने का तेज तरीका +Comment[hr]=Brz način izmjene KHTML postavki +Comment[hu]=A KHTML objektum beállításai +Comment[is]=Fljótvirk leið til að stilla KHTML +Comment[it]=Modo veloce per cambiare le impostazioni KHTML +Comment[ja]=KHTML 設定を素早く変更します +Comment[ka]=KHTML პარამეტრების შეცვლის სწრაფი გზა +Comment[kk]=KHTML параметрлерін шұғыл өзгертудің жолы +Comment[km]=វិធីដ៏រហ័សដើម្បីផ្លាស់ប្ដូរការកំណត់ KHTML +Comment[lt]=Greitas būdas KHTML parinktims pakeisti +Comment[mk]=Брз начин за промена на поставувањата за KHTML +Comment[ms]=Cara pantas untuk mengubah seting KHTML +Comment[nb]=Rask måte å endre KHTML-innstillinger +Comment[nds]=De KHTML-Instellen gau ännern +Comment[ne]=केएचटीएमएल सेटिङ परिवर्तन गर्ने छिटो तरिका +Comment[nl]=Snelle manier om de instellingen van KHTML te wijzigen +Comment[nn]=Ein rask måte å endra KHTML-innstillingane +Comment[pl]=Szybka zmiana ustawień KHTML +Comment[pt]=Uma forma rápida de alterar a configuração do KHTML +Comment[pt_BR]=Modo rápido de mudar as configurações do KHTML +Comment[ro]=Configurează rapid şi uşor setările KHTML +Comment[ru]=Быстрое изменение параметров KHTML +Comment[sk]=Rýchla cesta ako zmeniť nastavenia KHTML +Comment[sl]=Hiter način za spreminjanje nastavitev KHTML +Comment[sr]=Брз начин за промену подешавања KHTML-а +Comment[sr@Latn]=Brz način za promenu podešavanja KHTML-a +Comment[sv]=Snabbt sätt att ändra KHTML-inställningarna +Comment[ta]=KHTML அமைப்புகளை மாற்றுவதற்கான விரைவான வழி +Comment[tg]=Тағйирёбии тези танзимотҳои KHTML +Comment[tr]=KHTML ayarlarını değiştirmek için hızlı bir yol +Comment[uk]=Швидкий шлях змінити параметри KHTML +Comment[uz]=KHTML moslamalarini tez oʻzgartirish yoʻli +Comment[uz@cyrillic]=KHTML мосламаларини тез ўзгартириш йўли +Comment[vi]=Cách thay đổi nhanh thiết lập KHTML +Comment[xh]=Indlela ekhawulezayo yokutshintsha ucwangciso lwe KHTML +Comment[zh_CN]=改变 KHTML 设置的快速方式 +Comment[zh_TW]=快速變更 KHTML 設定的方法 +X-KDE-ParentApp=konqueror +Icon=configure +DocPath=konq-plugins/khtmlsettings/index.html diff --git a/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.lsm b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.lsm new file mode 100644 index 0000000..29d3818 --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.lsm @@ -0,0 +1,18 @@ +Begin3 +Title: KHTMLSettingsPlugin -- Java/Javascript/Cookies settings +Version: 0.1 +Entered-date: 01/28/2001 +Description: Puts a button with a dropdown menu with settings for + Java,Javascript,Cookies and Image-loading into Konqueror's + Extra-Toolbar +Keywords: KDE Qt +Author: Carsten Pfeiffer <pfeiffer@kde.org> +Maintained-by: Carsten Pfeiffer <pfeiffer@kde.org> +Home-page: +Alternate-site: http://devel-home.kde.org/~pfeiffer/ +Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils + xxxxxx khtmlsettingsplugin-0.1.tar.gz + xxx khtmlsettingsplugin-0.1.lsm +Platform: Linux. Needs Qt 2.2.x and KDE 2.0 (KDE 2.1 for Cookie config) +Copying-policy: GPL +End diff --git a/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc new file mode 100644 index 0000000..916a52e --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/khtmlsettingsplugin.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="khtmlsettingsplugin" library="libkhtmlsettingsplugin" version="3"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="action menu"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="action menu"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/khtmlsettingsplugin/settingsplugin.cpp b/konq-plugins/khtmlsettingsplugin/settingsplugin.cpp new file mode 100644 index 0000000..74f2613 --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/settingsplugin.cpp @@ -0,0 +1,328 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> + +#include <kapplication.h> +#include <kaction.h> +#include <kconfig.h> +#include <kglobal.h> +#include <khtml_part.h> +#include <kinstance.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kprotocolmanager.h> +#include <kgenericfactory.h> +#include <kaboutdata.h> + +#include "settingsplugin.h" + +typedef KGenericFactory<SettingsPlugin> SettingsPluginFactory; +static const KAboutData aboutdata("khtmlsettingsplugin", I18N_NOOP("HTML Settings") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY( libkhtmlsettingsplugin, + SettingsPluginFactory( &aboutdata ) ) + +SettingsPlugin::SettingsPlugin( QObject* parent, const char* name, + const QStringList & ) + : KParts::Plugin( parent, name ), mConfig(0) +{ + + setInstance(SettingsPluginFactory::instance()); + + if ( !kapp->dcopClient()->isAttached() ) + kapp->dcopClient()->attach(); + + KActionMenu *menu = new KActionMenu( i18n("HTML Settings"), "configure", + actionCollection(), "action menu" ); + menu->setDelayed( false ); + + KToggleAction *action; + + + action = new KToggleAction( i18n("Java&Script"), 0, + this, SLOT(toggleJavascript()), + actionCollection(), "javascript" ); + menu->insert( action ); + + action = new KToggleAction( i18n("&Java"), 0, + this, SLOT(toggleJava()), + actionCollection(), "java" ); + menu->insert( action ); + + action = new KToggleAction( i18n("&Cookies"), 0, + this, SLOT(toggleCookies()), + actionCollection(), "cookies" ); + menu->insert( action ); + + action = new KToggleAction( i18n("&Plugins"), 0, + this, SLOT(togglePlugins()), + actionCollection(), "plugins" ); + menu->insert( action ); + + action = new KToggleAction( i18n("Autoload &Images"), 0, + this, SLOT(toggleImageLoading()), + actionCollection(), "imageloading" ); + menu->insert( action ); + + menu->insert( new KActionSeparator(actionCollection()) ); + + action = new KToggleAction( i18n("Enable Pro&xy"), 0, + this, SLOT(toggleProxy()), + actionCollection(), "useproxy" ); + action->setCheckedState(i18n("Disable Pro&xy")); + menu->insert( action ); + + action = new KToggleAction( i18n("Enable Cac&he"), 0, + this, SLOT(toggleCache()), + actionCollection(), "usecache" ); + action->setCheckedState(i18n("Disable Cac&he")); + menu->insert( action ); + + + KSelectAction *sAction = new KSelectAction( i18n("Cache Po&licy"), 0, + 0, 0, actionCollection(), + "cachepolicy" ); + QStringList policies; + policies += i18n( "&Keep Cache in Sync" ); + policies += i18n( "&Use Cache if Possible" ); + policies += i18n( "&Offline Browsing Mode" ); + sAction->setItems( policies ); + connect( sAction, SIGNAL( activated( int ) ), SLOT( cachePolicyChanged(int) ) ); + + menu->insert( sAction ); + + connect( menu->popupMenu(), SIGNAL( aboutToShow() ), SLOT( showPopup() )); +} + +SettingsPlugin::~SettingsPlugin() +{ + delete mConfig; +} + +void SettingsPlugin::showPopup() +{ + if( !parent() || !parent()->inherits("KHTMLPart")) + return; + + if (!mConfig) + mConfig = new KConfig("settingspluginrc", false, false); + + KHTMLPart *part = static_cast<KHTMLPart *>( parent() ); + + KProtocolManager::reparseConfiguration(); + bool cookies = cookiesEnabled( part->url().url() ); + + ((KToggleAction*)actionCollection()->action("useproxy"))->setChecked(KProtocolManager::useProxy()); + ((KToggleAction*)actionCollection()->action("java"))->setChecked( part->javaEnabled() ); + ((KToggleAction*)actionCollection()->action("javascript"))->setChecked( part->jScriptEnabled() ); + ((KToggleAction*)actionCollection()->action("cookies"))->setChecked( cookies ); + ((KToggleAction*)actionCollection()->action("plugins"))->setChecked( part->pluginsEnabled() ); + ((KToggleAction*)actionCollection()->action("imageloading"))->setChecked( part->autoloadImages() ); + ((KToggleAction*)actionCollection()->action("usecache"))->setChecked(KProtocolManager::useCache()); + + KIO::CacheControl cc = KProtocolManager::cacheControl(); + switch ( cc ) + { + case KIO::CC_Verify: + ((KSelectAction*)actionCollection()->action("cachepolicy"))->setCurrentItem( 0 ); + break; + case KIO::CC_CacheOnly: + ((KSelectAction*)actionCollection()->action("cachepolicy"))->setCurrentItem( 2 ); + break; + case KIO::CC_Cache: + ((KSelectAction*)actionCollection()->action("cachepolicy"))->setCurrentItem( 1 ); + break; + case KIO::CC_Reload: // nothing for now + case KIO::CC_Refresh: + default: + break; + + } +} + +void SettingsPlugin::toggleJava() +{ + if( parent() && parent()->inherits("KHTMLPart")) + { + KHTMLPart *part = static_cast<KHTMLPart *>(parent()); + part->setJavaEnabled( ((KToggleAction*)actionCollection()->action("java"))->isChecked() ); + } +} + +void SettingsPlugin::toggleJavascript() +{ + if( parent() && parent()->inherits("KHTMLPart")) + { + KHTMLPart *part = static_cast<KHTMLPart *>(parent()); + part->setJScriptEnabled( ((KToggleAction*)actionCollection()->action("javascript"))->isChecked() ); + } +} + +void SettingsPlugin::toggleCookies() +{ + if( !parent() || !parent()->inherits("KHTMLPart")) + return; + + KHTMLPart *part = static_cast<KHTMLPart *>( parent() ); + + QString advice; + bool enable = ((KToggleAction*)actionCollection()->action("cookies"))->isChecked(); + advice = enable ? "Accept" : "Reject"; + + QCString replyType; + QByteArray data, replyData; + QDataStream stream( data, IO_WriteOnly ); + stream << part->url().url() << advice; + bool ok = kapp->dcopClient()->call( "kded", "kcookiejar", + "setDomainAdvice(QString,QString)", + data, replyType, replyData, true ); + + if ( !ok ) + KMessageBox::sorry( part->widget(), + i18n("I can't enable cookies, because the " + "cookie daemon could not be started."), + i18n("Cookies Disabled")); +} + +void SettingsPlugin::togglePlugins() +{ + if( parent() && parent()->inherits("KHTMLPart")) + { + KHTMLPart *part = static_cast<KHTMLPart *>(parent()); + part->setPluginsEnabled( ((KToggleAction*)actionCollection()->action("plugins"))->isChecked() ); + } +} + +void SettingsPlugin::toggleImageLoading() +{ + if( parent() && parent()->inherits("KHTMLPart")) + { + KHTMLPart *part = static_cast<KHTMLPart *>(parent()); + part->setAutoloadImages( ((KToggleAction*)actionCollection()->action("imageloading"))->isChecked() ); + } +} + +bool SettingsPlugin::cookiesEnabled( const QString& url ) +{ + QByteArray data, reply; + QCString replyType; + QDataStream stream( data, IO_WriteOnly ); + stream << url; + kapp->dcopClient()->call( "kcookiejar", "kcookiejar", "getDomainAdvice(QString)", data, replyType, reply, true ); + + bool enabled = false; + + if ( replyType == "QString" ) + { + QString advice; + QDataStream s( reply, IO_ReadOnly ); + s >> advice; + enabled = ( advice == "Accept" ); + if ( !enabled && advice == "Dunno" ) { + // TODO, check the global setting via dcop + KConfig kc( "kcookiejarrc", true, false ); + kc.setGroup( "Cookie Policy" ); + enabled = + (kc.readEntry( "CookieGlobalAdvice", "Reject" ) == "Accept"); + } + } + + return enabled; +} + + +// +// sync with kcontrol/kio/ksaveioconfig.* ! +// + +void SettingsPlugin::toggleProxy() +{ + bool enable = ((KToggleAction*)actionCollection()->action("useproxy"))->isChecked(); + + int type; + + if( enable ) + type = mConfig->readNumEntry( "SavedProxyType", KProtocolManager::ManualProxy ); + else + { + mConfig->writeEntry( "SavedProxyType", KProtocolManager::proxyType() ); + type = KProtocolManager::NoProxy; + } + + KConfig config("kioslaverc", false, false); + config.setGroup( "Proxy Settings" ); + config.writeEntry( "ProxyType", type ); + + ((KToggleAction*)actionCollection()->action("useproxy"))->setChecked(enable); + updateIOSlaves(); +} + + +void SettingsPlugin::toggleCache() +{ + bool usesCache = KProtocolManager::useCache(); + KConfig config( "kio_httprc", false, false ); + config.writeEntry( "UseCache", !usesCache ); + + ((KToggleAction*)actionCollection()->action("usecache"))->setChecked( !usesCache ); + + updateIOSlaves(); +} + +void SettingsPlugin::cachePolicyChanged( int p ) +{ + QString policy; + + switch ( p ) { + case 0: + policy = KIO::getCacheControlString( KIO::CC_Verify ); + break; + case 1: + policy = KIO::getCacheControlString( KIO::CC_Cache ); + break; + case 2: + policy = KIO::getCacheControlString( KIO::CC_CacheOnly ); + break; + }; + + if ( !policy.isEmpty() ) { + KConfig config("kio_httprc", false, false); + config.writeEntry("cache", policy); + + updateIOSlaves(); + } +} + +void SettingsPlugin::updateIOSlaves() +{ + QByteArray data; + QDataStream stream( data, IO_WriteOnly ); + + DCOPClient* client = kapp->dcopClient(); + if ( !client->isAttached() ) + client->attach(); + + QString protocol; // null -> all of them + stream << protocol; + client->send( "*", "KIO::Scheduler", + "reparseSlaveConfiguration(QString)", data ); +} + +#include "settingsplugin.moc" diff --git a/konq-plugins/khtmlsettingsplugin/settingsplugin.h b/konq-plugins/khtmlsettingsplugin/settingsplugin.h new file mode 100644 index 0000000..367846b --- /dev/null +++ b/konq-plugins/khtmlsettingsplugin/settingsplugin.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Carsten Pfeiffer <pfeiffer@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SETTINGS_PLUGIN +#define SETTINGS_PLUGIN + +#include <kparts/plugin.h> +#include <klibloader.h> + +class KConfig; + +class SettingsPlugin : public KParts::Plugin +{ + Q_OBJECT +public: + SettingsPlugin( QObject* parent, const char* name, + const QStringList & ); + virtual ~SettingsPlugin(); + +private: + bool cookiesEnabled( const QString& url ); + void updateIOSlaves(); + +private slots: + void toggleJavascript(); + void toggleJava(); + void toggleCookies(); + void togglePlugins(); + void toggleImageLoading(); + void toggleProxy(); + void toggleCache(); + void cachePolicyChanged( int p ); + + void showPopup(); + +private: + KConfig* mConfig; +}; + +#endif // SETTINGS_PLUGIN diff --git a/konq-plugins/kimgalleryplugin/Makefile.am b/konq-plugins/kimgalleryplugin/Makefile.am new file mode 100644 index 0000000..1efb965 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/Makefile.am @@ -0,0 +1,21 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = libkimgallery.la +libkimgallery_la_SOURCES = imgalleryplugin.cpp imgallerydialog.cpp +libkimgallery_la_LIBADD = -lkonq +libkimgallery_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +iconviewdir = $(kde_datadir)/konqiconview/kpartplugins +iconview_DATA = kimgalleryplugin.rc kimgalleryplugin.desktop + +listviewdir = $(kde_datadir)/konqlistview/kpartplugins +listview_DATA = kimgalleryplugin.rc kimgalleryplugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = kimgalleryplugin.desktop + +KDE_ICON = imagegallery + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/imgalleryplugin.pot diff --git a/konq-plugins/kimgalleryplugin/cr16-action-imagegallery.png b/konq-plugins/kimgalleryplugin/cr16-action-imagegallery.png Binary files differnew file mode 100644 index 0000000..537e4f1 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/cr16-action-imagegallery.png diff --git a/konq-plugins/kimgalleryplugin/cr22-action-imagegallery.png b/konq-plugins/kimgalleryplugin/cr22-action-imagegallery.png Binary files differnew file mode 100644 index 0000000..af66538 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/cr22-action-imagegallery.png diff --git a/konq-plugins/kimgalleryplugin/imgallerydialog.cpp b/konq-plugins/kimgalleryplugin/imgallerydialog.cpp new file mode 100644 index 0000000..54db458 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/imgallerydialog.cpp @@ -0,0 +1,455 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl <lukas@kde.org> +Andreas Schlapbach <schlpbch@iam.unibe.ch> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License version 2 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include <qlabel.h> +#include <qvbox.h> +#include <qgroupbox.h> +#include <qlayout.h> +#include <qcombobox.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> +#include <qlineedit.h> +#include <qspinbox.h> + + +#include <klocale.h> +#include <kurl.h> +#include <kfontdialog.h> +#include <kiconloader.h> +#include <kdebug.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kcolorbutton.h> +#include <kurlrequester.h> +#include <kglobalsettings.h> +#include <kconfig.h> + +#include "imgallerydialog.h" +#include "imgallerydialog.moc" + +KIGPDialog::KIGPDialog(QWidget *parent, const QString& path, const char *name ) + : KDialogBase( IconList, i18n("Configure"), Default|Ok|Cancel, + Ok, parent, name, true, true ), + m_dialogOk( false ) +{ + m_path = path; + setCaption(i18n("Create Image Gallery")); + setButtonOK( KGuiItem(i18n("Create"),"imagegallery") ); + m_config = new KConfig("kimgallerypluginrc", false, false); + setupLookPage(path); + setupDirectoryPage(path); + setupThumbnailPage(path); +} + +void KIGPDialog::slotDefault() +{ + m_title->setText(i18n("Image Gallery for %1").arg(m_path)); + m_imagesPerRow->setValue(4); + m_imageName->setChecked(true); + m_imageSize->setChecked(false); + m_imageProperty->setChecked(false); + m_fontName->setCurrentText( KGlobalSettings::generalFont().family() ); + m_fontSize->setValue(14); + m_foregroundColor->setColor( QColor( "#d0ffd0") ); + m_backgroundColor->setColor( QColor("#333333") ); + + m_imageNameReq->setURL(m_path + "images.html"); + m_recurseSubDir->setChecked( false ); + m_recursionLevel->setEnabled( false ); + m_copyOriginalFiles->setChecked( false ); + m_useCommentFile->setChecked( false ); + m_commentFileReq->setURL(m_path + "comments"); + m_commentFileReq->setEnabled( false ); + + m_imageFormat->setCurrentText( "JPEG"); + m_thumbnailSize->setValue(140); + m_colorDepthSet->setChecked(false); + m_colorDepth->setCurrentText("8"); +} + +void KIGPDialog::setupLookPage(const QString& path) { + QFrame *page = addPage( i18n("Look"), i18n("Page Look"), + BarIcon("colorize", KIcon::SizeMedium ) ); + + m_config->setGroup("Look"); + QVBoxLayout *vlay = new QVBoxLayout( page, 0, spacingHint() ); + + QLabel *label; + + label = new QLabel( i18n("&Page title:"), page); + vlay->addWidget(label); + + m_title = new QLineEdit(i18n("Image Gallery for %1").arg(path), page); + vlay->addWidget( m_title ); + label->setBuddy(m_title); + + m_imagesPerRow = new KIntNumInput(m_config->readNumEntry("ImagesPerRow", 4), page); + m_imagesPerRow->setRange(1, 8, 1, true ); + m_imagesPerRow->setLabel( i18n("I&mages per row:") ); + vlay->addWidget( m_imagesPerRow ); + + QGridLayout *grid = new QGridLayout( 2, 2 ); + vlay->addLayout( grid ); + + m_imageName = new QCheckBox( i18n("Show image file &name"), page); + m_imageName->setChecked( m_config->readBoolEntry("ImageName", true) ); + grid->addWidget( m_imageName, 0, 0 ); + + m_imageSize = new QCheckBox( i18n("Show image file &size"), page); + m_imageSize->setChecked( m_config->readBoolEntry("ImageSize", false) ); + grid->addWidget( m_imageSize, 0, 1 ); + + m_imageProperty = new QCheckBox( i18n("Show image &dimensions"), page); + m_imageProperty->setChecked( m_config->readBoolEntry("ImageProperty", false) ); + grid->addWidget( m_imageProperty, 1, 0 ); + + QHBoxLayout *hlay11 = new QHBoxLayout( ); + vlay->addLayout( hlay11 ); + + m_fontName = new QComboBox( false,page ); + QStringList standardFonts; + KFontChooser::getFontList(standardFonts, 0); + m_fontName->insertStringList( standardFonts ); + m_fontName->setCurrentText( m_config->readEntry("FontName", KGlobalSettings::generalFont().family() ) ); + + label = new QLabel( i18n("Fon&t name:"), page ); + label->setBuddy( m_fontName ); + hlay11->addWidget( label ); + hlay11->addStretch( 1 ); + hlay11->addWidget( m_fontName ); + + QHBoxLayout *hlay12 = new QHBoxLayout( ); + vlay->addLayout( hlay12 ); + + m_fontSize = new QSpinBox( 6, 15, 1, page ); + m_fontSize->setValue( m_config->readNumEntry("FontSize", 14) ); + + label = new QLabel( i18n("Font si&ze:"), page ); + label->setBuddy( m_fontSize ); + hlay12->addWidget( label ); + hlay12->addStretch( 1 ); + hlay12->addWidget( m_fontSize ); + + QHBoxLayout *hlay1 = new QHBoxLayout( spacingHint() ); + vlay->addLayout( hlay1 ); + + m_foregroundColor = new KColorButton(page); + m_foregroundColor->setColor( QColor( m_config->readEntry("ForegroundColor", "#d0ffd0") ) ); + + label = new QLabel( i18n("&Foreground color:"), page); + label->setBuddy( m_foregroundColor ); + hlay1->addWidget( label ); + hlay1->addStretch( 1 ); + hlay1->addWidget(m_foregroundColor); + + QHBoxLayout *hlay2 = new QHBoxLayout( spacingHint() ); + vlay->addLayout( hlay2 ); + + m_backgroundColor = new KColorButton(page); + m_backgroundColor->setColor( QColor(m_config->readEntry("BackgroundColor", "#333333") ) ); + + label = new QLabel( i18n("&Background color:"), page); + hlay2->addWidget( label ); + label->setBuddy( m_backgroundColor ); + hlay2->addStretch( 1 ); + hlay2->addWidget(m_backgroundColor); + + vlay->addStretch(1); +} + +void KIGPDialog::setupDirectoryPage(const QString& path) { + QFrame *page = addPage( i18n("Folders"), i18n("Folders"), + BarIcon("folder", KIcon::SizeMedium ) ); + + m_config->setGroup("Directory"); + QVBoxLayout *dvlay = new QVBoxLayout( page, 0, spacingHint() ); + + QLabel *label; + label = new QLabel(i18n("&Save to HTML file:"), page); + dvlay->addWidget( label ); + QString whatsThis; + whatsThis = i18n("<p>The name of the HTML file this gallery will be saved to."); + QWhatsThis::add( label, whatsThis ); + + m_imageNameReq = new KURLRequester(path + "images.html", page); + label->setBuddy( m_imageNameReq ); + dvlay->addWidget(m_imageNameReq); + connect( m_imageNameReq, SIGNAL(textChanged(const QString&)), + this, SLOT(imageUrlChanged(const QString&)) ); + QWhatsThis::add( m_imageNameReq, whatsThis ); + + const bool recurseSubDir = m_config->readBoolEntry("RecurseSubDirectories", false); + m_recurseSubDir = new QCheckBox(i18n("&Recurse subfolders"), page); + m_recurseSubDir->setChecked( recurseSubDir ); + whatsThis = i18n("<p>Whether subfolders should be included for the " + "image gallery creation or not."); + QWhatsThis::add( m_recurseSubDir, whatsThis ); + + const int recursionLevel = m_config->readNumEntry("RecursionLevel", 0); + m_recursionLevel = new KIntNumInput( recursionLevel, page ); + m_recursionLevel->setRange( 0, 99, 1, true ); + m_recursionLevel->setLabel( i18n("Rec&ursion depth:") ); + if ( recursionLevel == 0 ) + m_recursionLevel->setSpecialValueText( i18n("Endless")); + m_recursionLevel->setEnabled(recurseSubDir); + whatsThis = i18n("<p>You can limit the number of folders the " + "image gallery creator will traverse to by setting an " + "upper bound for the recursion depth."); + QWhatsThis::add( m_recursionLevel, whatsThis ); + + + connect(m_recurseSubDir, SIGNAL( toggled(bool) ), + m_recursionLevel, SLOT( setEnabled(bool) ) ); + + dvlay->addWidget(m_recurseSubDir); + dvlay->addWidget(m_recursionLevel); + + m_copyOriginalFiles = new QCheckBox(i18n("Copy or&iginal files"), page); + m_copyOriginalFiles->setChecked(m_config->readBoolEntry("CopyOriginalFiles", false) ); + dvlay->addWidget(m_copyOriginalFiles); + whatsThis = i18n("<p>This makes a copy of all images and the gallery will refer " + "to these copies instead of the original images."); + QWhatsThis::add( m_copyOriginalFiles, whatsThis ); + + + const bool useCommentFile = m_config->readBoolEntry("UseCommentFile", false); + m_useCommentFile = new QCheckBox(i18n("Use &comment file"), page); + m_useCommentFile->setChecked(useCommentFile); + dvlay->addWidget(m_useCommentFile); + + whatsThis = i18n("<p>If you enable this option you can specify " + "a comment file which will be used for generating " + "subtitles for the images." + "<p>For details about the file format please see " + "the \"What's This?\" help below."); + QWhatsThis::add( m_useCommentFile, whatsThis ); + + label = new QLabel(i18n("Comments &file:"), page); + label->setEnabled( useCommentFile ); + dvlay->addWidget( label ); + whatsThis = i18n("<p>You can specify the name of the comment file here. " + "The comment file contains the subtitles for the images. " + "The format of this file is:" + "<p>FILENAME1:" + "<br>Description" + "<br>" + "<br>FILENAME2:" + "<br>Description" + "<br>" + "<br>and so on"); + QWhatsThis::add( label, whatsThis ); + + m_commentFileReq = new KURLRequester(path + "comments", page); + m_commentFileReq->setEnabled(useCommentFile); + label->setBuddy( m_commentFileReq ); + dvlay->addWidget(m_commentFileReq); + QWhatsThis::add( m_commentFileReq, whatsThis ); + + connect(m_useCommentFile, SIGNAL(toggled(bool)), + label, SLOT(setEnabled(bool))); + connect(m_useCommentFile, SIGNAL(toggled(bool)), + m_commentFileReq, SLOT(setEnabled(bool))); + + dvlay->addStretch(1); +} + +void KIGPDialog::setupThumbnailPage(const QString& path) { + QFrame *page = addPage( i18n("Thumbnails"), i18n("Thumbnails"), + BarIcon("thumbnail", KIcon::SizeMedium ) ); + + m_config->setGroup("Thumbnails"); + QLabel *label; + + QVBoxLayout *vlay = new QVBoxLayout( page, 0, spacingHint() ); + + QHBoxLayout *hlay3 = new QHBoxLayout( spacingHint() ); + vlay->addLayout( hlay3 ); + + m_imageFormat = new QComboBox(false, page); + m_imageFormat->insertItem("JPEG"); + m_imageFormat->insertItem("PNG"); + m_imageFormat->setCurrentText( m_config->readEntry("ImageFormat", "JPEG") ); + + label = new QLabel( i18n("Image format f&or the thumbnails:"), page); + hlay3->addWidget( label ); + label->setBuddy( m_imageFormat ); + hlay3->addStretch( 1 ); + hlay3->addWidget(m_imageFormat); + + m_thumbnailSize = new KIntNumInput(m_config->readNumEntry("ThumbnailSize", 140), page); + m_thumbnailSize->setRange(10, 1000, 1, true ); + m_thumbnailSize->setLabel( i18n("Thumbnail size:") ); + vlay->addWidget( m_thumbnailSize ); + + QGridLayout *grid = new QGridLayout( 2, 2 ); + vlay->addLayout( grid ); + + QHBoxLayout *hlay4 = new QHBoxLayout( spacingHint() ); + vlay->addLayout( hlay4 ); + const bool colorDepthSet = m_config->readBoolEntry("ColorDepthSet", false); + m_colorDepthSet = new QCheckBox(i18n("&Set different color depth:"), page); + m_colorDepthSet->setChecked(colorDepthSet); + hlay4->addWidget( m_colorDepthSet ); + + m_colorDepth = new QComboBox(false, page); + m_colorDepth->insertItem("1"); + m_colorDepth->insertItem("8"); + m_colorDepth->insertItem("16"); + m_colorDepth->insertItem("32"); + m_colorDepth->setCurrentText(m_config->readEntry("ColorDepth", "8")); + m_colorDepth->setEnabled(colorDepthSet); + hlay4->addWidget( m_colorDepth ); + + connect(m_colorDepthSet, SIGNAL( toggled(bool) ), + m_colorDepth, SLOT( setEnabled(bool) ) ); + + vlay->addStretch(1); + +} + +void KIGPDialog::writeConfig() +{ + m_config->setGroup("Look"); + m_config->writeEntry("ImagesPerRow", getImagesPerRow()); + m_config->writeEntry("ImageName", printImageName()); + m_config->writeEntry("ImageSize", printImageSize()); + m_config->writeEntry("ImageProperty", printImageProperty()); + m_config->writeEntry("FontName", getFontName()); + m_config->writeEntry("FontSize", getFontSize()); + m_config->writeEntry("ForegroundColor", getForegroundColor().name() ); + m_config->writeEntry("BackgroundColor", getBackgroundColor().name()); + + m_config->setGroup("Directory"); + m_config->writeEntry("RecurseSubDirectories", recurseSubDirectories()); + m_config->writeEntry("RecursionLevel", recursionLevel()); + m_config->writeEntry("CopyOriginalFiles", copyOriginalFiles()); + m_config->writeEntry("UseCommentFile", useCommentFile()); + + m_config->setGroup("Thumbnails"); + m_config->writeEntry("ThumbnailSize", getThumbnailSize()); + m_config->writeEntry("ColorDepth", getColorDepth()); + m_config->writeEntry("ColorDepthSet", colorDepthSet()); + m_config->writeEntry("ImageFormat", getImageFormat()); + m_config->sync(); +} + +KIGPDialog::~KIGPDialog() +{ +} + +void KIGPDialog::imageUrlChanged(const QString &url ) +{ + enableButtonOK( !url.isEmpty()); +} + +bool KIGPDialog::printImageName() const +{ + return m_imageName->isChecked(); +} + +bool KIGPDialog::printImageSize() const +{ + return m_imageSize->isChecked(); +} + +bool KIGPDialog::printImageProperty() const +{ + return m_imageProperty->isChecked(); +} + +bool KIGPDialog::recurseSubDirectories() const +{ + return m_recurseSubDir->isChecked(); +} + +int KIGPDialog::recursionLevel() const +{ + return m_recursionLevel->value(); +} + +bool KIGPDialog::copyOriginalFiles() const +{ + return m_copyOriginalFiles->isChecked(); +} + +bool KIGPDialog::useCommentFile() const +{ + return m_useCommentFile->isChecked(); +} + +int KIGPDialog::getImagesPerRow() const +{ + return m_imagesPerRow->value(); +} + +int KIGPDialog::getThumbnailSize() const +{ + return m_thumbnailSize->value(); +} + +int KIGPDialog::getColorDepth() const +{ + return m_colorDepth->currentText().toInt(); +} + +bool KIGPDialog::colorDepthSet() const +{ + return m_colorDepthSet->isChecked(); +} + +const QString KIGPDialog::getTitle() const +{ + return m_title->text(); +} + +const QString KIGPDialog::getImageName() const +{ + return m_imageNameReq->url(); +} + +const QString KIGPDialog::getCommentFile() const +{ + return m_commentFileReq->url(); +} + +const QString KIGPDialog::getFontName() const +{ + return m_fontName->currentText(); +} + +const QString KIGPDialog::getFontSize() const +{ + return m_fontSize->text(); +} + +const QColor KIGPDialog::getBackgroundColor() const +{ + return m_backgroundColor->color(); +} + +const QColor KIGPDialog::getForegroundColor() const +{ + return m_foregroundColor->color(); +} + +const QString KIGPDialog::getImageFormat() const +{ + return m_imageFormat->currentText(); +} diff --git a/konq-plugins/kimgalleryplugin/imgallerydialog.h b/konq-plugins/kimgalleryplugin/imgallerydialog.h new file mode 100644 index 0000000..7aa6163 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/imgallerydialog.h @@ -0,0 +1,113 @@ +/* This file is part of the KDE project + + Copyright (C) 2001, 2003 Lukas Tinkl <lukas@kde.org> + Andreas Schlapbach <schlpbch@iam.unibe.ch> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef kimdialogplugin_h +#define kimdialogplugin_h + + +#include <kdialogbase.h> + +class QProgressDialog; +class KURL; +class KIntNumInput; +class QCheckBox; +class QLineEdit; +class KURLRequester; +class QSpinBox; +class KColorButton; +class KConfig; + +typedef QMap<QString,QString> CommentMap; + +class KIGPDialog : public KDialogBase +{ + Q_OBJECT + + public: + KIGPDialog(QWidget *parent=0, const QString& path=0, const char *name=0 ); + ~KIGPDialog(); + + bool isDialogOk() const; + bool printImageName() const; + bool printImageSize() const; + bool printImageProperty() const; + bool copyOriginalFiles() const; + bool useCommentFile() const; + bool recurseSubDirectories() const; + int recursionLevel() const; + bool colorDepthSet() const; + + int getImagesPerRow() const; + int getThumbnailSize() const; + int getColorDepth() const; + + const QString getTitle() const; + const QString getImageName() const; + const QString getCommentFile() const; + const QString getFontName() const; + const QString getFontSize() const; + + const QColor getBackgroundColor() const; + const QColor getForegroundColor() const; + + const QString getImageFormat() const; + + void writeConfig(); + protected slots: + void imageUrlChanged(const QString & ); + void slotDefault(); + + private: + KColorButton *m_foregroundColor; + KColorButton *m_backgroundColor; + + QLineEdit *m_title; + QString m_path; + + KIntNumInput *m_imagesPerRow; + KIntNumInput *m_thumbnailSize; + KIntNumInput *m_recursionLevel; + QSpinBox *m_fontSize; + + QCheckBox *m_copyOriginalFiles; + QCheckBox *m_imageName; + QCheckBox *m_imageSize; + QCheckBox *m_imageProperty; + QCheckBox *m_useCommentFile; + QCheckBox *m_recurseSubDir; + QCheckBox *m_colorDepthSet; + + QComboBox* m_fontName; + QComboBox* m_imageFormat; + QComboBox* m_colorDepth; + + KURLRequester *m_imageNameReq; + KURLRequester *m_commentFileReq; + bool m_dialogOk; + + KConfig *m_config; + + private: + void setupLookPage(const QString& path); + void setupDirectoryPage(const QString& path); + void setupThumbnailPage(const QString& path); +}; + +#endif diff --git a/konq-plugins/kimgalleryplugin/imgalleryplugin.cpp b/konq-plugins/kimgalleryplugin/imgalleryplugin.cpp new file mode 100644 index 0000000..43df35b --- /dev/null +++ b/konq-plugins/kimgalleryplugin/imgalleryplugin.cpp @@ -0,0 +1,499 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl <lukas@kde.org> +Andreas Schlapbach <schlpbch@iam.unibe.ch> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License version 2 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#include <qdir.h> +#include <qtextstream.h> +#include <qfile.h> +#include <qfont.h> +#include <qdatetime.h> +#include <qpixmap.h> +#include <qimage.h> +#include <qprogressdialog.h> +#include <qtextcodec.h> +#include <qstylesheet.h> + +#include <kaction.h> +#include <kglobal.h> +#include <klocale.h> +#include <kcharsets.h> +#include <kmessagebox.h> +#include <kurl.h> +#include <kapplication.h> +#include <kimageio.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kio/netaccess.h> +#include <kpushbutton.h> + +#include "imgallerydialog.h" +#include "imgalleryplugin.h" + +typedef KGenericFactory<KImGalleryPlugin> KImGalleryPluginFactory; +K_EXPORT_COMPONENT_FACTORY( libkimgallery, KImGalleryPluginFactory( "imgalleryplugin" ) ) + +KImGalleryPlugin::KImGalleryPlugin( QObject* parent, const char* name, const QStringList & ) + : KParts::Plugin( parent, name ), m_commentMap(0) +{ + new KAction( i18n( "&Create Image Gallery..." ), "imagegallery", CTRL+Key_I, this, + SLOT( slotExecute() ), actionCollection(), "create_img_gallery" ); +} + +void KImGalleryPlugin::slotExecute() +{ + m_progressDlg=0L; + if ( !parent() || !parent()->inherits("KonqDirPart")) + { + KMessageBox::sorry( 0L, i18n("Could not create the plugin, please report a bug.")); + return; + } + m_part = static_cast<KonqDirPart *>(parent()); + if (!m_part->url().isLocalFile()) { //TODO support remote URLs too? + KMessageBox::sorry(m_part->widget(), i18n("Creating an image gallery works only on local folders.")); + return; + } + kdDebug(90170) << "dialog is ok" << endl; + m_configDlg = new KIGPDialog(m_part->widget(), m_part->url().path(+1)); + + if ( m_configDlg->exec() == QDialog::Accepted ) { + kdDebug(90170) << "dialog is ok" << endl; + m_configDlg->writeConfig(); + m_copyFiles = m_configDlg->copyOriginalFiles(); + m_recurseSubDirectories = m_configDlg->recurseSubDirectories(); + m_useCommentFile = m_configDlg->useCommentFile(); + m_imagesPerRow = m_configDlg->getImagesPerRow(); + + KURL url(m_configDlg->getImageName()); + if ( !url.isEmpty() && url.isValid()) { + m_progressDlg = new QProgressDialog(m_part->widget(), "progressDlg", true ); + QObject::connect(m_progressDlg, SIGNAL( cancelled() ), this, SLOT( slotCancelled() ) ); + + m_progressDlg->setLabelText( i18n("Creating thumbnails") ); + m_progressDlg->setCancelButton(new KPushButton(KStdGuiItem::cancel(),m_progressDlg)); + m_cancelled = false; + m_progressDlg->show(); + if ( createHtml( url, m_part->url().path(), m_configDlg->recursionLevel() > 0 ? m_configDlg->recursionLevel() + 1 : 0 , m_configDlg->getImageFormat()) ) { + kapp->invokeBrowser(url.url()); // Open a browser to show the result + } else { + deleteCancelledGallery(url, m_part->url().path(), m_configDlg->recursionLevel() > 0 ? m_configDlg->recursionLevel() + 1 : 0, m_configDlg->getImageFormat()); + } + } + } else { + kdDebug(90170) << "dialog is not ok" << endl; + } + delete m_progressDlg; +} + +bool KImGalleryPlugin::createDirectory(QDir thumb_dir, QString imgGalleryDir, QString dirName) +{ + if (!thumb_dir.exists()) { + thumb_dir.setPath( imgGalleryDir); + if (!(thumb_dir.mkdir(dirName, false))) { + KMessageBox::sorry(m_part->widget(), i18n("Couldn't create folder: %1").arg(thumb_dir.path())); + return false; + } else { + thumb_dir.setPath( imgGalleryDir + "/" + dirName + "/" ); + return true; + } + } else { + return true; + } +} + +void KImGalleryPlugin::createHead(QTextStream& stream) +{ + const QString chsetName = QTextCodec::codecForLocale()->mimeName(); + + stream << "<?xml version=\"1.0\" encoding=\"" + chsetName + "\" ?>" << endl; + stream << "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">" << endl; + stream << "<html xmlns=\"http://www.w3.org/1999/xhtml\">" << endl; + stream << "<head>" << endl; + stream << "<title>" << QStyleSheet::escape(m_configDlg->getTitle()) << "</title>" << endl; + stream << "<meta http-equiv=\"content-type\" content=\"text/html; charset=" << chsetName << "\"/>" << endl; + stream << "<meta name=\"GENERATOR\" content=\"KDE Konqueror KImgallery plugin version " KDE_VERSION_STRING "\"/>" << endl; + createCSSSection(stream); + stream << "</head>" << endl; +} + +void KImGalleryPlugin::createCSSSection(QTextStream& stream) +{ + const QString backgroundColor = m_configDlg->getBackgroundColor().name(); + const QString foregroundColor = m_configDlg->getForegroundColor().name(); + //adding a touch of style + stream << "<style type='text/css'>\n"; + stream << "BODY {color: " << foregroundColor << "; background: " << backgroundColor << ";" << endl; + stream << " font-family: " << m_configDlg->getFontName() << ", sans-serif;" << endl; + stream << " font-size: " << m_configDlg->getFontSize() << "pt; margin: 8%; }" << endl; + stream << "H1 {color: " << foregroundColor << ";}" << endl; + stream << "TABLE {text-align: center; margin-left: auto; margin-right: auto;}" << endl; + stream << "TD { color: " << foregroundColor << "; padding: 1em}" << endl; + stream << "IMG { border: 1px solid " << foregroundColor << "; }" << endl; + stream << "</style>" << endl; +} + + +QString KImGalleryPlugin::extension(const QString& imageFormat) +{ + if (imageFormat == "PNG") + return ".png"; + if (imageFormat == "JPEG") + return ".jpg"; + Q_ASSERT(false); + return QString::null; +} + +void KImGalleryPlugin::createBody(QTextStream& stream, const QString& sourceDirName, const QStringList& subDirList, + const QDir& imageDir, const KURL& url, const QString& imageFormat) +{ + int numOfImages = imageDir.count(); + const QString imgGalleryDir = url.directory(); + const QString today(KGlobal::locale()->formatDate(QDate::currentDate())); + + stream << "<body>\n<h1>" << QStyleSheet::escape(m_configDlg->getTitle()) << "</h1><p>" << endl; + stream << i18n("<i>Number of images</i>: %1").arg(numOfImages) << "<br/>" << endl; + stream << i18n("<i>Created on</i>: %1").arg(today) << "</p>" << endl; + + stream << "<hr/>" << endl; + + if (m_recurseSubDirectories && subDirList.count() > 2) { //subDirList.count() is always >= 2 because of the "." and ".." directories + stream << i18n("<i>Subfolders</i>:") << "<br>" << endl; + for (QStringList::ConstIterator it = subDirList.begin(); it != subDirList.end(); it++) { + if (*it == "." || *it == "..") + continue; //disregard the "." and ".." directories + stream << "<a href=\"" << *it << "/" << url.fileName() + << "\">" << *it << "</a><br>" << endl; + } + stream << "<hr/>" << endl; + } + + stream << "<table>" << endl; + + //table with images + int imgIndex; + QFileInfo imginfo; + QPixmap imgProp; + for (imgIndex = 0; !m_cancelled && (imgIndex < numOfImages);) { + stream << "<tr>" << endl; + + for (int col=0; !m_cancelled && (col < m_imagesPerRow) && (imgIndex < numOfImages); col++) { + const QString imgName = imageDir[imgIndex]; + + if (m_copyFiles) { + stream << "<td align='center'>\n<a href=\"images/" << imgName << "\">"; + } else { + stream << "<td align='center'>\n<a href=\"" << imgName << "\">"; + } + + + if (createThumb(imgName, sourceDirName, imgGalleryDir, imageFormat)) { + const QString imgPath("thumbs/" + imgName + extension(imageFormat)); + stream << "<img src=\"" << imgPath << "\" width=\"" << m_imgWidth << "\" "; + stream << "height=\"" << m_imgHeight << "\" alt=\"" << imgPath << "\"/>"; + m_progressDlg->setLabelText( i18n("Created thumbnail for: \n%1").arg(imgName) ); + } else { + kdDebug(90170) << "Creating thumbnail for " << imgName << " failed" << endl; + m_progressDlg->setLabelText( i18n("Creating thumbnail for: \n%1\n failed").arg(imgName) ); + } + stream << "</a>" << endl; + + if (m_configDlg->printImageName()) { + stream << "<div>" << imgName << "</div>" << endl; + } + + if (m_configDlg->printImageProperty()) { + imgProp.load( imageDir.absFilePath(imgName,true) ); + stream << "<div>" << imgProp.width() << " x " << imgProp.height() << "</div>" << endl; + } + + if (m_configDlg->printImageSize()) { + imginfo.setFile( imageDir, imgName ); + stream << "<div>(" << (imginfo.size() / 1024) << " " << i18n("KB") << ")" << "</div>" << endl; + } + + if (m_useCommentFile) { + QString imgComment = (*m_commentMap)[imgName]; + stream << "<div>" << QStyleSheet::escape(imgComment) << "</div>" << endl; + } + stream << "</td>" << endl; + + m_progressDlg->setTotalSteps( numOfImages ); + m_progressDlg->setProgress( imgIndex ); + kapp->processEvents(); + imgIndex++; + } + stream << "</tr>" << endl; + } + //close the HTML + stream << "</table>\n</body>\n</html>" << endl; +} + + +bool KImGalleryPlugin::createHtml(const KURL& url, const QString& sourceDirName, int recursionLevel, const QString& imageFormat) +{ + if(m_cancelled) return false; + + + if( !parent() || !parent()->inherits("KonqDirPart")) + return false; + KonqDirPart * part = static_cast<KonqDirPart *>(parent()); + + QStringList subDirList; + if (m_recurseSubDirectories && (recursionLevel >= 0)) { //recursionLevel == 0 means endless + QDir toplevel_dir = QDir( sourceDirName ); + toplevel_dir.setFilter( QDir::Dirs | QDir::Readable | QDir::Writable ); + subDirList = toplevel_dir.entryList(); + + for (QStringList::ConstIterator it = subDirList.begin(); it != subDirList.end() && !m_cancelled; it++) { + const QString currentDir = *it; + if (currentDir == "." || currentDir == "..") { continue;} //disregard the "." and ".." directories + QDir subDir = QDir( url.directory() + "/" + currentDir ); + if (!subDir.exists()) { + subDir.setPath( url.directory() ); + if (!(subDir.mkdir(currentDir, false))) { + KMessageBox::sorry(part->widget(), i18n("Couldn't create folder: %1").arg(subDir.path())); + continue; + } else { + subDir.setPath( url.directory() + "/" + currentDir ); + } + } + if(!createHtml( KURL( subDir.path() + "/" + url.fileName() ), sourceDirName + "/" + currentDir, + recursionLevel > 1 ? recursionLevel - 1 : 0, imageFormat)) { return false; } + } + } + + if (m_useCommentFile) { + loadCommentFile(); + } + + kdDebug(90170) << "sourceDirName: " << sourceDirName << endl; + //We're interested in only the patterns, so look for the first | + //#### perhaps an accessor should be added to KImageIO instead? + QString filter = KImageIO::pattern(KImageIO::Reading).section('|', 0, 0); + + QDir imageDir( sourceDirName, filter.latin1(), + QDir::Name|QDir::IgnoreCase, QDir::Files|QDir::Readable); + + const QString imgGalleryDir = url.directory(); + kdDebug(90170) << "imgGalleryDir: " << imgGalleryDir << endl; + + // Create the "thumbs" subdirectory if necessary + QDir thumb_dir( imgGalleryDir + QString::fromLatin1("/thumbs/")); + if (createDirectory(thumb_dir, imgGalleryDir, "thumbs") == false) + return false; + + // Create the "images" subdirectory if necessary + QDir images_dir( imgGalleryDir + QString::fromLatin1("/images/")); + if (m_copyFiles) { + if (createDirectory(images_dir, imgGalleryDir, "images") == false) + return false; + } + + QFile file( url.path() ); + kdDebug(90170) << "url.path(): " << url.path() << ", thumb_dir: "<< thumb_dir.path() + << ", imageDir: "<< imageDir.path() << endl; + + if ( imageDir.exists() && file.open(IO_WriteOnly) ) { + QTextStream stream(&file); + stream.setEncoding(QTextStream::Locale); + + createHead(stream); + createBody(stream, sourceDirName, subDirList, imageDir, url, imageFormat); //ugly + + file.close(); + + return !m_cancelled; + + } else { + KMessageBox::sorry(m_part->widget(),i18n("Couldn't open file: %1").arg(url.path(+1))); + return false; + } +} + +void KImGalleryPlugin::deleteCancelledGallery(const KURL& url, const QString& sourceDirName, int recursionLevel, const QString& imageFormat) +{ + if (m_recurseSubDirectories && (recursionLevel >= 0)) { + QStringList subDirList; + QDir toplevel_dir = QDir( sourceDirName ); + toplevel_dir.setFilter( QDir::Dirs ); + subDirList = toplevel_dir.entryList(); + + for (QStringList::ConstIterator it = subDirList.begin(); it != subDirList.end(); it++) { + if (*it == "." || *it == ".." || *it == "thumbs" || (m_copyFiles && *it == "images")) { + continue; //disregard the "." and ".." directories + } + deleteCancelledGallery( KURL( url.directory() + "/" + *it + "/" + url.fileName() ), + sourceDirName + "/" + *it, + recursionLevel > 1 ? recursionLevel - 1 : 0, imageFormat); + } + } + + const QString imgGalleryDir = url.directory(); + QDir thumb_dir( imgGalleryDir + QString::fromLatin1("/thumbs/")); + QDir images_dir( imgGalleryDir + QString::fromLatin1("/images/")); + QDir imageDir( sourceDirName, "*.png *.PNG *.gif *.GIF *.jpg *.JPG *.jpeg *.JPEG *.bmp *.BMP", + QDir::Name|QDir::IgnoreCase, QDir::Files|QDir::Readable); + QFile file( url.path() ); + + // Remove the image file .. + file.remove(); + // ..all the thumbnails .. + for (uint i=0; i < imageDir.count(); i++) { + const QString imgName = imageDir[i]; + const QString imgNameFormat = imgName + extension(imageFormat); + bool isRemoved = thumb_dir.remove(imgNameFormat); + kdDebug(90170) << "removing: " << thumb_dir.path() << "/" << imgNameFormat << "; "<< isRemoved << endl; + } + // ..and the thumb directory + thumb_dir.rmdir(thumb_dir.path()); + + // ..and the images directory if images were to be copied + if (m_copyFiles) { + for (uint i=0; i < imageDir.count(); i++) { + const QString imgName = imageDir[i]; + bool isRemoved = images_dir.remove(imgName); + kdDebug(90170) << "removing: " << images_dir.path() << "/" << imgName << "; "<< isRemoved << endl; + } + images_dir.rmdir(images_dir.path()); + } +} + +void KImGalleryPlugin::loadCommentFile() +{ + QFile file(m_configDlg->getCommentFile()); + if (file.open(IO_ReadOnly)) { + kdDebug(90170) << "File opened."<< endl; + + QTextStream* m_textStream = new QTextStream(&file); + m_textStream->setEncoding(QTextStream::Locale); + + delete m_commentMap; + m_commentMap = new CommentMap; + + QString picName, picComment, curLine, curLineStripped; + while (!m_textStream->eof()) { + curLine = m_textStream->readLine(); + curLineStripped = curLine.stripWhiteSpace(); + // Lines starting with '#' are comment + if (!(curLineStripped.isEmpty()) && !curLineStripped.startsWith("#")) { + if (curLineStripped.endsWith(":")) { + picComment = QString::null; + picName = curLineStripped.left(curLineStripped.length()-1); + kdDebug(90170) << "picName: " << picName << endl; + } else { + do { + //kdDebug(90170) << "picComment" << endl; + picComment += curLine + "\n"; + curLine = m_textStream->readLine(); + } while (!m_textStream->eof() && !(curLine.stripWhiteSpace().isEmpty()) && + !curLine.stripWhiteSpace().startsWith("#")); + //kdDebug(90170) << "Pic comment: " << picComment << endl; + m_commentMap->insert(picName, picComment); + } + } + } + CommentMap::Iterator it; + for( it = m_commentMap->begin(); it != m_commentMap->end(); ++it ) { + kdDebug(90170) << "picName: " << it.key() << ", picComment: " << it.data() << endl; + } + file.close(); + kdDebug(90170) << "File closed." << endl; + delete m_textStream; + } else { + KMessageBox::sorry(m_part->widget(), i18n("Couldn't open file: %1").arg(m_configDlg->getCommentFile())); + m_useCommentFile = false; + } +} + +bool KImGalleryPlugin::createThumb( const QString& imgName, const QString& sourceDirName, + const QString& imgGalleryDir, const QString& imageFormat) +{ + QImage img; + const QString pixPath = sourceDirName + QString::fromLatin1("/") + imgName; + + if (m_copyFiles) { + KURL srcURL = KURL::fromPathOrURL(pixPath); + //kdDebug(90170) << "srcURL: " << srcURL << endl; + KURL destURL = KURL::fromPathOrURL(imgGalleryDir + QString::fromLatin1("/images/") + imgName); + //kdDebug(90170) << "destURL: " << destURL << endl; + KIO::NetAccess::copy(srcURL, destURL, static_cast<KParts::Part *>(parent())->widget()); + } + + const QString imgNameFormat = imgName + extension(imageFormat); + const QString thumbDir = imgGalleryDir + QString::fromLatin1("/thumbs/"); + int extent = m_configDlg->getThumbnailSize(); + + // this code is stolen from kdebase/kioslave/thumbnail/imagecreator.cpp + // (c) 2000 gis and malte + + m_imgWidth = 120; // Setting the size of the images is + m_imgHeight = 90; // required to generate faster 'loading' pages + if ( img.load( pixPath ) ) + { + int w = img.width(), h = img.height(); + // scale to pixie size + // kdDebug(90170) << "w: " << w << " h: " << h << endl; + // Resizing if to big + if(w > extent || h > extent) + { + if(w > h) + { + h = (int)( (double)( h * extent ) / w ); + if ( h == 0 ) h = 1; + w = extent; + Q_ASSERT( h <= extent ); + } + else + { + w = (int)( (double)( w * extent ) / h ); + if ( w == 0 ) w = 1; + h = extent; + Q_ASSERT( w <= extent ); + } + const QImage scaleImg(img.smoothScale( w, h )); + if ( scaleImg.width() != w || scaleImg.height() != h ) + { + kdDebug(90170) << "Resizing failed. Aborting." << endl; + return false; + } + img = scaleImg; + if (m_configDlg->colorDepthSet() == true ) + { + const QImage depthImg(img.convertDepth(m_configDlg->getColorDepth())); + img = depthImg; + } + } + kdDebug(90170) << "Saving thumbnail to: " << thumbDir + imgNameFormat << endl; + if (!img.save(thumbDir + imgNameFormat, imageFormat.latin1())) + { + kdDebug(90170) << "Saving failed. Aborting." << endl; + return false; + } + m_imgWidth = w; + m_imgHeight = h; + return true; + } + return false; +} + +void KImGalleryPlugin::slotCancelled() +{ + m_cancelled = true; +} + +#include "imgalleryplugin.moc" diff --git a/konq-plugins/kimgalleryplugin/imgalleryplugin.h b/konq-plugins/kimgalleryplugin/imgalleryplugin.h new file mode 100644 index 0000000..6b580a0 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/imgalleryplugin.h @@ -0,0 +1,80 @@ +/* This file is part of the KDE project + +Copyright (C) 2001, 2003 Lukas Tinkl <lukas@kde.org> +Andreas Schlapbach <schlpbch@iam.unibe.ch> + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License version 2 as published by the Free Software Foundation. + +This library is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public License +along with this library; see the file COPYING.LIB. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +Boston, MA 02110-1301, USA. +*/ + +#ifndef kimgalleryplugin_h +#define kimgalleryplugin_h + +#include <kparts/plugin.h> +#include <klibloader.h> +#include <konq_dirpart.h> +#include <kio/jobclasses.h> + +class QProgressDialog; +class KURL; +class KIGPDialog; + +typedef QMap<QString,QString> CommentMap; + +class KImGalleryPlugin : public KParts::Plugin +{ + Q_OBJECT + public: + KImGalleryPlugin( QObject* parent, const char* name, + const QStringList & ); + ~KImGalleryPlugin() {} + + public slots: + void slotExecute(); + void slotCancelled(); + + private: + bool m_cancelled; + bool m_recurseSubDirectories; + bool m_copyFiles; + bool m_useCommentFile; + + int m_imgWidth; + int m_imgHeight; + int m_imagesPerRow; + + QProgressDialog *m_progressDlg; + + KonqDirPart* m_part; + + KIGPDialog *m_configDlg; + + CommentMap* m_commentMap; + + bool createDirectory(QDir thumb_dir, QString imgGalleryDir, QString dirName); + + void createHead(QTextStream& stream); + void createCSSSection(QTextStream& stream); + void createBody(QTextStream& stream, const QString& sourceDirName, const QStringList& subDirList, const QDir& imageDir, const KURL& url, const QString& imageFormat); + + bool createThumb( const QString& imgName, const QString& sourceDirName, const QString& imgGalleryDir, const QString& imageFormat); + + bool createHtml( const KURL& url, const QString& sourceDirName, int recursionLevel, const QString& imageFormat); + void deleteCancelledGallery( const KURL& url, const QString& sourceDirName, int recursionLevel, const QString& imageFormat); + void loadCommentFile(); + + static QString extension(const QString& imageFormat); +}; + +#endif diff --git a/konq-plugins/kimgalleryplugin/kimgalleryplugin.desktop b/konq-plugins/kimgalleryplugin/kimgalleryplugin.desktop new file mode 100644 index 0000000..c8190e1 --- /dev/null +++ b/konq-plugins/kimgalleryplugin/kimgalleryplugin.desktop @@ -0,0 +1,129 @@ +[Desktop Entry] +X-KDE-PluginInfo-Author=Lukas Tinkl,Andreas Schlapbach +X-KDE-PluginInfo-Email=lukas@kde.org,schlpbch@iam.unibe.ch +X-KDE-PluginInfo-Name=ImgGalleryPlugin +X-KDE-PluginInfo-Version=3.4 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=LGPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Image Gallery +Name[bg]=Галерия с изображения +Name[br]=Garidell ar skeudennoù +Name[bs]=Galerija slika +Name[ca]=Galeria d'imatges +Name[cs]=Obrázková galerie +Name[cy]=Oriel Ddelweddau +Name[da]=Billedgalleri +Name[de]=Bildergalerie +Name[el]=Συλλογή εικόνων +Name[eo]=Bildprezentilo +Name[es]=Galería de imágenes +Name[et]=Pildigalerii +Name[eu]=Irudi galeria +Name[fa]=گالری تصویر +Name[fi]=Kuvagalleria +Name[fr]=Galerie d'images +Name[fy]=Ofbyldengalery +Name[ga]=Gailearaí Íomhánna +Name[gl]=Galeria de Imaxes +Name[he]=גלריית תמונות +Name[hi]=छवि दीर्घा +Name[hr]=Galerija slika +Name[hu]=Képbemutató +Name[is]=Myndasafn +Name[it]=Galleria di immagini +Name[ja]=イメージギャラリー +Name[ka]=გამოსახულებათა გალერეა +Name[kk]=Кескіндер галереясы +Name[km]=វិចិត្រសាលរូបភាព +Name[lt]=Paveikslėlių galerija +Name[mk]=Галерија со слики +Name[ms]=Galeri Imej +Name[nb]=Bildegalleri +Name[nds]=Bildgalerie +Name[ne]=छवि ग्यालरी +Name[nl]=Afbeeldingengalerij +Name[nn]=Biletgalleri +Name[pa]=ਚਿੱਤਰ ਗੈਲਰੀ +Name[pl]=Galeria obrazków +Name[pt]=Galeria de Imagens +Name[pt_BR]=Galeria de Imagens +Name[ru]=Галерея изображений +Name[sk]=Galéria obrázkov +Name[sl]=Galerija slik +Name[sr]=Галерија слика +Name[sr@Latn]=Galerija slika +Name[sv]=Bildgalleri +Name[ta]=பிம்ப படத் தொகுப்பு +Name[tg]=Силсилаи тасвирҳо +Name[tr]=Resim Galerisi +Name[uk]=Галерея зображень +Name[uz]=Rasmlar galereyasi +Name[uz@cyrillic]=Расмлар галереяси +Name[vi]=Nơi trưng bày ảnh +Name[zh_CN]=图像集 +Name[zh_TW]=相簿 +Comment=Easy way to generate a HTML image gallery +Comment[af]=Maklike weg na genereer 'n Html beeld galery +Comment[ar]=طريقة سهلة لانشاء معرض صور HTML +Comment[az]=HTML rəsm qalereyası yaradmanın asan yolu +Comment[bg]=Лесен начин за генериране на галерия от изображения във формат HTML +Comment[bs]=Lagan način za generisanje HTML galerija slika +Comment[ca]=Genera fàcilment una galeria HTML d'imatges +Comment[cs]=Jednoduchý způsob, jak vygenerovat HTML galerii obrázků +Comment[cy]=Ffordd hawdd i greu oriel delweddau HTML +Comment[da]=Nem måde at oprette et HTML-billedgalleri på +Comment[de]=Einfache Möglichkeit, um eine Bildergalerie in HTML zu erzeugen +Comment[el]=Εύκολος τρόπος δημιουργίας μιας συλλογής εικόνων σε HTML +Comment[eo]=Facila kielo por generi HTML bildgalieron +Comment[es]=Una forma sencilla para generar una galería de imágenes en HTML +Comment[et]=Kiirmeetod tekitada HTML pildigalerii +Comment[eu]=HTML irudi galeria sortzeko bide erraza +Comment[fa]=روش آسان تولید گالری تصویر زنگام +Comment[fi]=Nopea tapa luoda HTML kuvagalleria +Comment[fr]=Méthode rapide pour configurer une galerie HTML d'images +Comment[fy]=Ienfâldige manier om in HTML-ôfbyldengalery oan te meitsjen +Comment[gl]=Unha forma fácil de xerar unha galeria de imaxes en HTML +Comment[he]=דרך קלה ליצור גלריית תמונות מבוססת HTML +Comment[hi]=एचटीएमएल छवि दीर्घा बनाने का तेज तरीका +Comment[hr]=Jednostavan način izrade HTML galerije slika +Comment[hu]=HTML-alapú képmegjelenítő +Comment[is]=Einföld leið til að búa til HTML myndasöfn +Comment[it]=Modo facile per generare una galleria di immagini in HTML +Comment[ja]=HTML イメージギャラリーを簡単に作成します +Comment[ka]=HTML გამოსახულებათა გალერეის გენერაციის მარტივი ხერხი +Comment[kk]=HTML кескіндер галереясын құрудың оңай жолы +Comment[km]=វិធីដ៏ងាយស្រួលដើម្បីបង្កើតវិចិត្រសាលរូបភាព HTML +Comment[lt]=Lengvas būdas HTML paveikslėlių galerijai generuoti +Comment[mk]=Лесен начин за создавање на HTML-галерија со слики +Comment[ms]=Cara mudah untuk menghasilkan galery imej HTML +Comment[nb]=Lett måte å lage et bildegalleri for HTML +Comment[nds]=En HTML-Bildgalerie gau opstellen +Comment[ne]=एचटीएमएल छवि ग्यालरी उत्पन्न गर्ने सजिलो तरिका +Comment[nl]=Eenvoudige manier om een HTML-afbeeldingengalerij aan te maken +Comment[nn]=Ein enkel måte å laga eit biletgalleri som nettsider +Comment[pl]=Tworzenie galerii obrazków w HTML-u +Comment[pt]=Uma forma fácil de gerar uma galeria de imagens em HTML +Comment[pt_BR]=Modo fácil de gerar uma galeria de imagens HTML +Comment[ro]=O modalitate uşoară de a genera o galerie de imagini în HTML +Comment[ru]=Генератор веб-страницы с галереей изображений +Comment[sk]=Jednoduchá cesta ako vygenerovať HTML galériu obrázkov +Comment[sl]=Preprost način ustvarjanja galerije slik v HTML +Comment[sr]=Лак начин за прављење HTML галерије слика +Comment[sr@Latn]=Lak način za pravljenje HTML galerije slika +Comment[sv]=Enkelt sätt att skapa ett HTML-bildgalleri +Comment[ta]=ஒரு HTML பிம்ப படத்தொகுப்பை இயக்குவதற்கான சுலபமான வழி +Comment[tg]=Генератор бо веб-саҳифаҳо аз силсилаи тасвирҳо +Comment[tr]=HTML resim galerisi oluşturmak için kolay bir yol +Comment[uk]=Простий спосіб створити галерею зображень в HTML +Comment[uz]=HTML rasmlar galereyasini yaratish +Comment[uz@cyrillic]=HTML расмлар галереясини яратиш +Comment[vi]=Cách dễ tạo ra nơi trưng bày ảnh HTML +Comment[xh]=Indlela elula yokwenza iHTML igumbi lomboniso wemifanekiso +Comment[zh_CN]=生成 HTML 图像集的简捷方式 +Comment[zh_TW]=簡單建立 HTML 相簿的方法 +Icon=imagegallery +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/imgallery/index.html diff --git a/konq-plugins/kimgalleryplugin/kimgalleryplugin.rc b/konq-plugins/kimgalleryplugin/kimgalleryplugin.rc new file mode 100644 index 0000000..2376f8b --- /dev/null +++ b/konq-plugins/kimgalleryplugin/kimgalleryplugin.rc @@ -0,0 +1,8 @@ +<!DOCTYPE kpartplugin> +<kpartplugin library="libkimgallery"> +<MenuBar> + <Menu name="tools"><text>&Tools</text> + <Action name="create_img_gallery"/> + </Menu> +</MenuBar> +</kpartplugin> diff --git a/konq-plugins/kuick/Makefile.am b/konq-plugins/kuick/Makefile.am new file mode 100644 index 0000000..f0cfa4c --- /dev/null +++ b/konq-plugins/kuick/Makefile.am @@ -0,0 +1,26 @@ +SUBDIRS= kcmkuick + +INCLUDES = $(all_includes) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libkuickplugin.la + +# This is all standard. Remove the LIB_KHTML reference if you are not +# using the KHTML Part +libkuickplugin_la_SOURCES = kuick_plugin.cpp kdirmenu.cpp kmetamenu.cpp kimcontactmenu.cpp +libkuickplugin_la_LIBADD = $(LIB_KABC) -lkimproxy -lkonq +libkuickplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_servicesdir) +plugins_DATA = kuick_plugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = kuickplugin.desktop + +# Install the .rc file in the Part's directory (in this case, the part +# is KHTMLPart) + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/kuick_plugin.pot +noinst_HEADERS = kimcontactmenu.h diff --git a/konq-plugins/kuick/kcmkuick/Makefile.am b/konq-plugins/kuick/kcmkuick/Makefile.am new file mode 100644 index 0000000..6c81498 --- /dev/null +++ b/konq-plugins/kuick/kcmkuick/Makefile.am @@ -0,0 +1,17 @@ +INCLUDES= $(all_includes) + +kde_module_LTLIBRARIES = kcm_kuick.la + +kcm_kuick_la_SOURCES = kcmkuick.cpp kcmkuickdialog.ui + +kcm_kuick_la_LDFLAGS = $(all_libraries) -module -avoid-version -no-undefined +kcm_kuick_la_LIBADD = $(LIB_KDEUI) $(LIB_KIO) +kcm_kuick_la_METASOURCES = AUTO + +noinst_HEADERS = kcmkuick.h kcmkuickdialog.h + +apps_DATA = kcmkuick.desktop +appsdir = $(kde_appsdir)/.hidden + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/kcmkuick.pot diff --git a/konq-plugins/kuick/kcmkuick/kcmkuick.cpp b/konq-plugins/kuick/kcmkuick/kcmkuick.cpp new file mode 100644 index 0000000..fdbf5c0 --- /dev/null +++ b/konq-plugins/kuick/kcmkuick/kcmkuick.cpp @@ -0,0 +1,155 @@ +/*************************************************************************** + kcmkuick.cpp - control module for kuick + ------------------- + copyright : (C) 2001 by Holger Freyther <freyther@kde.org> + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + +#include "kcmkuick.h" + +#include <qlayout.h> +#include <qfile.h> +#include <kglobal.h> +#include <klocale.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kstandarddirs.h> +#include <kservice.h> + +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qstring.h> + +typedef KGenericFactory<KCMKuick, QWidget> KuickFactory; +K_EXPORT_COMPONENT_FACTORY ( kcm_kuick, KuickFactory( "kcmkuick" ) ) + +KCMKuick::KCMKuick(QWidget *parent, const char *name, const QStringList &) +:KCModule(parent, name) +{ + KAboutData *ab=new KAboutData( "kcmkuick", I18N_NOOP("KCM Kuick"), + "0.2",I18N_NOOP("KControl module for Kuick's configuration"), KAboutData::License_GPL, + "(c) 2001, Holger Freyther", 0, 0, "freyther@kde.org"); + ab->addAuthor("Holger Freyther",0, "freyther@kde.org"); + setAboutData( ab ); + + QVBoxLayout *topLayout = new QVBoxLayout(this, 0, 0); + dialog = new KCMKuickDialog(this); + topLayout->add(dialog); + topLayout->addStretch(); + + connect( dialog->m_sbCopy, SIGNAL(valueChanged(int) ), SLOT(configChanged() ) ); + connect( dialog->m_sbMove, SIGNAL(valueChanged(int) ), SLOT(configChanged() ) ); + connect( dialog->pbCopyClear, SIGNAL(pressed() ), SLOT(slotClearCopyCache() ) ); + connect( dialog->pbMoveClear, SIGNAL(pressed() ), SLOT(slotClearMoveCache() ) ); + connect( dialog->m_chkShow, SIGNAL(clicked() ), SLOT(slotShowToggled() ) ); + + load(); +} + +void KCMKuick::slotShowToggled() +{ + bool showChecked = dialog->m_chkShow->isChecked(); + dialog->m_grpCopy->setEnabled( showChecked ); + dialog->m_grpMove->setEnabled( showChecked ); + configChanged(); +} + +void KCMKuick::load() +{ + KConfig config( "konquerorrc"); + config.setGroup("kuick-copy"); + dialog->m_sbCopy->setValue(config.readNumEntry("ShowRecent",5) ); + + config.setGroup("kuick-move" ); + dialog->m_sbMove->setValue(config.readNumEntry("ShowRecent",5) ); + + KConfig cfg("kuick_plugin.desktop", true, false, "services"); + cfg.setDesktopGroup(); + bool hidden=cfg.readBoolEntry("Hidden", false); + dialog->m_chkShow->setChecked(!hidden); + slotShowToggled(); + + emit changed(false); +} + +KCMKuick::~KCMKuick() +{ +} + +void KCMKuick::load(const QString & /*s*/) +{ +} + +void KCMKuick::configChanged() +{ + emit changed(true); +} + +void KCMKuick::save() +{ + KConfig config("konquerorrc" ); + config.setGroup("kuick-copy"); + + config.writeEntry("ShowRecent", dialog->m_sbCopy->value() ); + + config.setGroup("kuick-move" ); + config.writeEntry("ShowRecent", dialog->m_sbMove->value() ); + + config.sync(); //is it necessary ? + + if ( dialog->m_chkShow->isChecked() ) { + QString servicespath = KGlobal::dirs()->saveLocation( "services"); + QFile::remove(servicespath+"/kuick_plugin.desktop"); + } + else { + KConfig cfg("kuick_plugin.desktop", false, false, "services"); + cfg.setDesktopGroup(); + cfg.writeEntry("Hidden", true); + } + KService::rebuildKSycoca(this); + + emit changed(false); +} + +void KCMKuick::slotClearCopyCache( ) { + KConfig config("konquerorrc"); + config.setGroup("kuick-copy" ); + config.writePathEntry("Paths", QStringList() ); + config.sync(); //is it necessary ? +} + +void KCMKuick::slotClearMoveCache() { + KConfig config("konquerorrc"); + config.setGroup("kuick-move" ); + config.writePathEntry("Paths", QStringList() ); + config.sync(); //is it necessary ? +} + +void KCMKuick::defaults() +{ + dialog->m_sbCopy->setValue(4); + dialog->m_sbMove->setValue(4); + + dialog->m_chkShow->setChecked(true); + slotShowToggled(); + + emit changed( true ); +} + +QString KCMKuick::quickHelp() const +{ + return i18n("<h1>Kuick</h1> With this module you can configure Kuick, the KDE quick" + "copy and move plugin for Konqueror."); +} + +#include "kcmkuick.moc" diff --git a/konq-plugins/kuick/kcmkuick/kcmkuick.desktop b/konq-plugins/kuick/kcmkuick/kcmkuick.desktop new file mode 100644 index 0000000..772dcce --- /dev/null +++ b/konq-plugins/kuick/kcmkuick/kcmkuick.desktop @@ -0,0 +1,202 @@ +[Desktop Entry] +Icon=editcopy +Type=Application +Exec=kcmshell kcmkuick +X-KDE-ModuleType=Library +X-KDE-Library=kuick +Name=Quick Copy & Move Plugin +Name[af]=Vinnige Kopie & Beweeg Inplak +Name[ar]=ملحق النقل و النسخ السريع +Name[az]=Əlavəni Sürətli Köçür və Daşı +Name[bg]=Приставка за бързо копиране и преместване +Name[bs]=Dodatak za brzo kopiranje i premještanje +Name[ca]=Connector copia i mou ràpidament +Name[cs]=Rychlé kopírování a přesouvání +Name[cy]=Ategyn Copïo & Symud Brys +Name[da]=Plugin for hurtig kopiering & flytning +Name[de]=Kopieren und Verschieben +Name[el]=Πρόσθετο γρήγορης αντιγραφής & μετακίνησης +Name[eo]=Kromaĵo por rapida kopiado kaj movado +Name[es]=Complemento para copiar y mover rápido +Name[et]=Kiire kopeerimise ja liigutamise plugin +Name[eu]=Kopiatu eta mugitzeko plugin azkarra +Name[fa]=وصلۀ حرکت و رونوشت سریع +Name[fi]=Nopea kopiointi ja siirto sovelma +Name[fo]=Skjót avrita-og-flyta-ístingur +Name[fr]=Outil de copie et de déplacement rapides +Name[fy]=Fluch kopiearje en ferpleatse +Name[gl]=Pugin para Copiar e Mover Axiña +Name[he]=תוסף העתקה והעברה מהירה +Name[hi]=जल्दी नक़ल व खिसकाना प्लगइन +Name[hr]=Dodatak za brzo kopiranje i premještanje +Name[hu]=Kuick modul +Name[is]=Quick Copy & Move Íforrit +Name[it]=Plugin copia/spostamento rapidi +Name[ja]=高速コピー & 移動プラグイン +Name[ka]=სწრაფი ასლის და გადატანის მოდული +Name[kk]=Шұғыл көшірмелеу және жылжыту плагин модулі +Name[km]=ចម្លង និងផ្លាស់ទីកម្មវិធីជំនួយដ៏រហ័ស +Name[lt]=Greito kopijavimo ir perkėlimo priedas +Name[lv]=Ātras Kopēšanas un Pārvietošanas Iespraudnis +Name[mk]=Приклучок за брзо копирање и преместување +Name[ms]=Salin Pantas & Alih Plugin +Name[mt]=Plugin għal ikkupjar u tmexxija malajr +Name[nb]=Programtillegg for rask kopi og flytt +Name[nds]=Fix-Koperen un -Verschuvenmoduul +Name[ne]=छिटो प्रतिलिपि गर्नुहोस् र प्लगइन सार्नुहोस् +Name[nl]=Snel kopiëren en verplaatsen +Name[nn]=Snøggkopi-og-flytt-modul +Name[nso]=Plugin ya Kapela ya Gatisa & Sutisa +Name[pa]=ਚੁਸਤ ਨਕਲ ਅਤੇ ਭੇਜਣ ਪਲੱਗਇਨ +Name[pl]=Szybkie kopiowanie i przesuwanie +Name[pt]='Plugin' de Cópia e Mudança Rápida +Name[pt_BR]= Plugin de Copiar & Mover Rápido +Name[ro]=Modul de copiere şi mutare rapidă +Name[ru]=Быстрый перенос и копирование файлов +Name[sk]=Modul pre rýchle kopírovanie a presun +Name[sl]=Vstavek za hitro kopiranje in premikanje +Name[sr]=Прикључак за брзо копирање и премештање +Name[sr@Latn]=Priključak za brzo kopiranje i premeštanje +Name[sv]=Snabbkopiera och -flytta +Name[ta]=விரைவான நகலெடு மற்றும் நகர்த்து சொருகுபொருள் +Name[tg]=Кӯчондани тез ва нусхаи файлҳо +Name[th]=ปลั๊กอินคัดลอกและย้ายอย่างรวดเร็ว +Name[tr]=Hızlı Kopyalama ve Taşıma Eklentisi +Name[uk]=Втулок швидкого копіювання та пересування +Name[uz]=Tez nusxa olish va koʻchirish plagini +Name[uz@cyrillic]=Тез нусха олиш ва кўчириш плагини +Name[ven]=Khophi ya tavhanya & tshimbidza Plugin +Name[vi]=Bổ sung sao chép và di chuyển nhanh +Name[xh]=Khawuleza Khuphela & Susa iplagi yangaphakathi +Name[zh_CN]=快速复制和移动文件的插件 +Name[zh_TW]=快速複製及搬移外掛程式 +Name[zu]=Kuick Khiphela futhi Ususe i Plugin +Comment=Kuick configuration module +Comment[af]=Vinnige opstelling module +Comment[ar]=أداة تهيئة Kuick +Comment[az]=Kuick quraşdırma modulu +Comment[bg]=Модул за настройване на Kuick +Comment[br]=Mollad kefluniañ buan +Comment[bs]=Modul za podešavanje Kuick-a +Comment[ca]=Mòdul de configuració per a Kuick +Comment[cs]=Konfigurační modul 'kuick' +Comment[cy]=Modiwl ffurfweddu Kuick +Comment[da]=Kuick indstillingsmodul +Comment[de]=Einstellungsmodul für die Kopier- und Verschieberoutine "Kuick" +Comment[el]=Άρθρωμα ρύθμισης του Kuick +Comment[eo]=Agordmodulo por Rapidkopiilo +Comment[es]=Módulo de configuración rápida +Comment[et]=Kuicki seadistamine +Comment[eu]=Kuick konfiguratzeko modulua +Comment[fa]=پیمانۀ پیکربندی Kuick +Comment[fi]=Kuick asetusmoduuli +Comment[fr]=Module de configuration de Kuick +Comment[fy]=Kuick-konfiguraasjemodule +Comment[ga]=Modúl cumraíochta Kuick +Comment[gl]=Módulo de configuración de Kuick +Comment[he]=שינוי הגדרות התוסף Kuick +Comment[hi]=क्विक कॉन्फ़िगरेशन मॉड्यूल +Comment[hr]=Modul za konfiguriranje Kuicka +Comment[hu]=A Kuick beállítómodulja +Comment[is]=Stillingatól Kuick +Comment[it]=Modulo di configurazione per Kuick +Comment[ja]=Kuick の設定モジュール +Comment[ka]=Kuick კონფიგურაციის მოდული +Comment[kk]=Kuick баптау модулі +Comment[km]=ម៉ូឌុលកំណត់រចនាសម្ព័ន្ធ Kuick +Comment[lt]=Kuick konfigūravimo modulis +Comment[mk]=Конфигурациски модул на Kuick +Comment[ms]=Modul konfigurasi Kuick +Comment[mt]=Konfigurazzjoni malajr +Comment[nb]=Oppsettsmodul for Kuick +Comment[nds]=Kuick-Instellenmoduul +Comment[ne]=छिटो कन्फिगरेसन मिड्युल +Comment[nl]=Kuick-configuratiemodule +Comment[nn]=Oppsettsmodul for Kuick +Comment[nso]=Seripa sa peakanyo ya Kuick +Comment[pl]=Moduł konfiguracji Kuick +Comment[pt]=Módulo de configuração do Kuick +Comment[pt_BR]=Módulo de configuração do Kuick +Comment[ro]=Modul configurare Kuick +Comment[ru]=Модуль настройки Kuick +Comment[sk]=Konfiguračný modul kuick +Comment[sl]=Nastavitveni modul Kuick +Comment[sr]=Kuick-ов модул за подешавање +Comment[sr@Latn]=Kuick-ov modul za podešavanje +Comment[sv]=Inställningsmodul för Kuick +Comment[ta]=விரைவான வடிவமைப்பு கூற்று +Comment[tg]=Модули танзими Kuick +Comment[th]=โมดูลปรับแต่ง Kuick +Comment[tr]=Hızlı yapılandırma modülü +Comment[uk]=Модуль конфігурації Kuick +Comment[uz]=Kuick moslamasi moduli +Comment[uz@cyrillic]=Kuick мосламаси модули +Comment[ven]=Modulu wa nzudzanyo wa Kuick +Comment[vi]=Mô-đun cấu hình Kuick +Comment[xh]=Uqwalaselo lomqongo womlinganiselo we Kuick +Comment[zh_CN]=Kuick 配置模块 +Comment[zh_TW]=Kuick 設定模組 +Comment[zu]=Kuick imojula yenhlanganiselo +Keywords=kuick,copy,move +Keywords[az]=kuick,copy,move,köçürt,daşı +Keywords[bg]=копиране, преместване, бързо, kuick, copy, move +Keywords[ca]=kuick,copia,mou +Keywords[cs]=kuick,kopírovat,přesunout +Keywords[cy]=kuick,copï,symud +Keywords[da]=kuick,kopiér,flyt +Keywords[de]=kuick,kopieren,verschieben +Keywords[el]=kuick,αντιγραφή,μετακίνηση +Keywords[eo]=rapida,kopio,movo +Keywords[es]=rápida,copiar,mover +Keywords[et]=kuick,kopeerimine,liigutamine +Keywords[fa]=kuick ،رونوشت، حرکت +Keywords[fi]=kuick,kopioi,siirrä +Keywords[fo]=kuick,avrita,flyta +Keywords[fr]=kuick,copie,déplacement +Keywords[fy]=kuick, kopiearje, ferpleatse +Keywords[ga]=kuick,cóipeáil,bog +Keywords[gl]=kuick,copiar,mover +Keywords[he]=מהיר,העתקה,העברה, kuick,copy,move, quick +Keywords[hi]=क्विक,नक़ल,खिसकाना +Keywords[hr]=kuick,copy,move,kopiraj,premjesti,kopiranje,premještanje +Keywords[hu]=Kuick,másolás,mozgatás +Keywords[is]=fljót,afrita,færa +Keywords[it]=kuick,copia,spostamento +Keywords[ja]=kuick,コピー,移動 +Keywords[ka]=kuick,ასლი,გადატანა +Keywords[km]=kuick ចម្លង ផ្លាស់ទី +Keywords[lt]=kuick,copy,move,kopijuoti, perkelti +Keywords[lv]=kuick,kopēt,pārvietot +Keywords[mk]=kuick,копирај,премести,копирање,преместување +Keywords[ms]=kuick,salin, alih +Keywords[mt]=kuick,copy,move,ikkopja,mexxi +Keywords[nb]=kuick,kopier,flytt +Keywords[nds]=kuick,koperen,verschuven +Keywords[ne]=छिटो,प्रतिलिपि,सार्नुहोस् +Keywords[nl]=kuick,kopiëren,verplaatsen +Keywords[nn]=kuick,kopier,flytt +Keywords[nso]=kapela,gatisa,suta +Keywords[pl]=kuick,kopiuj,przesuń +Keywords[pt]=kuick,copiar,mover +Keywords[pt_BR]=kuick,copiar,mover +Keywords[ro]=kuick,copiere,mutare +Keywords[ru]=kuick,копирование,перенос +Keywords[sk]=kuick,kopírovať,presun +Keywords[sl]=kuick,kopira,premakn +Keywords[sr]=kuick,copy,move,копирај,премести +Keywords[sr@Latn]=kuick,copy,move,kopiraj,premesti +Keywords[sv]=kuick,kopiera,flytta +Keywords[ta]=விரைவான,நகல் எடு, நகர்த்து +Keywords[tg]=kuick, нусха, гузарондан +Keywords[th]=รวดเร็ว,คัดลอก,ย้าย +Keywords[tr]=kuick,hızlı,kopyala,taşı +Keywords[uk]=kuick,копіювання,пересування +Keywords[uz]=kuick,nusxa olish,koʻchirish +Keywords[uz@cyrillic]=kuick,нусха олиш,кўчириш +Keywords[ven]=kuick,khophi,tshimbila +Keywords[vi]=kuick,sao chép,chép,di chuyển,chuyển +Keywords[xh]=kuick,khuphela,hambisa +Keywords[zh_CN]=kuick,copy,move,复制,移动 +Keywords[zu]=kuick,khiphela,susa +X-KDE-ParentApp=kcontrol +DocPath=konq-plugins/kuick/index.html diff --git a/konq-plugins/kuick/kcmkuick/kcmkuick.h b/konq-plugins/kuick/kcmkuick/kcmkuick.h new file mode 100644 index 0000000..c10d04e --- /dev/null +++ b/konq-plugins/kuick/kcmkuick/kcmkuick.h @@ -0,0 +1,46 @@ +/*************************************************************************** + kcmkuick.h + ------------------- + copyright : (C) 2001 by Holger Freyther + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; version 2 of the License. * + * * + ***************************************************************************/ + +#ifndef KCMKUICK_H +#define KCMKUICK_H + +#include <kcmodule.h> +#include <kaboutdata.h> +#include "kcmkuickdialog.h" + + +class KCMKuick + : public KCModule +{ + Q_OBJECT + +public: + KCMKuick (QWidget *parent, const char *name, const QStringList &); + ~KCMKuick(); + void load(); + void load(const QString &); + void save(); + void defaults(); + QString quickHelp() const; +public slots: + void configChanged(); +private: + KCMKuickDialog *dialog; +protected slots: + void slotClearMoveCache(); + void slotClearCopyCache(); + void slotShowToggled(); +}; + +#endif diff --git a/konq-plugins/kuick/kcmkuick/kcmkuickdialog.ui b/konq-plugins/kuick/kcmkuick/kcmkuickdialog.ui new file mode 100644 index 0000000..5001ad9 --- /dev/null +++ b/konq-plugins/kuick/kcmkuick/kcmkuickdialog.ui @@ -0,0 +1,197 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>KCMKuickDialog</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KCMKuickDialog</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>598</width> + <height>190</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>m_chkShow</cstring> + </property> + <property name="text"> + <string>&Show "Copy To" and "Move To" entries in context menus</string> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>m_grpCopy</cstring> + </property> + <property name="title"> + <string>Copy Operations</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QPushButton" row="2" column="0"> + <property name="name"> + <cstring>pbCopyClear</cstring> + </property> + <property name="text"> + <string>&Clear List</string> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>m_txtCopyDir</cstring> + </property> + <property name="text"> + <string>folders.</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_txtCopyCache</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Cache the last</string> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>m_sbCopy</cstring> + </property> + <property name="maxValue"> + <number>20</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <spacer row="0" column="3"> + <property name="name"> + <cstring>Spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>m_grpMove</cstring> + </property> + <property name="title"> + <string>Move Operations</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>11</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QPushButton" row="2" column="0"> + <property name="name"> + <cstring>pbMoveClear</cstring> + </property> + <property name="text"> + <string>Clear &List</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>m_txtMoveCache</cstring> + </property> + <property name="text"> + <string>Cache the last</string> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>m_sbMove</cstring> + </property> + <property name="maxValue"> + <number>20</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>m_txtMoveDir</cstring> + </property> + <property name="text"> + <string>folders.</string> + </property> + </widget> + <spacer row="0" column="3"> + <property name="name"> + <cstring>Spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + </vbox> +</widget> +<tabstops> + <tabstop>m_sbCopy</tabstop> + <tabstop>pbCopyClear</tabstop> + <tabstop>m_sbMove</tabstop> + <tabstop>pbMoveClear</tabstop> +</tabstops> +<slots> + <slot access="private">slotClearMoveCache()</slot> + <slot access="protected">slotClearCopyCache()</slot> +</slots> +<layoutdefaults spacing="6" margin="0"/> +<layoutfunctions spacing="KDialog::spacingHint"/> +</UI> diff --git a/konq-plugins/kuick/kdirmenu.cpp b/konq-plugins/kuick/kdirmenu.cpp new file mode 100644 index 0000000..2cbf6de --- /dev/null +++ b/konq-plugins/kuick/kdirmenu.cpp @@ -0,0 +1,169 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + Icon stroing inspired by Matthias Elters browser_mnu.* (currently not used) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ +#include <qiconset.h> +#include <qdir.h> +#include <qfileinfo.h> + +#include <kaction.h> +#include <kapplication.h> +#include <kiconloader.h> +#include <kio/global.h> +#include <klocale.h> +#include <kurl.h> +#include <ksimpleconfig.h> +#include "kdirmenu.h" + +#define CICON(a) (*_icons)[a] + +QMap<QString, QPixmap> *KDirMenu::_icons = 0; + +KDirMenu::KDirMenu ( QWidget *parent, const KURL &_src, + const QString &_path, const QString &_name, bool /*showfile*/ ) + : QPopupMenu(parent), + path(_path), + name(_name), + src( _src ), + action( 0 ) +{ + children.setAutoDelete( true ); + initIconMap( ); + connect( this, SIGNAL( aboutToShow( ) ), this, SLOT( slotAboutToShow( ) ) ); + connect( this, SIGNAL( aboutToHide( ) ), this, SLOT( slotAboutToHide( ) ) ); + children.clear(); // just in case + + QFileInfo fileInfo(path); + if (( src.path() != path || !src.isLocalFile()) && fileInfo.isWritable()) + action = new KAction(name, 0, this, SLOT(new_slot( ) ), this); +} +KDirMenu::~KDirMenu( ) { + delete action; + clear( ); + children.clear( ); +} +void KDirMenu::insert( KDirMenu *submenu, const QString &_path ) { + static const QIconSet folder = SmallIconSet("folder"); + QString escapedPath = _path; + QString completPath=path+'/'+_path; + // parse .directory if it does exist + if (QFile::exists(completPath + "/.directory")) { + + KSimpleConfig c(completPath + "/.directory", true); + c.setDesktopGroup(); + QString iconPath = c.readEntry("Icon"); + + if ( iconPath.startsWith("./") ) + iconPath = _path + '/' + iconPath.mid(2); + QPixmap icon; + icon = KGlobal::iconLoader()->loadIcon(iconPath, + KIcon::Small, KIcon::SizeSmall, + KIcon::DefaultState, 0, true); + if(icon.isNull()) + icon = CICON("folder"); + insertItem( icon, escapedPath.replace( "&", "&&" ), submenu ); + } + else + insertItem( folder, escapedPath.replace( "&", "&&" ), submenu ); + children.append( submenu ); + connect(submenu, SIGNAL(fileChosen(const QString &)), + this, SLOT(slotFileSelected(const QString &))); +} + +void KDirMenu::slotAboutToShow( ) { + + // ok, prepare the dir: list all dirs and insert the new menus + if (count() >= 1) return; + + //Precaution: if not a directory, exit, in case some path in KMetaMenu + //isn't checked right + if ( !QFileInfo(path).isDir() ) + return; + + if ( action ) + action->plug( this ); + else + setItemEnabled( insertItem( name ), false ); + + // all dirs writeable and readable + QDir dir(path, QString::null, + QDir::Name | QDir::DirsFirst | QDir::IgnoreCase, + QDir::Dirs | QDir::Readable | QDir::Executable); + + const QFileInfoList* dirList = dir.entryInfoList(); + if ( !dirList || dirList->isEmpty() ) { + if ( action ) + action->setEnabled( false ); + return; + } + + insertSeparator( ); + + if (dirList->count() == 2) { + insertItem(i18n("No Sub-Folders"), 0); + setItemEnabled(0, false); + return; + } + + static const QString& dot = KGlobal::staticQString( "." ); + static const QString& dotdot = KGlobal::staticQString( ".." ); + + for ( QFileInfoListIterator it( *dirList ); *it; ++it ) { + QString fileName = (*it)->fileName(); + if ( fileName == dot || fileName == dotdot ) + continue; + + KURL u; + u.setPath((*it)->absFilePath()); + if (kapp->authorizeURLAction("list", u, u)) + { + insert(new KDirMenu(this, src, (*it)->absFilePath(), name), + KIO::decodeFileName( fileName )); + } + } +} +void KDirMenu::slotAboutToHide( ) { + +} +void KDirMenu::initIconMap() +{ + if(_icons) return; + +// kdDebug(90160) << "PanelBrowserMenu::initIconMap" << endl; + + _icons = new QMap<QString, QPixmap>; + + _icons->insert("folder", SmallIcon("folder")); + _icons->insert("unknown", SmallIcon("mime_empty")); + _icons->insert("folder_open", SmallIcon("folder_open")); + _icons->insert("kdisknav", SmallIcon("kdisknav")); + _icons->insert("kfm", SmallIcon("kfm")); + _icons->insert("terminal", SmallIcon("terminal")); + _icons->insert("txt", SmallIcon("txt")); + _icons->insert("exec", SmallIcon("exec")); + _icons->insert("chardevice", SmallIcon("chardevice")); +} +void KDirMenu::slotFileSelected(const QString &_path ){ + emit fileChosen( _path ); +} + +void KDirMenu::new_slot() { + emit fileChosen(path ); +} + +#include "kdirmenu.moc" diff --git a/konq-plugins/kuick/kdirmenu.h b/konq-plugins/kuick/kdirmenu.h new file mode 100644 index 0000000..6356e83 --- /dev/null +++ b/konq-plugins/kuick/kdirmenu.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __kdirmenu_h +#define __kdirmenu_h + +#include <qpopupmenu.h> +#include <qptrlist.h> +#include <qmap.h> + +class KAction; +class KURL; + +class KDirMenu : public QPopupMenu { + Q_OBJECT +public: + KDirMenu( QWidget *parent, const KURL &src, const QString &_path, + const QString &name, bool showfiles = false ); + ~KDirMenu( ); + void setPath( const QString &_path); + void insert( KDirMenu *menu, const QString &path ); +protected: + int target_id; + static QMap<QString, QPixmap> *_icons; + +signals: + void fileChosen( const QString &_path ); +private: + QString path; + QString name; + KURL src; + KAction *action; + QPtrList<KDirMenu> children; + void initIconMap( ); +public slots: + void slotAboutToShow( ); + void slotAboutToHide( ); + void slotFileSelected(const QString &_path ); + /** No descriptions */ + void new_slot(); +}; + +#endif // __kdirmenu_h + diff --git a/konq-plugins/kuick/kimcontactmenu.cpp b/konq-plugins/kuick/kimcontactmenu.cpp new file mode 100644 index 0000000..42cf980 --- /dev/null +++ b/konq-plugins/kuick/kimcontactmenu.cpp @@ -0,0 +1,82 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + kimcontactmenu.cpp - Menu allowing a choice from a list of instant + messaging contacts + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qstringlist.h> + +// The following enables kabc for contact name lookups instead of using Kopete's idea of their name. +//#define KIMCONTACTS_USE_KABC + +#include <kimproxy.h> + +#ifdef KIMCONTACTS_USE_KABC +#include <kabc/addressbook.h> +#include <kabc/stdaddressbook.h> +#endif + +#include "kimcontactmenu.h" + +KIMContactMenu::KIMContactMenu( QWidget *parent, KIMProxy *proxy ) + : QPopupMenu( parent), mProxy( proxy ) +{ +#ifdef KIMCONTACTS_USE_KABC + m_addressBook = KABC::StdAddressBook::self( false ); +#endif + connect( this, SIGNAL( activated( int ) ), SLOT( slotItemActivated( int ) ) ); + connect( this, SIGNAL( aboutToShow( ) ), this, SLOT( slotAboutToShow( ) ) ); +} + +KIMContactMenu::~KIMContactMenu() +{ +} + +void KIMContactMenu::slotAboutToHide() +{ +} + +void KIMContactMenu::slotAboutToShow() +{ + // the pointer may be returning to the menu, if it's already populated, there's nothing to do + if (count() >= 1) return; + + mContacts = mProxy->fileTransferContacts(); + + int i = 0; + + for ( QStringList::Iterator it = mContacts.begin(); it != mContacts.end(); ++it, ++i ) + { +#ifdef KIMCONTACTS_USE_KABC + insertItem( mProxy->presenceIcon( *it ), m_addressBook->findByUid( *it ).realName(), i ); +#else + insertItem( mProxy->presenceIcon( *it ), mProxy->displayName( *it ), i ); +#endif + } +} + +void KIMContactMenu::slotItemActivated( int item ) +{ + // look up corresponding UID + QString uid = mContacts[ item ]; + // emit signal + emit contactChosen( uid ); +} + +#include "kimcontactmenu.moc" diff --git a/konq-plugins/kuick/kimcontactmenu.h b/konq-plugins/kuick/kimcontactmenu.h new file mode 100644 index 0000000..62c13bc --- /dev/null +++ b/konq-plugins/kuick/kimcontactmenu.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Will Stephenson <lists@stevello.free-online.co.uk> + + kimcontactmenu.cpp - Menu allowing a choice from a list of instant + messaging contacts + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __kim_contact_menu_h +#define __kim_contact_menu_h + +#include <qpopupmenu.h> +#include <qstringlist.h> + +class KIMProxy; +namespace KABC { + class AddressBook; +} + +class KIMContactMenu : public QPopupMenu +{ + Q_OBJECT +public: + KIMContactMenu( QWidget *parent, KIMProxy *proxy ); + ~KIMContactMenu(); +protected slots: + // populate menus if not already populated + void slotAboutToShow(); + void slotAboutToHide(); + void slotItemActivated( int item ); +signals: + void contactChosen( const QString &uid ); + +protected: + KIMProxy *mProxy; + QStringList mContacts; + KABC::AddressBook* m_addressBook; +}; + +#endif diff --git a/konq-plugins/kuick/kmetamenu.cpp b/konq-plugins/kuick/kmetamenu.cpp new file mode 100644 index 0000000..065a825 --- /dev/null +++ b/konq-plugins/kuick/kmetamenu.cpp @@ -0,0 +1,180 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <kiconloader.h> +#include <kimproxy.h> +#include <kapplication.h> +#include <klocale.h> +#include <kconfig.h> +#include <kfiledialog.h> +#include <kurl.h> +#include <konq_popupmenu.h> + +#include <qpixmap.h> +#include <qdir.h> +#include <qiconset.h> +#include <qstringlist.h> + +#include "kmetamenu.h" +#include "kdirmenu.h" +#include "kimcontactmenu.h" +#include "kmetamenu.moc" + +KMetaMenu::KMetaMenu( QWidget *parent, const KURL &url, + const QString &text, const QString &key, KIMProxy *imProxy ) +: QPopupMenu( parent), + m_root( 0 ), m_home( 0 ), m_etc( 0 ), m_current( 0 ), m_browse( 0 ) { + int recent_no; + group = key; + actions.setAutoDelete( TRUE ); + + QStringList dirList; + + KURL u; + + u.setPath(QDir::homeDirPath()); + if ( kapp->authorizeURLAction("list", u, u) ) + { + m_home = new KDirMenu( parent, url, u.path() , text ); + insertItem( SmallIcon( "kfm_home" ), i18n("&Home Folder"), m_home); + dirList << u.path(); + + connect(m_home, SIGNAL(fileChosen(const QString &)), + SLOT(slotFileChosen(const QString &) ) ); + } + + u.setPath(QDir::rootDirPath()); + if ( kapp->authorizeURLAction("list", u, u) ) + { + m_root = new KDirMenu( parent, url, u.path() , text ); + insertItem( SmallIcon( "folder_red" ), i18n("&Root Folder"), m_root); + dirList << u.path(); + + connect(m_root, SIGNAL(fileChosen(const QString &)), + SLOT(slotFileChosen(const QString &) ) ); + } + + QString confDir = QDir::rootDirPath()+ "etc"; + u.setPath(confDir); + if ( QFileInfo( confDir ).isWritable() && + kapp->authorizeURLAction("list", u, u) ) + { + m_etc = new KDirMenu( parent, url, confDir, text ); + insertItem( SmallIcon( "folder_yellow" ) , + i18n("&System Configuration"), m_etc); + dirList << confDir; + + connect(m_etc , SIGNAL(fileChosen(const QString &)), + SLOT(slotFileChosen(const QString &) ) ); + } + + if ( url.isLocalFile() + && dirList.find( url.path() ) == dirList.end() + && QFileInfo( url.path() ).isWritable() + && QFileInfo( url.path() ).isDir() + && kapp->authorizeURLAction("list", url, url) ) + //Need to check whether a directory so we don't crash trying to access it + //(#60192) + { + // Also add current working directory + m_current = new KDirMenu( parent, url, url.path(), text ); + insertItem( SmallIcon( "folder" ), i18n( "&Current Folder" ), + m_current ); + + connect(m_current, SIGNAL(fileChosen(const QString &)), + SLOT(slotFileChosen(const QString &) ) ); + } + + if ( imProxy ) + { + m_contacts = new KIMContactMenu( parent, imProxy ); + int item = insertItem( SmallIconSet( "personal" ), i18n( "C&ontact" ), m_contacts ); + connect ( m_contacts, SIGNAL( contactChosen( const QString &) ), SIGNAL( contactChosen( const QString & ) ) ); + if ( !imProxy->initialize() || imProxy->fileTransferContacts().isEmpty() ) + setItemEnabled( item, false ); + } + + + m_browse = new KAction(i18n("&Browse..."), 0, this, SLOT(slotBrowse()), this ); + m_browse->plug(this); + // read the last chosen dirs + // first set the group according to our parameter + conf = kapp->config( ); + conf->setGroup(key ); + recent_no = conf->readNumEntry("ShowRecent", 5); + list = conf->readPathListEntry("Paths"); + if ( list.count() > 0 ) + insertSeparator(); + int i=1; + QStringList::Iterator it = list.begin(); + while( it != list.end() ) { + if( i == (recent_no + 1) ) + break; + QDir dir( *it ); + u.setPath( *it ); + if ( !dir.exists() || !kapp->authorizeURLAction("list", u, u) ) { + it = list.remove( it ); + continue; + } + QString escapedDir = *it; + KAction *action = new KAction(escapedDir.replace("&", "&&"), 0, this, SLOT(slotFastPath()), this); + action->plug(this ); + actions.append( action ); + ++it; + i++; + } +} + +KMetaMenu::KMetaMenu( ){ + +} +KMetaMenu::~KMetaMenu(){ + delete m_root; + delete m_home; + delete m_etc; + delete m_current; + delete m_browse; + actions.clear(); +} +void KMetaMenu::slotFileChosen(const QString &path ){ + writeConfig(path ); + emit fileChosen(path ); +} + +void KMetaMenu::slotFastPath( ) { + KAction *action; + action = (KAction*) sender(); + QString text = action->plainText( ); + slotFileChosen( text ); +} +void KMetaMenu::writeConfig( const QString &path){ + list.remove(path ); + list.prepend(path ); + conf->setGroup( group ); + int c = conf->readNumEntry( "ShowRecent", 5 ); + while ( list.count() > c && !list.isEmpty() ) + list.remove(list.last()); + conf->writePathEntry("Paths", list); + conf->sync( ); +} +void KMetaMenu::slotBrowse() { + KURL dest = KFileDialog::getExistingURL(); + if( dest.isEmpty() ) return; + slotFileChosen( dest.isLocalFile() ? dest.path() : dest.url() ); +} diff --git a/konq-plugins/kuick/kmetamenu.h b/konq-plugins/kuick/kmetamenu.h new file mode 100644 index 0000000..f6670f6 --- /dev/null +++ b/konq-plugins/kuick/kmetamenu.h @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _kmetamenu_h +#define _kmetamenu_h + +#include <qpopupmenu.h> +#include <qptrlist.h> + +#include <kaction.h> + +class QIconSet; +class QStringList; +class KConfig; +class KDirMenu; +class KIMContactMenu; +class KIMProxy; +class KURL; + +class KMetaMenu : public QPopupMenu { + Q_OBJECT +public: + + KMetaMenu( QWidget *parent, const KURL &url, const QString &text, + const QString &key, KIMProxy * imProxy = 0L ); + KMetaMenu(); + ~KMetaMenu(); + void writeConfig( const QString &path ); +public slots: + void slotFileChosen( const QString &path); + void slotFastPath( ); + void slotBrowse( ); +signals: + void fileChosen( const QString &path ); + void contactChosen( const QString &uid ); +private: + KDirMenu *m_root; + KDirMenu *m_home; + KDirMenu *m_etc; + KDirMenu *m_current; + KIMContactMenu *m_contacts; + KIMProxy *m_proxy; + KAction *m_browse; + QStringList list; + KConfig *conf; + QString group; + QPtrList<KAction> actions; +}; + +#endif + diff --git a/konq-plugins/kuick/kuick_plugin.cpp b/konq-plugins/kuick/kuick_plugin.cpp new file mode 100644 index 0000000..80a7cc7 --- /dev/null +++ b/konq-plugins/kuick/kuick_plugin.cpp @@ -0,0 +1,114 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kuick_plugin.h" +#include "kuick_plugin.moc" +#include "kdirmenu.h" + +#include <kapplication.h> +#include <kaction.h> +#include <kinstance.h> +#include <kiconloader.h> +#include <kimproxy.h> +#include <klocale.h> +#include <konq_popupmenu.h> +#include <kmessagebox.h> +#include <kgenericfactory.h> +#include <qobject.h> +#include <kio/jobclasses.h> +#include <kio/job.h> +#include <kurl.h> + +typedef KGenericFactory<KTestMenu, KonqPopupMenu> KTestMenuFactory; +K_EXPORT_COMPONENT_FACTORY( libkuickplugin, KTestMenuFactory("kuick_plugin") ) + +KTestMenu::KTestMenu( KonqPopupMenu *popupmenu, const char *name, const QStringList& /*list*/ ) : KonqPopupMenuPlugin( popupmenu, name) { + popup= popupmenu ; + meta_copy_mmu = 0L; + meta_move_mmu = 0L; + my_action = new KAction( "kuick_plugin", 0, this, SLOT( slotPopupMaeh( ) ), actionCollection( ), "Do some funky stuff" ); + addAction( my_action ); + addSeparator(); + //popupmenu->addMerge(); + connect( popup, SIGNAL(aboutToShow() ), this, SLOT(slotPrepareMenu( ) ) ); + m_imProxy = KIMProxy::instance( kapp->dcopClient() ); +} +KTestMenu::~KTestMenu( ){ + delete meta_copy_mmu; + delete meta_move_mmu; +} +void KTestMenu::slotPopupMaeh( ){ + +} +void KTestMenu::slotStartCopyJob( const QString &path ) { + KURL url = KURL::fromPathOrURL( path ); + KIO::CopyJob *copy; + copy = KIO::copy( popup->popupURLList(), url); + copy->setAutoErrorHandlingEnabled( true ); +} +void KTestMenu::slotStartMoveJob( const QString &path) { + KURL url = KURL::fromPathOrURL( path ); + KIO::CopyJob *move; + move = KIO::move( popup->popupURLList(), url ); + move->setAutoErrorHandlingEnabled( true ); +} + +void KTestMenu::slotFileTransfer( const QString &uid ) { + m_imProxy->sendFile( uid, popup->popupURLList().first() ); +} + +void KTestMenu::slotPrepareMenu( ) { // now it's time to set up the menu... +// search for the dummy entry 'kuick_plugin' stores it index reomev it plug copy at the position + KGlobal::locale()->insertCatalogue("kuick_plugin"); + + bool isKDesktop = QCString( kapp->name() ) == "kdesktop"; + + for(int i= popup->count(); i >=1; i--) { + int id = popup->idAt( i ); + QString text = popup->text( id ); + if( text.contains("kuick_plugin") ) { + popup->removeItem( id ); + if (isKDesktop && !kapp->authorize("editable_desktop_icons")) + { + // Remove seperator as well + id = popup->idAt( i-1 ); + if (popup->text( id ).isEmpty()) + popup->removeItem( id ); + break; + } + meta_copy_mmu = new KMetaMenu(popup, popup->url(), + i18n("&Copy Here") , "kuick-copy", m_imProxy ); + popup->insertItem(i18n("Copy To"), meta_copy_mmu, -1, i ); + connect( meta_copy_mmu, SIGNAL(fileChosen(const QString &) ), + SLOT(slotStartCopyJob(const QString & )) ); + + connect( meta_copy_mmu, SIGNAL( contactChosen( const QString & ) ), + SLOT( slotFileTransfer( const QString & )) ); + + if( popup->protocolInfo().supportsMoving() ){ + meta_move_mmu = new KMetaMenu(popup, popup->url(), + i18n("&Move Here"), "kuick-move"); + popup->insertItem(i18n("Move To"), meta_move_mmu, -1, i+1 ); + connect( meta_move_mmu, SIGNAL(fileChosen(const QString &) ), + SLOT(slotStartMoveJob(const QString & )) ); + } + break; + } + } +} diff --git a/konq-plugins/kuick/kuick_plugin.desktop b/konq-plugins/kuick/kuick_plugin.desktop new file mode 100644 index 0000000..41138df --- /dev/null +++ b/konq-plugins/kuick/kuick_plugin.desktop @@ -0,0 +1,67 @@ +[Desktop Entry] +Type=Service +Name=Kuick Copy and Move +Name[af]=Vinnige Kopie en Beweeg +Name[az]=Kuik Köçür və Daşı +Name[bg]=Бързо копиране и преместване +Name[bs]=Kuick kopiranje i premještanje +Name[ca]=Kuick copia i mou +Name[cs]=Rychlé kopírování a přesouvání +Name[cy]=Copïo a Symud Kuick +Name[da]=Kuick kopiér & flyt +Name[de]=Kuick - Kopieren und Verschieben +Name[el]=Γρήγορη αντιγραφή και μετακίνηση +Name[eo]=Rapidkopiilo +Name[es]=Movimiento y copiado rápido +Name[et]=Kuicki kopeerimine ja liigutamine +Name[eu]=Kuick kopiatu eta mugitu +Name[fa]=رونوشت و حرکت Kuick +Name[fi]=Nopea kopiointi ja siirto +Name[fr]=Copie et déplacement rapides +Name[fy]=Kuick Kopiearje en Ferpleatse +Name[gl]=Copiar e Mover Rapidamente +Name[he]=העתקה והעברה מהירה +Name[hi]=क्विक नक़ल तथा खिसकाना +Name[hr]=KBrzo kopiranje i premještanje +Name[hu]=Kuick - másolás és mozgatás +Name[it]=Copia e spostamento rapidi +Name[ja]=高速コピー & 移動 +Name[ka]=Kuick ასლი და გადატანა +Name[kk]=Kuick көшірмелеу мен жылжыту +Name[km]=Kuick ចម្លង និងផ្លាស់ទី +Name[lt]=Kuick kopijavimas ir perkėlimas +Name[lv]=Kuick Kopēšana un Pārvietošana +Name[mk]=Kuick копирање и преместување +Name[ms]=Salin Kuick dan Alih +Name[nb]=Kuick kopier og flytt +Name[nds]=Kuick - Koperen un Verschuven +Name[ne]=छिटो प्रतिलिपि गर्नुहोस् र सार्नुहोस् +Name[nl]=Kuick Kopiëren en Verplaatsen +Name[nn]=Snøggkopi-og-flytt +Name[nso]=Tshutiso le Kgatiso ya Kuick +Name[pl]=Szybkie kopiowanie i przesuwanie +Name[pt]=Cópia e Mudança Rápida +Name[pt_BR]=Lançador rápido +Name[ro]=Mutare şi copiere Kuick +Name[ru]=Быстрое копирование +Name[sk]=Kuick Kopírovanie a Presun +Name[sl]=Kopiranje in premikanje Kuick +Name[sr]=Kuick, копирај и премести +Name[sr@Latn]=Kuick, kopiraj i premesti +Name[sv]=Snabbkopiera och -flytta +Name[ta]=விரைவான நகல் எடு மற்றும் நகர்த்து +Name[tg]=Нусхаи тез - Kuick +Name[th]=คัดลอกและย้ายอย่างรวดเร็ว +Name[tr]=Hızlı Kopyalama ve Taşıma +Name[uk]=Kuick копіювання та пересування +Name[uz]=Tez nusxa olish va koʻchirish +Name[uz@cyrillic]=Тез нусха олиш ва кўчириш +Name[ven]=Kuick khophi na u tshimbila +Name[vi]=Sao chép và di chuyển Kuick +Name[xh]=Ukhuphelo noHambiso lweKuick +Name[zh_CN]=快速复制和移动 +Name[zh_TW]=Kuick 複製與移動 +Name[zu]=Kuick Khiphela futhi Ususe +Icon=kmultiple +X-KDE-Library=libkuickplugin +ServiceTypes=KonqPopupMenu/Plugin,all/all diff --git a/konq-plugins/kuick/kuick_plugin.h b/konq-plugins/kuick/kuick_plugin.h new file mode 100644 index 0000000..15ffdcd --- /dev/null +++ b/konq-plugins/kuick/kuick_plugin.h @@ -0,0 +1,54 @@ +/* This file is part of the KDE project + Copyright (C) 2001 Holger Freyther <freyther@yahoo.com> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; version 2 + of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _PLUGIN_TEST_H_ +#define _PLUGIN_TEST_H_ + +#include <konq_popupmenu.h> + +#include "kmetamenu.h" + +class KAction; +class KURL; +class KTestMenu : public KonqPopupMenuPlugin { + Q_OBJECT +public: + KTestMenu (KonqPopupMenu *, const char *name, const QStringList &list); + virtual ~KTestMenu( ); + KMetaMenu *meta_copy_mmu; + KMetaMenu *meta_move_mmu; + KonqPopupMenu *popup; + +private: + KAction *my_action; + KIMProxy *m_imProxy; + +public slots: + void slotPopupMaeh( ); + void slotStartCopyJob(const QString &path ); + //void slotStartCopyJob(const KURL &url ); + void slotStartMoveJob(const QString &path ); + //void slotStartMoveJob(const KURL &url ); + void slotFileTransfer( const QString &uid ); + void slotPrepareMenu( ); +}; + + +#endif + diff --git a/konq-plugins/kuick/kuickplugin.desktop b/konq-plugins/kuick/kuickplugin.desktop new file mode 100644 index 0000000..da4b262 --- /dev/null +++ b/konq-plugins/kuick/kuickplugin.desktop @@ -0,0 +1,66 @@ +[Desktop Entry] +Name=Kuick Copy and Move +Name[af]=Vinnige Kopie en Beweeg +Name[az]=Kuik Köçür və Daşı +Name[bg]=Бързо копиране и преместване +Name[bs]=Kuick kopiranje i premještanje +Name[ca]=Kuick copia i mou +Name[cs]=Rychlé kopírování a přesouvání +Name[cy]=Copïo a Symud Kuick +Name[da]=Kuick kopiér & flyt +Name[de]=Kuick - Kopieren und Verschieben +Name[el]=Γρήγορη αντιγραφή και μετακίνηση +Name[eo]=Rapidkopiilo +Name[es]=Movimiento y copiado rápido +Name[et]=Kuicki kopeerimine ja liigutamine +Name[eu]=Kuick kopiatu eta mugitu +Name[fa]=رونوشت و حرکت Kuick +Name[fi]=Nopea kopiointi ja siirto +Name[fr]=Copie et déplacement rapides +Name[fy]=Kuick Kopiearje en Ferpleatse +Name[gl]=Copiar e Mover Rapidamente +Name[he]=העתקה והעברה מהירה +Name[hi]=क्विक नक़ल तथा खिसकाना +Name[hr]=KBrzo kopiranje i premještanje +Name[hu]=Kuick - másolás és mozgatás +Name[it]=Copia e spostamento rapidi +Name[ja]=高速コピー & 移動 +Name[ka]=Kuick ასლი და გადატანა +Name[kk]=Kuick көшірмелеу мен жылжыту +Name[km]=Kuick ចម្លង និងផ្លាស់ទី +Name[lt]=Kuick kopijavimas ir perkėlimas +Name[lv]=Kuick Kopēšana un Pārvietošana +Name[mk]=Kuick копирање и преместување +Name[ms]=Salin Kuick dan Alih +Name[nb]=Kuick kopier og flytt +Name[nds]=Kuick - Koperen un Verschuven +Name[ne]=छिटो प्रतिलिपि गर्नुहोस् र सार्नुहोस् +Name[nl]=Kuick Kopiëren en Verplaatsen +Name[nn]=Snøggkopi-og-flytt +Name[nso]=Tshutiso le Kgatiso ya Kuick +Name[pl]=Szybkie kopiowanie i przesuwanie +Name[pt]=Cópia e Mudança Rápida +Name[pt_BR]=Lançador rápido +Name[ro]=Mutare şi copiere Kuick +Name[ru]=Быстрое копирование +Name[sk]=Kuick Kopírovanie a Presun +Name[sl]=Kopiranje in premikanje Kuick +Name[sr]=Kuick, копирај и премести +Name[sr@Latn]=Kuick, kopiraj i premesti +Name[sv]=Snabbkopiera och -flytta +Name[ta]=விரைவான நகல் எடு மற்றும் நகர்த்து +Name[tg]=Нусхаи тез - Kuick +Name[th]=คัดลอกและย้ายอย่างรวดเร็ว +Name[tr]=Hızlı Kopyalama ve Taşıma +Name[uk]=Kuick копіювання та пересування +Name[uz]=Tez nusxa olish va koʻchirish +Name[uz@cyrillic]=Тез нусха олиш ва кўчириш +Name[ven]=Kuick khophi na u tshimbila +Name[vi]=Sao chép và di chuyển Kuick +Name[xh]=Ukhuphelo noHambiso lweKuick +Name[zh_CN]=快速复制和移动 +Name[zh_TW]=Kuick 複製與移動 +Name[zu]=Kuick Khiphela futhi Ususe +Icon=kmultiple +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/kuick/index.html diff --git a/konq-plugins/mediarealfolder/Makefile.am b/konq-plugins/mediarealfolder/Makefile.am new file mode 100644 index 0000000..76b7287 --- /dev/null +++ b/konq-plugins/mediarealfolder/Makefile.am @@ -0,0 +1,5 @@ +servicesdir = $(kde_datadir)/konqueror/servicemenus +services_DATA = media_realfolder.desktop + +bin_SCRIPTS = kio_media_realfolder + diff --git a/konq-plugins/mediarealfolder/kio_media_realfolder b/konq-plugins/mediarealfolder/kio_media_realfolder new file mode 100755 index 0000000..cbb3d06 --- /dev/null +++ b/konq-plugins/mediarealfolder/kio_media_realfolder @@ -0,0 +1,20 @@ +#! /usr/bin/env perl + +use warnings; +use strict; + +my @parts = split(/\//, $ARGV[0]); + +my $medium = $parts[$#parts]; + +open(IN, "-|") || exec "dcop", "kded", "mediamanager", "properties", $medium; +my @prop = <IN>; +close(IN); + +if ($prop[6] =~ /^\//) +{ + my $mountpoint = $prop[6]; + chomp($mountpoint); + exec "kfmclient", "exec", "file://$mountpoint/"; +} + diff --git a/konq-plugins/mediarealfolder/media_realfolder.desktop b/konq-plugins/mediarealfolder/media_realfolder.desktop new file mode 100644 index 0000000..9cee0c6 --- /dev/null +++ b/konq-plugins/mediarealfolder/media_realfolder.desktop @@ -0,0 +1,55 @@ +[Desktop Entry] +ServiceTypes=media/cdrom_mounted,media/cdwriter_mounted,media/dvd_mounted,media/floppy5_mounted,media/floppy_mounted,media/hdd_mounted,media/nfs_mounted,media/smb_mounted,media/removable_mounted,media/zip_mounted +Actions=MediaRealFolder +X-KDE-Priority=TopLevel +X-KDE-MediaNotifierHide=true + +[Desktop Action MediaRealFolder] +Name=Open Medium System Folder +Name[bg]=Отваряне на системната директория на носителя +Name[ca]=Obre la carpeta de mitjans del sistema +Name[cs]=Otevřít systémovou složku média +Name[da]=Åbn medium-system-mappen +Name[de]=Systemordner des Mediums öffnen +Name[el]=Άνοιγμα του φακέλου συστήματος του μέσου +Name[eo]=Malfermu mediosisteman dosierujon +Name[es]=Abrir la carpeta del administrador de medios +Name[et]=Ava andmekandja süsteemi kataloog +Name[eu]=Ireki euskarriaren kudeatzailea +Name[fa]=باز کردن پوشۀ سیستم رسانه +Name[fi]=Avaa mediajärjestelmän kansio +Name[fr]=Dossier système d'ouverture de média +Name[fy]=Systeemmap medium iepenje +Name[gl]=Cartafol de Sistema de Médio Aberto +Name[he]=פתח את תיקיית מדיית המערכת +Name[hr]=Otvaranje srednjih mapa sustava +Name[hu]=A médiaanyagok rendszerkönyvtárának megnyitása +Name[is]=Opin miðils kerfismappa +Name[it]=Cartella di sistema per l'apertura di supporti +Name[ja]=メディアシステムフォルダを開く +Name[ka]=მედიუმის სისტემური საქაღალდის გახსნა +Name[kk]=Жүйелік қалтаны ашу +Name[km]=បើកថតប្រព័ន្ធឧបករណ៍ផ្ទុក +Name[mk]=Отвори ја системската папка на медиумот +Name[nb]=Åpne systemmappe for medie +Name[nds]=Systeemorner vun't Medium opmaken +Name[ne]=मध्यम प्रणाली फोल्डर खोल्नुहोस् +Name[nl]=Systeemmap medium openen +Name[nn]=Opna mediesystemmappe +Name[pa]=ਮੀਡੀਅਮ ਸਿਸਟਮ ਫੋਲਡਰ ਖੋਲੋ +Name[pl]=Otwórz folder systemowy mediów +Name[pt]=Abrir a Pasta de Sistema do Dispositivo +Name[pt_BR]=Abrir a Pasta de Mídias do Sistema +Name[ru]=Открыть системную папку +Name[sk]=Otvoriť systémový priečinok médií +Name[sl]=Odpri sistemsko mapo z nosilci +Name[sr]=Отвори системску фасциклу медијума +Name[sr@Latn]=Otvori sistemsku fasciklu medijuma +Name[sv]=Öppna mediumsystemkatalog +Name[tr]=Aygıtın Sistem Dizinini Aç +Name[uk]=Відкрити системну теку носія +Name[vi]=Mở thư mục hệ thống vừa +Name[zh_CN]=打开介质系统文件夹 +Name[zh_TW]=開啟媒體系統資料夾 +Exec=kio_media_realfolder %u + diff --git a/konq-plugins/microformat/Makefile.am b/konq-plugins/microformat/Makefile.am new file mode 100644 index 0000000..d96b5c5 --- /dev/null +++ b/konq-plugins/microformat/Makefile.am @@ -0,0 +1,19 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libmfkonqmficon.la + +libmfkonqmficon_la_SOURCES = konqmficon.cpp pluginbase.cpp +libmfkonqmficon_la_LIBADD = -lkonq $(LIB_KHTML) +libmfkonqmficon_la_LDFLAGS = -module $(KDE_PLUGIN) -avoid-version -no-undefined $(all_libraries) + +konqmficondir = $(kde_datadir)/khtml/kpartplugins +konqmficon_DATA = mf_konqmficon.desktop mf_konqmficon.rc + +mficondir = $(kde_datadir)/microformat/pics +mficon_DATA = microformat.png + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/mf_konqplugin.pot diff --git a/konq-plugins/microformat/README b/konq-plugins/microformat/README new file mode 100644 index 0000000..896256f --- /dev/null +++ b/konq-plugins/microformat/README @@ -0,0 +1,14 @@ +Microformats +------------ + +Please see: + +http://developers.technorati.com/wiki/hCard +http://developers.technorati.com/wiki/hCalendar +http://developers.technorati.com/wiki/MicroFormat + + +Also try: +http://tantek.com/microformats/hcard-creator.html +http://theryanking.com/microformats/hcalendar-creator.html + diff --git a/konq-plugins/microformat/hcard.png b/konq-plugins/microformat/hcard.png Binary files differnew file mode 100644 index 0000000..b80213c --- /dev/null +++ b/konq-plugins/microformat/hcard.png diff --git a/konq-plugins/microformat/konqmficon.cpp b/konq-plugins/microformat/konqmficon.cpp new file mode 100644 index 0000000..51fdd97 --- /dev/null +++ b/konq-plugins/microformat/konqmficon.cpp @@ -0,0 +1,323 @@ +/* + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + Copyright (C) 2005 George Staikos <staikos@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include "konqmficon.h" + +#include <dcopref.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kiconloader.h> +#include <kparts/statusbarextension.h> +#include <kstandarddirs.h> +#include <kstatusbar.h> +#include <kurllabel.h> + +#include <qcursor.h> +#include <qstylesheet.h> +#include <qtimer.h> +#include <qtooltip.h> + +typedef KGenericFactory<KonqMFIcon> KonqMFIconFactory; +K_EXPORT_COMPONENT_FACTORY(libmfkonqmficon, + KonqMFIconFactory("mfkonqmficon")) + +KonqMFIcon::KonqMFIcon(QObject *parent, const char *name, const QStringList &) +: KParts::Plugin(parent, name), PluginBase(), m_part(0), m_mfIcon(0), m_statusBarEx(0), m_menu(0) { + KGlobal::locale()->insertCatalogue("mf_konqplugin"); + + m_part = dynamic_cast<KHTMLPart*>(parent); + if (!m_part) { + kdDebug() << "couldn't get part" << endl; + return; + } + QTimer::singleShot(0, this, SLOT(waitPartToLoad())); +} + + +void KonqMFIcon::waitPartToLoad() { + connect(m_part, SIGNAL(completed()), this, SLOT(addMFIcon())); + connect(m_part, SIGNAL(completed(bool)), this, SLOT(addMFIcon())); // to make pages with metarefresh to work + connect(m_part, SIGNAL(started(KIO::Job *)), this, SLOT(removeMFIcon())); +} + + +KonqMFIcon::~KonqMFIcon() { + KGlobal::locale()->removeCatalogue("mf_konqplugin"); + delete m_menu; + m_menu = 0L; +} + + +static QString textForNode(DOM::Node node) { + QString rc; + DOM::NodeList nl = node.childNodes(); + for (unsigned int i = 0; i < nl.length(); ++i) { + DOM::Node n = nl.item(i); + if (n.nodeType() == DOM::Node::TEXT_NODE) { + rc += n.nodeValue().string(); + } + } + // FIXME: entries need to be escaped for vcard/vevent + return rc.stripWhiteSpace(); +} + + +static QString extractAddress(DOM::Node node) { + QString rc = ";;"; + QMap<QString,QString> entry; + DOM::NodeList nodes = node.childNodes(); + unsigned int n = nodes.length(); + for (unsigned int i = 0; i < n; ++i) { + DOM::Node node = nodes.item(i); + DOM::NamedNodeMap map = node.attributes(); + for (unsigned int j = 0; j < map.length(); ++j) { + if (map.item(j).nodeName().string() != "class") { + continue; + } + QString a = map.item(j).nodeValue().string(); + if (a == "street-address") { + entry["street-address"] = textForNode(node); + } else if (a == "locality") { + entry["locality"] = textForNode(node); + } else if (a == "region") { + entry["region"] = textForNode(node); + } else if (a == "postal-code") { + entry["postal-code"] = textForNode(node); + } + } + } + + rc += entry["street-address"] + ";" + entry["locality"] + ";" + entry["region"] + ";" + entry["postal-code"] + ";" + entry["country"]; + return rc.stripWhiteSpace(); +} + + +void KonqMFIcon::extractCard(DOM::Node node) { + QString name, value; + DOM::NodeList nodes = node.childNodes(); + unsigned int n = nodes.length(); + value += "BEGIN:VCARD\nVERSION:3.0\n"; + for (unsigned int i = 0; i < n; ++i) { + DOM::Node node = nodes.item(i); + DOM::NamedNodeMap map = node.attributes(); + for (unsigned int j = 0; j < map.length(); ++j) { + if (map.item(j).nodeName().string() != "class") { + continue; + } + QStringList l = QStringList::split(' ', map.item(j).nodeValue().string()); + for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if (*it == "photo") { + } else if (*it == "adr") { + value += "ADR:" + extractAddress(node) + "\n"; + } else if (*it == "tel") { + value += "TEL;TYPE=VOICE:" + textForNode(node) + "\n"; + } else if (*it == "fn") { + name = textForNode(node); + value += "FN:" + name + "\n"; + } else if (*it == "url") { + DOM::Node at = node.attributes().getNamedItem("href"); + if (!at.isNull()) { + value += "URL:" + at.nodeValue().string().stripWhiteSpace() + "\n"; + } + } else if (*it == "email") { + DOM::Node at = node.attributes().getNamedItem("href"); + if (!at.isNull()) { + QString v = at.nodeValue().string(); + if (v.startsWith("mailto:")) { + v = v.mid(7); + } + value += "EMAIL:" + v.stripWhiteSpace() + "\n"; + } + } else if (*it == "org") { + value += "ORG:" + textForNode(node) + "\n"; + } + } + } + } + + if (!name.isEmpty()) { + value += "END:VCARD\n"; + _cards.append(qMakePair(name, value)); + } +} + + +void KonqMFIcon::extractEvent(DOM::Node node) { + QString name, value = "BEGIN:VCALENDAR\nPRODID:-//Konqueror//EN\nVERSION:2.0\nBEGIN:VEVENT\n"; + DOM::NodeList nodes = node.childNodes(); + unsigned int n = nodes.length(); + for (unsigned int i = 0; i < n; ++i) { + DOM::Node node = nodes.item(i); + DOM::NamedNodeMap map = node.attributes(); + for (unsigned int j = 0; j < map.length(); ++j) { + if (map.item(j).nodeName().string() != "class") { + continue; + } + QStringList l = QStringList::split(' ', map.item(j).nodeValue().string()); + for (QStringList::ConstIterator it = l.begin(); it != l.end(); ++it) { + if (*it == "url") { + DOM::Node at = node.attributes().getNamedItem("href"); + if (!at.isNull()) { + value += "URL:" + at.nodeValue().string().stripWhiteSpace() + "\n"; + } + } else if (*it == "dtstart") { + DOM::Node at = node.attributes().getNamedItem("title"); + if (!at.isNull()) { + value += "DTSTART:" + at.nodeValue().string().stripWhiteSpace() + "\n"; + } + } else if (*it == "dtend") { + DOM::Node at = node.attributes().getNamedItem("title"); + if (!at.isNull()) { + value += "DTEND:" + at.nodeValue().string().stripWhiteSpace() + "\n"; + } + } else if (*it == "summary") { + name = textForNode(node); + value += "SUMMARY:" + name + "\n"; + } else if (*it == "location") { + value += "LOCATION:" + textForNode(node) + "\n"; + } + } + } + } + + if (!name.isEmpty()) { + value += "END:VEVENT\nEND:VCALENDAR\n"; + _events.append(qMakePair(name, value)); + } +} + + +bool KonqMFIcon::hasMicroFormat(DOM::NodeList nodes) { + bool ok = false; + unsigned int n = nodes.length(); + for (unsigned int i = 0; i < n; ++i) { + DOM::Node node = nodes.item(i); + DOM::NamedNodeMap map = node.attributes(); + for (unsigned int j = 0; j < map.length(); ++j) { + if (map.item(j).nodeName().string() != "class") { + continue; + } + if (map.item(j).nodeValue().string() == "vevent") { + ok = true; + extractEvent(node); + break; + } + if (map.item(j).nodeValue().string() == "vcard") { + ok = true; + extractCard(node); + break; + } + } + if (hasMicroFormat(node.childNodes())) { + ok = true; + } + } + return ok; +} + + +bool KonqMFIcon::mfFound() { + _events.clear(); + _cards.clear(); + return hasMicroFormat(m_part->document().childNodes()); +} + + +void KonqMFIcon::contextMenu() { + delete m_menu; + m_menu = new KPopupMenu(m_part->widget()); + m_menu->insertTitle(i18n("Microformats")); + connect(m_menu, SIGNAL(activated(int)), this, SLOT(addMF(int))); + int id = 0; + for (QValueList<QPair<QString, QString> >::ConstIterator it = _events.begin(); it != _events.end(); ++it) { + m_menu->insertItem(SmallIcon("bookmark_add"), (*it).first, id); + id++; + } + for (QValueList<QPair<QString, QString> >::ConstIterator it = _cards.begin(); it != _cards.end(); ++it) { + m_menu->insertItem(SmallIcon("bookmark_add"), (*it).first, id); + id++; + } + m_menu->insertSeparator(); + m_menu->insertItem(SmallIcon("bookmark_add"), i18n("Import All Microformats"), this, SLOT(addMFs()), 0, 50000 ); + m_menu->popup(QCursor::pos()); +} + + +void KonqMFIcon::addMFIcon() { + if (!mfFound() || m_mfIcon) { + return; + } + + m_statusBarEx = KParts::StatusBarExtension::childObject(m_part); + if (!m_statusBarEx) { + return; + } + + m_mfIcon = new KURLLabel(m_statusBarEx->statusBar()); + m_mfIcon->setFixedHeight(instance()->iconLoader()->currentSize(KIcon::Small)); + m_mfIcon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed)); + m_mfIcon->setUseCursor(false); + //FIXME hackish + m_mfIcon->setPixmap(QPixmap(locate("data", "microformat/pics/microformat.png"))); + + QToolTip::remove(m_mfIcon); + QToolTip::add(m_mfIcon, i18n("This site has a microformat entry", "This site has %n microformat entries", _events.count() + _cards.count())); + + m_statusBarEx->addStatusBarItem(m_mfIcon, 0, true); + + connect(m_mfIcon, SIGNAL(leftClickedURL()), this, SLOT(contextMenu())); +} + + +void KonqMFIcon::removeMFIcon() { + _events.clear(); + _cards.clear(); + if (m_mfIcon) { + m_statusBarEx->removeStatusBarItem(m_mfIcon); + delete m_mfIcon; + m_mfIcon = 0; + } + + // Close the popup if it's open, otherwise we crash + delete m_menu; + m_menu = 0L; +} + + +void KonqMFIcon::addMF(int id) { + if (id < int(_events.count())) { + } else if (id < int(_cards.count())) { + id -= _cards.count() - 1; + addVCardViaDCOP(_cards[id].second); + } +} + + +void KonqMFIcon::addMFs() { + int n = _events.count() + _cards.count(); + for (int i = 0; i < n; ++i) { + addMF(i); + } +} + +#include "konqmficon.moc" diff --git a/konq-plugins/microformat/konqmficon.h b/konq-plugins/microformat/konqmficon.h new file mode 100644 index 0000000..819bb2e --- /dev/null +++ b/konq-plugins/microformat/konqmficon.h @@ -0,0 +1,70 @@ +/* + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + Copyright (C) 2005 George Staikos <staikos@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef KONQFEEDICON_H +#define KONQFEEDICON_H + +#include <khtml_part.h> +#include <kparts/plugin.h> +#include <kpopupmenu.h> +#include "pluginbase.h" + +/** +@author Teemu Rytilahti +*/ +class KURLLabel; +class QStringList; + +namespace KParts { + class StatusBarExtension; +} + +class KonqMFIcon : public KParts::Plugin, PluginBase { + Q_OBJECT + public: + KonqMFIcon(QObject *parent, const char *name, const QStringList &); + + ~KonqMFIcon(); + + private: + bool mfFound(); + bool hasMicroFormat(DOM::NodeList nodes); + void extractCard(DOM::Node node); + void extractEvent(DOM::Node node); + + QGuardedPtr<KHTMLPart> m_part; + KURLLabel *m_mfIcon; + KParts::StatusBarExtension *m_statusBarEx; + QGuardedPtr<KPopupMenu> m_menu; + QValueList<QPair<QString, QString> > _events, _cards; + + private slots: + void waitPartToLoad(); + void contextMenu(); + void addMFIcon(); + void removeMFIcon(); + void addMFs(); + void addMF(int id); +}; + +#endif diff --git a/konq-plugins/microformat/mf_konqmficon.desktop b/konq-plugins/microformat/mf_konqmficon.desktop new file mode 100644 index 0000000..27edbc6 --- /dev/null +++ b/konq-plugins/microformat/mf_konqmficon.desktop @@ -0,0 +1,110 @@ +[Desktop Entry] +Name=Konqueror Microformat Plugin +Name[bg]=Приставка за Microformat (Konqueror) +Name[br]=Lugent Microformat Konqueror +Name[ca]=Connector de microformat pel Konqueror +Name[cs]=Microformat modul pro Konqueror +Name[da]=Konqueror mikroformat-plugin +Name[de]=Konqueror-Modul für Microformat +Name[el]=Πρόσθετο Microformat του Konqueror +Name[eo]=Mikroformata kromaĵo por Konkeranto +Name[es]=Complemento Microformato de Konqueror +Name[et]=Konquerori Microformati plugin +Name[eu]=Konqueror-en Microformat-en plugina +Name[fa]=وصلۀ ریزقالب Konqueror +Name[fi]=Konqueror mikromuotoliitännäinen +Name[fr]=Module d'icône de flux pour Konqueror +Name[fy]=Konqueror Microformat-plugin +Name[ga]=Breiseán Micreafhormáid Konqueror +Name[gl]=Plugin de Micro-formato de Konqueror +Name[he]=תוסף Microformat עבור Konqueror +Name[hr]=Konqueror Microformat dodatak +Name[hu]=Konqueror Microformat-bővítőmodul +Name[is]=Konqueror Microformat íforrit +Name[it]=Plugin per il formato microformat di Konqueror +Name[ja]=Konqueror マイクロフォーマット プラグイン +Name[ka]=Konqueror მიკროფორმატის მოდული +Name[kk]=Konqueror Microformat плагин модулі +Name[km]=កម្មវិធីជំនួយទ្រង់ទ្រាយមីក្រូរបស់ Konqueror +Name[lt]=Konqueror mikroformatų priedai +Name[mk]=Приклучок за микроформат на Konqueror +Name[nb]=Mikroformat programtillegg for Konqueror +Name[nds]=Mikroformaat-Moduul för Konqueror +Name[ne]=कन्क्वेर सूक्ष्म ढाँचा प्लगइन +Name[nl]=Konqueror Microformat-plugin +Name[nn]=Programtillegg for mikroformat i Konqueror +Name[pa]=ਕੋਨਕਿਊਰੋਰ ਮਾਈਕਰੋਫਾਰਮਿਟ ਪਲੱਗਇਨ +Name[pl]=Wtyczka Mikroformatu dla Konquerora +Name[pt]='Plugin' de Micro-formato do Konqueror +Name[pt_BR]=Plug-in de fonte de notícias RSS do Konqueror +Name[ru]=Микроформаты для Konqueror +Name[sk]=Modul Konqueror microformat +Name[sl]=Vstavek Konquerorja za Microformat +Name[sr]=Прикључак Konqueror-а за микроформат +Name[sr@Latn]=Priključak Konqueror-a za mikroformat +Name[sv]=Konqueror-insticksprogram för mikroformat +Name[tr]=Konqueror Besleme Simge Eklentisi +Name[uk]=Втулок мікроформату для Konqueror +Name[vi]=Bổ sung định dạng vi Konqueror +Name[zh_CN]=Konqueror 微格式插件 +Name[zh_TW]=Konqueror Microformat 外掛程式 +Icon=akregator +Comment=Displays icon in the statusbar when the page has a microformat +Comment[bg]=Показване на икона в лентата за състоянието, когато страницата има умален формат +Comment[ca]=Mostra la icona a la barra d'estat quan la pàgina té un microformat +Comment[cs]=Zobrazí na panelu ikonku, pokud má stránka mikroformát +Comment[da]=Viser ikon i statusfelt når siden har et mikroformat +Comment[de]=Zeigt das Symbol in der Statusleiste, wenn die Seite ein Microformat hat +Comment[el]=Εμφανίζει το εικονίδιο στη γραμμή κατάστασης όταν η σελίδα έχει microformat +Comment[eo]=Montras piktogramon en la statolistelo kiam la paĝo enhavas mikroformaton +Comment[es]=Muestra el icono en la barra de estado cuando la página tiene un microformato +Comment[et]=Näitab olekuribal kanaliikooni, kui saidil on microformat +Comment[eu]=Orriak mikroformatu bat badu ikono bat bistaratzen du egoera-barran +Comment[fa]=وقتی صفحه دارای ریزقالب باشد، شمایل را در میله وضعیت نمایش میدهد +Comment[fi]=Näyttää syötekuvakkeen tilapalkissa jos sivulla on mikromuoto +Comment[fr]=Affiche une icône dans la barre d'état lorsque la page possède un microformat +Comment[fy]=Toant in piktogram yn de tastânbalke as de side in mikroformaat hat. +Comment[ga]=Taispeánann sé deilbhín sa bharra stádais nuair atá micreafhormáid ag an leathanach +Comment[gl]=Mostra un ícone na barra de estado cando a páxina ten un micro-formato +Comment[hr]=Prikazuje ikonu u traci stanja ako stranica posjeduje mikro-oblikovanje +Comment[hu]=Ikont jelenít meg az állapotsorban, ha az oldalhoz található Microformat-információ +Comment[is]=Sýnir táknmynd í stöðuslá þegar síða inniheldur microformat +Comment[it]=Mostra l'icona nella barra di stato quando la pagina ha un microformat +Comment[ja]=ページにマイクロフォーマットがある場合、ステータスバーにアイコンを表示します +Comment[ka]=სტატუსის ველში ასახავს ხატულას როდესაც გვერდს გააჩნია მიკროფორმატი +Comment[kk]=Бетте микроформат болса, күй-жай жолағында таңбашасын көрсету +Comment[km]=បង្ហាញរូបតំណាងនៅក្នុងរបារស្ថានភាព នៅពេលដែលទំព័រមានទ្រង់ទ្រាយមីក្រូ +Comment[lt]=Rodo ženkliuką būsenos juostoje kai puslapis turi mikroformatą +Comment[mk]=Прикажува икона во статусната лента кога страницата има микроформат +Comment[nb]=Viser ikon for nyhetskilde på statuslinja når nettstedet har etmikroformat +Comment[nds]=Wiest en Lüttbild op den Statusbalken, wenn de Siet en Mikroformaat hett +Comment[ne]=पृष्ठमा सूक्ष्म ढाँचा हुदाँ स्थितिपट्टीमा प्रतिमा प्रदर्शन गर्छ +Comment[nl]=Toont een pictogram in de statusbalk als een pagina een microformaat bevat. +Comment[nn]=Viser eit ikon på statuslinja når sida har eit mikroformat +Comment[pl]=Wyświetla ikonę w pasku stanu, jeśli strona zawiera mikroformat +Comment[pt]=Mostra um ícone na barra de estado quando a página tem um micro-formato +Comment[pt_BR]=Mostra um ícone na barra de status quando a página possui uma fonte de notícias RSS +Comment[ru]=Показать в строке состояния значок поддержки микроформата на странице +Comment[sk]=Zobrazí ikonu v statovom riadku keď strana obsahuje microformat +Comment[sl]=Ko stran vsebuje Microformat se v vrstici stanja prikaže ikona +Comment[sr]=Приказује икону у статусној траци када страна има микроформат +Comment[sr@Latn]=Prikazuje ikonu u statusnoj traci kada strana ima mikroformat +Comment[sv]=Visar en ikon i statusraden när sidan har ett mikroformat +Comment[tr]=Sayfaya özgü bir biçim olduğunda simgeyi durum çubuğunda göster +Comment[uk]=Показує піктограму в рядку стану, коли сторінка має мікроформат +Comment[uz]=Sahifada mikroformat boʻlsa, holat panelida nishonchani koʻrsatish +Comment[uz@cyrillic]=Саҳифада микроформат бўлса, ҳолат панелида нишончани кўрсатиш +Comment[vi]=Hiển thị biểu tượng trên thanh trạng thái khi trang có định dạng vi +Comment[zh_CN]=当页面有微格式时在状态栏显示图标 +Comment[zh_TW]=當網頁有 microformat 時在狀態列顯示圖示 +Type=Service +X-KDE-Library=libakregatorkonqfeedicon +X-KDE-PluginInfo-Author=George Staikos +X-KDE-PluginInfo-Email=staikos@kde.org +X-KDE-PluginInfo-Name=konqmficon +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-Category=Statusbar +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +X-KDE-ParentApp=konqueror diff --git a/konq-plugins/microformat/mf_konqmficon.rc b/konq-plugins/microformat/mf_konqmficon.rc new file mode 100644 index 0000000..466b14e --- /dev/null +++ b/konq-plugins/microformat/mf_konqmficon.rc @@ -0,0 +1,3 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="konqmficon" library="libmfkonqmficon" version="1"> +</kpartplugin> diff --git a/konq-plugins/microformat/microformat.png b/konq-plugins/microformat/microformat.png Binary files differnew file mode 100644 index 0000000..0217918 --- /dev/null +++ b/konq-plugins/microformat/microformat.png diff --git a/konq-plugins/microformat/microformat.svgz b/konq-plugins/microformat/microformat.svgz Binary files differnew file mode 100644 index 0000000..5975616 --- /dev/null +++ b/konq-plugins/microformat/microformat.svgz diff --git a/konq-plugins/microformat/pluginbase.cpp b/konq-plugins/microformat/pluginbase.cpp new file mode 100644 index 0000000..9f73dd6 --- /dev/null +++ b/konq-plugins/microformat/pluginbase.cpp @@ -0,0 +1,43 @@ +/* + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + Copyright (C) 2005 George Staikos <staikos@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#include <kprocess.h> +#include <dcopref.h> +#include <klocale.h> + +#include "pluginbase.h" + +#include <kdebug.h> + +PluginBase::PluginBase() { +} + + +PluginBase::~PluginBase() { +} + + +void PluginBase::addVCardViaDCOP(const QString& card) { + DCOPRef("kaddressbook", "AddressBookServiceIface").send("importVCard", card); +} + diff --git a/konq-plugins/microformat/pluginbase.h b/konq-plugins/microformat/pluginbase.h new file mode 100644 index 0000000..e37ea36 --- /dev/null +++ b/konq-plugins/microformat/pluginbase.h @@ -0,0 +1,38 @@ +/* + Copyright (C) 2004 Teemu Rytilahti <tpr@d5k.net> + Copyright (C) 2005 George Staikos <staikos@kde.org> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + As a special exception, permission is given to link this program + with any edition of Qt, and distribute the resulting executable, + without including the source code for Qt in the source distribution. +*/ + +#ifndef PLUGINBASE_H +#define PLUGINBASE_H + +class QString; + +class PluginBase { + public: + PluginBase(); + ~PluginBase(); + + public: + void addVCardViaDCOP(const QString& vcard); +}; + +#endif diff --git a/konq-plugins/minitools/Makefile.am b/konq-plugins/minitools/Makefile.am new file mode 100644 index 0000000..48f63e4 --- /dev/null +++ b/konq-plugins/minitools/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO +KDE_ICON = AUTO + +kde_module_LTLIBRARIES = libminitoolsplugin.la +libminitoolsplugin_la_SOURCES = minitoolsplugin.cpp +libminitoolsplugin_la_LIBADD = $(LIB_KHTML) -lkonq +libminitoolsplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = minitoolsplugin.rc minitoolsplugin.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/minitoolsplugin.pot diff --git a/konq-plugins/minitools/cr16-action-minitools.png b/konq-plugins/minitools/cr16-action-minitools.png Binary files differnew file mode 100644 index 0000000..5e76158 --- /dev/null +++ b/konq-plugins/minitools/cr16-action-minitools.png diff --git a/konq-plugins/minitools/cr22-action-minitools.png b/konq-plugins/minitools/cr22-action-minitools.png Binary files differnew file mode 100644 index 0000000..ced954c --- /dev/null +++ b/konq-plugins/minitools/cr22-action-minitools.png diff --git a/konq-plugins/minitools/cr32-action-minitools.png b/konq-plugins/minitools/cr32-action-minitools.png Binary files differnew file mode 100644 index 0000000..028869c --- /dev/null +++ b/konq-plugins/minitools/cr32-action-minitools.png diff --git a/konq-plugins/minitools/cr48-action-minitools.png b/konq-plugins/minitools/cr48-action-minitools.png Binary files differnew file mode 100644 index 0000000..aa335b2 --- /dev/null +++ b/konq-plugins/minitools/cr48-action-minitools.png diff --git a/konq-plugins/minitools/minitoolsplugin.cpp b/konq-plugins/minitools/minitoolsplugin.cpp new file mode 100644 index 0000000..53f109b --- /dev/null +++ b/konq-plugins/minitools/minitoolsplugin.cpp @@ -0,0 +1,156 @@ +/* + Copyright (c) 2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qfile.h> + +#include <kdebug.h> +#include <kaction.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kinstance.h> +#include <khtml_part.h> +#include <kgenericfactory.h> + +#include <kstandarddirs.h> + +#include <krun.h> +#include <kservice.h> + +#include <kpopupmenu.h> +#include <kbookmarkimporter.h> +#include <kbookmarkmanager.h> + +#include "minitoolsplugin.h" + +typedef KGenericFactory<MinitoolsPlugin> MinitoolsPluginFactory; +K_EXPORT_COMPONENT_FACTORY( libminitoolsplugin, MinitoolsPluginFactory("minitoolsplugin") ) + +MinitoolsPlugin::MinitoolsPlugin(QObject* parent, const char* name, const QStringList &) + : KParts::Plugin(parent, name) { + m_part = (parent && parent->inherits( "KHTMLPart" )) ? static_cast<KHTMLPart*>(parent) : 0L; + + m_pMinitoolsMenu = new KActionMenu(i18n("&Minitools"), "minitools", actionCollection(), "minitools"); + + m_pMinitoolsMenu->setDelayed(false); + m_pMinitoolsMenu->setEnabled(true); + + connect(m_pMinitoolsMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotAboutToShow() )); +} + +MinitoolsPlugin::~MinitoolsPlugin() { + ; +} + +void MinitoolsPlugin::slotAboutToShow() { + + m_minitoolsList.clear(); + KXBELBookmarkImporterImpl importer; + connect(&importer, SIGNAL( newBookmark( const QString &, const QCString &, const QString &) ), + SLOT( newBookmarkCallback( const QString &, const QCString &, const QString & ) )); + connect(&importer, SIGNAL( endFolder() ), + SLOT( endFolderCallback() )); + QString filename = minitoolsFilename(true); + if (!filename.isEmpty() && QFile::exists(filename)) { + importer.setFilename(filename); + importer.parse(); + } + filename = minitoolsFilename(false); + if (!filename.isEmpty() && QFile::exists(filename)) { + importer.setFilename(filename); + importer.parse(); + } + + m_pMinitoolsMenu->popupMenu()->clear(); + + int count = m_pMinitoolsMenu->popupMenu()->count(); // why not 0??? + bool gotSep = true; // don't start with a sep + + if (m_minitoolsList.count() > 0) { + MinitoolsList::ConstIterator e = m_minitoolsList.begin(); + for( ; e != m_minitoolsList.end(); ++e ) { + if ( ((*e).first == "-") + && ((*e).second == "-") + ) { + if (!gotSep) + m_pMinitoolsMenu->popupMenu()->insertSeparator(); + gotSep = true; + count++; + } else { + QString str = (*e).first; + // emsquieezzy thingy? + if (str.length() > 48) { + str.truncate(48); + str.append("..."); + } + m_pMinitoolsMenu->popupMenu()->insertItem( + str, this, + SLOT(slotItemSelected(int)), + 0, ++count ); + gotSep = false; + } + } + } + + if (!gotSep) { + // don't have an extra sep + m_pMinitoolsMenu->popupMenu()->insertSeparator(); + } + + m_pMinitoolsMenu->popupMenu() + ->insertItem(i18n("&Edit Minitools"), + this, SLOT(slotEditBookmarks()), + 0, ++count ); +} + +void MinitoolsPlugin::newBookmarkCallback( + const QString & text, const QCString & url, const QString & +) { + kdDebug(90150) << "MinitoolsPlugin::newBookmarkCallback" << text << url << endl; + m_minitoolsList.prepend(qMakePair(text,url)); +} + +void MinitoolsPlugin::endFolderCallback() { + kdDebug(90150) << "MinitoolsPlugin::endFolderCallback" << endl; + m_minitoolsList.prepend(qMakePair(QString("-"),QCString("-"))); +} + +QString MinitoolsPlugin::minitoolsFilename(bool local) { + return local ? locateLocal("data", QString::fromLatin1("konqueror/minitools.xml")) + : locateLocal("data", QString::fromLatin1("konqueror/minitools-global.xml")); +} + +void MinitoolsPlugin::slotEditBookmarks() { + KBookmarkManager *manager = KBookmarkManager::managerForFile(minitoolsFilename(true)); + manager->slotEditBookmarks(); +} + +void MinitoolsPlugin::slotItemSelected(int id) { + if (m_minitoolsList.count() == 0) + return; + QString tmp = m_minitoolsList[id-1].second; + QString script = KURL::decode_string(tmp.right(tmp.length() - 11)); // sizeof("javascript:") + connect(this, SIGNAL( executeScript(const QString &) ), + m_part, SLOT( executeScript(const QString &) )); + emit executeScript(script); + disconnect(this, SIGNAL( executeScript(const QString &) ), 0, 0); +} + +#include "minitoolsplugin.moc" diff --git a/konq-plugins/minitools/minitoolsplugin.desktop b/konq-plugins/minitools/minitoolsplugin.desktop new file mode 100644 index 0000000..4f6894c --- /dev/null +++ b/konq-plugins/minitools/minitoolsplugin.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +X-KDE-Library=Minitools +X-KDE-PluginInfo-Author=Alexander Kellett +X-KDE-PluginInfo-Email=lypanov@kde.org +X-KDE-PluginInfo-Name=Minitools +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Icon=minitools +Name=Mini-Tools +Name[az]=Kiçik-Vasitələr +Name[bg]=Мини инструменти +Name[bs]=Mini-alati +Name[ca]=Mini-eines +Name[cs]=Mini nástroje +Name[cy]=Mini-Offer +Name[da]=Mini-værktøjer +Name[de]=Mini-Dienstprogramme +Name[el]=Μικρά εργαλεία +Name[eo]=Iletoj +Name[es]=Mini-herramientas +Name[eu]=Mini-tresnak +Name[fa]=ریزابزارها +Name[fi]=Minityökalut +Name[fr]=Mini-outils +Name[fy]=Miny-Ark +Name[ga]=Mion-Uirlisí +Name[gl]=Mini-Ferramentas +Name[hi]=मिनि-औज़ार +Name[hr]=Mini-alati +Name[hu]=Mini könyvjelzők +Name[is]=Lítil tól +Name[it]=Strumenti miniaturizzati +Name[ja]=ミニツール +Name[ka]=მინი-ხელსაწყოები +Name[kk]=Шағын құралдар +Name[km]=ឧបករណ៍ខ្នាតតូច +Name[lt]=Mini įrankiai +Name[mk]=Мини-алатки +Name[ms]=Minialat +Name[nb]=Mini-verktøy +Name[nds]=Lüttwarktüüch +Name[ne]=साना-उपकरण +Name[nn]=Miniverktøy +Name[pa]=ਮਿੰਨੀ-ਸੰਦ +Name[pl]=Mini-narzędzia +Name[pt]=Mini-Ferramentas +Name[pt_BR]=Mini Ferramentas +Name[ro]=Mini-unelte +Name[ru]=Мини-утилиты +Name[sk]=Mini-nástroje +Name[sl]=Mini orodja +Name[sr]=Мини алати +Name[sr@Latn]=Mini alati +Name[sv]=Miniverktyg +Name[ta]=மிகச்சிறிய-கருவிகள் +Name[tg]=Мини-асбобҳо +Name[tr]=Küçük Araçlar +Name[uk]=Міні-засоби +Name[vi]=Công cụ nhỏ +Name[zh_CN]=小工具 +Comment=Mini-Tools +Comment[az]=Kiçik-Vasitələr +Comment[bg]=Миниатюрни инструменти +Comment[bs]=Mini-alati +Comment[ca]=Mini-eines +Comment[cs]=Mini nástroje +Comment[cy]=Mini-Offer +Comment[da]=Mini-værktøjer +Comment[de]=Kleine Dienstprogramme +Comment[el]=Μικρά εργαλεία +Comment[eo]=Iletoj +Comment[es]=Mini-herramientas +Comment[et]=Mini-tööriistad +Comment[eu]=Mini-tresnak +Comment[fa]=ریزابزارها +Comment[fi]=Minityökalut +Comment[fr]=Mini-outils +Comment[fy]=Miny-helpmiddels +Comment[ga]=Mion-Uirlisí +Comment[gl]=Mini-Ferramentas +Comment[he]=מיני כלים +Comment[hi]=मिनि-औज़ार +Comment[hr]=Minijaturni alati +Comment[hu]=Mini könyvjelzők +Comment[is]=Lítil tól +Comment[it]=Strumenti miniaturizzati +Comment[ja]=ミニツール +Comment[ka]=მინი-ხელსაწყოები +Comment[kk]=Шағын құралдар +Comment[km]=ឧបករណ៍ខ្នាតតូច +Comment[lt]=Mini įrankiai +Comment[mk]=Мини-алатки +Comment[ms]=Minialat +Comment[nb]=Mini-verktøy +Comment[nds]=Lütte Warktüüch +Comment[ne]=साना-उपकरण +Comment[nl]=Mini-hulpmiddelen +Comment[nn]=Miniverktøy +Comment[pa]=ਮਿੰਨੀ-ਸੰਦ +Comment[pl]=Mini-narzędzia +Comment[pt]=Mini-Ferramentas +Comment[pt_BR]=Mini Ferramentas +Comment[ro]=Mini-unelte +Comment[ru]=Мини-утилиты +Comment[sk]=Mini-nástroje +Comment[sl]=Mini orodja +Comment[sr]=Мини-алати +Comment[sr@Latn]=Mini-alati +Comment[sv]=Miniverktyg +Comment[ta]=மிகச்சிறியக்- கருவிகள் +Comment[tg]=Мини-асбобҳо +Comment[tr]=Küçük Araçlar +Comment[uk]=Міні-засоби +Comment[vi]=Công cụ nhỏ +Comment[zh_CN]=小工具 +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/minitools/index.html diff --git a/konq-plugins/minitools/minitoolsplugin.h b/konq-plugins/minitools/minitoolsplugin.h new file mode 100644 index 0000000..7db1a77 --- /dev/null +++ b/konq-plugins/minitools/minitoolsplugin.h @@ -0,0 +1,66 @@ +/* + Copyright (c) 2003 Alexander Kellett <lypanov@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __MINITOOLS_PLUGIN_H +#define __MINITOOLS_PLUGIN_H + +#include <qmap.h> +#include <qvaluelist.h> +#include <qstringlist.h> + +#include <kurl.h> +#include <klibloader.h> +#include <kparts/plugin.h> + +class KHTMLPart; +class KActionMenu; + +class MinitoolsPlugin : public KParts::Plugin { + Q_OBJECT + +public: + MinitoolsPlugin( QObject* parent, const char* name, const QStringList & ); + ~MinitoolsPlugin(); + +protected slots: + void slotAboutToShow(); + void slotEditBookmarks(); + void slotItemSelected(int); + void newBookmarkCallback( const QString &, const QCString &, const QString & ); + void endFolderCallback( ); + +signals: + void executeScript( const QString &script ); + +private: + QString minitoolsFilename(bool local); + + int m_selectedItem; + + KHTMLPart* m_part; + KActionMenu* m_pMinitoolsMenu; + + typedef QPair<QString,QCString> Minitool; + typedef QValueList<Minitool> MinitoolsList; + + MinitoolsList m_minitoolsList; +}; + +#endif diff --git a/konq-plugins/minitools/minitoolsplugin.rc b/konq-plugins/minitools/minitoolsplugin.rc new file mode 100644 index 0000000..b5af77a --- /dev/null +++ b/konq-plugins/minitools/minitoolsplugin.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartplugin> +<kpartplugin name="Minitools" library="libminitoolsplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="minitools"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="minitools"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/rellinks/AUTHORS b/konq-plugins/rellinks/AUTHORS new file mode 100644 index 0000000..0e65688 --- /dev/null +++ b/konq-plugins/rellinks/AUTHORS @@ -0,0 +1,3 @@ +Kevin Krammer <kevin.krammer@gmx.at> (author of sitelinks, merged project on 2004-01-28) +Franck Qulain <shift@free.fr> (konq-rellinks) +Anders Lund <anders@alweb.dk> (First version : rellinks) diff --git a/konq-plugins/rellinks/ChangeLog b/konq-plugins/rellinks/ChangeLog new file mode 100644 index 0000000..bc62fdf --- /dev/null +++ b/konq-plugins/rellinks/ChangeLog @@ -0,0 +1,31 @@ +Mon Jan 21 00:31:29 CET 2002 - Anders Lund <anders@alweb.dk> + o Initial Creation (of the rellinks plugin) +Sat May 17 14:46:33 CET 2003 - Franck Qulain <shift@free.fr> + o Rename it konqSiteNavBar for better understanding + o The plugin is now a full toolbar + o Add navigation buttons (home, up, prev, next,...) + o "Document" and "More" menus la Mozilla site navigation bar + o Toolip and contextuel help on most of the items + o Menu for Unclassified links +Mon Jun 9 23:10:00 CET 2003 - Franck Qulain <shift@free.fr> + o Configuration Menu + o "When necessary" mode : show / hide toolbar only when necessary + o Configuration stored in .kde/share/config/konq_rellinksrc +Wed Jun 18 22:05:00 CET 2003 - Franck Qulain <shift@free.fr> + o The name has changed to konq-rellinks after an interesting + discussion with Anders Lund. +Fri Jan 30 16:23 CET 2004 - Kevin Krammer <kevin.krammer@gmx.at> + o Bugfix: enabling "more" menu instead of "document" when links + are "help", "made" or "copyright" + o Made "search" a top level action + o Polling for links while the page is loading. This presents + clickable actions as soon as possible, nice on slow connections or + in large documents. +Sun Mar 21 16:23 CET 2004 - Franck Qulain <shift@free.fr> + o Support for "target" attribute + o Distinction between "rel" and "rev" relations +Tue Jun 22 23:05 CET 2004 - Kevin Krammer <kevin.krammer@gmx.at> + o Move toolbar creation from XML GUI to code as a workaround + because KHTML loads the plugins before it initializes its + d pointer and so there is no way to get to either the view or + the toolbar in the plugin's contructor. diff --git a/konq-plugins/rellinks/Makefile.am b/konq-plugins/rellinks/Makefile.am new file mode 100644 index 0000000..aeec3fc --- /dev/null +++ b/konq-plugins/rellinks/Makefile.am @@ -0,0 +1,12 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO +kde_module_LTLIBRARIES = librellinksplugin.la +librellinksplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +librellinksplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +librellinksplugin_la_SOURCES = plugin_rellinks.cpp +plugins_DATA = plugin_rellinks.rc plugin_rellinks.desktop +pluginsdir = $(kde_datadir)/khtml/kpartplugins + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/rellinks.pot + diff --git a/konq-plugins/rellinks/README b/konq-plugins/rellinks/README new file mode 100644 index 0000000..e5f3324 --- /dev/null +++ b/konq-plugins/rellinks/README @@ -0,0 +1,13 @@ +What is Konq Rellinks ? +======================= + +Konq Rellinks is an add-on for Konqueror, the official KDE browser. + +It allows you to access the relations defined in the header of the document. These relations can be links to other versions of the document, RSS backend, search page, copyright informations,.... For more informations about this, see "The 'link'-Element in (X)HTML" at http://www.subotnik.net/html/link. + +The look of the Rellinks add-on is similar to the "Site Navigation Toolbar" of the Mozilla browser (not Mozilla Firebird). + +More Info +========= + +See http://shift.freezope.org/konq_rellinks
\ No newline at end of file diff --git a/konq-plugins/rellinks/TODO b/konq-plugins/rellinks/TODO new file mode 100644 index 0000000..28f206b --- /dev/null +++ b/konq-plugins/rellinks/TODO @@ -0,0 +1,20 @@ +Rellinks : +========= + +* Support multiple same relations for all relations in a beautiful way + (as FireFox Link Toolbar Extension do) : + by transfoming buttons (KAction) in menus (KActionMenu) if more than one item is found for a relation ? +* Possibility to configure keyboard shortcuts +* Manage "rel" and "rev" differently +* Manage "media" +* Respect the specifications : A LinkTypes value refers to a space-separated list of link types. White space characters are not permitted within link types. +* Send the referer when going to a link +* Support target attribut ? (Cf. Mozilla link toolbar bug : http://mozdev.org/bugs/show_bug.cgi?id=5259) + + +Rellinks website (http://shift.freezope.org/konq_rellinks) : +============================================================ + +* Add more testcasess +* Add more documentation +* Compare implementation with other browsers
\ No newline at end of file diff --git a/konq-plugins/rellinks/plugin_rellinks.cpp b/konq-plugins/rellinks/plugin_rellinks.cpp new file mode 100644 index 0000000..212c37f --- /dev/null +++ b/konq-plugins/rellinks/plugin_rellinks.cpp @@ -0,0 +1,618 @@ +/*************************************************************************** + * Copyright (C) 2002, Anders Lund <anders@alweb.dk> * + * Copyright (C) 2003, 2004, Franck Qulain <shift@free.fr> * + * Copyright (C) 2004, Kevin Krammer <kevin.krammer@gmx.at> * + * Copyright (C) 2004, 2006, Oliviet Goffart <ogoffart @ kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + + + +// Qt includes +#include <qapplication.h> +#include <qtimer.h> + +// KDE include +#include <dom/dom_doc.h> +#include <dom/dom_element.h> +#include <dom/dom_string.h> +#include <dom/html_document.h> +#include <kaction.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <khtml_part.h> +#include <khtmlview.h> +#include <kiconloader.h> +#include <kinstance.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kshortcut.h> +#include <ktoolbar.h> +#include <kurl.h> + +// local includes +#include "plugin_rellinks.h" + + +/** Rellinks factory */ +typedef KGenericFactory<RelLinksPlugin> RelLinksFactory; +#include <kdeversion.h> +#if KDE_IS_VERSION(3,2,90) +#include <kaboutdata.h> +static const KAboutData aboutdata("rellinks", I18N_NOOP("Rellinks") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY( librellinksplugin, RelLinksFactory(&aboutdata) ) +#else +K_EXPORT_COMPONENT_FACTORY( librellinksplugin, RelLinksFactory("rellinks") ) +#endif + +/** Constructor of the plugin. */ +RelLinksPlugin::RelLinksPlugin(QObject *parent, const char *name, const QStringList &) + : KParts::Plugin( parent, name ), + m_part(0), + m_viewVisible(false) +{ + + setInstance(RelLinksFactory::instance()); + + // ------------- Navigation links -------------- + kaction_map["home"] = new KAction( i18n("&Top"), "2uparrow", KShortcut("Ctrl+Alt+T"), this, SLOT(goHome()), actionCollection(), "rellinks_top" ); + kaction_map["home"]->setWhatsThis( i18n("<p>This link references a home page or the top of some hierarchy.</p>") ); + + kaction_map["up"] = new KAction( i18n("&Up"), "1uparrow", KShortcut("Ctrl+Alt+U"), this, SLOT(goUp()), actionCollection(), "rellinks_up" ); + kaction_map["up"]->setWhatsThis( i18n("<p>This link references the immediate parent of the current document.</p>") ); + + bool isRTL = QApplication::reverseLayout(); + + kaction_map["begin"] = new KAction( i18n("&First"), isRTL ? "2rightarrow" : "2leftarrow", KShortcut("Ctrl+Alt+F"), this, SLOT(goFirst()), actionCollection(), "rellinks_first" ); + kaction_map["begin"]->setWhatsThis( i18n("<p>This link type tells search engines which document is considered by the author to be the starting point of the collection.</p>") ); + + kaction_map["prev"] = new KAction( i18n("&Previous"), isRTL ? "1rightarrow" : "1leftarrow", KShortcut("Ctrl+Alt+P"), this, SLOT(goPrevious()), actionCollection(), "rellinks_previous" ); + kaction_map["prev"]->setWhatsThis( i18n("<p>This link references the previous document in an ordered series of documents.</p>") ); + + kaction_map["next"] = new KAction( i18n("&Next"), isRTL ? "1leftarrow" : "1rightarrow", KShortcut("Ctrl+Alt+N"), this, SLOT(goNext()), actionCollection(), "rellinks_next" ); + kaction_map["next"]->setWhatsThis( i18n("<p>This link references the next document in an ordered series of documents.</p>") ); + + kaction_map["last"] = new KAction( i18n("&Last"), isRTL ? "2leftarrow" : "2rightarrow", KShortcut("Ctrl+Alt+L"), this, SLOT(goLast()), actionCollection(), "rellinks_last" ); + kaction_map["last"]->setWhatsThis( i18n("<p>This link references the end of a sequence of documents.</p>") ); + + // ------------ special items -------------------------- + kaction_map["search"] = new KAction( i18n("&Search"), "filefind", KShortcut("Ctrl+Alt+S"), this, SLOT(goSearch()), actionCollection(), "rellinks_search" ); + kaction_map["search"]->setWhatsThis( i18n("<p>This link references the search.</p>") ); + + // ------------ Document structure links --------------- + m_document = new KActionMenu( i18n("Document"), "contents", actionCollection(), "rellinks_document" ); + m_document->setWhatsThis( i18n("<p>This menu contains the links referring the document information.</p>") ); + m_document->setDelayed(false); + + kaction_map["contents"] = new KAction( i18n("Table of &Contents"), "contents", KShortcut("Ctrl+Alt+C"), this, SLOT(goContents()), actionCollection(), "rellinks_toc" ); + m_document->insert(kaction_map["contents"]); + kaction_map["contents"]->setWhatsThis( i18n("<p>This link references the table of contents.</p>") ); + + kactionmenu_map["chapter"] = new KActionMenu( i18n("Chapters"), "fileopen", actionCollection(), "rellinks_chapters" ); + m_document->insert(kactionmenu_map["chapter"]); + connect( kactionmenu_map["chapter"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT(goChapter(int))); + kactionmenu_map["chapter"]->setWhatsThis( i18n("<p>This menu references the chapters of the document.</p>") ); + kactionmenu_map["chapter"]->setDelayed(false); + + kactionmenu_map["section"] = new KActionMenu( i18n("Sections"), "fileopen", actionCollection(), "rellinks_sections" ); + m_document->insert(kactionmenu_map["section"]); + connect( kactionmenu_map["section"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goSection( int ) ) ); + kactionmenu_map["section"]->setWhatsThis( i18n("<p>This menu references the sections of the document.</p>") ); + kactionmenu_map["section"]->setDelayed(false); + + kactionmenu_map["subsection"] = new KActionMenu( i18n("Subsections"), "fileopen", actionCollection(), "rellinks_subsections" ); + m_document->insert(kactionmenu_map["subsection"]); + connect( kactionmenu_map["subsection"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goSubsection( int ) ) ); + kactionmenu_map["subsection"]->setWhatsThis( i18n("<p>This menu references the subsections of the document.</p>") ); + kactionmenu_map["subsection"]->setDelayed(false); + + kactionmenu_map["appendix"] = new KActionMenu( i18n("Appendix"), "edit", actionCollection(), "rellinks_appendix" ); + m_document->insert(kactionmenu_map["appendix"]); + connect( kactionmenu_map["appendix"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goAppendix( int ) ) ); + kactionmenu_map["appendix"]->setWhatsThis( i18n("<p>This link references the appendix.</p>") ); + kactionmenu_map["appendix"]->setDelayed(false); + + kaction_map["glossary"] = new KAction( i18n("&Glossary"), "flag", KShortcut("Ctrl+Alt+G"), this, SLOT(goGlossary()), actionCollection(), "rellinks_glossary" ); + m_document->insert(kaction_map["glossary"]); + kaction_map["glossary"]->setWhatsThis( i18n("<p>This link references the glossary.</p>") ); + + kaction_map["index"] = new KAction( i18n("&Index"), "info", KShortcut("Ctrl+Alt+I"), this, SLOT(goIndex()), actionCollection(), "rellinks_index" ); + m_document->insert(kaction_map["index"]); + kaction_map["index"]->setWhatsThis( i18n("<p>This link references the index.</p>") ); + + // Other links + m_more = new KActionMenu( i18n("More"), "misc", actionCollection(), "rellinks_more" ); + m_more->setWhatsThis( i18n("<p>This menu contains other important links.</p>") ); + m_more->setDelayed(false); + + kaction_map["help"] = new KAction( i18n("&Help"), "help", KShortcut("Ctrl+Alt+H"), this, SLOT(goHelp()), actionCollection(), "rellinks_help" ); + m_more->insert(kaction_map["help"]); + kaction_map["help"]->setWhatsThis( i18n("<p>This link references the help.</p>") ); + + kaction_map["author"] = new KAction( i18n("&Authors"), "mail_new", KShortcut("Ctrl+Alt+A"), this, SLOT(goAuthor()), actionCollection(), "rellinks_authors" ); + m_more->insert(kaction_map["author"]); + kaction_map["author"]->setWhatsThis( i18n("<p>This link references the author.</p>") ); + + kaction_map["copyright"] = new KAction( i18n("Copy&right"), "signature", KShortcut("Ctrl+Alt+R"), this, SLOT(goCopyright()), actionCollection(), "rellinks_copyright" ); + m_more->insert(kaction_map["copyright"]); + kaction_map["copyright"]->setWhatsThis( i18n("<p>This link references the copyright.</p>") ); + + kactionmenu_map["bookmark"] = new KActionMenu( i18n("Bookmarks"), "bookmark_folder", actionCollection(), "rellinks_bookmarks" ); + m_more->insert(kactionmenu_map["bookmark"]); + kactionmenu_map["bookmark"]->setWhatsThis( i18n("<p>This menu references the bookmarks.</p>") ); + connect( kactionmenu_map["bookmark"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goBookmark( int ) ) ); + kactionmenu_map["bookmark"]->setDelayed(false); + + kactionmenu_map["alternate"] = new KActionMenu( i18n("Other Versions"), "attach", actionCollection(), "rellinks_other_versions" ); + m_more->insert(kactionmenu_map["alternate"]); + kactionmenu_map["alternate"]->setWhatsThis( i18n("<p>This link references the alternate versions of this document.</p>") ); + connect( kactionmenu_map["alternate"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goAlternate( int ) ) ); + kactionmenu_map["alternate"]->setDelayed(false); + + // Unclassified menu + m_links = new KActionMenu( i18n("Miscellaneous"), "rellinks", actionCollection(), "rellinks_links" ); + kactionmenu_map["unclassified"] = m_links; + kactionmenu_map["unclassified"]->setWhatsThis( i18n("<p>Miscellaneous links.</p>") ); + connect( kactionmenu_map["unclassified"]->popupMenu(), SIGNAL( activated( int ) ), this, SLOT( goAllElements( int ) ) ); + kactionmenu_map["unclassified"]->setDelayed(false); + + // We unactivate all the possible actions + disableAll(); + + // When the rendering of the HTML is done, we update the site navigation bar + m_part = dynamic_cast<KHTMLPart *>(parent); + if (!m_part) + return; + + connect( m_part, SIGNAL( docCreated() ), this, SLOT( newDocument() ) ); + connect( m_part, SIGNAL( completed() ), this, SLOT( loadingFinished() ) ); + + // create polling timer and connect it + m_pollTimer = new QTimer(this, "polling timer"); + connect( m_pollTimer, SIGNAL( timeout() ), this, SLOT( updateToolbar() ) ); + + // delay access to our part's members until it has finished its initialisation + QTimer::singleShot(0, this, SLOT(delayedSetup())); +} + +/** Destructor */ +RelLinksPlugin::~RelLinksPlugin() { +} + +bool RelLinksPlugin::eventFilter(QObject *watched, QEvent* event) { + if (m_part == 0) return false; + + if (watched == 0 || event == 0) return false; + + if (watched == m_view) + { + switch (event->type()) + { + case QEvent::Show: + m_viewVisible = true; + updateToolbar(); + break; + + case QEvent::Hide: + m_viewVisible = false; + updateToolbar(); + break; + + case QEvent::Close: + m_pollTimer->stop(); + m_view->removeEventFilter(this); + break; + + default: + break; + } + } + + // we never filter an event, we just want to know about it + return false; +} + +void RelLinksPlugin::delayedSetup() +{ + if (m_part == 0) return; + + m_view = m_part->view(); + m_view->installEventFilter(this); + m_viewVisible = m_view->isVisible(); +} + +void RelLinksPlugin::newDocument() { + // start calling upateToolbar periodically to get the new links as soon as possible + + m_pollTimer->start(500); + //kdDebug(90210) << "newDocument()" << endl; + + updateToolbar(); +} + +void RelLinksPlugin::loadingFinished() { + m_pollTimer->stop(); + //kdDebug(90210) << "loadingFinished()" << endl; + updateToolbar(); + guessRelations(); +} + +/* Update the site navigation bar */ +void RelLinksPlugin::updateToolbar() { + + // If we have a part + if (!m_part) + return; + + // We disable all + disableAll(); + + // get a list of LINK nodes in document + DOM::NodeList linkNodes = m_part->document().getElementsByTagName( "link" ); + + //kdDebug(90210) << "Rellinks: Link nodes =" << linkNodes.length() << endl; + + bool showBar = false; + unsigned long nodeLength = linkNodes.length(); + + for ( unsigned int i=0; i < nodeLength; i++ ) { + // create a entry for each one + DOM::Element e( linkNodes.item( i ) ); + + + // --- Retrieve of the relation type -- + + QString rel = e.getAttribute( "rel" ).string(); + rel = rel.simplifyWhiteSpace(); + if (rel.isEmpty()) { + // If the "rel" attribut is null then use the "rev" attribute... + QString rev = e.getAttribute( "rev" ).string(); + rev = rev.simplifyWhiteSpace(); + if (rev.isEmpty()) { + // if "rev" attribut is also empty => ignore + continue; + } + // Determine the "rel" equivalent of "rev" type + rel = transformRevToRel(rev); + } + // Determin the name used internally + QString lrel = getLinkType(rel.lower()); + // relation to ignore + if (lrel.isEmpty()) continue; +// kdDebug() << "lrel=" << lrel << endl; + + // -- Retrieve of other usefull informations -- + + QString href = e.getAttribute( "href" ).string(); + // if nowhere to go, ignore the link + if (href.isEmpty()) continue; + QString title = e.getAttribute( "title" ).string(); + QString hreflang = e.getAttribute( "hreflang" ).string(); + + KURL ref( m_part->url(), href ); + if ( title.isEmpty() ) + title = ref.prettyURL(); + + // escape ampersand before settings as action title, otherwise the menu entry will interpret it as an + // accelerator + title.replace('&', "&&"); + + // -- Menus activation -- + + // Activation of "Document" menu ? + if (lrel == "contents" || lrel == "glossary" || lrel == "index" || lrel == "appendix") { + m_document->setEnabled(true); + } + // Activation of "More" menu ? + if (lrel == "help" || lrel == "author" || lrel == "copyright" ) { + m_more->setEnabled(true); + } + + // -- Buttons or menu items activation / creation -- + if (lrel == "bookmark" || lrel == "alternate") { + int id = kactionmenu_map[lrel]->popupMenu()->insertItem( title ); + m_more->setEnabled(true); + kactionmenu_map[lrel]->setEnabled(true); + element_map[lrel][id] = e; + + } else if (lrel == "appendix" || lrel == "chapter" || lrel == "section" || lrel == "subsection") { + int id = kactionmenu_map[lrel]->popupMenu()->insertItem( title ); + m_document->setEnabled(true); + kactionmenu_map[lrel]->setEnabled(true); + element_map[lrel][id] = e; + + } else { + // It is a unique action + element_map[lrel][0] = e; + if (kaction_map[lrel]) { + kaction_map[lrel]->setEnabled(true); + // Tooltip + if (hreflang.isEmpty()) { + kaction_map[lrel]->setToolTip( title ); + } else { + kaction_map[lrel]->setToolTip( title + " [" + hreflang + "]"); + } + } else { + // For the moment all the elements are reference in a separated menu + // TODO : reference the unknown ? + int id = kactionmenu_map["unclassified"]->popupMenu()->insertItem( lrel + " : " + title ); + kactionmenu_map["unclassified"]->setEnabled(true); + element_map["unclassified"][id] = e; + } + + } + + showBar = true; + } +} + + +void RelLinksPlugin::guessRelations() +{ + m_part = dynamic_cast<KHTMLPart *>(parent()); + if (!m_part || m_part->document().isNull() ) + return; + + //If the page already contains some link, that mean the webmaster is aware + //of the meaning of <link> so we can consider that if prev/next was possible + //they are already there. + if(!element_map.isEmpty()) + return; + + // - The number of didgit may not be more of 3, or this is certenly an id. + // - We make sure that the number is followed by a dot, a &, or the end, we + // don't want to match stuff like that: page.html?id=A14E12FD + // - We make also sure the number is not preceded dirrectly by others number + QRegExp rx("^(.*[=/?&][^=/?&.\\-0-9]*)([\\d]{1,3})([.&][^/0-9]{0,15})?$"); + + + const QString zeros("0000"); + QString url=m_part->url().url(); + if(rx.search(url)!=-1) + { + uint val=rx.cap(2).toUInt(); + uint lenval=rx.cap(2).length(); + QString nval_str=QString::number(val+1); + //prepend by zeros if the original also contains zeros. + if(nval_str.length() < lenval && rx.cap(2)[0]=='0') + nval_str.prepend(zeros.left(lenval-nval_str.length())); + + QString href=rx.cap(1)+ nval_str + rx.cap(3); + KURL ref( m_part->url(), href ); + QString title = i18n("[Autodetected] %1").arg(ref.prettyURL()); + DOM::Element e= m_part->document().createElement("link"); + e.setAttribute("href",href); + element_map["next"][0] = e; + kaction_map["next"]->setEnabled(true); + kaction_map["next"]->setToolTip( title ); + + if(val>1) + { + nval_str=QString::number(val-1); + if(nval_str.length() < lenval && rx.cap(2)[0]=='0') + nval_str.prepend(zeros.left(lenval-nval_str.length())); + QString href=rx.cap(1)+ nval_str + rx.cap(3); + KURL ref( m_part->url(), href ); + QString title = i18n("[Autodetected] %1").arg(ref.prettyURL()); + e= m_part->document().createElement("link"); + e.setAttribute("href",href); + element_map["prev"][0] = e; + kaction_map["prev"]->setEnabled(true); + kaction_map["prev"]->setToolTip( title ); + } + } +} + + +/** Menu links */ +void RelLinksPlugin::goToLink(const QString & rel, int id) { + // have the KHTML part open it + KHTMLPart *part = dynamic_cast<KHTMLPart *>(parent()); + if (!part) + return; + + DOM::Element e = element_map[rel][id]; + QString href = e.getAttribute("href").string(); + KURL url( part->url(), href ); + QString target = e.getAttribute("target").string(); + + // URL arguments + KParts::URLArgs args; + args.frameName = target; + + // Add base url if not valid + if (url.isValid()) { + part->browserExtension()->openURLRequest(url, args); + } else { + KURL baseURL = part->baseURL(); + QString endURL = url.prettyURL(); + KURL realURL = KURL(baseURL, endURL); + part->browserExtension()->openURLRequest(realURL, args); + } + +} + +void RelLinksPlugin::goHome() { + goToLink("home"); +} + +void RelLinksPlugin::goUp() { + goToLink("up"); +} + +void RelLinksPlugin::goFirst() { + goToLink("begin"); +} + +void RelLinksPlugin::goPrevious() { + goToLink("prev"); +} + +void RelLinksPlugin::goNext() { + goToLink("next"); +} + +void RelLinksPlugin::goLast() { + goToLink("last"); +} + +void RelLinksPlugin::goContents() { + goToLink("contents"); +} + +void RelLinksPlugin::goIndex() { + goToLink("index"); +} + +void RelLinksPlugin::goGlossary() { + goToLink("glossary"); +} + +void RelLinksPlugin::goHelp() { + goToLink("help"); +} + +void RelLinksPlugin::goSearch() { + goToLink("search"); +} + +void RelLinksPlugin::goAuthor() { + goToLink("author"); +} + + +void RelLinksPlugin::goCopyright() { + goToLink("copyright"); +} + +void RelLinksPlugin::goBookmark(int id) { + goToLink("bookmark", id); +} + +void RelLinksPlugin::goChapter(int id) { + goToLink("chapter", id); +} + +void RelLinksPlugin::goSection(int id) { + goToLink("section", id); +} + +void RelLinksPlugin::goSubsection(int id) { + goToLink("subsection", id); +} + +void RelLinksPlugin::goAppendix(int id) { + goToLink("appendix", id); +} + +void RelLinksPlugin::goAlternate(int id) { + goToLink("alternate", id); +} + +void RelLinksPlugin::goAllElements(int id) { + goToLink("unclassified", id); +} + +void RelLinksPlugin::disableAll() { + element_map.clear(); + + // Clear actions + KActionMap::Iterator it; + for ( it = kaction_map.begin(); it != kaction_map.end(); ++it ) { + // If I don't test it crash :( + if (it.data()) { + it.data()->setEnabled(false); + it.data()->setToolTip(it.data()->text().remove('&')); + } + } + + // Clear actions + KActionMenuMap::Iterator itmenu; + for ( itmenu = kactionmenu_map.begin(); itmenu != kactionmenu_map.end(); ++itmenu ) { + // If I don't test it crash :( + if (itmenu.data()) { + itmenu.data()->popupMenu()->clear(); + itmenu.data()->setEnabled(false); + itmenu.data()->setToolTip(itmenu.data()->text().remove('&')); + } + } + + // Unactivate menus + m_more->setEnabled(false); + m_document->setEnabled(false); + +} + + +QString RelLinksPlugin::getLinkType(const QString &lrel) { + // Relations to ignore... + if (lrel.contains("stylesheet") + || lrel == "script" + || lrel == "icon" + || lrel == "shortcut icon" + || lrel == "prefetch" ) + return QString::null; + + // ...known relations... + if (lrel == "top" || lrel == "origin" || lrel == "start") + return "home"; + if (lrel == "parent") + return "up"; + if (lrel == "first") + return "begin"; + if (lrel == "previous") + return "prev"; + if (lrel == "child") + return "next"; + if (lrel == "end") + return "last"; + if (lrel == "toc") + return "contents"; + if (lrel == "find") + return "search"; + if (lrel == "alternative stylesheet") + return "alternate stylesheet"; + if (lrel == "authors") + return "author"; + if (lrel == "toc") + return "contents"; + + //...unknown relations or name that don't need to change + return lrel; +} + +QString RelLinksPlugin::transformRevToRel(const QString &rev) { + QString altRev = getLinkType(rev); + + // Known relations + if (altRev == "prev") + return getLinkType("next"); + if (altRev == "next") + return getLinkType("prev"); + if (altRev == "made") + return getLinkType("author"); + if (altRev == "up") + return getLinkType("child"); + if (altRev == "sibling") + return getLinkType("sibling"); + + //...unknown inverse relation => ignore for the moment + return QString::null; +} + +#include "plugin_rellinks.moc" diff --git a/konq-plugins/rellinks/plugin_rellinks.desktop b/konq-plugins/rellinks/plugin_rellinks.desktop new file mode 100644 index 0000000..fba32e5 --- /dev/null +++ b/konq-plugins/rellinks/plugin_rellinks.desktop @@ -0,0 +1,120 @@ +[Desktop Entry] +X-KDE-Library=rellinks +X-KDE-PluginInfo-Author=Anders Lund, Franck Quélain, Kevin Krammer, Olivier Goffart +X-KDE-PluginInfo-Email=anders@alweb.dk, shift@free.fr, kevin.krammer@gmx.at, ogoffart@kde.org +X-KDE-PluginInfo-Name=rellinks +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +## TODO +##Icon=rellinks +Name=Document Relations Plugin +Name[bg]=Приставка за връзки между документите +Name[ca]=Connector de relacions entre documents +Name[cs]=Modul vztahů v dokumentu +Name[da]=Dokmentrelationer-plugin +Name[de]=Dokumentbeziehungs-Modul +Name[el]=Πρόσθετο συσχετίσεων εγγράφου +Name[eo]=Dokumenta rilata kromaĵo +Name[es]=Complemento de relaciones de documentos +Name[et]=Dokumendi seoste plugin +Name[eu]=Dokumentuen harreman plugina +Name[fa]=وصلۀ روابط سند +Name[fi]=Asiakirjojen suhteet sovelma +Name[fr]=Module de relations entre documents +Name[fy]=Dokumint Relaasjes plugin +Name[gl]=Plugin de Relacións de Documento +Name[he]=תוסף יחסי מסמך +Name[hi]=दस्तावेज़ सम्बन्ध प्लग-इन +Name[hr]=Dodatak za relacije dokumenata +Name[hu]=Dokumentumkapcsolatok modul +Name[is]=Skjalatengsla íforrit +Name[it]=Relazioni tra documenti +Name[ja]=ドキュメント関係プラグイン +Name[ka]=დოკუმენტის კავშირთა მოდული +Name[kk]=Құжаттың қатынастар плагин модулі +Name[km]=កម្មវិធីជំនួយទំនាក់ទំនងឯកសារ +Name[lt]=Dokumentų sąsajų priedas +Name[mk]=Приклучок за релации во документ +Name[ms]=Plugin Kehubungan Dokumen +Name[nb]=Programtillegg for dokumentrelasjoner +Name[nds]=Dokmentbetöög-Moduul +Name[ne]=कागजात सम्बन्धी प्लगइन +Name[nl]=Documentrelatiesplugin +Name[nn]=Programtillegg for dokumentrelasjonar +Name[pa]=ਦਸਤਾਵੇਜ਼ ਸਬੰਧ ਪਲੱਗਇਨ +Name[pl]=Wtyczka zależności w dokumencie +Name[pt]='Plugin' de Relações de Documento +Name[pt_BR]=Plug-in de Relações em Documentos +Name[ru]=Модуль связей документов +Name[sk]=Modul súvislosti dokumentov +Name[sl]=Vstavek povezav dokumenta +Name[sr]=Прикључак за односе међу документима +Name[sr@Latn]=Priključak za odnose među dokumentima +Name[sv]=Insticksprogram för dokumentförhållande +Name[ta]=ஆவண சம்பந்தப்பட்ட சொருகுப்பொருள் +Name[tg]=Модули санади робитаҳо +Name[tr]=Dosya İlişkileri Eklentisi +Name[uk]=Втулок зв'язку між документами +Name[uz]=Hujjatlar orasidagi bogʻliqlik plagini +Name[uz@cyrillic]=Ҳужжатлар орасидаги боғлиқлик плагини +Name[vi]=Bổ sung quan hệ tài liệu +Name[zh_CN]=文档关系插件 +Name[zh_TW]=文件關係外掛程式 +Comment=Document Relations plugin +Comment[bg]=Приставка за връзки между документите +Comment[ca]=Connector de relacions entre documents +Comment[cs]=Modul vztahů v dokumentu +Comment[da]=Dokumentrelationer-plugin +Comment[de]=Dokumentbeziehungs-Modul +Comment[el]=Πρόσθετο συσχετίσεων εγγράφου +Comment[eo]=Dokumenta rilata kromaĵo +Comment[es]=Complemento de relaciones de documentos +Comment[et]=Dokumendi seoste plugin +Comment[eu]=Dokumentuen harreman plugina +Comment[fa]=وصلۀ روابط سند +Comment[fi]=Asiakirjojen suhteet sovelma +Comment[fr]=Module de relations entre documents +Comment[fy]=Dokumint Relaasjes plugin +Comment[gl]=Plugin de relacións do documento +Comment[he]=תוסף יחסי מסמך +Comment[hi]=दस्तावेज़ सम्बन्ध प्लग-इन +Comment[hr]=Dodatak za relacije dokumenata +Comment[hu]=Dokumentumkapcsolatok bővítőmodul +Comment[is]=Skjalatengsla íforrit +Comment[it]=Plugin per gestire le relazioni tra documenti +Comment[ja]=ドキュメント関係プラグイン +Comment[ka]=დოკუმენტის კავშირთა მოდული +Comment[kk]=Құжаттың қатынастар плагин модулі +Comment[km]=កម្មវិធីជំនួយទំនាក់ទំនងឯកសារ +Comment[lt]=Dokumentų sąsajų priedas +Comment[mk]=Приклучок за релации во документ +Comment[ms]=Plugin Kehubungan Dokumen +Comment[nb]=Programtillegg for dokumentrelasjoner +Comment[nds]=Dokmentbetöög-Moduul +Comment[ne]=कागजात सम्बन्धी प्लगइन +Comment[nl]=Documentrelatiesplugin +Comment[nn]=Programtillegg for dokumentrelasjonar +Comment[pa]=ਦਸਤਾਵੇਜ਼ ਸਬੰਧ ਪਲੱਗਇਨ +Comment[pl]=Wtyczka zależności w dokumencie +Comment[pt]='Plugin' de relações de documento +Comment[pt_BR]=Plug-in para Relacionamentos entre Documentos +Comment[ru]=Модуль связей документов +Comment[sk]=Modul súvislosti dokumentov +Comment[sl]=Vstavek povezav dokumenta +Comment[sr]=Прикључак за односе међу документима +Comment[sr@Latn]=Priključak za odnose među dokumentima +Comment[sv]=Insticksprogram för dokumentförhållande +Comment[ta]= =ஆவண சம்பந்தப்பட்ட சொருகுப்பொருள் +Comment[tg]=Модули санади робитаҳо +Comment[tr]=Dosya İlişkileri Eklentisi +Comment[uk]=Втулок зв'язку між документами +Comment[uz]=Hujjatlar orasidagi bogʻliqlik plagini +Comment[uz@cyrillic]=Ҳужжатлар орасидаги боғлиқлик плагини +Comment[vi]=Bổ sung quan hệ tài liệu +Comment[zh_CN]=文档关系插件 +Comment[zh_TW]=文件關係外掛程式 +X-KDE-ParentApp=konqueror diff --git a/konq-plugins/rellinks/plugin_rellinks.h b/konq-plugins/rellinks/plugin_rellinks.h new file mode 100644 index 0000000..63260ce --- /dev/null +++ b/konq-plugins/rellinks/plugin_rellinks.h @@ -0,0 +1,170 @@ +/*************************************************************************** + * Copyright (C) 2002, Anders Lund <anders@alweb.dk> * + * Copyright (C) 2003, 2004, Franck Qulain <shift@free.fr> * + * Copyright (C) 2004, Kevin Krammer <kevin.krammer@gmx.at> * + * Copyright (C) 2004, 2005, Oliviet Goffart <ogoffart @ kde.org> * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***************************************************************************/ + + +#ifndef _PLUGIN_RELLINKS_H_ +#define _PLUGIN_RELLINKS_H_ + +/* + This plugin queries the current HTML document for LINK elements. + + This plugin create a toolbar similar to the Site Navigation Bar of Mozilla +*/ + +// Qt includes +#include <qmap.h> + +// KDE includes +#include <kparts/plugin.h> +#include <dom/dom_string.h> + +// type definitions +typedef QMap<int,DOM::Element> DOMElementMap; +typedef QMap<QString, KAction*> KActionMap; +typedef QMap<QString, KActionMenu*> KActionMenuMap; + +// forward declarations +class KActionMenu; +class KHTMLPart; +class KHTMLView; +class KToolBar; +class KURL; +class QTimer; + +/** + * KPart plugin adding document relations toolbar to Konqueror + * @author Franck Qulain + * @author Anders Lund + */ +class RelLinksPlugin : public KParts::Plugin { + Q_OBJECT +public: + /** Constructor */ + RelLinksPlugin( QObject *parent, const char *name, const QStringList & ); + /** Destructor */ + virtual ~RelLinksPlugin(); + + bool eventFilter(QObject *watched, QEvent* event); + +private slots: + void delayedSetup(); + + /** + * KHTMLPart has created a new document, disable actions and + * start polling for links + */ + void newDocument(); + + /** + * KHTMLPart has finished loading, stop the poller and + * parse the document a last time. + */ + void loadingFinished(); + + /** + * Update the toolbar (Parse the document again) + */ + void updateToolbar(); + + + void goHome(); + void goUp(); + void goFirst(); + void goPrevious(); + void goNext(); + void goLast(); + void goContents(); + void goIndex(); + void goGlossary(); + void goHelp(); + void goSearch(); + void goCopyright(); + void goAuthor(); + + void goBookmark(int id); + void goChapter(int id); + void goSection(int id); + void goSubsection(int id); + void goAppendix(int id); + void goAlternate(int id); + void goAllElements(int id); + +private: + + /** + * Try to guess some relations from the url, if the document doesn't contains relations + * example: http://example.com/page4.html + * the "next" relation will be set to page5.html + */ + void guessRelations(); + + /** + * Function used to get link type of a relation. + * For example "prev" is of type "previous" and "toc" is of type "contents" + * If the relation must be ignored return NULL. + * If the relation is unknow return the input relation type. + * @param lrel Previous relation name + * @return New relation name + */ + QString getLinkType(const QString &lrel); + + /** + * Function used to return the "rel" equivalent of "rev" link type + * If the equivalent is not found return NULL + * @param rev Inverse relation name + * @return Equivalent relation name + */ + QString transformRevToRel(const QString &rev) ; + + /** + * Function used to disable all the item of the toolbar + */ + void disableAll(); + + /** + * Go to the link + * @param rel Relation name + * @param id Identifier of the menu item + */ + void goToLink(const QString & rel, int id=0); + +private: + KHTMLPart* m_part; + KHTMLView* m_view; + bool m_viewVisible; + + KActionMenu *m_document; + KActionMenu *m_more; + KActionMenu *m_links; + + /** Map of KAction */ + KActionMap kaction_map; + /** Map of KActionMenu */ + KActionMenuMap kactionmenu_map; + + /** Map of all the link element which can be managed by rellinks */ + QMap<QString,DOMElementMap> element_map; + + QTimer* m_pollTimer; +}; + +#endif // _PLUGIN_RELLINKS_H_ diff --git a/konq-plugins/rellinks/plugin_rellinks.rc b/konq-plugins/rellinks/plugin_rellinks.rc new file mode 100644 index 0000000..3c5dbcc --- /dev/null +++ b/konq-plugins/rellinks/plugin_rellinks.rc @@ -0,0 +1,38 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="rellinks" library="librellinksplugin" version="3"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Menu name="rellinksMenu"><Text>Document Relations</Text> + <Action name="rellinks_top"/> + <Action name="rellinks_up"/> + <Action name="rellinks_first"/> + <Action name="rellinks_previous"/> + <Action name="rellinks_next"/> + <Action name="rellinks_last"/> + <Action name="rellinks_search"/> + <Action name="rellinks_document"/> + <Action name="rellinks_more"/> + <Action name="rellinks_links"/> + </Menu> + </Menu> +</MenuBar> + + +<ToolBar name="rellinksToolBar" hidden="true"><Text>Document Relations</Text> + <Action name="rellinks_top"/> + <Action name="rellinks_up"/> + <Action name="rellinks_first"/> + <Action name="rellinks_previous"/> + <Action name="rellinks_next"/> + <Action name="rellinks_last"/> + <Action name="rellinks_search"/> + <Separator /> + <Action name="rellinks_document"/> + <Separator /> + <Action name="rellinks_more"/> + <Separator /> + <Action name="rellinks_links"/> +</ToolBar> + + +</kpartplugin> diff --git a/konq-plugins/rellinks/rellinks.kdevelop b/konq-plugins/rellinks/rellinks.kdevelop new file mode 100644 index 0000000..5496bfc --- /dev/null +++ b/konq-plugins/rellinks/rellinks.kdevelop @@ -0,0 +1,157 @@ +<?xml version = '1.0'?> +<kdevelop> + <general> + <author>Franck Quélain</author> + <email>shift@free.fr</email> + <version>0.3</version> + <projectmanagement>KDevKDEAutoProject</projectmanagement> + <primarylanguage>C++</primarylanguage> + <keywords> + <keyword>C++</keyword> + <keyword>Code</keyword> + <keyword>Qt</keyword> + <keyword>KDE</keyword> + </keywords> + <projectdirectory>../..</projectdirectory> + <absoluteprojectpath>false</absoluteprojectpath> + <description/> + <ignoreparts/> + <secondaryLanguages/> + </general> + <kdevautoproject> + <general> + <activetarget>konq_plugins/rellinks/librellinksplugin.la</activetarget> + <useconfiguration>debug</useconfiguration> + </general> + <configurations> + <optimized> + <builddir>optimized</builddir> + <ccompiler>GccOptions</ccompiler> + <cxxcompiler>GppOptions</cxxcompiler> + <f77compiler>G77Options</f77compiler> + <cxxflags>-O2 -g0</cxxflags> + </optimized> + <debug> + <configargs>--enable-debug=full --prefix=/usr/local/kde</configargs> + <builddir>debug</builddir> + <ccompiler>kdevgccoptions</ccompiler> + <cxxcompiler>kdevgppoptions</cxxcompiler> + <f77compiler>kdevg77options</f77compiler> + <cxxflags>-O0 -g3</cxxflags> + <topsourcedir/> + <cppflags/> + <ldflags/> + <ccompilerbinary/> + <cxxcompilerbinary/> + <f77compilerbinary/> + <cflags/> + <f77flags/> + </debug> + </configurations> + <make> + <envvars> + <envvar value="1" name="WANT_AUTOCONF_2_5" /> + <envvar value="1" name="WANT_AUTOMAKE_1_6" /> + </envvars> + <abortonerror>false</abortonerror> + <numberofjobs>1</numberofjobs> + <dontact>false</dontact> + <makebin/> + </make> + <run> + <directoryradio>executable</directoryradio> + <customdirectory>/</customdirectory> + <mainprogram/> + <programargs/> + <terminal>false</terminal> + <autocompile>true</autocompile> + <envvars/> + </run> + </kdevautoproject> + <kdevfileview> + <groups> + <group pattern="*.cpp;*.cxx;*.h" name="Sources" /> + <group pattern="*.ui" name="User Interface" /> + <group pattern="*.png" name="Icons" /> + <group pattern="*.po;*.ts" name="Translations" /> + <group pattern="*" name="Others" /> + <hidenonprojectfiles>false</hidenonprojectfiles> + <hidenonlocation>false</hidenonlocation> + </groups> + <tree> + <hidepatterns>*.o,*.lo,CVS</hidepatterns> + <hidenonprojectfiles>false</hidenonprojectfiles> + <showvcsfields>false</showvcsfields> + </tree> + </kdevfileview> + <kdevdoctreeview> + <ignoretocs> + <toc>gtk</toc> + <toc>gnustep</toc> + <toc>python</toc> + <toc>php</toc> + <toc>perl</toc> + </ignoretocs> + <projectdoc> + <userdocDir>html/</userdocDir> + <apidocDir>html/</apidocDir> + </projectdoc> + <ignoreqt_xml/> + <ignoredoxygen/> + <ignorekdocs/> + <ignoredevhelp/> + </kdevdoctreeview> + <kdevdebugger> + <general> + <dbgshell>libtool</dbgshell> + <programargs/> + <gdbpath/> + <configGdbScript/> + <runShellScript/> + <runGdbScript/> + <breakonloadinglibs>true</breakonloadinglibs> + <separatetty>false</separatetty> + <floatingtoolbar>false</floatingtoolbar> + </general> + <display> + <staticmembers>false</staticmembers> + <demanglenames>true</demanglenames> + </display> + </kdevdebugger> + <kdevfilecreate> + <filetypes/> + <useglobaltypes> + <type ext="ui" /> + <type ext="cpp" /> + <type ext="h" /> + </useglobaltypes> + </kdevfilecreate> + <kdevcppsupport> + <references/> + <codecompletion> + <includeGlobalFunctions>true</includeGlobalFunctions> + <includeTypes>true</includeTypes> + <includeEnums>true</includeEnums> + <includeTypedefs>false</includeTypedefs> + <automaticCodeCompletion>true</automaticCodeCompletion> + <automaticArgumentsHint>true</automaticArgumentsHint> + <automaticHeaderCompletion>true</automaticHeaderCompletion> + <codeCompletionDelay>250</codeCompletionDelay> + <argumentsHintDelay>400</argumentsHintDelay> + <headerCompletionDelay>250</headerCompletionDelay> + </codecompletion> + </kdevcppsupport> + <cppsupportpart> + <filetemplates> + <interfacesuffix>.h</interfacesuffix> + <implementationsuffix>.cpp</implementationsuffix> + </filetemplates> + </cppsupportpart> + <kdevcvsservice> + <recursivewhenupdate>true</recursivewhenupdate> + <prunedirswhenupdate>true</prunedirswhenupdate> + <createdirswhenupdate>true</createdirswhenupdate> + <recursivewhencommitremove>true</recursivewhencommitremove> + <revertoptions>-C</revertoptions> + </kdevcvsservice> +</kdevelop> diff --git a/konq-plugins/rellinks/rellinks.lsm b/konq-plugins/rellinks/rellinks.lsm new file mode 100644 index 0000000..df11ae6 --- /dev/null +++ b/konq-plugins/rellinks/rellinks.lsm @@ -0,0 +1,16 @@ +Begin3 +Title: RelLinks -- Some description +Version: 0.3 +Entered-date: +Description: +Keywords: KDE Qt +Author: Franck Quélain <shift@free.fr> +Maintained-by: Franck Quélain <shift@free.fr> +Home-page: +Alternate-site: +Primary-site: ftp://ftp.kde.org/pub/kde/unstable/apps/utils + xxxxxx rellinks-0.3.tar.gz + xxx rellinks-0.3.lsm +Platform: Linux. Needs KDE +Copying-policy: GPL +End diff --git a/konq-plugins/searchbar/Makefile.am b/konq-plugins/searchbar/Makefile.am new file mode 100644 index 0000000..3a4c1b5 --- /dev/null +++ b/konq-plugins/searchbar/Makefile.am @@ -0,0 +1,21 @@ +SUBDIRS = icons + +INCLUDES = $(all_includes) + +kde_module_LTLIBRARIES = libsearchbarplugin.la + +libsearchbarplugin_la_SOURCES = searchbar.cpp +libsearchbarplugin_la_LIBADD = $(LIB_KHTML) +libsearchbarplugin_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +pluginsdir = $(kde_datadir)/konqueror/kpartplugins +plugins_DATA = searchbar.rc searchbar.desktop + +install-data-local: $(srcdir)/../uninstall.desktop + $(mkinstalldirs) $(DESTDIR)$(pluginsdir) + $(INSTALL_DATA) $(srcdir)/../uninstall.desktop $(DESTDIR)$(pluginsdir)/searchbarplugin.desktop + +METASOURCES = AUTO + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/searchbarplugin.pot diff --git a/konq-plugins/searchbar/icons/Makefile.am b/konq-plugins/searchbar/icons/Makefile.am new file mode 100644 index 0000000..131e26a --- /dev/null +++ b/konq-plugins/searchbar/icons/Makefile.am @@ -0,0 +1,3 @@ +searchbariconsdir = $(kde_datadir)/konqueror/icons +searchbaricons_ICON = AUTO + diff --git a/konq-plugins/searchbar/icons/cr16-action-google.png b/konq-plugins/searchbar/icons/cr16-action-google.png Binary files differnew file mode 100644 index 0000000..03ae14a --- /dev/null +++ b/konq-plugins/searchbar/icons/cr16-action-google.png diff --git a/konq-plugins/searchbar/searchbar.cpp b/konq-plugins/searchbar/searchbar.cpp new file mode 100644 index 0000000..51f5455 --- /dev/null +++ b/konq-plugins/searchbar/searchbar.cpp @@ -0,0 +1,556 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Arend van Beelen jr. <arend@auton.nl> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <unistd.h> + +#include <dcopclient.h> +#include <kapplication.h> +#include <kaction.h> +#include <kconfig.h> +#include <kdebug.h> +#include <kdesktopfile.h> +#include <kgenericfactory.h> +#include <kglobal.h> +#include <khtml_part.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kmimetype.h> +#include <kprocess.h> +#include <kprotocolmanager.h> +#include <kstandarddirs.h> +#include <kurifilter.h> + +#include <kparts/mainwindow.h> +#include <kparts/partmanager.h> + +#include <qpainter.h> +#include <qpopupmenu.h> +#include <qtimer.h> +#include <qstyle.h> +#include <qwhatsthis.h> +#include "searchbar.h" + +typedef KGenericFactory<SearchBarPlugin> SearchBarPluginFactory; +K_EXPORT_COMPONENT_FACTORY(libsearchbarplugin, + SearchBarPluginFactory("searchbarplugin")) + + +SearchBarPlugin::SearchBarPlugin(QObject *parent, const char *name, + const QStringList &) : + KParts::Plugin(parent, name), + m_searchCombo(0), + m_searchMode(UseSearchProvider), + m_urlEnterLock(false) +{ + m_searchCombo = new SearchBarCombo(0L, "search combo"); + m_searchCombo->setDuplicatesEnabled(false); + m_searchCombo->setMaxCount(5); + m_searchCombo->setFixedWidth(180); + m_searchCombo->setLineEdit(new KLineEdit(m_searchCombo)); + m_searchCombo->lineEdit()->installEventFilter(this); + + m_popupMenu = 0; + + m_searchComboAction = new KWidgetAction(m_searchCombo, i18n("Search Bar"), 0, + 0, 0, actionCollection(), "toolbar_search_bar"); + m_searchComboAction->setShortcutConfigurable(false); + + connect(m_searchCombo, SIGNAL(activated(const QString &)), + SLOT(startSearch(const QString &))); + connect(m_searchCombo, SIGNAL(iconClicked()), SLOT(showSelectionMenu())); + + QWhatsThis::add(m_searchCombo, i18n("Search Bar<p>" + "Enter a search term. Click on the icon to change search mode or provider.")); + + new KAction( i18n( "Focus Searchbar" ), CTRL+Key_S, + this, SLOT(focusSearchbar()), + actionCollection(), "focus_search_bar"); + + configurationChanged(); + + KParts::MainWindow *mainWin = static_cast<KParts::MainWindow*>(parent); + + //Grab the part manager. Don't know of any other way, and neither does Tronical, so.. + KParts::PartManager *partMan = static_cast<KParts::PartManager*>(mainWin->child(0, "KParts::PartManager")); + if (partMan) + { + connect(partMan, SIGNAL(activePartChanged(KParts::Part*)), + SLOT (partChanged (KParts::Part*))); + partChanged(partMan->activePart()); + } +} + +SearchBarPlugin::~SearchBarPlugin() +{ + KConfig *config = kapp->config(); + config->setGroup("SearchBar"); + config->writeEntry("Mode", (int) m_searchMode); + config->writeEntry("CurrentEngine", m_currentEngine); + + delete m_searchCombo; + m_searchCombo = 0L; +} + +QChar delimiter() +{ + KConfig config( "kuriikwsfilterrc", true, false ); + config.setGroup( "General" ); + return config.readNumEntry( "KeywordDelimiter", ':' ); +} + +bool SearchBarPlugin::eventFilter(QObject *o, QEvent *e) +{ + if( o==m_searchCombo->lineEdit() && e->type() == QEvent::KeyPress ) + { + QKeyEvent *k = (QKeyEvent *)e; + if(k->state() & ControlButton) + { + if(k->key()==Key_Down) + { + nextSearchEntry(); + return true; + } + if(k->key()==Key_Up) + { + previousSearchEntry(); + return true; + } + } + } + return false; +} + +void SearchBarPlugin::nextSearchEntry() +{ + if(m_searchMode == FindInThisPage) + { + m_searchMode = UseSearchProvider; + if(m_searchEngines.count()) + { + m_currentEngine = *m_searchEngines.at(0); + } + else + { + m_currentEngine = "google"; + } + } + else + { + QStringList::ConstIterator it = m_searchEngines.find(m_currentEngine); + it++; + if(it==m_searchEngines.end()) + { + m_searchMode = FindInThisPage; + } + else + { + m_currentEngine = *it; + } + } + setIcon(); +} + +void SearchBarPlugin::previousSearchEntry() +{ + if(m_searchMode == FindInThisPage) + { + m_searchMode = UseSearchProvider; + if(m_searchEngines.count()) + { + m_currentEngine = *m_searchEngines.fromLast(); + } + else + { + m_currentEngine = "google"; + } + } + else + { + QStringList::ConstIterator it = m_searchEngines.find(m_currentEngine); + if(it==m_searchEngines.begin()) + { + m_searchMode = FindInThisPage; + } + else + { + it--; + m_currentEngine = *it; + } + } + setIcon(); +} + +void SearchBarPlugin::startSearch(const QString &search) +{ + if(m_urlEnterLock || search.isEmpty() || !m_part) + return; + + if(m_searchMode == FindInThisPage) + { + m_part->findText(search, 0); + m_part->findTextNext(); + } + else if(m_searchMode == UseSearchProvider) + { + m_urlEnterLock = true; + KService::Ptr service; + KURIFilterData data; + QStringList list; + list << "kurisearchfilter" << "kuriikwsfilter"; + + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_currentEngine)); + if (service) { + const QString searchProviderPrefix = *(service->property("Keys").toStringList().begin()) + delimiter(); + data.setData( searchProviderPrefix + search ); + } + + if(!service || !KURIFilter::self()->filterURI(data, list)) + { + data.setData( QString::fromLatin1( "google" ) + delimiter() + search ); + KURIFilter::self()->filterURI( data, list ); + } + + if(KApplication::keyboardMouseState() & Qt::ControlButton) + { + KParts::URLArgs args; + args.setNewTab(true); + emit m_part->browserExtension()->createNewWindow( data.uri(), args ); + } + else + { + emit m_part->browserExtension()->openURLRequest(data.uri()); + } + } + + if(m_searchCombo->text(0).isEmpty()) + { + m_searchCombo->changeItem(m_searchIcon, search, 0); + } + else + { + if(m_searchCombo->findHistoryItem(search) == -1) + { + m_searchCombo->insertItem(m_searchIcon, search, 0); + } + } + + m_searchCombo->setCurrentText(""); + m_urlEnterLock = false; +} + +void SearchBarPlugin::setIcon() +{ + QString hinttext; + if(m_searchMode == FindInThisPage) + { + m_searchIcon = SmallIcon("find"); + hinttext = i18n("Find in This Page"); + } + else + { + QString providername; + KService::Ptr service; + KURIFilterData data; + QStringList list; + list << "kurisearchfilter" << "kuriikwsfilter"; + + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(m_currentEngine)); + if (service) { + const QString searchProviderPrefix = *(service->property("Keys").toStringList().begin()) + delimiter(); + data.setData( searchProviderPrefix + "some keyword" ); + } + + if (service && KURIFilter::self()->filterURI(data, list)) + { + QString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png"); + if(iconPath.isEmpty()) + { + m_searchIcon = SmallIcon("enhanced_browsing"); + } + else + { + m_searchIcon = QPixmap(iconPath); + } + providername = service->name(); + } + else + { + m_searchIcon = SmallIcon("google"); + providername = "Google"; + } + hinttext = i18n("%1 Search").arg(providername);; + } + static_cast<KLineEdit*>(m_searchCombo->lineEdit())->setClickMessage(hinttext); + + // Create a bit wider icon with arrow + QPixmap arrowmap = QPixmap(m_searchIcon.width()+5,m_searchIcon.height()+5); + arrowmap.fill(m_searchCombo->lineEdit()->backgroundColor()); + QPainter p( &arrowmap ); + p.drawPixmap(0, 2, m_searchIcon); + QStyle::SFlags arrowFlags = QStyle::Style_Default; + m_searchCombo->style().drawPrimitive(QStyle::PE_ArrowDown, &p, QRect(arrowmap.width()-6, + arrowmap.height()-6, 6, 5), m_searchCombo->colorGroup(), arrowFlags, QStyleOption() ); + p.end(); + m_searchIcon = arrowmap; + + m_searchCombo->setIcon(m_searchIcon); +} + +void SearchBarPlugin::showSelectionMenu() +{ + if(!m_popupMenu) + { + KService::Ptr service; + QPixmap icon; + KURIFilterData data; + QStringList list; + list << "kurisearchfilter" << "kuriikwsfilter"; + + m_popupMenu = new QPopupMenu(m_searchCombo, "search selection menu"); + m_popupMenu->insertItem(SmallIcon("find"), i18n("Find in This Page"), this, SLOT(useFindInThisPage()), 0, 999); + m_popupMenu->insertSeparator(); + + int i=-1; + for (QStringList::ConstIterator it = m_searchEngines.begin(); it != m_searchEngines.end(); ++it ) + { + i++; + service = KService::serviceByDesktopPath(QString("searchproviders/%1.desktop").arg(*it)); + if(!service) + { + continue; + } + const QString searchProviderPrefix = *(service->property("Keys").toStringList().begin()) + delimiter(); + data.setData( searchProviderPrefix + "some keyword" ); + + if(KURIFilter::self()->filterURI(data, list)) + { + QString iconPath = locate("cache", KMimeType::favIconForURL(data.uri()) + ".png"); + if(iconPath.isEmpty()) + { + icon = SmallIcon("enhanced_browsing"); + } + else + { + icon = QPixmap( iconPath ); + } + m_popupMenu->insertItem(icon, service->name(), i); + } + } + + m_popupMenu->insertSeparator(); + m_popupMenu->insertItem(SmallIcon("enhanced_browsing"), i18n("Select Search Engines..."), + this, SLOT(selectSearchEngines()), 0, 1000); + connect(m_popupMenu, SIGNAL(activated(int)), SLOT(useSearchProvider(int))); + } + m_popupMenu->popup(m_searchCombo->mapToGlobal(QPoint(0, m_searchCombo->height() + 1)), 0); +} + +void SearchBarPlugin::useFindInThisPage() +{ + m_searchMode = FindInThisPage; + setIcon(); +} + +void SearchBarPlugin::useSearchProvider(int id) +{ + if(id>900) + { + // Not a search engine entry selected + return; + } + m_searchMode = UseSearchProvider; + m_currentEngine = *m_searchEngines.at(id); + setIcon(); +} + +void SearchBarPlugin::selectSearchEngines() +{ + KProcess *process = new KProcess; + + *process << "kcmshell" << "ebrowsing"; + + connect(process, SIGNAL(processExited(KProcess *)), SLOT(searchEnginesSelected(KProcess *))); + + if(!process->start()) + { + kdDebug(1202) << "Couldn't invoke kcmshell." << endl; + delete process; + } +} + +void SearchBarPlugin::searchEnginesSelected(KProcess *process) +{ + if(!process || process->exitStatus() == 0) + { + KConfig *config = kapp->config(); + config->setGroup("SearchBar"); + config->writeEntry("CurrentEngine", m_currentEngine); + config->sync(); + configurationChanged(); + } + delete process; +} + +void SearchBarPlugin::configurationChanged() +{ + KConfig *config = new KConfig("kuriikwsfilterrc"); + config->setGroup("General"); + QString engine = config->readEntry("DefaultSearchEngine", "google"); + + QStringList favoriteEngines; + favoriteEngines << "google" << "google_groups" << "google_news" << "webster" << "dmoz" << "wikipedia"; + favoriteEngines = config->readListEntry("FavoriteSearchEngines", favoriteEngines); + + delete m_popupMenu; + m_popupMenu = 0; + m_searchEngines.clear(); + m_searchEngines << engine; + for (QStringList::ConstIterator it = favoriteEngines.begin(); it != favoriteEngines.end(); ++it ) + if(*it!=engine) + m_searchEngines << *it; + + delete config; + if(engine.isEmpty()) + { + m_providerName = "Google"; + } + else + { + KDesktopFile file("searchproviders/" + engine + ".desktop", true, "services"); + m_providerName = file.readName(); + } + + config = kapp->config(); + config->setGroup("SearchBar"); + m_searchMode = (SearchModes) config->readNumEntry("Mode", (int) UseSearchProvider); + m_currentEngine = config->readEntry("CurrentEngine", engine); + + if ( m_currentEngine.isEmpty() ) + m_currentEngine = "google"; + + setIcon(); +} + +void SearchBarPlugin::partChanged(KParts::Part *newPart) +{ + m_part = ::qt_cast<KHTMLPart*>(newPart); + + //Delay since when destroying tabs part 0 gets activated for a bit, before the proper part + QTimer::singleShot(0, this, SLOT(updateComboVisibility())); +} + +void SearchBarPlugin::updateComboVisibility() +{ + if (m_part.isNull() || !m_searchComboAction->isPlugged()) + { + m_searchCombo->setPluginActive(false); + m_searchCombo->hide(); + } + else + { + m_searchCombo->setPluginActive(true); + m_searchCombo->show(); + } +} + +void SearchBarPlugin::focusSearchbar() +{ + QFocusEvent::setReason( QFocusEvent::Shortcut ); + m_searchCombo->setFocus(); + QFocusEvent::resetReason(); +} + +SearchBarCombo::SearchBarCombo(QWidget *parent, const char *name) : + KHistoryCombo(parent, name), + m_pluginActive(true) +{ + connect(this, SIGNAL(cleared()), SLOT(historyCleared())); +} + +const QPixmap &SearchBarCombo::icon() const +{ + return m_icon; +} + +void SearchBarCombo::setIcon(const QPixmap &icon) +{ + m_icon = icon; + + if(count() == 0) + { + insertItem(m_icon, 0); + } + else + { + for(int i = 0; i < count(); i++) + { + changeItem(m_icon, text(i), i); + } + } +} + +int SearchBarCombo::findHistoryItem(const QString &searchText) +{ + for(int i = 0; i < count(); i++) + { + if(text(i) == searchText) + { + return i; + } + } + + return -1; +} + +void SearchBarCombo::mousePressEvent(QMouseEvent *e) +{ + int x0 = QStyle::visualRect( style().querySubControlMetrics( QStyle::CC_ComboBox, this, QStyle::SC_ComboBoxEditField ), this ).x(); + + if(e->x() > x0 + 2 && e->x() < lineEdit()->x()) + { + emit iconClicked(); + + e->accept(); + } + else + { + KHistoryCombo::mousePressEvent(e); + } +} + +void SearchBarCombo::historyCleared() +{ + setIcon(m_icon); +} + +void SearchBarCombo::setPluginActive(bool pluginActive) +{ + m_pluginActive = pluginActive; +} + +void SearchBarCombo::show() +{ + if(m_pluginActive) + { + KHistoryCombo::show(); + } +} + +#include "searchbar.moc" diff --git a/konq-plugins/searchbar/searchbar.desktop b/konq-plugins/searchbar/searchbar.desktop new file mode 100644 index 0000000..cbb2f57 --- /dev/null +++ b/konq-plugins/searchbar/searchbar.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +Icon=google +Type=Service +X-KDE-Library=searchbar +X-KDE-PluginInfo-Author=Arend van Beelen jr. +X-KDE-PluginInfo-Email=arend@auton.nl +X-KDE-PluginInfo-Name=searchbar +X-KDE-PluginInfo-Version=1.0.0 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Extensions +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Search Bar Plugin +Name[bg]=Приставка за търсене +Name[br]=Lugent ar varenn glask +Name[bs]=Dodatak za traku pretrage +Name[ca]=Connector de barra de cerca +Name[cs]=Modul vyhledávací lišty +Name[da]=Søgelinje plugin +Name[de]=Suchleisten-Modul +Name[el]=Πρόσθετο γραμμής αναζήτησης +Name[eo]=Serĉlistela kromaĵo +Name[es]=Complemento de barra de búsqueda +Name[et]=Otsimisriba plugin +Name[eu]=Bilaketa-barra plugina +Name[fa]=وصلۀ میلۀ جستجو +Name[fi]=Etsintäpalkki-liitännäinen +Name[fr]=Module de barre de recherche +Name[fy]=Sykbalkeplugin +Name[ga]=Breiseán Barra Cuardaigh +Name[gl]=Plugin de Barra de Procura +Name[he]=תוסף סרגל חיפוש +Name[hi]=सर्च बार प्लगइन +Name[hr]=Dodatak trake za pretraživanje +Name[hu]=Keresősáv-bővítőmodul +Name[is]=Leitarslár-íforrit +Name[it]=Plugin per la barra di ricerca +Name[ja]=検索バープラグイン +Name[ka]=ძიების ველის მოდული +Name[kk]=Іздеу панелінің плагин модулі +Name[km]=កម្មវិធីជំនួយរបារស្វែងរក +Name[lt]=Paieškos juostos priedas +Name[mk]=Приклучок за лента за барање +Name[ms]=Plugin Bar Carian +Name[nb]=Søkelinje-programtillegg +Name[nds]=Söökbalken-Moduul +Name[ne]=पट्टी प्लगइन खोज्नुहोस् +Name[nl]=Zoekbalkplugin +Name[nn]=Søkelinjeprogramtillegg +Name[pa]=ਖੋਜ ਪੱਟੀ ਪਲੱਗਇਨ +Name[pl]=Wtyczka paska wyszukiwania +Name[pt]='Plugin' de Barra de Procura +Name[pt_BR]=Plug-in de Barra de Busca +Name[ru]=Модуль панели поиска +Name[sk]=Modul pre vyhľadávací pruh +Name[sl]=Vstavek iskalne vrstice +Name[sr]=Прикључак претраживачке траке +Name[sr@Latn]=Priključak pretraživačke trake +Name[sv]=Sökradsinsticksprogram +Name[ta]=பட்டி சொருகு சாதனத்தைத் தேடு +Name[tg]=Модули панели ҷустуҷӯ +Name[tr]=Arama Çubuğu Eklentisi +Name[uk]=Втулок смужки пошуку +Name[uz]=Qidirish paneli plagini +Name[uz@cyrillic]=Қидириш панели плагини +Name[vi]=Bổ sung thanh tìm +Name[zh_CN]=搜索栏插件 +Name[zh_TW]=搜尋列外掛程式 +Comment=Presents you with a textbox for direct access to search engines like Google. +Comment[bg]=Поле за търсене на в търсещите машини от сорта на Google +Comment[bs]=Prikazuje tekstualno polja za direktan pristup pretraživačima kao što je Google. +Comment[ca]=Presenta una àrea de text per accés directe a motors de cerca com Google. +Comment[cs]=Textové pole pro přímý přístup k vyhledávání jako je Google. +Comment[da]=Præsenterer dig for et tekstfelt med direkte adgang til søgemaskiner såsom Google. +Comment[de]=Zeigt ein Eingabefeld für direkten Zugriff auf Suchmaschinen wie Google. +Comment[el]=Σας παρουσιάζει ένα πεδίο κειμένου για απευθείας πρόσβαση σε μηχανές αναζήτησης όπως το Google. +Comment[eo]=Elmontras al vi tekstoskatolon por senpera aliro al serĉiloj kiel Guglo. +Comment[es]=Se muestra como un cuadro de texto con el que se tendrá acceso directo a motores de búsqueda del estilo de Google. +Comment[et]=Pakub tekstikasti, mis võimaldab vahetult kasutada mitmesuguseid otsingumootoreid, näiteks Google. +Comment[eu]=Google bezalako bilaketa motoreak zuzenean atzitzeko testu kutxa bat aurkezten dizu +Comment[fa]=جعبه متنی را برای دستیابی مستقیم به موتورهای جستجو نظیر گوگل، به شما ارائه میکند. +Comment[fi]=Lisää tekstilaatikon suoraan hakukoneen käyttöön kuten Google. +Comment[fr]=Vous présente une zone de texte pour un accès direct aux moteurs de recherche comme Google. +Comment[fy]=Levert in ynfierfjild wêrmei't jo direkte tagong krije ta sykmasines lykas Google. +Comment[gl]=Dá-lle unha caixa de texto para aceder directamente a motores de procura como Google. +Comment[he]= מציג לך שורת קלט לגישה ישירה אל מנועי חיפוש כמו Google +Comment[hi]=गूगल जैसे सर्च इंजनों पर सीधे पहुँच के लिए आपको एक पाठ बक्सा प्रदान करता है. +Comment[hr]=Pruža tekstualni okvir za izravan pristup tražilicama poput Google-a. +Comment[hu]=Gyors hozzáférést biztosít az internetes keresők (pl. Google) szolgáltatásaihoz. +Comment[is]=Birtir textabox sem er beintengt leitarvélum eins og Google. +Comment[it]=Ti presenta una casella di testo per l'accesso diretto a dei motori di ricerca quali Google. +Comment[ja]=Google のような検索エンジンへの直接アクセスのテキストボックスを提供します。 +Comment[ka]=წარმოგიდგენთ ტექსტურ ველს რომელის საძიებო სისტემასთანაა კავსირში, მაგ. Google. +Comment[kk]=Google секілді іздеу тетіктеріне тікелей қатынау панелі. +Comment[km]=បង្ហាញអ្នកដោយប្រអប់អត្ថបទមួយ ដើម្បីចូលដំណើរការម៉ាស៊ីនស្វែងរក ដូចជា Google ។ +Comment[lt]=Pateikia teksto lauką tiesioginei prieigai prie paieškos sistemų, tokių, kaip Google. +Comment[mk]=Ви дава текстуално поле за директен пристап до машини за пребарување како Google +Comment[ms]=Mempersembahkan kepada anda buku teks untuk akses terus ke enjin cari seperti Google. +Comment[nb]=Viser en tekstboks for direkte tilgang til søkemotorer som Google. +Comment[nds]=Gifft Di en Textfeld för den Direkttogriep op Söökmaschinen, as t.B. "Google". +Comment[ne]=तपाईँलाई गुगल जस्तै खोजी इन्जिनमा प्रत्यक्ष पहुँच प्राप्त गर्न पाठबाकस प्रस्तुत गर्छ । +Comment[nl]=Levert een invoerveld waarmee u directe toegang hebt tot zoekmachines zoals Google. +Comment[nn]=Visar ein tekstboks for direkte tilgang til søkemotorar som Google. +Comment[pl]=Pokazuje okienko umożliwiające bezpośrednie uruchamianie przeszukiwarek, takich jak Google. +Comment[pt]=Dá-lhe uma caixa de texto para acesso directo a motores de procura com o Google. +Comment[pt_BR]=Apresenta a você uma caixa de texto para o acesso direto a mecanismos de busca como o Google. +Comment[ru]=Поле ввода для быстрого поиска в Google. +Comment[sk]=Zobrazí textové pole pre priamy prístup k vyhľadávačom ako je Google. +Comment[sl]=Poda besedilni okvir za neposreden odnos do iskalnih strežnikov, kot je Google. +Comment[sr]=Приказује текстуално поље за директан приступ претраживачима као што је Google. +Comment[sr@Latn]=Prikazuje tekstualno polje za direktan pristup pretraživačima kao što je Google. +Comment[sv]=Visar en textruta för direktåtkomst av söktjänster som Google. +Comment[ta]=கூகுலில் இருப்பது போன்று தேடு இயந்திரங்களின் நேரடியான அணுகலுக்கு ஒரு உரைப்பெட்டியுடன் வழங்கும். +Comment[tg]=Фосидаи хурди воридот барои ҷустуҷуйи тез дар Google. +Comment[tr]=Bir metin kutusu ile sizin Google gibi arma motorlarına ulaşmanızı sağlar. +Comment[uk]=Надає прямий доступ до пошукових систем таких, як Google. +Comment[vi]=Hiển thị hộp nhập trực tiếp chuỗi tìm bằng Google v.v. +Comment[zh_CN]=为您添加一个文本框,以便可直接访问像 Google 这样的搜索引擎。 +Comment[zh_TW]=提供您直接到像 Google 之類的搜尋引擎搜尋文字的方法 +X-KDE-ParentApp=konqueror diff --git a/konq-plugins/searchbar/searchbar.h b/konq-plugins/searchbar/searchbar.h new file mode 100644 index 0000000..3f03eb9 --- /dev/null +++ b/konq-plugins/searchbar/searchbar.h @@ -0,0 +1,168 @@ +/* This file is part of the KDE project + Copyright (C) 2004 Arend van Beelen jr. <arend@auton.nl> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef SEARCHBAR_PLUGIN +#define SEARCHBAR_PLUGIN + +#include <kcombobox.h> +#include <klibloader.h> +#include <kparts/plugin.h> +#include <kparts/mainwindow.h> + +#include <qguardedptr.h> +#include <qpixmap.h> +#include <qstring.h> + +class KHTMLPart; +class KProcess; +class QPopupMenu; + +/** + * Combo box which catches mouse clicks on the pixmap. + */ +class SearchBarCombo : public KHistoryCombo +{ + Q_OBJECT + + public: + /** + * Constructor. + */ + SearchBarCombo(QWidget *parent, const char *name); + + /** + * Returns the icon currently displayed in the combo box. + */ + const QPixmap &icon() const; + + /** + * Sets the icon displayed in the combo box. + */ + void setIcon(const QPixmap &icon); + + /** + * Finds a history item by its text. + * @return The item number, or -1 if the item is not found. + */ + int findHistoryItem(const QString &text); + + /** + * Sets whether the plugin is active. It can be inactive + * in case the current Konqueror part isn't a KHTML part. + */ + void setPluginActive(bool pluginActive); + + public slots: + virtual void show(); + + signals: + /** + * Emitted when the icon was clicked. + */ + void iconClicked(); + + protected: + /** + * Captures mouse clicks and emits iconClicked() if the icon + * was clicked. + */ + virtual void mousePressEvent(QMouseEvent *e); + + private slots: + void historyCleared(); + + private: + QPixmap m_icon; + bool m_pluginActive; +}; + +/** + * Plugin that provides a search bar for Konqueror. This search bar is located + * next to the location bar and will show a small icon indicating the search + * provider it will use. + * + * @author Arend van Beelen jr. <arend@auton.nl> + * @version $Id$ + */ +class SearchBarPlugin : public KParts::Plugin +{ + Q_OBJECT + + public: + /** Possible search modes */ + enum SearchModes { FindInThisPage = 0, UseSearchProvider }; + + SearchBarPlugin(QObject *parent, const char *name, + const QStringList &); + virtual ~SearchBarPlugin(); + + protected: + bool eventFilter(QObject *o, QEvent *e); + + private slots: + /** + * Starts a search by putting the query URL from the selected + * search provider in the locationbar and calling goURL() + */ + void startSearch(const QString &search); + + /** + * Sets the icon to indicate which search engine is used. + */ + void setIcon(); + + /** + * Opens the selection menu. + */ + void showSelectionMenu(); + + void useFindInThisPage(); + void useSearchProvider(int); + void selectSearchEngines(); + void searchEnginesSelected(KProcess *process); + void configurationChanged(); + + /** + * We keep track of part activations to know when to show or hide ourselves + */ + void partChanged(KParts::Part *newPart); + + /** + * Show or hide the combo box + */ + void updateComboVisibility(); + + void focusSearchbar(); + private: + void nextSearchEntry(); + void previousSearchEntry(); + + QGuardedPtr<KHTMLPart> m_part; + SearchBarCombo *m_searchCombo; + KWidgetAction *m_searchComboAction; + QPopupMenu *m_popupMenu; + QPixmap m_searchIcon; + SearchModes m_searchMode; + QString m_providerName; + bool m_urlEnterLock; + QString m_currentEngine; + QStringList m_searchEngines; +}; + +#endif // SEARCHBAR_PLUGIN diff --git a/konq-plugins/searchbar/searchbar.lsm b/konq-plugins/searchbar/searchbar.lsm new file mode 100644 index 0000000..94537f9 --- /dev/null +++ b/konq-plugins/searchbar/searchbar.lsm @@ -0,0 +1,13 @@ +Begin3 +Title: SearchBarPlugin +Version: 0.1 +Entered-date: 08/02/2004 +Description: Puts an extra textbox for access to search engines like + Google next to Konqueror's location bar. +Keywords: KDE Qt +Author: Arend van Beelen jr. <arend@auton.nl> +Maintained-by: Arend van Beelen jr. <arend@auton.nl> +Home-page: +Platform: Linux. Tested against Qt/KDE 3.2, might work with earlier versions. +Copying-policy: GPL +End diff --git a/konq-plugins/searchbar/searchbar.rc b/konq-plugins/searchbar/searchbar.rc new file mode 100644 index 0000000..c98fdb5 --- /dev/null +++ b/konq-plugins/searchbar/searchbar.rc @@ -0,0 +1,6 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="searchbar" library="libsearchbarplugin" version="3"> +<ToolBar fullWidth="true" name="locationToolBar" newline="true"><text>Search Toolbar</text> + <Action name="toolbar_search_bar" /> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/sidebar/Makefile.am b/konq-plugins/sidebar/Makefile.am new file mode 100644 index 0000000..165352a --- /dev/null +++ b/konq-plugins/sidebar/Makefile.am @@ -0,0 +1,5 @@ +if include_ARTS +mediaplayer_subdir = mediaplayer +endif + +SUBDIRS = $(mediaplayer_subdir) newsticker delicious metabar diff --git a/konq-plugins/sidebar/delicious/Makefile.am b/konq-plugins/sidebar/delicious/Makefile.am new file mode 100644 index 0000000..cb8eb48 --- /dev/null +++ b/konq-plugins/sidebar/delicious/Makefile.am @@ -0,0 +1,22 @@ +SUBDIRS = . pics + +METASOURCES = AUTO +INCLUDES = -I$(kde_includes)/kio $(all_includes) + +################################ +# these are the headers for your project +noinst_HEADERS = plugin.h mainWidget.h tagListItem.h bookmarkListItem.h + +kde_module_LTLIBRARIES = konqsidebar_delicious.la + +# the Part's source, library search path, and link libraries +konqsidebar_delicious_la_SOURCES = plugin.cpp widget.ui mainWidget.cpp plugin.skel tagListItem.cpp \ + bookmarkListItem.cpp +konqsidebar_delicious_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +konqsidebar_delicious_la_LIBADD = $(LIB_KPARTS) $(LIB_KIO) -lkonqsidebarplugin + +globaladddir = $(kde_datadir)/konqsidebartng/add +globaladd_DATA = delicious_add.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/konqsidebar_delicious.pot diff --git a/konq-plugins/sidebar/delicious/bookmarkListItem.cpp b/konq-plugins/sidebar/delicious/bookmarkListItem.cpp new file mode 100644 index 0000000..f4bd8f5 --- /dev/null +++ b/konq-plugins/sidebar/delicious/bookmarkListItem.cpp @@ -0,0 +1,72 @@ +////////////////////////////////////////////////////////////////////////// +// bookmarkListItem.cpp // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#include "bookmarkListItem.h" + +#include <kglobal.h> +#include <klocale.h> + +BookmarkListItem::BookmarkListItem( QListView *parent, const QString & url, const QString & desc, time_t time ) + : KListViewItem( parent ), m_desc( desc ) +{ + m_url = KURL::fromPathOrURL( url ); + m_dateTime.setTime_t( time ); +} + +int BookmarkListItem::compare( QListViewItem * i, int col, bool ascending ) const +{ + if ( col == 1 ) + { + QDateTime them = static_cast<BookmarkListItem *>( i )->date(); + if ( m_dateTime < them ) + return -1; + else if ( m_dateTime > them ) + return 1; + else + return 0; + } + return QListViewItem::compare( i, col, ascending ); +} + +QString BookmarkListItem::text( int column ) const +{ + if ( column == 0 ) + return m_desc; + else if ( column == 1 ) + return KGlobal::locale()->formatDateTime( m_dateTime ); + + return QString::null; +} + +KURL BookmarkListItem::url() const +{ + return m_url; +} + +QDateTime BookmarkListItem::date() const +{ + return m_dateTime; +} + +QString BookmarkListItem::desc() const +{ + return m_desc; +} diff --git a/konq-plugins/sidebar/delicious/bookmarkListItem.h b/konq-plugins/sidebar/delicious/bookmarkListItem.h new file mode 100644 index 0000000..9188fcd --- /dev/null +++ b/konq-plugins/sidebar/delicious/bookmarkListItem.h @@ -0,0 +1,51 @@ +////////////////////////////////////////////////////////////////////////// +// bookmarkListItem.h // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#ifndef _BOOKMARKLISTITEM_H_ +#define _BOOKMARKLISTITEM_H_ + +#include <qdatetime.h> + +#include <klistview.h> +#include <kurl.h> + +#include <time.h> + +class QString; + +class BookmarkListItem: public KListViewItem +{ +public: + BookmarkListItem( QListView *parent, const QString & url, const QString & desc, time_t time ); + KURL url() const; + QDateTime date() const; + QString desc() const; + +protected: + virtual int compare( QListViewItem * i, int col, bool ascending ) const; + virtual QString text( int column ) const; + + KURL m_url; + QString m_desc; + QDateTime m_dateTime; +}; + +#endif diff --git a/konq-plugins/sidebar/delicious/delicious_add.desktop b/konq-plugins/sidebar/delicious/delicious_add.desktop new file mode 100644 index 0000000..b2e3e07 --- /dev/null +++ b/konq-plugins/sidebar/delicious/delicious_add.desktop @@ -0,0 +1,57 @@ +[Desktop Entry] +Type=Link +URL= +Icon=konqsidebar_delicious +Name=del.icio.us Bookmarks +Name[bg]=Отметки del.icio.us +Name[br]=Sinedoù del.icio.us +Name[ca]=Punts del.icio.us +Name[cs]=del.icio.us záložky +Name[da]=del.icio.us Bogmærker +Name[de]=Lesezeichen von del.icio.us +Name[el]=Σελιδοδείκτες del.icio.us +Name[eo]=del.icio.us legosignoj +Name[es]=Marcadores del.icio.us +Name[et]=del.icio.us järjehoidjad +Name[eu]=del.icio.us laster-markak +Name[fa]=چوب الفهای del.icio.us +Name[fi]=del.icio.us kirjanmerkit +Name[fr]=Signets del.icio.us +Name[fy]=del.icio.us-blêdwizers +Name[ga]=Leabharmharcanna del.icio.us +Name[gl]=Favoritos del.icio.us +Name[he]=סימניות של del.icio.us +Name[hr]=del.icio.us oznake +Name[hu]=Del.icio.us könyvjelzők +Name[is]=del.icio.us bókamerki +Name[it]=Segnalibri di del.icio.us +Name[ja]=del.icio.us ブックマーク +Name[ka]=del.icio.us სანიშნეები +Name[kk]=del.icio.us бетбелгілері +Name[km]=ចំណាំ del.icio.us +Name[lt]=del.icio.us žymelės +Name[mk]=Обележувачи за del.icio.us +Name[nb]=del.icio.us bokmerker +Name[nds]="del.icio.us"-Leestekens +Name[ne]=del.icio.us पुस्तकचिनोहरू +Name[nl]=del.icio.us-bladwijzers +Name[nn]=del.icio.us-bokmerke +Name[pa]=del.icio.us ਬੁੱਕਮਾਰਕ +Name[pl]=Zakładki del.icio.us +Name[pt]=Favoritos del.icio.us +Name[pt_BR]=Favorito do del.icio.us +Name[ru]=Закладки del.icio.us +Name[sk]=del.icio.us záložky +Name[sl]=Zaznamki del.icio.us +Name[sr]=ук.ус.ни маркери +Name[sr@Latn]=uk.us.ni markeri +Name[sv]=del.icio.us bokmärken +Name[tr]=del.icio.us Yer İmleri +Name[uk]=Закладки del.icio.us +Name[uz]=del.icio.us xatchoʻplari +Name[uz@cyrillic]=del.icio.us хатчўплари +Name[vi]=Dấu nhớ del.icio.us +Name[zh_CN]=del.icio.us 书签 +Open=false +X-KDE-KonqSidebarAddModule=konqsidebar_delicious +X-KDE-KonqSidebarUniversal=true diff --git a/konq-plugins/sidebar/delicious/mainWidget.cpp b/konq-plugins/sidebar/delicious/mainWidget.cpp new file mode 100644 index 0000000..759e348 --- /dev/null +++ b/konq-plugins/sidebar/delicious/mainWidget.cpp @@ -0,0 +1,354 @@ +// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +////////////////////////////////////////////////////////////////////////// +// mainWidget.cpp // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#include "mainWidget.h" +#include "tagListItem.h" +#include "bookmarkListItem.h" + +#include <qlistview.h> +#include <qdom.h> +#include <qpopupmenu.h> +#include <qpushbutton.h> +#include <qtimer.h> +#include <qdatetime.h> + +#include <kdebug.h> +#include <kio/job.h> +#include <krfcdate.h> +#include <klistview.h> +#include <klocale.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kmessagebox.h> +#include <kconfig.h> +#include <kinputdialog.h> + +MainWidget::MainWidget( KConfig * config, QWidget * parent ) + : MainWidget_base( parent ), m_config( config ) +{ + loadTags(); + + KIconLoader * il = KGlobal::iconLoader(); + + btnRefreshTags->setIconSet( il->loadIconSet( "reload", KIcon::Small ) ); + btnRefreshBookmarks->setIconSet( il->loadIconSet( "reload", KIcon::Small ) ); + btnNew->setIconSet( il->loadIconSet( "bookmark_add", KIcon::Small ) ); + + connect( ( QWidget * ) btnRefreshTags, SIGNAL( clicked() ), + this, SLOT( slotGetTags() ) ); + + connect( ( QWidget * ) btnRefreshBookmarks, SIGNAL( clicked() ), + this, SLOT( slotGetBookmarks() ) ); + + connect( ( QWidget * ) btnNew, SIGNAL( clicked() ), + this, SLOT( slotNewBookmark() ) ); + + connect( lvBookmarks, SIGNAL( executed( QListViewItem * ) ), + this, SLOT( slotBookmarkExecuted( QListViewItem * ) ) ); + connect( lvBookmarks, SIGNAL( mouseButtonClicked ( int, QListViewItem *, const QPoint &, int ) ), + this, SLOT( slotBookmarkClicked( int, QListViewItem *, const QPoint &, int ) ) ); + + connect( lvTags, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ), + this, SLOT( slotTagsContextMenu( QListViewItem *, const QPoint &, int ) ) ); + + connect( lvBookmarks, SIGNAL( contextMenuRequested( QListViewItem *, const QPoint &, int ) ), + this, SLOT( slotBookmarksContextMenu( QListViewItem *, const QPoint &, int ) ) ); + + m_updateTimer = new QTimer( this ); + connect( m_updateTimer, SIGNAL( timeout() ), SLOT( slotGetBookmarks() ) ); + + slotGetTags(); +} + +MainWidget::~MainWidget() +{ + saveTags(); +} + +void MainWidget::setCurrentURL( const KURL & url ) +{ + m_currentURL = url; +} + +void MainWidget::slotGetTags() +{ + kdDebug() << k_funcinfo << endl; + + KIO::StoredTransferJob * job = KIO::storedGet( "http://del.icio.us/api/tags/get" ); + connect( job, SIGNAL( result( KIO::Job * ) ), + this, SLOT( slotFillTags( KIO::Job * ) ) ); +} + +void MainWidget::slotFillTags( KIO::Job * job ) +{ + kdDebug() << k_funcinfo << endl; + + if ( job->error() ) + { + job->showErrorDialog( this ); + return; + } + + lvTags->clear(); + m_tags.clear(); + + // fill lvTags with job->data() + QDomDocument doc; + doc.setContent( static_cast<KIO::StoredTransferJob *>( job )->data() ); + QDomNodeList tags = doc.elementsByTagName( "tag" ); + for ( uint i = 0; i < tags.length(); ++i ) + { + QDomElement tag = tags.item( i ).toElement(); + if ( !tag.isNull() ) + { + TagListItem *item = new TagListItem( lvTags, tag.attribute( "tag" ), tag.attribute( "count" ).toInt() ); + m_tags.append( tag.attribute( "tag" ) ); + connect( item, SIGNAL( signalItemChecked( TagListItem * ) ), SLOT( itemToggled() ) ); + } + } +} + +void MainWidget::slotGetBookmarks() +{ + KURL url( "http://del.icio.us/api/posts/recent" ); + url.setQuery( "tag=" + checkedTags().join( " " ) ); + + kdDebug() << k_funcinfo << url.url() << endl; + + KIO::StoredTransferJob * job = KIO::storedGet( url ); + connect( job, SIGNAL( result( KIO::Job * ) ), + this, SLOT( slotFillBookmarks( KIO::Job * ) ) ); +} + +void MainWidget::slotFillBookmarks( KIO::Job * job ) +{ + kdDebug() << k_funcinfo << endl; + + if ( job->error() ) + { + job->showErrorDialog( this ); + return; + } + + lvBookmarks->clear(); + + // fill lvBookmarks with job->data() + QDomDocument doc; + doc.setContent( static_cast<KIO::StoredTransferJob *>( job )->data() ); + QDomNodeList posts = doc.elementsByTagName( "post" ); + + for ( uint i = 0; i < posts.length(); ++i ) + { + QDomElement post = posts.item( i ).toElement(); + if ( !post.isNull() ) + { + new BookmarkListItem( lvBookmarks, post.attribute( "href" ), post.attribute( "description" ), + KRFCDate::parseDateISO8601( post.attribute( "time" ) ) ); + } + } +} + +QStringList MainWidget::checkedTags() const +{ + QListViewItemIterator it( lvTags, QListViewItemIterator::Visible | QListViewItemIterator::Checked ); + + QStringList tmp; + + while ( it.current() ) + { + tmp.append( it.current()->text( 0 ) ); + ++it; + } + + return tmp; +} + +void MainWidget::slotBookmarkExecuted( QListViewItem * item ) +{ + BookmarkListItem * bookmark = static_cast<BookmarkListItem *>( item ); + if ( bookmark ) + { + kdDebug() << k_funcinfo << "Clicked bookmark URL: " << bookmark->url() << endl; + emit signalURLClicked( bookmark->url() ); + } +} + +void MainWidget::slotBookmarkClicked( int button, QListViewItem * item, const QPoint &, int ) +{ + BookmarkListItem * bookmark = static_cast<BookmarkListItem *>( item ); + if ( bookmark && button == Qt::MidButton ) // handle middle click + { + kdDebug() << k_funcinfo << "Middle clicked bookmark URL: " << bookmark->url() << endl; + emit signalURLMidClicked( bookmark->url() ); + } +} + +QStringList MainWidget::tags() const +{ + return m_tags; +} + +QStringList MainWidget::bookmarks() const +{ + QListViewItemIterator it( lvBookmarks ); + + QStringList tmp; + + while ( it.current() ) + { + tmp.append( static_cast<BookmarkListItem *>( it.current() )->url().url() ); + ++it; + } + + return tmp; +} + +void MainWidget::slotTagsContextMenu( QListViewItem *, const QPoint & pos, int ) +{ + if ( lvTags->childCount() == 0 ) + return; + + QPopupMenu * tagMenu = new QPopupMenu( this ); + Q_CHECK_PTR( tagMenu ); + + tagMenu->insertItem( i18n( "Check All" ), this, SLOT( slotCheckAllTags() ) ); + tagMenu->insertItem( i18n( "Uncheck All" ), this, SLOT( slotUncheckAllTags() ) ); + tagMenu->insertItem( i18n( "Toggle All" ), this, SLOT( slotToggleTags() ) ); + tagMenu->insertSeparator(); + tagMenu->insertItem( KGlobal::iconLoader()->loadIconSet( "edit", KIcon::Small ), + i18n( "Rename Tag..." ), this, SLOT( slotRenameTag() ) ); + + tagMenu->exec( pos ); +} + +void MainWidget::slotCheckAllTags() +{ + QListViewItemIterator it( lvTags ); + while ( it.current() ) + { + QCheckListItem * item = static_cast<QCheckListItem *>( *it ); + if ( item ) + item->setOn( true ); + ++it; + } +} + +void MainWidget::slotUncheckAllTags() +{ + QListViewItemIterator it( lvTags ); + while ( it.current() ) + { + QCheckListItem * item = static_cast<QCheckListItem *>( *it ); + if ( item ) + item->setOn( false ); + ++it; + } +} + +void MainWidget::slotToggleTags() +{ + QListViewItemIterator it( lvTags ); + while ( it.current() ) + { + QCheckListItem * item = static_cast<QCheckListItem *>( *it ); + if ( item ) + item->setOn( !item->isOn() ); + ++it; + } +} + +void MainWidget::itemToggled() +{ + m_updateTimer->start( 2000, true ); +} + +void MainWidget::slotNewBookmark() +{ + emit signalURLClicked( "http://del.icio.us/post/?url=" + m_currentURL.url() ); +} + +void MainWidget::saveTags() +{ + m_config->writeEntry( "Tags", m_tags ); +} + +void MainWidget::loadTags() +{ + m_tags = m_config->readListEntry( "Tags" ); +} + +void MainWidget::slotRenameTag() +{ + TagListItem * tag = static_cast<TagListItem *>( lvTags->currentItem() ); + if ( tag ) + { + QString oldName = tag->name(); + QString newName = KInputDialog::getText( i18n( "Rename Tag" ), i18n( "Provide a new name for tag '%1':" ).arg( oldName ) ); + if ( !newName.isEmpty() ) + { + KURL url( "http://del.icio.us/api/tags/rename" ); + url.addQueryItem( "old", oldName ); + url.addQueryItem( "new", newName ); + KIO::get( url ); // rename the tag + + tag->setName( newName ); + } + } +} + +void MainWidget::slotBookmarksContextMenu( QListViewItem *, const QPoint & pos, int ) +{ + if ( lvBookmarks->childCount() == 0 ) + return; + + QPopupMenu * menu = new QPopupMenu( this ); + Q_CHECK_PTR( menu ); + + menu->insertItem( KGlobal::iconLoader()->loadIconSet( "editdelete", KIcon::Small ), + i18n( "Delete Bookmark" ), this, SLOT( slotDeleteBookmark() ) ); + + menu->exec( pos ); +} + +void MainWidget::slotDeleteBookmark() +{ + BookmarkListItem * bookmark = static_cast<BookmarkListItem *>( lvBookmarks->currentItem() ); + if ( bookmark ) + { + int result = KMessageBox::warningContinueCancel( this, i18n( "Do you really want to remove the bookmark\n%1?" ).arg( bookmark->desc() ), + i18n( "Delete Bookmark" ), KStdGuiItem::del() ); + + if ( result == KMessageBox::Continue ) + { + KURL url( "http://del.icio.us/api/posts/delete" ); + url.addQueryItem( "url", bookmark->url().url() ); + kdDebug() << k_funcinfo << url << endl; + KIO::get( url ); + + delete bookmark; + + slotGetTags(); // re-read the tags + } + } +} + +#include "mainWidget.moc" diff --git a/konq-plugins/sidebar/delicious/mainWidget.h b/konq-plugins/sidebar/delicious/mainWidget.h new file mode 100644 index 0000000..5970524 --- /dev/null +++ b/konq-plugins/sidebar/delicious/mainWidget.h @@ -0,0 +1,175 @@ +// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +////////////////////////////////////////////////////////////////////////// +// mainWidget.h // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#ifndef _MAINWIDGET_H_ +#define _MAINWIDGET_H_ + +#include "widget.h" + +#include <kio/jobclasses.h> +#include <kparts/browserextension.h> + +class QStringList; +class KURL; +class KConfig; + +/** + * Main widget of the del.icio.us bookmarks panel + */ +class MainWidget: public MainWidget_base +{ + Q_OBJECT +public: + MainWidget( KConfig * config, QWidget * parent ); + ~MainWidget(); + + /** + * @return all the tags user has + * (used in the DCOP iface) + */ + QStringList tags() const; + + /** + * @return all the (currently visible) bookmark (URLs) + * (used in the DCOP iface) + */ + QStringList bookmarks() const; + + /** + * Set the internal URL to @p url + */ + void setCurrentURL( const KURL & url ); + +public slots: + /** + * Show a dialog for adding a new bookmark + */ + void slotNewBookmark(); + +private slots: + /** + * Start the job to get the list of tags + */ + void slotGetTags(); + + /** + * Fill the Tags listview with job->data() + * (parses the XML returned by the server) + */ + void slotFillTags( KIO::Job * job ); + + /** + * Start the job to get the list of bookmarks + * for checked tags + */ + void slotGetBookmarks(); + + /** + * Fill the Bookmarks listview with job->data() + * (parses the XML returned by the server) + */ + void slotFillBookmarks( KIO::Job * job ); + + /** + * Handle clicking on a bookmark (KDE mode) + */ + void slotBookmarkExecuted( QListViewItem * item ); + + /** + * Handle middle clicking a bookmark + */ + void slotBookmarkClicked( int button, QListViewItem * item, const QPoint & pnt, int col ); + + /** + * Popup a tag context menu over @p item and position @pos + */ + void slotTagsContextMenu( QListViewItem * item, const QPoint & pos, int col ); + + /** + * Popup a bookmark context menu over @p item and position @pos + */ + void slotBookmarksContextMenu( QListViewItem * item, const QPoint & pos, int col ); + + /** + * Put a checkmark before all tags + */ + void slotCheckAllTags(); + + /** + * Cancel the checkmark before all tags + */ + void slotUncheckAllTags(); + + /** + * Toggle the checkmark before all tags + */ + void slotToggleTags(); + + /** + * Starts a singleshot timer once an item (tag) has been toggled. Timer will update bookmarks. + */ + void itemToggled(); + + /** + * Display a dialog box that allows renaming of tags + */ + void slotRenameTag(); + + /** + * Delete the selected bookmark + */ + void slotDeleteBookmark(); + +signals: + /** + * Emit a signal to the plugin interface that a @p url has been left-clicked + */ + void signalURLClicked( const KURL & url, const KParts::URLArgs & args = KParts::URLArgs() ); + + /** + * Emit a signal to the plugin interface that a @p url has been mid-clicked + */ + void signalURLMidClicked( const KURL & url, const KParts::URLArgs & args = KParts::URLArgs() ); + +private: + /** + * @return list of checked tags + */ + QStringList checkedTags() const; + + /** + * Save the tag list to the config file + */ + void saveTags(); + + /** + * Load the tag list from the config file + */ + void loadTags(); + + QTimer *m_updateTimer; + KURL m_currentURL; + QStringList m_tags; + KConfig * m_config; +}; + +#endif diff --git a/konq-plugins/sidebar/delicious/pics/Makefile.am b/konq-plugins/sidebar/delicious/pics/Makefile.am new file mode 100644 index 0000000..e5515a8 --- /dev/null +++ b/konq-plugins/sidebar/delicious/pics/Makefile.am @@ -0,0 +1 @@ +KDE_ICON = AUTO diff --git a/konq-plugins/sidebar/delicious/pics/cr16-app-konqsidebar_delicious.png b/konq-plugins/sidebar/delicious/pics/cr16-app-konqsidebar_delicious.png Binary files differnew file mode 100644 index 0000000..f28df92 --- /dev/null +++ b/konq-plugins/sidebar/delicious/pics/cr16-app-konqsidebar_delicious.png diff --git a/konq-plugins/sidebar/delicious/plugin.cpp b/konq-plugins/sidebar/delicious/plugin.cpp new file mode 100644 index 0000000..cd400aa --- /dev/null +++ b/konq-plugins/sidebar/delicious/plugin.cpp @@ -0,0 +1,108 @@ +////////////////////////////////////////////////////////////////////////// +// plugin.cpp // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#include "plugin.h" + +#include <qstring.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kglobal.h> + +KonqSidebarDelicious::KonqSidebarDelicious( KInstance *instance, QObject *parent, + QWidget *widgetParent, QString &desktopName_, + const char* name ) + : KonqSidebarPlugin( instance, parent, widgetParent, desktopName_, name ), + DCOPObject( "sidebar-delicious" ) + +{ + m_widget = new MainWidget( instance->config(), widgetParent ); + connect( m_widget, SIGNAL( signalURLClicked( const KURL &, const KParts::URLArgs & ) ), + this, SIGNAL( openURLRequest( const KURL &, const KParts::URLArgs & ) ) ); + connect( m_widget, SIGNAL( signalURLMidClicked( const KURL &, const KParts::URLArgs & ) ), + this, SIGNAL( createNewWindow( const KURL &, const KParts::URLArgs & ) ) ); +} + +KonqSidebarDelicious::~KonqSidebarDelicious() +{ + +} + +void * KonqSidebarDelicious::provides( const QString & ) +{ + return 0; +} + +QWidget * KonqSidebarDelicious::getWidget() +{ + return m_widget; +} + +void KonqSidebarDelicious::handleURL( const KURL & url ) +{ + m_widget->setCurrentURL( url ); +} + +bool KonqSidebarDelicious::universalMode() +{ + return true; +} + +extern "C" +{ + KDE_EXPORT void* create_konqsidebar_delicious( KInstance *instance, QObject *par, QWidget *widp, + QString &desktopname, const char *name ) + { + KGlobal::locale()->insertCatalogue( "konqsidebar_delicious" ); + return new KonqSidebarDelicious( instance, par, widp, desktopname, name ); + } +} + +extern "C" +{ + KDE_EXPORT bool add_konqsidebar_delicious( QString* fn, QString* /*param*/, QMap<QString,QString> *map ) + { + map->insert("Type", "Link"); + map->insert("Icon", "konqsidebar_delicious"); + map->insert("Name", i18n( "del.icio.us Bookmarks" ) ); + map->insert("Open", "false"); + map->insert("X-KDE-KonqSidebarModule", "konqsidebar_delicious"); + fn->setLatin1("delicious%1.desktop"); + return true; + } +} + +QStringList KonqSidebarDelicious::tags() const +{ + return m_widget->tags(); +} + +QStringList KonqSidebarDelicious::bookmarks() const +{ + return m_widget->bookmarks(); +} + +void KonqSidebarDelicious::newBookmark() +{ + m_widget->slotNewBookmark(); +} + +#include "plugin.moc" diff --git a/konq-plugins/sidebar/delicious/plugin.h b/konq-plugins/sidebar/delicious/plugin.h new file mode 100644 index 0000000..96f7082 --- /dev/null +++ b/konq-plugins/sidebar/delicious/plugin.h @@ -0,0 +1,85 @@ +////////////////////////////////////////////////////////////////////////// +// plugin.h // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#ifndef _PLUGIN_H_ +#define _PLUGIN_H_ + +#include "mainWidget.h" + +#include <konqsidebarplugin.h> +#include <kparts/part.h> +#include <kparts/factory.h> +#include <kparts/browserextension.h> +#include <kinstance.h> +#include <dcopobject.h> + +class QString; + +/** + * @brief del.icio.us bookmarks plugin + * @author Lukas Tinkl <lukas@kde.org> + */ +class KonqSidebarDelicious: public KonqSidebarPlugin, DCOPObject +{ + Q_OBJECT + K_DCOP +public: + KonqSidebarDelicious( KInstance * instance, QObject * parent, QWidget * widgetParent, + QString & desktopName_, const char * name = 0 ); + ~KonqSidebarDelicious(); + virtual void * provides( const QString & ); + /** + * @return the main widget + */ + virtual QWidget * getWidget(); + +k_dcop: + QStringList tags() const; + QStringList bookmarks() const; + void newBookmark(); + +protected: + /** + * Called when the shell's @p url changes + */ + virtual void handleURL( const KURL & url ); + + /** + * @return true if we are in universal (e.g. desktop) mode + */ + bool universalMode(); + +signals: + /** + * Emitted in order to open @p url in the shell app + */ + void openURLRequest( const KURL & url, const KParts::URLArgs & args = KParts::URLArgs() ); + + /** + * Emitted in order to open @p url in the shell app's new window + */ + void createNewWindow( const KURL & url, const KParts::URLArgs & args = KParts::URLArgs() ); + +private: + MainWidget * m_widget; +}; + +#endif diff --git a/konq-plugins/sidebar/delicious/tagListItem.cpp b/konq-plugins/sidebar/delicious/tagListItem.cpp new file mode 100644 index 0000000..866cc09 --- /dev/null +++ b/konq-plugins/sidebar/delicious/tagListItem.cpp @@ -0,0 +1,78 @@ +////////////////////////////////////////////////////////////////////////// +// tagListItem.cpp // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#include "tagListItem.h" + +TagListItem::TagListItem( QListView * parent, const QString & tagName, int count ) + : QCheckListItem( parent, tagName, QCheckListItem::CheckBox ), m_name( tagName ), m_count( count ) +{ +} + +// virtual +void TagListItem::stateChange( bool state ) +{ + QCheckListItem::stateChange( state ); + emit signalItemChecked( this ); +} + +// virtual +int TagListItem::compare( QListViewItem * i, int col, bool ascending ) const +{ + if ( col == 1 ) + { + int them = static_cast<TagListItem *>( i )->count(); + if ( m_count < them ) + return -1; + else if ( m_count > them ) + return 1; + else + return 0; + } + return QCheckListItem::compare( i, col, ascending ); +} + +int TagListItem::count() const +{ + return m_count; +} + +// virtual +QString TagListItem::text( int column ) const +{ + if ( column == 0 ) + return m_name; + else if ( column == 1 ) + return QString::number( m_count ); + else + return QString::null; +} + +QString TagListItem::name() const +{ + return m_name; +} + +void TagListItem::setName( const QString & name ) +{ + m_name = name; +} + +#include "tagListItem.moc" diff --git a/konq-plugins/sidebar/delicious/tagListItem.h b/konq-plugins/sidebar/delicious/tagListItem.h new file mode 100644 index 0000000..0bc293e --- /dev/null +++ b/konq-plugins/sidebar/delicious/tagListItem.h @@ -0,0 +1,50 @@ +////////////////////////////////////////////////////////////////////////// +// tagListItem.h // +// // +// Copyright (C) 2005 Lukas Tinkl <lukas@kde.org> // +// // +// This program is free software; you can redistribute it and/or // +// modify it under the terms of the GNU General Public License // +// as published by the Free Software Foundation; either version 2 // +// of the License, or (at your option) any later version. // +// // +// This program is distributed in the hope that it will be useful, // +// but WITHOUT ANY WARRANTY; without even the implied warranty of // +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // +// GNU General Public License for more details. // +// // +// You should have received a copy of the GNU General Public License // +// along with this program; if not, write to the Free Software // +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA // +// 02111-1307, USA. // +////////////////////////////////////////////////////////////////////////// + +#ifndef _TAGLISTITEM_H_ +#define _TAGLISTITEM_H_ + +#include <qobject.h> +#include <qlistview.h> + +class TagListItem: public QObject, public QCheckListItem +{ + Q_OBJECT +public: + TagListItem( QListView * parent, const QString & tagName, int count = 1 ); + int count() const; + QString name() const; + void setName( const QString & name ); + +protected: + virtual void stateChange( bool state ); + virtual int compare( QListViewItem * i, int col, bool ascending ) const; + virtual QString text( int column ) const; + +signals: + void signalItemChecked( TagListItem * ); + +private: + QString m_name; + int m_count; +}; + +#endif diff --git a/konq-plugins/sidebar/delicious/widget.ui b/konq-plugins/sidebar/delicious/widget.ui new file mode 100644 index 0000000..daccbe9 --- /dev/null +++ b/konq-plugins/sidebar/delicious/widget.ui @@ -0,0 +1,165 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>MainWidget_base</class> +<author>Lukáš Tinkl <lukas@kde.org></author> +<widget class="QWidget"> + <property name="name"> + <cstring>Form1</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>411</width> + <height>595</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSplitter"> + <property name="name"> + <cstring>splitter3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="title"> + <string>Tags</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnRefreshTags</cstring> + </property> + <property name="text"> + <string>&Refresh Tags</string> + </property> + <property name="toolTip" stdset="0"> + <string>Refresh the list of tags</string> + </property> + </widget> + <widget class="QListView"> + <column> + <property name="text"> + <string>Tag</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Count</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>lvTags</cstring> + </property> + <property name="showSortIndicator"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + </widget> + </vbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Bookmarks</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton" row="1" column="0"> + <property name="name"> + <cstring>btnRefreshBookmarks</cstring> + </property> + <property name="text"> + <string>Refresh &Bookmarks</string> + </property> + <property name="toolTip" stdset="0"> + <string>Refresh the list of bookmarks according to the selected tags</string> + </property> + </widget> + <widget class="QPushButton" row="1" column="1"> + <property name="name"> + <cstring>btnNew</cstring> + </property> + <property name="text"> + <string>Post &New...</string> + </property> + <property name="toolTip" stdset="0"> + <string>Post a new bookmark</string> + </property> + </widget> + <widget class="KListView" row="0" column="0" rowspan="1" colspan="2"> + <column> + <property name="text"> + <string>Description</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>Date</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>lvBookmarks</cstring> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <property name="showSortIndicator"> + <bool>true</bool> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + <property name="itemsMovable"> + <bool>false</bool> + </property> + </widget> + </grid> + </widget> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klistview.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/sidebar/mediaplayer/AUTHORS b/konq-plugins/sidebar/mediaplayer/AUTHORS new file mode 100644 index 0000000..12b5dc2 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/AUTHORS @@ -0,0 +1,13 @@ +konqsidebarmediaplayer: +Joseph Wenninger <jowenn@kde.org> + + + +For the parts I took from kaboodle/noatun/...: + +Neil Stevens <multivac@fcmail.com> +Charles Samuels <charles@kde.org> +Stefan Schimanski <1Stein@gmx.de> +Malte Starostik <malte@kde.org> +Stefan Westerfeld <stefan@space.twc.de> +Nikolas Zimmermann <wildfox@kde.org> diff --git a/konq-plugins/sidebar/mediaplayer/COPYING b/konq-plugins/sidebar/mediaplayer/COPYING new file mode 100644 index 0000000..5714d40 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/COPYING @@ -0,0 +1,12 @@ +There are some licenses involved in this small plugin: +1) konqsidebarplugin.h: LGPL +2) player.*, engine.* are taken from noatun/kaboodle/arts and have there own licenes. + Look in these projects for their licenses (At the time I write this I think they are licencesed under the BSD + license) + +3) All other files are copyrighted under the GPL + + +Joseph Wenninger <jowenn@kde.org> + +June 23rd 2001 diff --git a/konq-plugins/sidebar/mediaplayer/Makefile.am b/konq-plugins/sidebar/mediaplayer/Makefile.am new file mode 100644 index 0000000..12ba913 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/Makefile.am @@ -0,0 +1,33 @@ +# this has all of the subdirectories that make will recurse into. if +# there are none, comment this out +SUBDIRS = . pics + +# set the include path for X, qt and KDE +INCLUDES = -I$(kde_includes)/kio -I$(kde_includes)/arts $(all_includes) + +# these are the headers for your project +noinst_HEADERS = +# let automoc handle all of the meta source files (moc) +METASOURCES = AUTO + +kde_module_LTLIBRARIES = konqsidebar_mediaplayer.la + +# the Part's source, library search path, and link libraries +konqsidebar_mediaplayer_la_SOURCES = mediawidget_skel.ui engine.cpp player.cpp mediawidget.cpp mediaplayer.cpp controls.cpp +konqsidebar_mediaplayer_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +konqsidebar_mediaplayer_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) -lkonqsidebarplugin -lqtmcop -lkmedia2_idl -lsoundserver_idl -lartskde + +globaladddir = $(kde_datadir)/konqsidebartng/add +globaladd_DATA = mplayer_add.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = mediaplayerplugin.desktop + +mediawidget_skel.ui: mediawidget_skel_designer.ui + perl -p -e "s/QSlider/L33tSlider/" mediawidget_skel_designer.ui >mediawidget_skel.ui + +extendedclean: + rm mediawidget_skel.* + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/konqsidebar_mediaplayer.pot diff --git a/konq-plugins/sidebar/mediaplayer/controls.cpp b/konq-plugins/sidebar/mediaplayer/controls.cpp new file mode 100644 index 0000000..76671d5 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/controls.cpp @@ -0,0 +1,138 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include "controls.h" + +L33tSlider::L33tSlider(QWidget * parent, const char * name) : + QSlider(parent,name), pressed(false) +{} +L33tSlider::L33tSlider(Orientation o, QWidget * parent, const char * name) : + QSlider(o,parent,name), pressed(false) +{} +L33tSlider::L33tSlider(int minValue, int maxValue, int pageStep, int value, + Orientation o, QWidget * parent, const char * name) : + QSlider(minValue, maxValue, pageStep, value, o, parent,name), pressed(false) +{} + +bool L33tSlider::currentlyPressed() const +{ + return pressed; +} + +void L33tSlider::setValue(int i) +{ + if (!pressed) + QSlider::setValue(i); +} + +void L33tSlider::mousePressEvent(QMouseEvent*e) +{ + if (e->button()!=RightButton) + { + pressed=true; + QSlider::mousePressEvent(e); + } +} + +void L33tSlider::mouseReleaseEvent(QMouseEvent*e) +{ + pressed=false; + QSlider::mouseReleaseEvent(e); + emit userChanged(value()); +} + +void L33tSlider::wheelEvent(QWheelEvent *e) +{ + QSlider::wheelEvent(e); + int newValue = value(); + + if(newValue < minValue()) + newValue = minValue(); + else if(newValue > maxValue()) + newValue = maxValue(); + + setValue(newValue); + emit userChanged(newValue); +} + +SliderAction::SliderAction(const QString& text, int accel, const QObject *receiver, + const char *member, QObject* parent, const char* name ) + : KAction( text, accel, parent, name ) +{ + m_receiver = receiver; + m_member = member; +} + +int SliderAction::plug( QWidget *w, int index ) +{ + if (!w->inherits("KToolBar")) return -1; + + KToolBar *toolBar = (KToolBar *)w; + int id = KAction::getToolButtonID(); + + //Create it. + m_slider=new L33tSlider(0, 1000, 100, 0, Horizontal, toolBar); + m_slider->setMinimumWidth(10); + toolBar->insertWidget(id, 10, m_slider, index ); + + + addContainer( toolBar, id ); + connect( toolBar, SIGNAL( destroyed() ), this, SLOT( slotDestroyed() ) ); + toolBar->setItemAutoSized( id, true ); + + if (w->inherits( "KToolBar" )) + connect(toolBar, SIGNAL(moved(KToolBar::BarPosition)), this, SLOT(toolbarMoved(KToolBar::BarPosition))); + + emit plugged(); + + return containerCount() - 1; +} + +void SliderAction::toolbarMoved(KToolBar::BarPosition) +{ +// I wish this worked :) +return; +/* + if (pos == KToolBar::Left || pos == KToolBar::Right) + { + m_slider->setOrientation(Vertical); + m_slider->setFixedWidth(m_slider->height()); + } + else + { + m_slider->setOrientation(Horizontal); + m_slider->resize(m_slider->height(), m_slider->height()); + } +*/ +} + +void SliderAction::unplug( QWidget *w ) +{ + KToolBar *toolBar = (KToolBar *)w; + int idx = findContainer( w ); + + toolBar->removeItem( itemId( idx ) ); + removeContainer( idx ); +} + +#include "controls.moc" diff --git a/konq-plugins/sidebar/mediaplayer/controls.h b/konq-plugins/sidebar/mediaplayer/controls.h new file mode 100644 index 0000000..d05a977 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/controls.h @@ -0,0 +1,93 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef __CONTROLS_H +#define __CONTROLS_H + +#include <qguardedptr.h> + +#include <kaction.h> +#include <ktoolbar.h> +#include <qslider.h> +#include <qstringlist.h> + +class QComboBox; +class QLabel; + +/** + * A slider that can be moved around while being + * changed internally + **/ +class L33tSlider : public QSlider +{ +Q_OBJECT +public: + L33tSlider(QWidget * parent, const char * name=0); + L33tSlider(Orientation, QWidget * parent, const char * name=0); + L33tSlider(int minValue, int maxValue, int pageStep, int value, + Orientation, QWidget * parent, const char * name=0); + + bool currentlyPressed() const; +signals: + /** + * emmited only when the user changes the value by hand + **/ + void userChanged(int value); + +public slots: + virtual void setValue(int); +protected: + virtual void mousePressEvent(QMouseEvent*); + virtual void mouseReleaseEvent(QMouseEvent*); + virtual void wheelEvent(QWheelEvent *e); + +private: + bool pressed; +}; + +/** + * A slider for your toolbar + **/ +class SliderAction : public KAction +{ +Q_OBJECT +public: + SliderAction(const QString& text, int accel, const QObject *receiver, + const char *member, QObject* parent, const char* name ); + virtual int plug( QWidget *w, int index = -1 ); + virtual void unplug( QWidget *w ); + QSlider* slider() const { return m_slider; } + +signals: + void plugged(); + +public slots: + void toolbarMoved(KToolBar::BarPosition pos); +private: + QGuardedPtr<QSlider> m_slider; + QStringList m_items; + const QObject *m_receiver; + const char *m_member; +}; + +#endif diff --git a/konq-plugins/sidebar/mediaplayer/engine.cpp b/konq-plugins/sidebar/mediaplayer/engine.cpp new file mode 100644 index 0000000..cdb9486 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/engine.cpp @@ -0,0 +1,207 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +extern "C" +{ +#include <sys/wait.h> +} + +#include <kconfig.h> +#include <kdebug.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <kstandarddirs.h> +#include <kurl.h> +#include <qtimer.h> +#include <qfile.h> +#include <qdir.h> + +#include <connect.h> +#include <dynamicrequest.h> +#include <flowsystem.h> +#include <kartsdispatcher.h> +#include <kartsserver.h> +#include <kplayobjectfactory.h> +#include <soundserver.h> + +#include "engine.h" +#include <string.h> + +using namespace std; + +class Engine::EnginePrivate +{ +public: + EnginePrivate() + : playobj(0) + , dispatcher() + , server() + { + } + + ~EnginePrivate() + { + delete playobj; + } + + KDE::PlayObject *playobj; + KArtsDispatcher dispatcher; + KArtsServer server; + KURL file; +}; + +Engine::Engine(QObject *parent) + : QObject(parent) + , d(new EnginePrivate) +{ +} + +Engine::~Engine() +{ + stop(); + delete d; +} + +bool Engine::load(const KURL &file) +{ + if(file.path().length()) + { + d->file = file; + return reload(); + } + else return false; +} + +bool Engine::reload(void) +{ + // Only You can prevent memory leaks + delete d->playobj; + d->playobj = 0; + + KDE::PlayObjectFactory factory(d->server.server()); + d->playobj = factory.createPlayObject(d->file, true); + + needReload = false; + + return !d->playobj->isNull(); +} + +void Engine::play() +{ + if(d->playobj) + { + switch(d->playobj->state()) + { + case Arts::posIdle: + if(needReload) + reload(); + d->playobj->play(); + break; + case Arts::posPaused: + d->playobj->play(); + break; + default: + break; + } + } +} + +void Engine::pause() +{ + if(d->playobj && !d->playobj->isNull()) + d->playobj->pause(); +} + +void Engine::stop() +{ + if(d->playobj && !d->playobj->isNull()) + { + d->playobj->halt(); + needReload = true; + } +} + +// pass time in msecs +void Engine::seek(unsigned long msec) +{ + Arts::poTime t; + + t.ms = (long) msec % 1000; + t.seconds = (long) ((long)msec - t.ms) / 1000; + + if(d->playobj && !d->playobj->isNull()) + d->playobj->seek(t); +} + +// return position in milliseconds +long Engine::position() +{ + if(!d->playobj || d->playobj->isNull()) return 0; + + Arts::poTime time(d->playobj->currentTime()); + return (time.ms + (time.seconds*1000)); +} + +// return track-length in milliseconds +unsigned long Engine::length() +{ + if(!d->playobj || d->playobj->isNull()) return 0; + + Arts::poTime time(d->playobj->overallTime()); + return (time.ms + (time.seconds*1000)); +} + +KMediaPlayer::Player::State Engine::state() +{ + if(!d->playobj || d->playobj->isNull()) return KMediaPlayer::Player::Empty; + + switch(d->playobj->state()) + { + case Arts::posIdle: + return KMediaPlayer::Player::Stop; + break; + case Arts::posPlaying: + return KMediaPlayer::Player::Play; + break; + case Arts::posPaused: + return KMediaPlayer::Player::Pause; + break; + default: + return KMediaPlayer::Player::Stop; + break; + } +} + +bool Engine::seekable(void) +{ + if(!d->playobj || d->playobj->isNull()) return false; + return d->playobj->capabilities() & Arts::capSeek; +} + +Arts::PlayObject Engine::playObject() const +{ + return d->playobj ? d->playobj->object() : Arts::PlayObject::null(); +} + +#include "engine.moc" diff --git a/konq-plugins/sidebar/mediaplayer/engine.h b/konq-plugins/sidebar/mediaplayer/engine.h new file mode 100644 index 0000000..1a5638f --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/engine.h @@ -0,0 +1,97 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef _ENGINE_H +#define _ENGINE_H + +#include <qobject.h> +#include <kmedia2.h> +#include <kmediaplayer/player.h> +#include <kurl.h> + +namespace Arts +{ +class PlayObject; +class SoundServerV2; +} + +/** + * Handles all playing, connecting to aRts. + * Does almost everything related to multimedia. + * Most interfacing should be done with Player + **/ +class Engine : public QObject +{ +Q_OBJECT + +public: + Engine(QObject *parent=0); + ~Engine(); + + Arts::PlayObject playObject() const; + +public slots: + /** + * Load a file + **/ + bool load(const KURL &file); + + /** + * Pause while playing + **/ + void pause(); + + /** + * Start + **/ + void play(); + + /** + * stops, and unloads + **/ + void stop(); + + /** + * skips to a time + **/ + void seek(unsigned long msec); + +public: + KMediaPlayer::Player::State state(); + long position(); // NOT unsigned + unsigned long length(); + + /** + * returns if the current track is seekable + */ + bool seekable(void); + +private: + bool reload(void); + bool needReload; + + class EnginePrivate; + EnginePrivate *d; +}; + +#endif diff --git a/konq-plugins/sidebar/mediaplayer/mediaplayer.cpp b/konq-plugins/sidebar/mediaplayer/mediaplayer.cpp new file mode 100644 index 0000000..ce8d1af --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediaplayer.cpp @@ -0,0 +1,74 @@ +/*************************************************************************** + mediaplayer.cpp - The real sidebar plugin + ------------------- + begin : Sat June 23 13:35:30 CEST 2001 + copyright : (C) 2001 Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "mediaplayer.h" +#include <klocale.h> +#include "mediaplayer.moc" +#include <kdebug.h> +#include <ksimpleconfig.h> +#include <kconfig.h> +#include <kstandarddirs.h> +#include <kmessagebox.h> +#include <kglobal.h> +#include <kdemacros.h> +#include "mediawidget.h" + +KonqSidebar_MediaPlayer::KonqSidebar_MediaPlayer(KInstance *instance,QObject *parent,QWidget *widgetParent, QString &desktopName_, const char* name): + KonqSidebarPlugin(instance,parent,widgetParent,desktopName_,name) + { + widget=new KSB_MediaWidget(widgetParent); + } + + +KonqSidebar_MediaPlayer::~KonqSidebar_MediaPlayer(){;} + +void* KonqSidebar_MediaPlayer::provides(const QString &) {return 0;} + +void KonqSidebar_MediaPlayer::emitStatusBarText (const QString &) {;} + +QWidget *KonqSidebar_MediaPlayer::getWidget(){return widget;} + +void KonqSidebar_MediaPlayer::handleURL(const KURL &/*url*/) + { + } + + + + +extern "C" +{ + KDE_EXPORT void* create_konqsidebar_mediaplayer(KInstance *instance,QObject *par,QWidget *widp,QString &desktopname,const char *name) + { + KGlobal::locale()->insertCatalogue("konqsidebar_mediaplayer"); + return new KonqSidebar_MediaPlayer(instance,par,widp,desktopname,name); + } +} + +extern "C" +{ + KDE_EXPORT bool add_konqsidebar_mediaplayer(QString* fn, QString* /*param*/, QMap<QString,QString> *map) + { + map->insert("Type","Link"); + map->insert("Icon","konqsidebar_mediaplayer"); + map->insert("Name",i18n("Media Player")); + map->insert("Open","false"); + map->insert("X-KDE-KonqSidebarModule","konqsidebar_mediaplayer"); + fn->setLatin1("mplayer%1.desktop"); + return true; + } +} + diff --git a/konq-plugins/sidebar/mediaplayer/mediaplayer.h b/konq-plugins/sidebar/mediaplayer/mediaplayer.h new file mode 100644 index 0000000..c563e20 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediaplayer.h @@ -0,0 +1,43 @@ +/*************************************************************************** + mediaplayer.h - The real sidebar plugin + ------------------- + begin : Sat June 23 13:35:30 CEST 2001 + copyright : (C) 2001 Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _konq_sidebar_mediaplayer_h_ +#define _konq_sidebar_mediaplayer_h_ +#include <konqsidebarplugin.h> +#include <kparts/part.h> +#include <kparts/factory.h> +#include <kparts/browserextension.h> + +class KSB_MediaWidget; + +class KonqSidebar_MediaPlayer: public KonqSidebarPlugin + { + Q_OBJECT + public: + KonqSidebar_MediaPlayer(KInstance *instance,QObject *parent,QWidget *widgetParent, QString &desktopName_, const char* name=0); + ~KonqSidebar_MediaPlayer(); + virtual void *provides(const QString &); + void emitStatusBarText (const QString &); + virtual QWidget *getWidget(); + protected: + virtual void handleURL(const KURL &url); + private: + KSB_MediaWidget *widget; + }; + + +#endif diff --git a/konq-plugins/sidebar/mediaplayer/mediaplayerplugin.desktop b/konq-plugins/sidebar/mediaplayer/mediaplayerplugin.desktop new file mode 100644 index 0000000..110fd36 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediaplayerplugin.desktop @@ -0,0 +1,115 @@ +[Desktop Entry] +Name=Mediaplayer +Name[ar]=مشغل الوسائط المتعددة +Name[az]=Mediya çalğıcısı +Name[bg]=Медия плеър +Name[br]=Soner liesvedia +Name[ca]=Reproductor Multimèdia +Name[cs]=Přehrávač médií +Name[cy]=Chwaraewr Cyfryngau +Name[da]=Medieafspiller +Name[de]=Medienabspieler +Name[el]=Αναπαραγωγέας μέσων +Name[eo]=Medioludilo +Name[es]=Reproductor de medios +Name[et]=Meediafailide mängija +Name[eu]=Multimedia-erreproduzigailua +Name[fa]=پخشکنندۀ رسانه +Name[fi]=Mediasoitin +Name[fr]=Lecteur multimédia +Name[fy]=Mediaspiler +Name[he]=נגן מדיה +Name[hi]=मीडिया-प्लेयर +Name[hr]=Medijski program +Name[hu]=Médialejátszó +Name[is]=Margmiðlunarspilari +Name[it]=Multimedia +Name[ja]=メディアプレーヤ +Name[kk]=Медиа ойнатқышы +Name[km]=កម្មវិធីចាក់មេឌៀ +Name[mk]=Медијаплеер +Name[nb]=Mediaspiller +Name[nds]=Medienafspeler +Name[ne]=मिडियाप्लेएर +Name[nl]=Mediaspeler +Name[nn]=Mediespelar +Name[nso]=Sebapadi sa Media +Name[pa]=ਮੀਡਿਆਪਲੇਅਰ +Name[pl]=Odtwarzacz multimedialny +Name[pt_BR]=Reprodutor de Mídia +Name[ro]=Redare multimedia +Name[ru]=Медиаплеер +Name[sk]=Prehrávač médií +Name[sv]=Mediaspelare +Name[ta]=ஊடக இயக்கி +Name[tg]=Медиаплеер +Name[tr]=Çokluortam oynatıcı +Name[uz]=Media-pleyer +Name[uz@cyrillic]=Медиа-плейер +Name[vi]=Bộ phát nhạc/ảnh +Name[xh]=Umdlali wosasazo lwendaba +Name[zh_CN]=媒体播放器 +Name[zh_TW]=媒體播放器 +Comment=Mediaplayer plugin in Konqueror's navigation panel +Comment[ar]=ملحق يشغل الوسائط المتعددة في لوحة التنقل في كونكيورر +Comment[az]=Konqueror-un naviqasiya panelindəki mediya çalğıcı əlavəsi +Comment[bg]=Навигационен панел за плеър за мултимедийни файлове +Comment[bs]=Mediaplayer dodatak za Konqueror-ov navigatorski panel +Comment[ca]=Connector del reproductor multimèdia en el plafó de navegació de Konqueror +Comment[cs]=Přehrávací modul pro postranní lištu Konqueroru +Comment[cy]=Ategyn chwarae cyfryngau yn y panel morlywio Konqueror +Comment[da]=Medieafspiller-plugin i Konquerors navigationspanel +Comment[de]=Medienabspieler-Modul im Navigationsbereich von Konqueror +Comment[el]=Πρόσθετο αναπαραγωγέα μέσων στο πλαίσιο πλοήγησης του Konqueror +Comment[eo]=Medioludila kromaĵo en foliuma panelo de Konkeranto +Comment[es]=Complemento del reproductor de medios en el panel de navegación de Konqueror +Comment[et]=Meediafailide mängija plugin Konquerori navigeerimispaneelil +Comment[eu]=Konquerorren arakatze paneleko multimedia-erreproduzigailuaren plugina +Comment[fa]=وصلۀ پخشکنندۀ رسانه در تابلوی ناوش Konqueror +Comment[fi]=Mediasoitinsovelma Konquerorin navigaatiopaneeliin +Comment[fr]=Le module de lecteur multimédia pour la barre de navigation de Konqueror +Comment[fy]=Mediaspiler-plugin foar Konqueror's navigaasjepaneel +Comment[ga]=Breiseán Mediaplayer i bpainéal nascleanúna Konqueror +Comment[gl]=Un plugin de reproduición multimédia no painel de navegación de Konqueror +Comment[he]=תוסף נגן מדיה ללוח הניווט של Konqueror +Comment[hi]=कॉन्करर के नेविगेशन फलक में मीडियाप्लेयर प्लगइन +Comment[hr]=Medijski dodatak u navigacijskoj ploči Konquerora +Comment[hu]=Médialejátszó bővítőmodul a Konqueror navigációs paneljéhez +Comment[is]=Margmiðlunareining fyrir spjaldið í Konqueror +Comment[it]=Plugin multimediale nella barra di navigazione di Konqueror +Comment[ja]=Konqueror のナビゲーションパネル内のメディアプレーヤプラグイン +Comment[ka]=Mediaplayer მოდული Konqueror-ის ნავიგაციის პანელზე +Comment[kk]=Konqueror панеліндегі медиа ойнатқыш плагин модулі +Comment[km]=កម្មវិធីជំនួយរបស់កម្មវិធីចាក់មេឌៀនៅក្នុងបន្ទះរុករករបស់ Konqueror +Comment[lt]=Mediaplayer priedas Konqueror navigacijos pulte +Comment[mk]=Приклучок за медијаплеер во панелот за навигација на Konqueror +Comment[ms]=Plugin Mediaplayer dalam panel Pandu Arah Konqueror +Comment[nb]=Mediaspiller-modul til Konquerors navigasjonspanel +Comment[nds]=Medienafspeler-Moduul för dat Sietpaneel vun Konqueror +Comment[ne]=कन्क्वेररको नेभिगेसन प्यानलको मिडियाप्लेएर प्लगइन +Comment[nl]=Mediaspeler-plugin voor Konqueror's navigatiepaneel +Comment[nn]=Mediespelar-programtillegg til navigasjonspanelet i Konqueror +Comment[pl]=Wtyczka odtwarzacza multimediów w panelu nawigacyjnym Konquerora +Comment[pt]=Um 'plugin' de reprodução multimédia no painel de navegação do Konqueror +Comment[pt_BR]=plug-ins do reprodutor de mídia no painel de navegação do Konqueror +Comment[ro]=Modul de redare multimedia în panoul de navigare Konqueror +Comment[ru]=Модуль Konqueror для проигрывания мультимедиа +Comment[sk]=Mediaplayer modul v navigačnom panely Konquerora +Comment[sl]=Vstavek večpredstavnostnega predvajalnika v Konquerorjevi navigacijski plošči +Comment[sr]=Прикључак за медија плејер у Konqueror-овом навигационом панелу +Comment[sr@Latn]=Priključak za medija plejer u Konqueror-ovom navigacionom panelu +Comment[sv]=Instickprogram för mediaspelare i Konquerors sidopanel +Comment[ta]=கான்கொரர்ரின் நாவிகேஷன் பலகத்தில் உள்ள ஊடக இயக்கி சொருகுப்பொருள் +Comment[tg]=Модули Konqueror барои бозӣ кардани мултимедиа +Comment[tr]=Konqueror çokluortam oynatıcısı +Comment[uk]=Втулок програвача в панелі навігації Konqueror +Comment[uz]=Konqueror yon paneli uchun multimediya fayllarini oʻynash vositasi +Comment[uz@cyrillic]=Konqueror ён панели учун мультимедия файлларини ўйнаш воситаси +Comment[vi]=Bổ sung phát nhạc/ảnh trên bảng duyệt qua Konqueror +Comment[xh]=Umdlali wosasazo lwendaba zeplagi yangaphakathi seqela lenjongo ethile lolawulo lwe Konqueror +Comment[zh_CN]=Konqueror 的导航面板中的媒体播放器插件 +Comment[zh_TW]=在 Konqueror 導覽面板上的媒體播放器外掛程式 +Icon=konqsidebar_mediaplayer +X-KDE-ParentApp=konqueror +X-KDE-KonqSidebarUniversal=true +DocPath=konq-plugins/mediaplayer/index.html diff --git a/konq-plugins/sidebar/mediaplayer/mediawidget.cpp b/konq-plugins/sidebar/mediaplayer/mediawidget.cpp new file mode 100644 index 0000000..c460c3c --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediawidget.cpp @@ -0,0 +1,169 @@ +/*************************************************************************** + mediawidget.cpp - The main widget + ------------------- + begin : Sat June 23 13:35:30 CEST 2001 + copyright : (C) 2001 Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#include "mediawidget.h" +#include "mediawidget.moc" +#include "player.h" + +#include <kdebug.h> +#include <kurl.h> +#include <kurldrag.h> +#include <klocale.h> + +#include <qlabel.h> +#include <qwidget.h> +#include <qpushbutton.h> +#include <qlcdnumber.h> +#include <qpopupmenu.h> +#include <qslider.h> +#include <qtooltip.h> + +KSB_MediaWidget::KSB_MediaWidget(QWidget *parent):KSB_MediaWidget_skel(parent) +{ + player = new Player(this); + empty(); + + QFont labelFont = time->font(); + labelFont.setPointSize(18); + labelFont.setBold(true); + time->setFont(labelFont); + + connect(Play, SIGNAL(clicked()), player, SLOT(play())); + connect(Pause, SIGNAL(clicked()), player, SLOT(pause())); + connect(Stop, SIGNAL(clicked()), player, SLOT(stop())); + + connect(player, SIGNAL(timeout()), this, SLOT(playerTimeout())); + connect(player, SIGNAL(finished()), this, SLOT(playerFinished())); + connect(player, SIGNAL(playing()), this, SLOT(playing())); + connect(player, SIGNAL(paused()), this, SLOT(paused())); + connect(player, SIGNAL(stopped()), this, SLOT(stopped())); + connect(player, SIGNAL(empty()), this, SLOT(empty())); + + connect(Position, SIGNAL(userChanged(int)), this, SLOT(skipToWrapper(int))); + connect(this, SIGNAL(skipTo(unsigned long)), player, SLOT(skipTo(unsigned long))); + setAcceptDrops(true); + + pretty=""; + needLengthUpdate=false; + + QToolTip::add(Play,i18n("Play")); + QToolTip::add(Pause,i18n("Pause")); + QToolTip::add(Stop,i18n("Stop")); +} + +void KSB_MediaWidget::skipToWrapper(int second) +{ + emit skipTo((unsigned long)(second*1000)); +} + +void KSB_MediaWidget::dragEnterEvent ( QDragEnterEvent * e) +{ + e->accept(KURLDrag::canDecode(e)); +} + +void KSB_MediaWidget::dropEvent ( QDropEvent * e) +{ + m_kuri_list.clear(); + if (KURLDrag::decode(e, m_kuri_list)) + { + playerFinished(); + } +} + + +void KSB_MediaWidget::playerTimeout() +{ + if(player->current().isEmpty()) + return; + + if(Position->currentlyPressed()) + return; + +// update the scrollbar length + if(player->getLength()) + { + int range = (int)(player->getLength() / 1000); + Position->setRange(0, range); + if (needLengthUpdate) + { + int counter = player->lengthString().length() - (player->lengthString().find("/")+1); + QString length=player->lengthString().right(counter); + needLengthUpdate=false; + } + } + else + { + Position->setRange(0, 1); + } + // set the position + Position->setValue((int)(player->getTime() / 1000)); + + // update the time label + // catch files with duration > 99mins correctly + time->setText(player->lengthString()); +} + +void KSB_MediaWidget::playerFinished() +{ + if( m_kuri_list.count() > 0 ) + { + KURL kurl = m_kuri_list.first(); + m_kuri_list.remove( kurl ); + bool validFile = player->openFile( kurl ); + if (validFile) { + currentFile->setText( kurl.fileName() ); + player->play(); + needLengthUpdate=true; + pretty=kurl.prettyURL(); + } else { + currentFile->setText( i18n("Not a sound file") ); + playerFinished(); + } + } +} + +void KSB_MediaWidget::playing() +{ + Play->setEnabled(false); + Pause->setEnabled(true); + Stop->setEnabled(true); +} + +void KSB_MediaWidget::paused() +{ + Play->setEnabled(true); + Pause->setEnabled(false); + Stop->setEnabled(true); +} + +void KSB_MediaWidget::stopped() +{ + Position->setValue(0); + time->setText("00:00/00:00"); + Play->setEnabled(true); + Pause->setEnabled(false); + Stop->setEnabled(false); +} + +void KSB_MediaWidget::empty() +{ + Position->setValue(0); + time->setText("00:00/00:00"); + Play->setEnabled(false); + Pause->setEnabled(false); + Stop->setEnabled(false); +} diff --git a/konq-plugins/sidebar/mediaplayer/mediawidget.h b/konq-plugins/sidebar/mediaplayer/mediawidget.h new file mode 100644 index 0000000..ff2137b --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediawidget.h @@ -0,0 +1,57 @@ +/*************************************************************************** + mediawidget.h - The main widget + ------------------- + begin : Sat June 23 13:35:30 CEST 2001 + copyright : (C) 2001 Joseph Wenninger + email : jowenn@kde.org + ***************************************************************************/ + +/*************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + ***************************************************************************/ + +#ifndef _MEDIAWIDGET_H_ +#define _MEDIAWIDGET_H_ + +#include <kurl.h> +#include "mediawidget_skel.h" + +class KSB_MediaWidget: public KSB_MediaWidget_skel +{ + Q_OBJECT +public: + KSB_MediaWidget(QWidget *parent); + ~KSB_MediaWidget(){;} + +private: + class Player *player; + QString pretty; + bool needLengthUpdate; + KURL::List m_kuri_list; + +protected: + virtual void dragEnterEvent ( QDragEnterEvent * ); + virtual void dropEvent ( QDropEvent * ); + +private slots: + void playerTimeout(); + void playerFinished(); + void playing(); + void paused(); + void stopped(); + void empty(); + +public slots: + void skipToWrapper(int); + +signals: + void skipTo(unsigned long); + +}; + +#endif diff --git a/konq-plugins/sidebar/mediaplayer/mediawidget_skel.ui b/konq-plugins/sidebar/mediaplayer/mediawidget_skel.ui new file mode 100644 index 0000000..8780a72 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediawidget_skel.ui @@ -0,0 +1,340 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>KSB_MediaWidget_skel</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KSB_MediaWidget_skel</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>277</width> + <height>151</height> + </rect> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>1</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer5_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>Play</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>Pause</cstring> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>Stop</cstring> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image2</pixmap> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="L33tSlider"> + <property name="name"> + <cstring>Position</cstring> + </property> + <property name="maxValue"> + <number>1000</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>Frame3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>time</cstring> + </property> + <property name="text"> + <cstring>00:00/00:00</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>Frame4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>currentFile</cstring> + </property> + <property name="text"> + <cstring>Drag sound files here</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6_3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer17</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<images> + <image name="image0"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141ac02ba68c4d4c199b98323631656c62cad8c494891423ce0ee2dc4c6418208bd55a7301009c7f45ef</data> + </image> + <image name="image1"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa08698b2b23294189c6254f36fad351700741b45ad</data> + </image> + <image name="image2"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa0869832140c5631aaf9b7d69a0b00046344fd</data> + </image> + <image name="image3"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa08d98321280ab431682eb45124298871042b2032e846c2f4c8846fe4013abb5e602007fec45ef</data> + </image> +</images> +<includes> + <include location="global" impldecl="in declaration">controls.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/konq-plugins/sidebar/mediaplayer/mediawidget_skel_designer.ui b/konq-plugins/sidebar/mediaplayer/mediawidget_skel_designer.ui new file mode 100644 index 0000000..a88dfde --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mediawidget_skel_designer.ui @@ -0,0 +1,340 @@ +<!DOCTYPE UI><UI version="3.0" stdsetdef="1"> +<class>KSB_MediaWidget_skel</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KSB_MediaWidget_skel</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>277</width> + <height>151</height> + </rect> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>1</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer5_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>Play</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>Pause</cstring> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>Stop</cstring> + </property> + <property name="maximumSize"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image2</pixmap> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>Position</cstring> + </property> + <property name="maxValue"> + <number>1000</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>Frame3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>time</cstring> + </property> + <property name="text"> + <cstring>00:00/00:00</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>Frame4</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <spacer> + <property name="name"> + <cstring>Spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>currentFile</cstring> + </property> + <property name="text"> + <cstring>Drag sound files here</cstring> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer6_3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer17</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<images> + <image name="image0"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141ac02ba68c4d4c199b98323631656c62cad8c494891423ce0ee2dc4c6418208bd55a7301009c7f45ef</data> + </image> + <image name="image1"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa08698b2b23294189c6254f36fad351700741b45ad</data> + </image> + <image name="image2"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa0869832140c5631aaf9b7d69a0b00046344fd</data> + </image> + <image name="image3"> + <data format="XPM.GZ" length="394">789cd3d7528808f055d0d2e72a2e492cc94c5648ce482c52d04a29cdcdad8c8eb5ade6523234530022230543251d2e253d856405bffcbc54105b19c856360003b0141aa08d98321280ab431682eb45124298871042b2032e846c2f4c8846fe4013abb5e602007fec45ef</data> + </image> +</images> +<includes> + <include location="global" impldecl="in declaration">controls.h</include> +</includes> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/konq-plugins/sidebar/mediaplayer/mplayer_add.desktop b/konq-plugins/sidebar/mediaplayer/mplayer_add.desktop new file mode 100644 index 0000000..1632ec4 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/mplayer_add.desktop @@ -0,0 +1,61 @@ +[Desktop Entry] +Type=Link +URL= +Icon=konqsidebar_mediaplayer +Name=Media Player +Name[bg]=Медия плеър +Name[br]=Soner liesvedia +Name[ca]=Reproductor Multimèdia +Name[cs]=Přehrávač médií +Name[cy]=Chwaraewr Cyfryngau +Name[da]=Medieafspiller +Name[de]=Medienabspieler +Name[el]=Αναπαραγωγέας μέσων +Name[eo]=Medioludilo +Name[es]=Reproductor de medios +Name[et]=Meediafailide mängija +Name[eu]=Multimedia erreproduzigailua +Name[fa]=پخشکنندۀ رسانه +Name[fi]=Mediasoitin +Name[fr]=Lecteur multimédia +Name[fy]=Mediaspiler +Name[ga]=Seinnteoir Meán +Name[gl]=Reprodutor Multimédia +Name[he]=נגן מדיה +Name[hi]=मीडिया-प्लेयर +Name[hr]=Multimedijski program +Name[hu]=Médialejátszó +Name[is]=Margmiðlunarspilari +Name[it]=Lettore multimediale +Name[ja]=メディアプレーヤ +Name[ka]=მედია დამკვრელი +Name[kk]=Медиа ойнатқышы +Name[km]=កម្មវិធីចាក់មេឌៀ +Name[lt]=Media grotuvas +Name[mk]=Медијаплеер +Name[nb]=Mediaspiller +Name[nds]=Medienafspeler +Name[ne]=मिडिया प्लेएर +Name[nl]=Mediaspeler +Name[nn]=Mediespelar +Name[pa]=ਮੀਡਿਆ ਪਲੇਅਰ +Name[pl]=Odtwarzacz multimedialny +Name[pt]=Reprodutor Multimédia +Name[pt_BR]=Reprodutor de Mídia +Name[ru]=Медиаплеер +Name[sk]=Prehrávač médií +Name[sl]=Večpredstavnostni predvajalnik +Name[sv]=Mediaspelare +Name[ta]=ஊடகங்கள் இயக்கி +Name[tg]=Медиаплеер +Name[tr]=Çokluortam Oynatıcı +Name[uk]=Медіа-програвач +Name[uz]=Media-pleyer +Name[uz@cyrillic]=Медиа-плейер +Name[vi]=Bộ phát nhạc và ảnh +Name[zh_CN]=媒体播放器 +Name[zh_TW]=媒體播放器 + +Open=false +X-KDE-KonqSidebarAddModule=konqsidebar_mediaplayer +X-KDE-KonqSidebarUniversal=true diff --git a/konq-plugins/sidebar/mediaplayer/pics/Makefile.am b/konq-plugins/sidebar/mediaplayer/pics/Makefile.am new file mode 100644 index 0000000..e5515a8 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/Makefile.am @@ -0,0 +1 @@ +KDE_ICON = AUTO diff --git a/konq-plugins/sidebar/mediaplayer/pics/cr16-app-konqsidebar_mediaplayer.png b/konq-plugins/sidebar/mediaplayer/pics/cr16-app-konqsidebar_mediaplayer.png Binary files differnew file mode 100644 index 0000000..71e4dd5 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/cr16-app-konqsidebar_mediaplayer.png diff --git a/konq-plugins/sidebar/mediaplayer/pics/cr22-app-konqsidebar_mediaplayer.png b/konq-plugins/sidebar/mediaplayer/pics/cr22-app-konqsidebar_mediaplayer.png Binary files differnew file mode 100644 index 0000000..838cf9d --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/cr22-app-konqsidebar_mediaplayer.png diff --git a/konq-plugins/sidebar/mediaplayer/pics/cr32-app-konqsidebar_mediaplayer.png b/konq-plugins/sidebar/mediaplayer/pics/cr32-app-konqsidebar_mediaplayer.png Binary files differnew file mode 100644 index 0000000..87ac58b --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/cr32-app-konqsidebar_mediaplayer.png diff --git a/konq-plugins/sidebar/mediaplayer/pics/cr48-app-konqsidebar_mediaplayer.png b/konq-plugins/sidebar/mediaplayer/pics/cr48-app-konqsidebar_mediaplayer.png Binary files differnew file mode 100644 index 0000000..509c022 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/cr48-app-konqsidebar_mediaplayer.png diff --git a/konq-plugins/sidebar/mediaplayer/pics/lo32-app-konqsidebar_mediaplayer.png b/konq-plugins/sidebar/mediaplayer/pics/lo32-app-konqsidebar_mediaplayer.png Binary files differnew file mode 100644 index 0000000..db177a9 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/pics/lo32-app-konqsidebar_mediaplayer.png diff --git a/konq-plugins/sidebar/mediaplayer/player.cpp b/konq-plugins/sidebar/mediaplayer/player.cpp new file mode 100644 index 0000000..360f8e8 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/player.cpp @@ -0,0 +1,180 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#include <kdebug.h> +#include <klocale.h> +#include <kurl.h> +#include <kmediaplayer/player.h> + +#include "engine.h" +#include "player.h" + +Player::Player(QObject *parent) + : QObject(parent) + , position(0) + , unfinished(false) +{ + mEngine = new Engine; + mLooping = false; + connect(&ticker, SIGNAL(timeout()), SLOT(tickerTimeout())); + ticker.start(500); + stop(); +} + +Player::~Player() +{ + delete mEngine; +} + +bool Player::isPlaying()const +{ + return mEngine->state() == KMediaPlayer::Player::Play; +} + +bool Player::isPaused()const +{ + return mEngine->state() == KMediaPlayer::Player::Pause; +} + +bool Player::isStopped()const +{ + return mEngine->state() == KMediaPlayer::Player::Stop || mEngine->state() == KMediaPlayer::Player::Empty; +} + +void Player::handleButtons() +{ + switch(mEngine->state()) + { + case KMediaPlayer::Player::Play: + emit playing(); + break; + case KMediaPlayer::Player::Pause: + emit paused(); + break; + case KMediaPlayer::Player::Stop: + emit stopped(); + break; + case KMediaPlayer::Player::Empty: + emit empty(); + break; + } +} + +void Player::stop(void) +{ + unfinished = false; + position = 0; + mEngine->stop(); +} + +void Player::play() +{ + mEngine->play(); +} + +void Player::pause() +{ + if(mEngine->state() == KMediaPlayer::Player::Play) + { + mEngine->pause(); + } +} + +// skip to a certain time in the track +void Player::skipTo(unsigned long msec) +{ + if(!mCurrent.isEmpty()) + mEngine->seek(msec); +} + +void Player::tickerTimeout() +{ + position = mEngine->position(); + mLength = mEngine->length(); + + handleButtons(); + + if(mEngine->state() == KMediaPlayer::Player::Stop && unfinished) + { + if(mLooping) + { + play(); + } + else + { + stop(); + emit finished(); + } + } + else if(mEngine->state() != KMediaPlayer::Player::Stop) + { + emit timeout(); + unfinished = true; + } + +} + +QString Player::lengthString(long _position) +{ + if(_position == -1) _position = position; + + int posSecs = (int)(_position / 1000); + int posSeconds = posSecs % 60; + int posMinutes = (posSecs - posSeconds) / 60; + + int totSecs = (int)(mLength / 1000); + int totSeconds = totSecs % 60; + int totMinutes = (totSecs - totSeconds) / 60; + + QString result; + result.sprintf("%.2d:%.2d/%.2d:%.2d", posMinutes, posSeconds, totMinutes, totSeconds); + return result; +} + +bool Player::openFile(const KURL &f) +{ + stop(); + mCurrent = f; + + bool work = mEngine->load(mCurrent); + + if(!work) + { + mCurrent = KURL(); + return false; + } + else + { + emit opened(mCurrent); + tickerTimeout(); + return true; + } +} + +void Player::setLooping(bool b) +{ + mLooping = b; + emit loopingChange(mLooping); +} + +#include "player.moc" diff --git a/konq-plugins/sidebar/mediaplayer/player.h b/konq-plugins/sidebar/mediaplayer/player.h new file mode 100644 index 0000000..6acf146 --- /dev/null +++ b/konq-plugins/sidebar/mediaplayer/player.h @@ -0,0 +1,178 @@ +/***************************************************************** + +Copyright (c) 2000-2001 the noatun authors. See file AUTHORS. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIAB\ILITY, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +******************************************************************/ + +#ifndef PLAYER_H +#define PLAYER_H + +#include <qobject.h> +#include <qtimer.h> +#include <kurl.h> + +class Engine; + +/** + * This class has slots for all the common media player buttons + **/ +class Player : public QObject +{ +Q_OBJECT + +friend class KaboodlePart; +public: + Player(QObject *parent = 0); + ~Player(); + + /** + * returns a string with the time that can + * be used in the UI: + * CC:CC/LL:LL (mm:ss) + **/ + QString lengthString(long _position = -1); + + bool looping(void) const { return mLooping; } + + /** + * the position in milliseconds + **/ + long getTime() const { return position; } + + /** + * the track-length in milliseconds + **/ + unsigned long getLength() const { return mLength; } + + /** + * true if we're playing + **/ + bool isPlaying()const; + + /** + * true if paused + **/ + bool isPaused()const; + + /** + * true if stopped + **/ + bool isStopped()const; + + /** + * get the current opened URL + * this may be empty + **/ + KURL current() const { return mCurrent; } + + /** + * Change the file to have open + * @return true if file is playable, false otherwise + */ + bool openFile(const KURL &f); + +public slots: + /** + * force the playing/paused/stopped/playlist shown signals to + * be sent out + **/ + void handleButtons(); + + /** + * stop playing + **/ + void stop(void); + + /** + * start playing + **/ + void play(); + + /** + * pause playing + **/ + void pause(); + + /** + * skip to the position + **/ + void skipTo(unsigned long msec); + + /** + * Set whether to restart playing when the playing is done + */ + void setLooping(bool); + +signals: + /** + * Tells you to update display information + **/ + void timeout(); + + /** + * State is to Empty + */ + void empty(); + + /** + * State is to Stopped + */ + void stopped(); + + /** + * State is to Playing + */ + void playing(); + + /** + * State is to Paused + */ + void paused(); + + /** + * The file ended, and looping was off + */ + void finished(); + + void loopingChange(bool); + + /** + * The current URL changed + */ + void opened(const KURL &); + +private slots: + void tickerTimeout(); + +protected: + Engine *engine()const { return mEngine; } + +private: + Engine *mEngine; + QTimer ticker; + long position; + bool mLooping; + unsigned long mLength; + KURL mCurrent; + bool unfinished; +}; + +#endif + diff --git a/konq-plugins/sidebar/metabar/AUTHORS b/konq-plugins/sidebar/metabar/AUTHORS new file mode 100644 index 0000000..01255ff --- /dev/null +++ b/konq-plugins/sidebar/metabar/AUTHORS @@ -0,0 +1 @@ +Florian Roth <florian@synatic.net> diff --git a/konq-plugins/sidebar/metabar/COPYING b/konq-plugins/sidebar/metabar/COPYING new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/konq-plugins/sidebar/metabar/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/konq-plugins/sidebar/metabar/ChangeLog b/konq-plugins/sidebar/metabar/ChangeLog new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/ChangeLog diff --git a/konq-plugins/sidebar/metabar/Doxyfile b/konq-plugins/sidebar/metabar/Doxyfile new file mode 100644 index 0000000..323c79e --- /dev/null +++ b/konq-plugins/sidebar/metabar/Doxyfile @@ -0,0 +1,275 @@ +# Doxyfile 1.4.1-KDevelop + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- +PROJECT_NAME = metabar.kdevelop +PROJECT_NUMBER = 0.1 +OUTPUT_DIRECTORY = +CREATE_SUBDIRS = NO +OUTPUT_LANGUAGE = English +USE_WINDOWS_ENCODING = NO +BRIEF_MEMBER_DESC = YES +REPEAT_BRIEF = YES +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the +ALWAYS_DETAILED_SEC = NO +INLINE_INHERITED_MEMB = NO +FULL_PATH_NAMES = YES +STRIP_FROM_PATH = /home/florian/metabar_widget/debug/src/ +STRIP_FROM_INC_PATH = +SHORT_NAMES = NO +JAVADOC_AUTOBRIEF = NO +MULTILINE_CPP_IS_BRIEF = NO +DETAILS_AT_TOP = NO +INHERIT_DOCS = YES +DISTRIBUTE_GROUP_DOC = NO +TAB_SIZE = 8 +ALIASES = +OPTIMIZE_OUTPUT_FOR_C = NO +OPTIMIZE_OUTPUT_JAVA = NO +SUBGROUPING = YES +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- +EXTRACT_ALL = NO +EXTRACT_PRIVATE = NO +EXTRACT_STATIC = NO +EXTRACT_LOCAL_CLASSES = YES +EXTRACT_LOCAL_METHODS = NO +HIDE_UNDOC_MEMBERS = NO +HIDE_UNDOC_CLASSES = NO +HIDE_FRIEND_COMPOUNDS = NO +HIDE_IN_BODY_DOCS = NO +INTERNAL_DOCS = NO +CASE_SENSE_NAMES = YES +HIDE_SCOPE_NAMES = NO +SHOW_INCLUDE_FILES = YES +INLINE_INFO = YES +SORT_MEMBER_DOCS = YES +SORT_BRIEF_DOCS = NO +SORT_BY_SCOPE_NAME = NO +GENERATE_TODOLIST = YES +GENERATE_TESTLIST = YES +GENERATE_BUGLIST = YES +GENERATE_DEPRECATEDLIST= YES +ENABLED_SECTIONS = +MAX_INITIALIZER_LINES = 30 +SHOW_USED_FILES = YES +SHOW_DIRECTORIES = YES +FILE_VERSION_FILTER = +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- +QUIET = NO +WARNINGS = YES +WARN_IF_UNDOCUMENTED = YES +WARN_IF_DOC_ERROR = YES +WARN_NO_PARAMDOC = NO +WARN_FORMAT = "$file:$line: $text" +WARN_LOGFILE = +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- +INPUT = /home/florian/metabar +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.java \ + *.ii \ + *.ixx \ + *.ipp \ + *.i++ \ + *.inl \ + *.h \ + *.hh \ + *.hxx \ + *.hpp \ + *.h++ \ + *.idl \ + *.odl \ + *.cs \ + *.php \ + *.php3 \ + *.inc \ + *.m \ + *.mm \ + *.dox \ + *.C \ + *.CC \ + *.C++ \ + *.II \ + *.I++ \ + *.H \ + *.HH \ + *.H++ \ + *.CS \ + *.PHP \ + *.PHP3 \ + *.M \ + *.MM \ + *.C \ + *.H \ + *.tlh \ + *.diff \ + *.patch \ + *.moc \ + *.xpm \ + *.dox +RECURSIVE = yes +EXCLUDE = +EXCLUDE_SYMLINKS = NO +EXCLUDE_PATTERNS = +EXAMPLE_PATH = +EXAMPLE_PATTERNS = * +EXAMPLE_RECURSIVE = NO +IMAGE_PATH = +INPUT_FILTER = +FILTER_PATTERNS = +FILTER_SOURCE_FILES = NO +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- +SOURCE_BROWSER = NO +INLINE_SOURCES = NO +STRIP_CODE_COMMENTS = YES +REFERENCED_BY_RELATION = YES +REFERENCES_RELATION = YES +VERBATIM_HEADERS = YES +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- +ALPHABETICAL_INDEX = NO +COLS_IN_ALPHA_INDEX = 5 +IGNORE_PREFIX = +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- +GENERATE_HTML = YES +HTML_OUTPUT = html +HTML_FILE_EXTENSION = .html +HTML_HEADER = +HTML_FOOTER = +HTML_STYLESHEET = +HTML_ALIGN_MEMBERS = YES +GENERATE_HTMLHELP = NO +CHM_FILE = +HHC_LOCATION = +GENERATE_CHI = NO +BINARY_TOC = NO +TOC_EXPAND = NO +DISABLE_INDEX = NO +ENUM_VALUES_PER_LINE = 4 +GENERATE_TREEVIEW = NO +TREEVIEW_WIDTH = 250 +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- +GENERATE_LATEX = YES +LATEX_OUTPUT = latex +LATEX_CMD_NAME = latex +MAKEINDEX_CMD_NAME = makeindex +COMPACT_LATEX = NO +PAPER_TYPE = a4wide +EXTRA_PACKAGES = +LATEX_HEADER = +PDF_HYPERLINKS = NO +USE_PDFLATEX = NO +LATEX_BATCHMODE = NO +LATEX_HIDE_INDICES = NO +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- +GENERATE_RTF = NO +RTF_OUTPUT = rtf +COMPACT_RTF = NO +RTF_HYPERLINKS = NO +RTF_STYLESHEET_FILE = +RTF_EXTENSIONS_FILE = +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- +GENERATE_MAN = NO +MAN_OUTPUT = man +MAN_EXTENSION = .3 +MAN_LINKS = NO +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- +GENERATE_XML = yes +XML_OUTPUT = xml +XML_SCHEMA = +XML_DTD = +XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- +GENERATE_AUTOGEN_DEF = NO +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- +GENERATE_PERLMOD = NO +PERLMOD_LATEX = NO +PERLMOD_PRETTY = YES +PERLMOD_MAKEVAR_PREFIX = +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- +ENABLE_PREPROCESSING = YES +MACRO_EXPANSION = NO +EXPAND_ONLY_PREDEF = NO +SEARCH_INCLUDES = YES +INCLUDE_PATH = +INCLUDE_FILE_PATTERNS = +PREDEFINED = +EXPAND_AS_DEFINED = +SKIP_FUNCTION_MACROS = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- +TAGFILES = +GENERATE_TAGFILE = metabar.tag +ALLEXTERNALS = NO +EXTERNAL_GROUPS = YES +PERL_PATH = /usr/bin/perl +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- +CLASS_DIAGRAMS = YES +HIDE_UNDOC_RELATIONS = YES +HAVE_DOT = NO +CLASS_GRAPH = YES +COLLABORATION_GRAPH = YES +GROUP_GRAPHS = YES +UML_LOOK = NO +TEMPLATE_RELATIONS = NO +INCLUDE_GRAPH = YES +INCLUDED_BY_GRAPH = YES +CALL_GRAPH = NO +GRAPHICAL_HIERARCHY = YES +DIRECTORY_GRAPH = YES +DOT_IMAGE_FORMAT = png +DOT_PATH = +DOTFILE_DIRS = +MAX_DOT_GRAPH_WIDTH = 1024 +MAX_DOT_GRAPH_HEIGHT = 1024 +MAX_DOT_GRAPH_DEPTH = 1000 +DOT_TRANSPARENT = NO +DOT_MULTI_TARGETS = NO +GENERATE_LEGEND = YES +DOT_CLEANUP = YES +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- +SEARCHENGINE = NO diff --git a/konq-plugins/sidebar/metabar/INSTALL b/konq-plugins/sidebar/metabar/INSTALL new file mode 100644 index 0000000..02a4a07 --- /dev/null +++ b/konq-plugins/sidebar/metabar/INSTALL @@ -0,0 +1,167 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes a while. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Type `make install' to install the programs and any data files and + documentation. + + 4. You can remove the program binaries and object files from the + source code directory by typing `make clean'. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. + diff --git a/konq-plugins/sidebar/metabar/Makefile.am b/konq-plugins/sidebar/metabar/Makefile.am new file mode 100644 index 0000000..af437a6 --- /dev/null +++ b/konq-plugins/sidebar/metabar/Makefile.am @@ -0,0 +1 @@ +SUBDIRS = src diff --git a/konq-plugins/sidebar/metabar/NEWS b/konq-plugins/sidebar/metabar/NEWS new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/NEWS diff --git a/konq-plugins/sidebar/metabar/README b/konq-plugins/sidebar/metabar/README new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/README diff --git a/konq-plugins/sidebar/metabar/TODO b/konq-plugins/sidebar/metabar/TODO new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/TODO diff --git a/konq-plugins/sidebar/metabar/config.h.in b/konq-plugins/sidebar/metabar/config.h.in new file mode 100644 index 0000000..978129e --- /dev/null +++ b/konq-plugins/sidebar/metabar/config.h.in @@ -0,0 +1,244 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <Carbon/Carbon.h> header file. */ +#undef HAVE_CARBON_CARBON_H + +/* Define if you have the CoreAudio API */ +#undef HAVE_COREAUDIO + +/* Define to 1 if you have the <crt_externs.h> header file. */ +#undef HAVE_CRT_EXTERNS_H + +/* Defines if your system has the crypt function */ +#undef HAVE_CRYPT + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define if you have libjpeg */ +#undef HAVE_LIBJPEG + +/* Define if you have libpng */ +#undef HAVE_LIBPNG + +/* Define if you have a working libpthread (will enable threaded code) */ +#undef HAVE_LIBPTHREAD + +/* Define if you have libz */ +#undef HAVE_LIBZ + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define if your system needs _NSGetEnviron to set up the environment */ +#undef HAVE_NSGETENVIRON + +/* Define if you have res_init */ +#undef HAVE_RES_INIT + +/* Define if you have the res_init prototype */ +#undef HAVE_RES_INIT_PROTO + +/* Define if you have a STL implementation by SGI */ +#undef HAVE_SGI_STL + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define if you have strlcat */ +#undef HAVE_STRLCAT + +/* Define if you have the strlcat prototype */ +#undef HAVE_STRLCAT_PROTO + +/* Define if you have strlcpy */ +#undef HAVE_STRLCPY + +/* Define if you have the strlcpy prototype */ +#undef HAVE_STRLCPY_PROTO + +/* Define to 1 if you have the <sys/bitypes.h> header file. */ +#undef HAVE_SYS_BITYPES_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Suffix for lib directories */ +#undef KDELIBSUFF + +/* Define a safe value for MAXPATHLEN */ +#undef KDEMAXPATHLEN + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of a `char *', as computed by sizeof. */ +#undef SIZEOF_CHAR_P + +/* The size of a `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of a `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of a `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of a `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of a `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Defined if compiling without arts */ +#undef WITHOUT_ARTS + +/* Define to 1 if your processor stores words with the most significant byte + first (like Motorola and SPARC, unlike Intel and VAX). */ +#undef WORDS_BIGENDIAN + +/* + * jpeg.h needs HAVE_BOOLEAN, when the system uses boolean in system + * headers and I'm too lazy to write a configure test as long as only + * unixware is related + */ +#ifdef _UNIXWARE +#define HAVE_BOOLEAN +#endif + + + +/* + * AIX defines FD_SET in terms of bzero, but fails to include <strings.h> + * that defines bzero. + */ + +#if defined(_AIX) +#include <strings.h> +#endif + + + +#if defined(HAVE_NSGETENVIRON) && defined(HAVE_CRT_EXTERNS_H) +# include <sys/time.h> +# include <crt_externs.h> +# define environ (*_NSGetEnviron()) +#endif + + + +#if !defined(HAVE_RES_INIT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +int res_init(void); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCAT_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcat(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +#if !defined(HAVE_STRLCPY_PROTO) +#ifdef __cplusplus +extern "C" { +#endif +unsigned long strlcpy(char*, const char*, unsigned long); +#ifdef __cplusplus +} +#endif +#endif + + + +/* + * On HP-UX, the declaration of vsnprintf() is needed every time ! + */ + +#if !defined(HAVE_VSNPRINTF) || defined(hpux) +#if __STDC__ +#include <stdarg.h> +#include <stdlib.h> +#else +#include <varargs.h> +#endif +#ifdef __cplusplus +extern "C" +#endif +int vsnprintf(char *str, size_t n, char const *fmt, va_list ap); +#ifdef __cplusplus +extern "C" +#endif +int snprintf(char *str, size_t n, char const *fmt, ...); +#endif + + + +#if defined(__SVR4) && !defined(__svr4__) +#define __svr4__ 1 +#endif + + +/* type to use in place of socklen_t if not defined */ +#undef kde_socklen_t + +/* type to use in place of socklen_t if not defined (deprecated, use + kde_socklen_t) */ +#undef ksize_t diff --git a/konq-plugins/sidebar/metabar/configure.in.in b/konq-plugins/sidebar/metabar/configure.in.in new file mode 100644 index 0000000..d2a3d40 --- /dev/null +++ b/konq-plugins/sidebar/metabar/configure.in.in @@ -0,0 +1,5 @@ +#MIN_CONFIG(3.2.0) + +AM_INIT_AUTOMAKE(metabar, 0.1) +AC_C_BIGENDIAN +AC_CHECK_KDEMAXPATHLEN diff --git a/konq-plugins/sidebar/metabar/metabar.kdevelop b/konq-plugins/sidebar/metabar/metabar.kdevelop new file mode 100644 index 0000000..e87e8d9 --- /dev/null +++ b/konq-plugins/sidebar/metabar/metabar.kdevelop @@ -0,0 +1,213 @@ +<?xml version = '1.0'?> +<kdevelop> + <general> + <author>Florian Roth</author> + <email>florian@synatic.net</email> + <version>0.1</version> + <projectmanagement>KDevKDEAutoProject</projectmanagement> + <primarylanguage>C++</primarylanguage> + <keywords> + <keyword>C++</keyword> + <keyword>Code</keyword> + <keyword>Qt</keyword> + <keyword>KDE</keyword> + <keyword>Kicker</keyword> + </keywords> + <ignoreparts/> + <projectdirectory>.</projectdirectory> + <absoluteprojectpath>false</absoluteprojectpath> + <description/> + <versioncontrol>kdevsubversion</versioncontrol> + </general> + <kdevautoproject> + <general> + <activetarget>src/konqsidebar_metabar.la</activetarget> + <useconfiguration>debug</useconfiguration> + </general> + <configurations> + <optimized> + <builddir>optimized</builddir> + <ccompiler>kdevgccoptions</ccompiler> + <cxxcompiler>kdevgppoptions</cxxcompiler> + <f77compiler>kdevg77options</f77compiler> + <cxxflags>-O2 -g0</cxxflags> + </optimized> + <debug> + <configargs>--enable-debug=full --prefix=`kde-config --prefix`</configargs> + <builddir>debug</builddir> + <ccompiler>kdevgccoptions</ccompiler> + <cxxcompiler>kdevgppoptions</cxxcompiler> + <f77compiler>kdevg77options</f77compiler> + <cxxflags>-O0 -g3</cxxflags> + <envvars/> + <topsourcedir/> + <cppflags/> + <ldflags/> + <ccompilerbinary/> + <cxxcompilerbinary/> + <f77compilerbinary/> + <cflags/> + <f77flags/> + </debug> + </configurations> + <make> + <envvars> + <envvar value="1" name="WANT_AUTOCONF_2_5" /> + <envvar value="1" name="WANT_AUTOMAKE_1_6" /> + </envvars> + <abortonerror>true</abortonerror> + <numberofjobs>1</numberofjobs> + <dontact>false</dontact> + <makebin/> + <prio>0</prio> + </make> + <run> + <directoryradio>executable</directoryradio> + <customdirectory>/</customdirectory> + <mainprogram/> + <programargs/> + <terminal>false</terminal> + <autocompile>true</autocompile> + <envvars/> + </run> + </kdevautoproject> + <kdevfileview> + <groups> + <group pattern="*.cpp;*.cxx;*.h" name="Sources" /> + <group pattern="*.ui" name="User Interface" /> + <group pattern="*.png" name="Icons" /> + <group pattern="*.po;*.ts" name="Translations" /> + <group pattern="*" name="Others" /> + <hidenonprojectfiles>false</hidenonprojectfiles> + <hidenonlocation>false</hidenonlocation> + </groups> + <tree> + <hidepatterns>*.o,*.lo,CVS</hidepatterns> + <hidenonprojectfiles>false</hidenonprojectfiles> + <showvcsfields>false</showvcsfields> + </tree> + </kdevfileview> + <kdevdoctreeview> + <ignoretocs> + <toc>ada</toc> + <toc>ada_bugs_gcc</toc> + <toc>bash</toc> + <toc>bash_bugs</toc> + <toc>clanlib</toc> + <toc>fortran_bugs_gcc</toc> + <toc>gnome1</toc> + <toc>gnustep</toc> + <toc>gtk</toc> + <toc>gtk_bugs</toc> + <toc>haskell</toc> + <toc>haskell_bugs_ghc</toc> + <toc>java_bugs_gcc</toc> + <toc>java_bugs_sun</toc> + <toc>opengl</toc> + <toc>pascal_bugs_fp</toc> + <toc>php</toc> + <toc>php_bugs</toc> + <toc>perl</toc> + <toc>perl_bugs</toc> + <toc>python</toc> + <toc>python_bugs</toc> + <toc>ruby</toc> + <toc>ruby_bugs</toc> + <toc>sdl</toc> + <toc>stl</toc> + <toc>sw</toc> + <toc>w3c-dom-level2-html</toc> + <toc>w3c-svg</toc> + <toc>w3c-uaag10</toc> + <toc>wxwidgets_bugs</toc> + </ignoretocs> + <ignoreqt_xml> + <toc>qmake User Guide</toc> + </ignoreqt_xml> + </kdevdoctreeview> + <kdevdebugger> + <general> + <dbgshell>libtool</dbgshell> + <programargs/> + <gdbpath/> + <configGdbScript/> + <runShellScript/> + <runGdbScript/> + <breakonloadinglibs>true</breakonloadinglibs> + <separatetty>false</separatetty> + <floatingtoolbar>false</floatingtoolbar> + </general> + <display> + <staticmembers>false</staticmembers> + <demanglenames>true</demanglenames> + <outputradix>10</outputradix> + </display> + </kdevdebugger> + <kdevfilecreate> + <filetypes/> + <useglobaltypes> + <type ext="ui" /> + <type ext="cpp" /> + <type ext="h" /> + </useglobaltypes> + </kdevfilecreate> + <kdevdocumentation> + <projectdoc> + <docsystem>Doxygen-Dokumentation</docsystem> + <docurl>sidebar.tag</docurl> + <usermanualurl/> + </projectdoc> + </kdevdocumentation> + <substmap> + <APPNAME>sidebar</APPNAME> + <APPNAMELC>sidebar</APPNAMELC> + <APPNAMESC>Sidebar</APPNAMESC> + <APPNAMEUC>SIDEBAR</APPNAMEUC> + <AUTHOR>Florian Roth</AUTHOR> + <EMAIL>florian@synatic.net</EMAIL> + <LICENSE>GPL</LICENSE> + <LICENSEFILE>COPYING</LICENSEFILE> + <VERSION>0.1</VERSION> + <YEAR>2005</YEAR> + <dest>/home/florian/sidebar</dest> + </substmap> + <cppsupportpart> + <filetemplates> + <interfacesuffix>.h</interfacesuffix> + <implementationsuffix>.cpp</implementationsuffix> + </filetemplates> + </cppsupportpart> + <kdevcppsupport> + <codecompletion> + <includeGlobalFunctions>true</includeGlobalFunctions> + <includeTypes>true</includeTypes> + <includeEnums>true</includeEnums> + <includeTypedefs>false</includeTypedefs> + <automaticCodeCompletion>true</automaticCodeCompletion> + <automaticArgumentsHint>true</automaticArgumentsHint> + <automaticHeaderCompletion>true</automaticHeaderCompletion> + <codeCompletionDelay>250</codeCompletionDelay> + <argumentsHintDelay>400</argumentsHintDelay> + <headerCompletionDelay>250</headerCompletionDelay> + </codecompletion> + <creategettersetter> + <prefixGet/> + <prefixSet>set</prefixSet> + <prefixVariable>m_,_</prefixVariable> + <parameterName>theValue</parameterName> + <inlineGet>true</inlineGet> + <inlineSet>true</inlineSet> + </creategettersetter> + <references/> + <designerintegration> + <qtdesigner> + <implementation class="ThemeEditor" path="src/editor/themeeditor.ui" implementationpath="src/editor/themeeditor.h" /> + <implementation class="ThemeEditor" path="src/editor/themeeditorui.ui" implementationpath="src/editor/themeeditor.h" /> + </qtdesigner> + </designerintegration> + </kdevcppsupport> + <ctagspart> + <customArguments/> + <customTagfilePath/> + </ctagspart> +</kdevelop> diff --git a/konq-plugins/sidebar/metabar/metabar.kdevses b/konq-plugins/sidebar/metabar/metabar.kdevses new file mode 100644 index 0000000..f28c20e --- /dev/null +++ b/konq-plugins/sidebar/metabar/metabar.kdevses @@ -0,0 +1,47 @@ +<?xml version = '1.0' encoding = 'UTF-8'?> +<!DOCTYPE KDevPrjSession> +<KDevPrjSession> + <DocsAndViews NumberOfDocuments="8" > + <Doc0 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/metabarwidget.cpp" > + <View0 Type="Source" /> + </Doc0> + <Doc1 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/metabarwidget.h" > + <View0 line="84" Type="Source" /> + </Doc1> + <Doc2 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/configdialog.cpp" > + <View0 line="109" Type="Source" /> + </Doc2> + <Doc3 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/configdialog.h" > + <View0 line="69" Type="Source" /> + </Doc3> + <Doc4 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/protocolplugin.cpp" > + <View0 line="69" Type="Source" /> + </Doc4> + <Doc5 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/defaultplugin.cpp" > + <View0 line="343" Type="Source" /> + </Doc5> + <Doc6 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/httpplugin.cpp" > + <View0 line="76" Type="Source" /> + </Doc6> + <Doc7 NumberOfViews="1" URL="file:///home/florian/metabar/metabar/src/httpplugin.h" > + <View0 line="22" Type="Source" /> + </Doc7> + </DocsAndViews> + <pluginList> + <kdevdebugger> + <breakpointList/> + </kdevdebugger> + <kdevbookmarks> + <bookmarks/> + </kdevbookmarks> + <kdevsubversion> + <subversion recurseresolve="1" recurserelocate="1" recursemerge="1" recursecommit="1" base="" recursepropget="1" recurseswitch="1" recurseupdate="1" recursepropset="1" recursediff="1" recurserevert="1" forcemove="1" recursecheckout="1" forceremove="1" recurseadd="1" recurseproplist="1" forcemerge="1" /> + </kdevsubversion> + <kdevvalgrind> + <executable path="" params="" /> + <valgrind path="" params="" /> + <calltree path="calltree" params="" /> + <kcachegrind path="/usr/kde/3.4/bin/kcachegrind" /> + </kdevvalgrind> + </pluginList> +</KDevPrjSession> diff --git a/konq-plugins/sidebar/metabar/src/Makefile.am b/konq-plugins/sidebar/metabar/src/Makefile.am new file mode 100644 index 0000000..cd18deb --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = $(all_includes) -I$(kde_includes)/dom +METASOURCES = AUTO + +kde_module_LTLIBRARIES = konqsidebar_metabar.la + +KDE_ICON = AUTO + +konqsidebar_metabar_la_SOURCES = metabar.cpp metabarwidget.cpp configdialog.cpp \ + serviceloader.cpp defaultplugin.cpp protocolplugin.cpp settingsplugin.cpp \ + remoteplugin.cpp httpplugin.cpp metabarfunctions.cpp +konqsidebar_metabar_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -lkonqsidebarplugin +konqsidebar_metabar_la_LIBADD = $(LIB_KIO) $(LIB_KHTML) $(LIB_KPARTS) + +metabar_entrydir = $(kde_datadir)/konqsidebartng/entries +metabar_entry_DATA = metabar.desktop +metabar_adddir = $(kde_datadir)/konqsidebartng/add +metabar_add_DATA = metabar_add.desktop +metabar_datadir = $(kde_datadir)/metabar +metabar_data_DATA = iconsrc +metabar_themedir = $(kde_datadir)/metabar/themes/default +metabar_theme_DATA = default.css layout.html + +noinst_HEADERS = metabarwidget.h protocolplugin.h defaultplugin.h \ + settingsplugin.h remoteplugin.h httpplugin.h metabarfunctions.h + +messages: + $(XGETTEXT) *.cpp *.h -o $(podir)/konqsidebar_metabar.pot + diff --git a/konq-plugins/sidebar/metabar/src/configdialog.cpp b/konq-plugins/sidebar/metabar/src/configdialog.cpp new file mode 100644 index 0000000..a6ee429 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/configdialog.cpp @@ -0,0 +1,611 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + + +#include <qgroupbox.h> +#include <qlayout.h> +#include <qtabwidget.h> +#include <qlabel.h> +#include <qlineedit.h> +#include <qdir.h> +#include <qfileinfo.h> +#include <qmap.h> +#include <qcstring.h> +#include <qdatastream.h> + +#include <kdebug.h> +#include <klocale.h> +#include <kicondialog.h> +#include <kapplication.h> +#include <kiconloader.h> +#include <kstandarddirs.h> +#include <kfiledialog.h> +#include <ktar.h> +#include <karchive.h> +#include <dcopref.h> +#include <dcopclient.h> + +#include "configdialog.h" + +LinkEntry::LinkEntry(QString name, QString url, QString icon){ + LinkEntry::name = name; + LinkEntry::url = url; + LinkEntry::icon = icon; +} + +ActionListItem::ActionListItem(QListBox *listbox, const QString &action, const QString &text, const QPixmap &pixmap) : QListBoxPixmap(listbox, pixmap) +{ + setAction(action); + setText(text); +} + +ConfigDialog::ConfigDialog(QWidget *parent, const char *name) : QDialog(parent, name) +{ + topWidgetName = parent->topLevelWidget()->name(); + config = new KConfig("metabarrc"); + iconConfig = new KConfig(locate("data", "metabar/iconsrc")); + + setCaption(i18n("Configuration - Metabar")); + setIcon(SmallIcon("metabar")); + + ok = new KPushButton(KStdGuiItem::ok(), this); + connect(ok, SIGNAL(clicked()), this, SLOT(accept())); + + cancel = new KPushButton(KStdGuiItem::cancel(), this); + connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); + + QTabWidget *tab = new QTabWidget(this); + + //general page + config->setGroup("General"); + QWidget *general = new QWidget; + + QGroupBox *entries_group = new QGroupBox(2, Qt::Horizontal, i18n("Items"), general); + entries_group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + QLabel *entries_label = new QLabel(i18n("Open with:"), entries_group); + max_entries = new KIntSpinBox(entries_group); + max_entries->setMinValue(1); + max_entries->setMaxValue(99); + max_entries->setLineStep(1); + max_entries->setValue(config->readNumEntry("MaxEntries", 3)); + entries_label->setBuddy(max_entries); + + QLabel *actions_label = new QLabel(i18n("Actions:"), entries_group); + max_actions = new KIntSpinBox(entries_group); + max_actions->setMinValue(1); + max_actions->setMaxValue(99); + max_actions->setLineStep(1); + max_actions->setValue(config->readNumEntry("MaxActions", 3)); + actions_label->setBuddy(max_actions); + + + QGroupBox *appearance_group = new QGroupBox(1, Qt::Horizontal, i18n("Appearance"), general); + appearance_group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + animate = new QCheckBox(i18n("Animate resize"), appearance_group); + animate->setChecked(config->readBoolEntry("AnimateResize", false)); + + servicemenus = new QCheckBox(i18n("Show service menus"), appearance_group); + servicemenus->setChecked(config->readBoolEntry("ShowServicemenus", true)); + + showframe = new QCheckBox(i18n("Show frame"), appearance_group); + showframe->setChecked(config->readBoolEntry("ShowFrame", true)); + + QGroupBox *theme_group = new QGroupBox(2, Qt::Horizontal, i18n("Themes"), general); + theme_group->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + + themes = new KComboBox(theme_group); + themes->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); + + install_theme = new KPushButton(i18n("Install New Theme..."), theme_group); + install_theme->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred); + connect(install_theme, SIGNAL(clicked()), this, SLOT(installTheme())); + + loadThemes(); + + //link page + QWidget *links = new QWidget; + + link_create = new KPushButton(i18n("New..."), links); + connect(link_create, SIGNAL(clicked()), this, SLOT(createLink())); + + link_delete = new KPushButton(i18n("Delete"), links); + connect(link_delete, SIGNAL(clicked()), this, SLOT(deleteLink())); + + link_edit = new KPushButton(i18n("Edit..."), links); + connect(link_edit, SIGNAL(clicked()), this, SLOT(editLink())); + + link_up = new KPushButton(links); + link_up->setIconSet(SmallIconSet("up")); + link_up->setEnabled(false); + connect(link_up, SIGNAL(clicked()), this, SLOT(moveLinkUp())); + + link_down = new KPushButton(links); + link_down->setIconSet(SmallIconSet("down")); + link_down->setEnabled(false); + connect(link_down, SIGNAL(clicked()), this, SLOT(moveLinkDown())); + + link_list = new KListView(links); + link_list->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + link_list->setSorting(-1); + link_list->setItemsMovable(TRUE); + link_list->addColumn(i18n("Name")); + link_list->addColumn(i18n("Address")); + connect(link_list, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(editLink(QListViewItem*))); + connect(link_list, SIGNAL(selectionChanged()), SLOT(updateArrows())); + + QWidget *actionPage = new QWidget; + + actionSelector = new KActionSelector(actionPage); + loadAvailableActions(); + + tab->addTab(general, i18n("General")); + tab->addTab(actionPage, i18n("Actions")); + tab->addTab(links, i18n("Links")); + + //layout + QGridLayout *general_layout = new QGridLayout(general, 2, 2, 5, 5); + general_layout->addWidget(entries_group, 0, 0); + general_layout->addWidget(appearance_group, 0, 1); + general_layout->addMultiCellWidget(theme_group, 1, 1, 0, 1); + general_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding), 2, 0); + //general_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding), 0, 2); + + QVBoxLayout *link_button_layout = new QVBoxLayout(0, 0, 5); + link_button_layout->addWidget(link_create); + link_button_layout->addWidget(link_edit); + link_button_layout->addWidget(link_delete); + link_button_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding)); + link_button_layout->addWidget(link_up); + link_button_layout->addWidget(link_down); + + QHBoxLayout *link_layout = new QHBoxLayout(links, 5, 5); + link_layout->addWidget(link_list); + link_layout->addLayout(link_button_layout); + + QHBoxLayout *action_layout = new QHBoxLayout(actionPage, 5, 5); + action_layout->addWidget(actionSelector); + + QHBoxLayout *bottom_layout = new QHBoxLayout(0, 5, 5); + bottom_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum)); + bottom_layout->addWidget(ok); + bottom_layout->addWidget(cancel); + + QVBoxLayout *main_layout = new QVBoxLayout(this, 5, 5); + main_layout->addWidget(tab); + main_layout->addLayout(bottom_layout); + + //load config + config->setGroup("General"); + + QStringList _links = config->readListEntry("Links"); + + for(QStringList::Iterator it = _links.begin(); it != _links.end(); ++it){ + config->setGroup("Link_" + (*it)); + + QString icon_str = config->readEntry("Icon", "folder"); + QPixmap icon(icon_str); + if(icon.isNull()){ + icon = SmallIcon(icon_str); + } + + QListViewItem *item = new QListViewItem(link_list, link_list->lastItem(), config->readEntry("Name"), config->readEntry("URL")); + item->setPixmap(0, icon); + + linkList.insert(item, new LinkEntry(config->readEntry("Name"), config->readEntry("URL"), icon_str)); + } + + config->setGroup("General"); + QStringList actions = config->readListEntry("Actions"); + for(QStringList::Iterator it = actions.begin(); it != actions.end(); ++it){ + if((*it).startsWith("metabar/")){ + if((*it).right((*it).length() - 8) == "share"){ + QString text = i18n("Share"); + + ActionListItem *item = new ActionListItem(actionSelector->selectedListBox(), *it, text, SmallIcon("network")); + + QListBoxItem *avItem = actionSelector->availableListBox()->findItem(text, Qt::ExactMatch); + if(avItem){ + delete avItem; + } + } + } + else{ + DCOPRef action(kapp->dcopClient()->appId(), QCString(topWidgetName).append("/action/").append((*it).utf8())); + + QString text = action.call("plainText()"); + QString icon = iconConfig->readEntry(*it, action.call("icon()")); + + ActionListItem *item = new ActionListItem(actionSelector->selectedListBox(), QString(*it), text, SmallIcon(icon)); + + QListBoxItem *avItem = actionSelector->availableListBox()->findItem(text, Qt::ExactMatch); + if(avItem){ + delete avItem; + } + } + } + + resize(400, 300); +} + +ConfigDialog::~ConfigDialog() +{ + delete config; + delete iconConfig; +} + +void ConfigDialog::accept() +{ + QStringList groups = config->groupList(); + for(QStringList::Iterator it = groups.begin(); it != groups.end(); ++it){ + if((*it).startsWith("Link_")){ + config->deleteGroup(*it); + } + } + + QStringList links; + QPtrDictIterator<LinkEntry> it(linkList); + + QListViewItem *item = link_list->firstChild(); + while(item) { + LinkEntry *entry = linkList[item]; + config->setGroup("Link_" + entry->name); + config->writeEntry("Name", entry->name); + config->writeEntry("URL", entry->url); + config->writeEntry("Icon", entry->icon); + + links.append(entry->name); + + item = item->nextSibling(); + } + + QStringList actions; + QListBox *box = actionSelector->selectedListBox(); + + for(int i = 0; i < box->numRows(); i++){ + ActionListItem *item = static_cast<ActionListItem*>(box->item(i)); + if(item){ + actions.append(item->action()); + } + } + + config->setGroup("General"); + config->writeEntry("Links", links); + config->writeEntry("Actions", actions); + config->writeEntry("Theme", themes->currentText()); + + config->writeEntry("MaxEntries", max_entries->value()); + config->writeEntry("MaxActions", max_actions->value()); + + config->writeEntry("AnimateResize", animate->isChecked()); + config->writeEntry("ShowServicemenus", servicemenus->isChecked()); + config->writeEntry("ShowFrame", showframe->isChecked()); + + config->sync(); + + QDialog::accept(); +} + +void ConfigDialog::createLink() +{ + QDialog *main = new QDialog(this); + main->setCaption(i18n("Create Link")); + main->setIcon(SmallIcon("metabar")); + + KPushButton *ok = new KPushButton(KStdGuiItem::ok(), main); + connect(ok, SIGNAL(clicked()), main, SLOT(accept())); + + KPushButton *cancel = new KPushButton(KStdGuiItem::cancel(), main); + connect(cancel, SIGNAL(clicked()), main, SLOT(reject())); + + QLineEdit *name = new QLineEdit(i18n("New link"), main); + QLineEdit *url = new QLineEdit("file:/", main); + + KIconButton *icon = new KIconButton(main); + icon->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + icon->setIconType(KIcon::Small, KIcon::Any); + icon->setStrictIconSize(true); + icon->setIcon("folder"); + + QHBoxLayout *bottom_layout = new QHBoxLayout(0, 0, 5); + bottom_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum)); + bottom_layout->addWidget(ok); + bottom_layout->addWidget(cancel); + + QGridLayout *layout = new QGridLayout(0, 2, 3, 0, 5); + layout->addMultiCellWidget(icon, 0, 1, 0, 0); + layout->addWidget(new QLabel(i18n("Name:"), main), 0, 1); + layout->addWidget(name, 0, 2); + layout->addWidget(new QLabel(i18n("URL:"), main), 1, 1); + layout->addWidget(url, 1, 2); + + QVBoxLayout *main_layout = new QVBoxLayout(main, 5, 5); + main_layout->addLayout(layout); + main_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding)); + main_layout->addLayout(bottom_layout); + + main->resize(300, main->sizeHint().height()); + + if(main->exec() == QDialog::Accepted){ + QString name_str = name->text(); + QString url_str = url->text(); + QString icon_str = icon->icon(); + + if(!name_str.isEmpty() && !url_str.isEmpty()){ + if(icon_str.isEmpty()){ + icon_str = kapp->iconLoader()->iconPath("folder", KIcon::Small); + } + + QPixmap icon(icon_str); + if(icon.isNull()){ + icon = SmallIcon(icon_str); + } + + QListViewItem *item = new QListViewItem(link_list, link_list->lastItem(), name_str, url_str); + item->setPixmap(0, icon); + + linkList.insert(item, new LinkEntry(name_str, url_str, icon_str)); + updateArrows(); + } + } + + delete main; +} + +void ConfigDialog::deleteLink() +{ + QListViewItem *item = link_list->selectedItem(); + if(item){ + linkList.remove(item); + delete item; + updateArrows(); + } +} + +void ConfigDialog::editLink() +{ + QListViewItem *item = link_list->selectedItem(); + editLink(item); +} + +void ConfigDialog::editLink(QListViewItem *item) +{ + if(item){ + QDialog *main = new QDialog(this); + main->setCaption(i18n("Edit Link")); + main->setIcon(SmallIcon("metabar")); + + KPushButton *ok = new KPushButton(KStdGuiItem::ok(), main); + connect(ok, SIGNAL(clicked()), main, SLOT(accept())); + + KPushButton *cancel = new KPushButton(KStdGuiItem::cancel(), main); + connect(cancel, SIGNAL(clicked()), main, SLOT(reject())); + + QLineEdit *name = new QLineEdit(linkList[item]->name, main); + QLineEdit *url = new QLineEdit(linkList[item]->url, main); + + KIconButton *icon = new KIconButton(main); + icon->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + icon->setIconType(KIcon::Small, KIcon::Any); + icon->setStrictIconSize(true); + icon->setIcon(linkList[item]->icon); + + QHBoxLayout *bottom_layout = new QHBoxLayout(0, 0, 5); + bottom_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum)); + bottom_layout->addWidget(ok); + bottom_layout->addWidget(cancel); + + QGridLayout *layout = new QGridLayout(0, 2, 3, 0, 5); + layout->addMultiCellWidget(icon, 0, 1, 0, 0); + layout->addWidget(new QLabel(i18n("Name:"), main), 0, 1); + layout->addWidget(name, 0, 2); + layout->addWidget(new QLabel(i18n("URL:"), main), 1, 1); + layout->addWidget(url, 1, 2); + + QVBoxLayout *main_layout = new QVBoxLayout(main, 5, 5); + main_layout->addLayout(layout); + main_layout->addItem(new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding)); + main_layout->addLayout(bottom_layout); + + main->resize(300, main->sizeHint().height()); + + if(main->exec() == QDialog::Accepted){ + QString name_str = name->text(); + QString url_str = url->text(); + QString icon_str = icon->icon(); + + if(!name_str.isEmpty() && !url_str.isEmpty()){ + if(icon_str.isEmpty()){ + icon_str = kapp->iconLoader()->iconPath("folder", KIcon::Small); + } + + QPixmap icon(icon_str); + if(icon.isNull()){ + icon = SmallIcon(icon_str); + } + + linkList[item]->name = name_str; + linkList[item]->url = url_str; + linkList[item]->icon = icon_str; + + item->setText(0, name_str); + item->setText(1, url_str); + item->setPixmap(0, icon); + } + } + + delete main; + } +} + +void ConfigDialog::moveLinkUp() +{ + QListViewItem *item = link_list->selectedItem(); + if(item){ + if(link_list->itemIndex(item) > 0){ + + QListViewItem *after; + QListViewItem *above = item->itemAbove(); + if(above){ + after = above->itemAbove(); + } + + QString name = linkList[item]->name; + QString url = linkList[item]->url; + QString icon_str = linkList[item]->icon; + + QPixmap icon(icon_str); + if(icon.isNull()){ + icon = SmallIcon(icon_str); + } + + delete linkList[item]; + linkList.remove(item); + delete item; + + QListViewItem *newItem = new QListViewItem(link_list, after, name, url); + newItem->setPixmap(0, icon); + link_list->setSelected(newItem, TRUE); + + linkList.insert(newItem, new LinkEntry(name, url, icon_str)); + updateArrows(); + } + } +} + +void ConfigDialog::moveLinkDown() +{ + QListViewItem *item = link_list->selectedItem(); + if(item){ + if(link_list->itemIndex(item) < linkList.count() - 1){ + + QListViewItem *after = item->itemBelow(); + + QString name = linkList[item]->name; + QString url = linkList[item]->url; + QString icon_str = linkList[item]->icon; + + QPixmap icon(icon_str); + if(icon.isNull()){ + icon = SmallIcon(icon_str); + } + + delete linkList[item]; + linkList.remove(item); + delete item; + + QListViewItem *newItem = new QListViewItem(link_list, after, name, url); + newItem->setPixmap(0, icon); + link_list->setSelected(newItem, TRUE); + + linkList.insert(newItem, new LinkEntry(name, url, icon_str)); + updateArrows(); + } + } +} + +void ConfigDialog::loadAvailableActions() +{ + QListBox *box = actionSelector->availableListBox(); + + QByteArray data, replyData; + QCString replyType; + + if(DCOPClient::mainClient()->call(kapp->dcopClient()->appId(), topWidgetName, "actionMap()", data, replyType, replyData)){ + if(replyType == "QMap<QCString,DCOPRef>"){ + QMap<QCString,DCOPRef> actionMap; + + QDataStream reply(replyData, IO_ReadOnly); + reply >> actionMap; + + iconConfig->setGroup("Icons"); + + QMap<QCString,DCOPRef>::Iterator it; + for(it = actionMap.begin(); it != actionMap.end(); ++it){ + DCOPRef action = it.data(); + + QString text = action.call("plainText()"); + QCString cname = action.call("name()"); + QString icon = iconConfig->readEntry(QString(cname), action.call("icon()")); + + ActionListItem *item = new ActionListItem(box, QString(cname), text, SmallIcon(icon)); + } + } + } + + //metabar's own actions + ActionListItem *item = new ActionListItem(box, "metabar/share", i18n("Share"), SmallIcon("network")); +} + +void ConfigDialog::updateArrows() +{ + link_up->setEnabled( link_list->childCount()>1 && link_list->currentItem()!=link_list->firstChild() ); + link_down->setEnabled( link_list->childCount()>1 && link_list->currentItem()!=link_list->lastItem() ); +} + +void ConfigDialog::loadThemes() +{ + themes->clear(); + + QString theme = config->readEntry("Theme", "default"); + bool foundTheme = false; + + QStringList dirs = kapp->dirs()->findDirs("data", "metabar/themes"); + for(QStringList::Iterator it = dirs.begin(); it != dirs.end(); ++it){ + QStringList theme_list = QDir(*it).entryList(QDir::Dirs); + + theme_list.remove("."); + theme_list.remove(".."); + themes->insertStringList(theme_list); + + if(theme_list.find(theme) != theme_list.end()){ + foundTheme = true; + } + } + + if(foundTheme){ + themes->setCurrentText(theme); + } + else{ + themes->insertItem(theme); + } +} + +void ConfigDialog::installTheme() +{ + QString file = KFileDialog::getOpenFileName(); + if(file.isNull() && file.isEmpty()) return; + + QString themedir = locateLocal("data", "metabar/themes"); + if(themedir.isNull()) return; + + KTar archive(file); + archive.open(IO_ReadOnly); + kapp->processEvents(); + + const KArchiveDirectory* rootDir = archive.directory(); + rootDir->copyTo(themedir); + + archive.close(); + loadThemes(); +} + +#include "configdialog.moc" diff --git a/konq-plugins/sidebar/metabar/src/configdialog.h b/konq-plugins/sidebar/metabar/src/configdialog.h new file mode 100644 index 0000000..872bd8b --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/configdialog.h @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef _CONFIGDIALOG_H_ +#define _CONFIGDIALOG_H_ + +#include <qdialog.h> +#include <kpushbutton.h> +#include <klistview.h> +#include <knuminput.h> +#include <kconfig.h> +#include <qptrdict.h> +#include <qlistbox.h> +#include <kactionselector.h> +#include <qcheckbox.h> +#include <kcombobox.h> + +class LinkEntry{ + public: + LinkEntry(QString name, QString url, QString icon); + + ~LinkEntry(){} + + QString name; + QString url; + QString icon; +}; + +class ConfigDialog : public QDialog +{ + Q_OBJECT + + public: + ConfigDialog(QWidget *parent = 0, const char *name = 0); + ~ConfigDialog(); + + protected: + KPushButton *ok; + KPushButton *cancel; + + KPushButton *link_create; + KPushButton *link_delete; + KPushButton *link_edit; + KPushButton *link_up; + KPushButton *link_down; + + KPushButton *install_theme; + + KIntSpinBox *max_entries; + KIntSpinBox *max_actions; + + QCheckBox *animate; + QCheckBox *servicemenus; + QCheckBox *showframe; + + KListView *link_list; + + KComboBox *themes; + + QCString topWidgetName; + + KActionSelector *actionSelector; + + QPtrDict<LinkEntry> linkList; + + KConfig *config; + KConfig *iconConfig; + + protected slots: + void accept(); + void createLink(); + void deleteLink(); + void editLink(); + void editLink(QListViewItem *item); + void moveLinkUp(); + void moveLinkDown(); + void updateArrows(); + void installTheme(); + + private: + void loadAvailableActions(); + void loadThemes(); +}; + +class ActionListItem : public QListBoxPixmap +{ + public: + ActionListItem(QListBox *listbox, const QString &action, const QString &text, const QPixmap &pixmap); + ~ActionListItem(){} + + const QString action() { return act; } + void setAction(const QString act){ ActionListItem::act = act; } + + private: + QString act; +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/default.css b/konq-plugins/sidebar/metabar/src/default.css new file mode 100644 index 0000000..0bae4ab --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/default.css @@ -0,0 +1,64 @@ +body { + background-color: window; + font-family: sans-serif; + font-size: 11px; + color: windowtext; +} + +.frame { + background-color: threedface; + margin-bottom: 10px; + position: relative; + +} + +li { + list-style-type: none; + overflow: hidden; +} + +li ul { + margin: 0px; + padding: 0px; + height: 20px; + white-space: nowrap; +} + +a { + display: block; + padding-top: 5px; + padding-left: 24px; + background-position: 4px 2px; + background-repeat: no-repeat; + + text-decoration: none; + color: buttontext; + +} + +a:hover { + text-decoration: underline; +} + +a.title { + font-weight: bold; + border-bottom: solid 1px threeddarkshadow; + cursor: pointer; + height: 15px; + background-repeat: none; +} + +a.infotitle { + font-weight: bold; + padding-left: 5px; + cursor: pointer; +} + +.preview { + padding: 5px; + text-align: center; +} + +ul.info { + padding-left: 5px; +}
\ No newline at end of file diff --git a/konq-plugins/sidebar/metabar/src/defaultplugin.cpp b/konq-plugins/sidebar/metabar/src/defaultplugin.cpp new file mode 100644 index 0000000..6c8dec3 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/defaultplugin.cpp @@ -0,0 +1,458 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "defaultplugin.h" +#include "metabarwidget.h" + +#include <kurl.h> +#include <kstandarddirs.h> +#include <kicontheme.h> +#include <khtmlview.h> +#include <klocale.h> +#include <kapplication.h> +#include <kdesktopfile.h> +#include <ktrader.h> +#include <krun.h> +#include <kfilemetainfo.h> +#include <kconfig.h> +#include <kimageio.h> +#include <kdebug.h> +#include <kmdcodec.h> + +#include <kio/previewjob.h> + +#include <dcopclient.h> +#include <dcopref.h> + +#include <qdir.h> +#include <qfile.h> +#include <qrect.h> +#include <qpoint.h> +#include <qbuffer.h> + +#include <dom_string.h> +#include <html_image.h> + +#define EVENT_TYPE DOM::DOMString("click") +#define MODIFICATION 1 + +DefaultPlugin::DefaultPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name) : ProtocolPlugin (html, functions, name) +{ + services = new ServiceLoader(m_html->view(), "serviceloader"); + + preview_job = 0; +} + +DefaultPlugin::~DefaultPlugin() +{ +} + +void DefaultPlugin::killJobs(){ + if(preview_job){ + preview_job->kill(); + preview_job = 0; + } +} + +void DefaultPlugin::deactivate() +{ + m_functions->hide("actions"); + m_functions->hide("open"); + m_functions->hide("info"); + m_functions->hide("preview"); +} + +void DefaultPlugin::loadActions(DOM::HTMLElement node) +{ + KFileItem *item = m_items.getFirst(); + KURL url = item->url(); + + KConfig config("metabarrc", true, false); + config.setGroup("General"); + + KConfig iconConfig(locate("data", "metabar/iconsrc")); + iconConfig.setGroup("Icons"); + + DOM::DOMString innerHTML; + + QStringList actions = config.readListEntry("Actions"); + int maxActions = config.readNumEntry("MaxActions", 5); + int actionCount = 0; + + for(QStringList::Iterator it = actions.begin(); it != actions.end(); ++it){ + if((*it).startsWith("metabar/")){ + if((*it).right((*it).length() - 8) == "share"){ + MetabarWidget::addEntry(innerHTML, i18n("Share"), "action://" + *it, "network", QString::null, actionCount < maxActions ? QString::null : QString("hiddenaction"), actionCount >= maxActions); + actionCount++; + } + } + else{ + DCOPRef action(kapp->dcopClient()->appId(), QCString(m_html->view()->topLevelWidget()->name()).append("/action/").append((*it).utf8())); + + if(!action.isNull()){ + if(action.call("enabled()")){ + QString text = action.call("plainText()"); + QString icon = iconConfig.readEntry(*it, action.call("icon()")); + + MetabarWidget::addEntry(innerHTML, text, "action://" + *it, icon, QString::null, actionCount < maxActions ? QString::null : QString("hiddenaction"), actionCount >= maxActions); + actionCount++; + } + } + } + } + + config.setGroup("General"); + if(config.readBoolEntry("ShowServicemenus", true)){ + services->loadServices(*(m_items.getFirst()), innerHTML, actionCount); + } + + if(actionCount == 0) { + m_functions->hide("actions"); + } + else{ + if(actionCount > maxActions){ + MetabarWidget::addEntry(innerHTML, i18n("More"), "more://hiddenaction", "1downarrow", "hiddenaction"); + } + + node.setInnerHTML(innerHTML); + m_functions->show("actions"); + } +} + +void DefaultPlugin::loadApplications(DOM::HTMLElement node) +{ + if(m_items.count() == 1){ + KFileItem *item = m_items.getFirst(); + KURL url = item->url(); + + QDir dir(url.path()); + dir = dir.canonicalPath(); + + if(item->isDir() || dir.isRoot()){ + m_functions->hide("open"); + node.setInnerHTML(DOM::DOMString()); + } + else{ + DOM::DOMString innerHTML; + + if(KDesktopFile::isDesktopFile(item->url().path())){ //Desktop file + KDesktopFile desktop(url.path(), TRUE); + + if(desktop.hasApplicationType ()){ + MetabarWidget::addEntry(innerHTML, i18n("Run %1").arg(desktop.readName()), "desktop://" + url.path(), desktop.readIcon()); + + m_functions->show("open"); + } + + else{ + m_functions->hide("open"); + } + } + else{ //other files + KTrader::OfferList offers; + + offers = KTrader::self()->query(item->mimetype(), "Type == 'Application'"); + if(!offers.isEmpty()){ + KConfig config("metabarrc", true, false); + config.setGroup("General"); + + int id = 0; + int max = config.readNumEntry("MaxEntries", 5); + + runMap.clear(); + KTrader::OfferList::ConstIterator it = offers.begin(); + + for(; it != offers.end(); it++){ + QString nam; + nam.setNum(id); + + bool hide = id >= max; + MetabarWidget::addEntry(innerHTML, (*it)->name(), "exec://" + nam, (*it)->icon(), QString::null, hide ? QString("hiddenapp") : QString::null, hide); + + runMap.insert(id, *it); + id++; + } + + if(id > max){ + MetabarWidget::addEntry(innerHTML, i18n("More"), "more://hiddenapp", "1downarrow", "hiddenapp"); + } + } + else{ + MetabarWidget::addEntry(innerHTML, i18n("Choose Application"), "openwith:///", "run"); + } + } + + node.setInnerHTML(innerHTML); + + m_functions->show("open"); + } + } + else{ + m_functions->hide("open"); + } +} + +void DefaultPlugin::loadInformation(DOM::HTMLElement node) +{ + if(m_items.count() == 1){ + KFileItem *item = m_items.getFirst(); + KFileItem *that = const_cast<KFileItem *>(item); + + DOM::DOMString innerHTML; + innerHTML += "<ul class=\"info\"><b>" + i18n("Type") + ": </b>"; + innerHTML += that->determineMimeType()->comment(); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Size") + ": </b>"; + innerHTML += KIO::convertSize(item->size()); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("User") + ": </b>"; + innerHTML += item->user(); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Group") + ": </b>"; + innerHTML += item->group(); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Permissions") + ": </b>"; + innerHTML += (item->permissionsString()); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Modified") + ": </b>"; + innerHTML += item->timeString(KIO::UDS_MODIFICATION_TIME); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Accessed") + ": </b>"; + innerHTML += item->timeString(KIO::UDS_ACCESS_TIME); + innerHTML += "</ul>"; + + if(item->isLink()){ + innerHTML += "<ul class=\"info\"><b>" + i18n("Linktarget") + ": </b>"; + innerHTML += item->linkDest(); + innerHTML += "</ul>"; + } + + if(!item->isDir()){ + const KFileMetaInfo &metaInfo = item->metaInfo(); + if(metaInfo.isValid()){ + QStringList groups = metaInfo.supportedGroups(); + + int id = 0; + QString nam; + + for(QStringList::ConstIterator it = groups.begin(); it != groups.end(); ++it){ + KFileMetaInfoGroup group = metaInfo.group(*it); + if(group.isValid()){ + nam.setNum(id); + + innerHTML += "<ul class=\"info\"><a class=\"infotitle\" id=\"info_" + nam + "\" href=\"more://info_" + nam + "\">" + group.translatedName() + "</a></ul>"; + + QStringList keys = group.supportedKeys(); + + for(QStringList::ConstIterator it = keys.begin(); it != keys.end(); ++it){ + const KFileMetaInfoItem metaInfoItem = group.item(*it); + + if(metaInfoItem.isValid()){ + + innerHTML += "<ul class=\"info\" style=\"display:none\"><b name=\"info_" + nam + "\">" + metaInfoItem.translatedKey() + ": </b>"; + innerHTML += metaInfoItem.string(); + innerHTML += "</ul>"; + } + } + + id++; + } + } + } + } + + node.setInnerHTML(innerHTML); + } + else{ + KIO::filesize_t size = 0; + int files = 0; + int dirs = 0; + + for(KFileItemListIterator it(m_items); it.current(); ++it){ + size += (*it)->size(); + + if((*it)->isDir()){ + dirs++; + } + else{ + files++; + } + } + + DOM::DOMString innerHTML; + innerHTML += "<ul class=\"info\"><b>" + i18n("Size") + ": </b>"; + innerHTML += KIO::convertSize(size); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Files") + ": </b>"; + innerHTML += QString().setNum(files); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Folders") + ": </b>"; + innerHTML += QString().setNum(dirs); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Total Entries") + ": </b>"; + innerHTML += QString().setNum(m_items.count()); + innerHTML += "</ul>"; + node.setInnerHTML(innerHTML); + } + m_functions->show("info"); +} + +void DefaultPlugin::loadPreview(DOM::HTMLElement node) +{ + if(m_items.count() == 1){ + KFileItem *item = m_items.getFirst(); + KURL url = item->url(); + + QDir dir(url.path()); + dir = dir.canonicalPath(); + + if(item->isDir() || dir.isRoot()){ + m_functions->hide("preview"); + } + else{ + if(item->mimetype().startsWith("audio/")){ + DOM::DOMString innerHTML("<ul><a class=\"previewdesc\" href=\"preview:///\">"); + innerHTML += i18n("Click to start preview"); + innerHTML += "</a></ul>"; + node.setInnerHTML(innerHTML); + + //m_functions->show("preview"); + } + else{ + DOM::DOMString innerHTML("<ul style=\"text-align-center\"><nobr>"); + innerHTML += i18n("Creating preview"); + innerHTML += "</nobr></ul>"; + node.setInnerHTML(innerHTML); + + //m_functions->show("preview"); + + preview_job = KIO::filePreview(KURL::List(url), m_html->view()->width() - 30); + + connect(preview_job, SIGNAL(gotPreview(const KFileItem*, const QPixmap&)), this, SLOT(slotSetPreview(const KFileItem*, const QPixmap&))); + connect(preview_job, SIGNAL(failed(const KFileItem *)), this, SLOT(slotPreviewFailed(const KFileItem *))); + connect(preview_job, SIGNAL(result(KIO::Job *)), this, SLOT(slotJobFinished(KIO::Job *))); + } + + m_functions->show("preview"); + } + } + else{ + m_functions->hide("preview"); + } +} + +void DefaultPlugin::loadBookmarks(DOM::HTMLElement node) +{ + m_functions->hide("bookmarks"); +} + +void DefaultPlugin::slotSetPreview(const KFileItem *item, const QPixmap &pix) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = doc.getElementById("preview"); + + QByteArray data; + QBuffer buffer(data); + buffer.open(IO_WriteOnly); + pix.save(&buffer, "PNG"); + + QString src = QString::fromLatin1("data:image/png;base64,%1").arg(KCodecs::base64Encode(data)); + bool media = item->mimetype().startsWith("video/"); + + DOM::DOMString innerHTML; + + innerHTML += QString("<ul style=\"height: %1px\"><a class=\"preview\"").arg(pix.height() + 15); + + if(media){ + innerHTML += " href=\"preview:///\""; + } + innerHTML +="><img id=\"previewimage\" src=\""; + innerHTML += src; + innerHTML += "\" width=\""; + innerHTML += QString().setNum(pix.width()); + innerHTML += "\" height=\""; + innerHTML += QString().setNum(pix.height()); + innerHTML += "\" /></a></ul>"; + + if(media){ + innerHTML += "<ul><a class=\"previewdesc\" href=\"preview:///\">" + i18n("Click to start preview") + "</a></ul>"; + } + + node.setInnerHTML(innerHTML); + + //script.append("adjustPreviewSize(" + height_str + ");"); + m_functions->show("preview"); + m_functions->adjustSize("preview"); +} + +void DefaultPlugin::slotPreviewFailed(const KFileItem *item) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement preview = static_cast<DOM::HTMLElement>(doc.getElementById("preview_image")); + if(!preview.isNull()){ + preview.setAttribute(DOM::DOMString("src"), DOM::DOMString()); + } + + m_functions->hide("preview"); +} + +void DefaultPlugin::slotJobFinished(KIO::Job *job) +{ + if(preview_job && job == preview_job){ + preview_job = 0; + } +} + +bool DefaultPlugin::handleRequest(const KURL &url) +{ + QString protocol = url.protocol(); + + if(protocol == "exec"){ + int id = url.host().toInt(); + + QMap<int,KService::Ptr>::Iterator it = runMap.find(id); + if(it != runMap.end()){ + + KFileItem *item = m_items.getFirst(); + if(item){ + KRun::run( **it, KURL::List(item->url())); + return true; + } + } + } + + else if(protocol == "service"){ + QString name = url.url().right(url.url().length() - 10); + + services->runAction(name); + return true; + } + + else if(protocol == "servicepopup"){ + QString id = url.host(); + + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById("popup" + id)); + + if(!node.isNull()){ + QRect rect = node.getRect(); + QPoint p = m_html->view()->mapToGlobal(rect.bottomLeft()); + + services->showPopup(id, p); + } + + return true; + } + + return false; +} + +#include "defaultplugin.moc" diff --git a/konq-plugins/sidebar/metabar/src/defaultplugin.h b/konq-plugins/sidebar/metabar/src/defaultplugin.h new file mode 100644 index 0000000..15b2e73 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/defaultplugin.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _DEFAULT_PLUGIN_H_ +#define _DEFAULT_PLUGIN_H_ + +#include "protocolplugin.h" +#include "serviceloader.h" + +#include <kio/previewjob.h> + +#include <qdict.h> +#include <qmap.h> + +class DefaultPlugin : public ProtocolPlugin +{ + Q_OBJECT + + public: + DefaultPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name = 0); + ~DefaultPlugin(); + + void deactivate(); + bool handleRequest(const KURL &url); + + protected: + void killJobs(); + + void loadActions(DOM::HTMLElement node); + void loadApplications(DOM::HTMLElement node); + void loadInformation(DOM::HTMLElement node); + void loadPreview(DOM::HTMLElement node); + void loadBookmarks(DOM::HTMLElement node); + + private: + QMap<int,KService::Ptr> runMap; + KIO::PreviewJob *preview_job; + + ServiceLoader *services; + + private slots: + void slotSetPreview(const KFileItem*, const QPixmap&); + void slotPreviewFailed(const KFileItem *item); + void slotJobFinished(KIO::Job *item); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/hi128-app-metabar.png b/konq-plugins/sidebar/metabar/src/hi128-app-metabar.png Binary files differnew file mode 100644 index 0000000..1ee89bf --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hi128-app-metabar.png diff --git a/konq-plugins/sidebar/metabar/src/hi16-app-metabar.png b/konq-plugins/sidebar/metabar/src/hi16-app-metabar.png Binary files differnew file mode 100644 index 0000000..c47b0b0 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hi16-app-metabar.png diff --git a/konq-plugins/sidebar/metabar/src/hi32-app-metabar.png b/konq-plugins/sidebar/metabar/src/hi32-app-metabar.png Binary files differnew file mode 100644 index 0000000..c0d6213 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hi32-app-metabar.png diff --git a/konq-plugins/sidebar/metabar/src/hi48-app-metabar.png b/konq-plugins/sidebar/metabar/src/hi48-app-metabar.png Binary files differnew file mode 100644 index 0000000..763ec38 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hi48-app-metabar.png diff --git a/konq-plugins/sidebar/metabar/src/hi64-app-metabar.png b/konq-plugins/sidebar/metabar/src/hi64-app-metabar.png Binary files differnew file mode 100644 index 0000000..89fa615 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hi64-app-metabar.png diff --git a/konq-plugins/sidebar/metabar/src/hisc-app-metabar.svgz b/konq-plugins/sidebar/metabar/src/hisc-app-metabar.svgz Binary files differnew file mode 100644 index 0000000..6b955f5 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/hisc-app-metabar.svgz diff --git a/konq-plugins/sidebar/metabar/src/httpplugin.cpp b/konq-plugins/sidebar/metabar/src/httpplugin.cpp new file mode 100644 index 0000000..aec402a --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/httpplugin.cpp @@ -0,0 +1,119 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "metabarwidget.h" +#include "httpplugin.h" + +#include <kbookmark.h> +#include <kstandarddirs.h> +#include <kapplication.h> +#include <kicontheme.h> +#include <khtmlview.h> +#include <kurl.h> +#include <klocale.h> + +#include <dcopref.h> +#include <dcopclient.h> + +#include <qregexp.h> +#include <qfile.h> + +#include <dom_node.h> +#include <html_inline.h> + +HTTPPlugin::HTTPPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name) : ProtocolPlugin (html, functions, name) +{ +} + +HTTPPlugin::~HTTPPlugin() +{ + //delete bookmarkManager; +} + +void HTTPPlugin::deactivate() +{ + m_functions->hide("actions"); + m_functions->hide("info"); +} + +void HTTPPlugin::killJobs() +{ +} + +void HTTPPlugin::loadInformation(DOM::HTMLElement node) +{ + /*DOM::DOMString innerHTML; + innerHTML += "<form action=\"find:///\" method=\"GET\">"; + innerHTML += "<ul>"; + innerHTML += i18n("Keyword"); + innerHTML += " <input onFocus=\"this.value = ''\" type=\"text\" name=\"find\" id=\"find_text\" value=\""; + innerHTML += i18n("Web search"); + innerHTML += "\"></ul>"; + innerHTML += "<ul><input type=\"submit\" id=\"find_button\" value=\""; + innerHTML += i18n("Find"); + innerHTML += "\"></ul>"; + innerHTML += "</form>"; + + node.setInnerHTML(innerHTML); + m_functions->show("info");*/ + + m_functions->hide("info"); +} + +void HTTPPlugin::loadActions(DOM::HTMLElement node) +{ + m_functions->hide("actions"); +} + +void HTTPPlugin::loadApplications(DOM::HTMLElement node) +{ + m_functions->hide("open"); +} + +void HTTPPlugin::loadPreview(DOM::HTMLElement node) +{ + m_functions->hide("preview"); +} + +void HTTPPlugin::loadBookmarks(DOM::HTMLElement node) +{ + m_functions->hide("bookmarks"); +} + +bool HTTPPlugin::handleRequest(const KURL &url) +{ + if(url.protocol() == "find"){ + QString keyword = url.queryItem("find"); + QString type = url.queryItem("type"); + + if(!keyword.isNull() && !keyword.isEmpty()){ + KURL url("http://www.google.com/search"); + url.addQueryItem("q", keyword); + + DCOPRef ref(kapp->dcopClient()->appId(), m_html->view()->topLevelWidget()->name()); + DCOPReply reply = ref.call("openURL", url.url()); + } + + return true; + } + return false; +} + +#include "httpplugin.moc" diff --git a/konq-plugins/sidebar/metabar/src/httpplugin.h b/konq-plugins/sidebar/metabar/src/httpplugin.h new file mode 100644 index 0000000..c840e8f --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/httpplugin.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _HTTP_PLUGIN_H_ +#define _HTTP_PLUGIN_H_ + +#include "protocolplugin.h" + +#include <kdirwatch.h> +#include <kbookmarkmanager.h> + +#include <dom_string.h> + +class HTTPPlugin : public ProtocolPlugin +{ + Q_OBJECT + + public: + HTTPPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name = 0); + ~HTTPPlugin(); + + bool handleRequest(const KURL &url); + void deactivate(); + + protected: + void loadActions(DOM::HTMLElement node); + void loadApplications(DOM::HTMLElement node); + void loadPreview(DOM::HTMLElement node); + void loadBookmarks(DOM::HTMLElement node); + void loadInformation(DOM::HTMLElement node); + void killJobs(); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/iconsrc b/konq-plugins/sidebar/metabar/src/iconsrc new file mode 100644 index 0000000..a30f532 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/iconsrc @@ -0,0 +1,4 @@ +[Icons] +rename=edit +konq_create_dir=folder_new +properties=messagebox_info
\ No newline at end of file diff --git a/konq-plugins/sidebar/metabar/src/layout.html b/konq-plugins/sidebar/metabar/src/layout.html new file mode 100644 index 0000000..6bae311 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/layout.html @@ -0,0 +1,48 @@ +<html> +<head> +<title></title> + +</head> + +<body> + +<div class="frame"> + <div class="head"><a i18n image="wizard" class="title" onClick="this.blur();" href="function://toggle/actions">Actions</a></div> + <li id="actions" expanded="true" style="height:0px"> + </li> +</div> + +<div class="frame"> + <div class="head"><a i18n image="run" class="title" onClick="this.blur();" href="function://toggle/open">Open With</a></div> + <li id="open" expanded="true" style="height:0px"> + </li> +</div> + +<div class="frame"> + <div class="head"><a i18n image="bookmark" class="title" onClick="this.blur();" href="function://toggle/bookmarks">Bookmarks</a></div> + <li id="bookmarks" expanded="true" style="height:0px"> + </li> +</div> + +<div class="frame"> + <div class="head"><a i18n image="browser" class="title" onClick="this.blur();" href="function://toggle/links">Links</a></div> + <li id="links" expanded="true" style="height:0px"> + </li> +</div> + +<div class="frame"> + <div class="head"><a i18n image="messagebox_info" class="title" onClick="this.blur();" href="function://toggle/info">Information</a></div> +<li id="info" expanded="true" style="height:0px"> +</li> +</div> + +<div class="frame"> + <div class="head"><a i18n image="player_play" class="title" onClick="this.blur();" href="function://toggle/preview">Preview</a></div> + <li id="preview" expanded="true" style="height:0px"> + </li> +</div> + + +</body> + +</html> diff --git a/konq-plugins/sidebar/metabar/src/metabar.cpp b/konq-plugins/sidebar/metabar/src/metabar.cpp new file mode 100644 index 0000000..8181a11 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabar.cpp @@ -0,0 +1,59 @@ +#include <kinstance.h> +#include <qstring.h> +#include <kimageio.h> +#include <klocale.h> + +#include "metabarwidget.h" +#include "metabar.h" +#include "metabar.moc" + +Metabar::Metabar(KInstance *inst,QObject *parent,QWidget *widgetParent, QString &desktopName, const char* name): + KonqSidebarPlugin(inst,parent,widgetParent,desktopName,name) +{ + KImageIO::registerFormats(); + KGlobal::locale()->insertCatalogue( "konqsidebar_metabar" ); + + widget = new MetabarWidget(widgetParent, "metabarwidget"); +} + + +Metabar::~Metabar() +{ +} + +void Metabar::handleURL(const KURL &url) +{ + const KFileItem *item = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true); + KFileItemList list; + list.append(item); + + widget->setFileItems(list); +} + +void Metabar::handlePreview(const KFileItemList &items) +{ + widget->setFileItems(items); +} + + +extern "C" { + bool add_konqsidebar_metabar(QString* fn, QString* param, QMap<QString,QString> *map) { + Q_UNUSED(param); + + map->insert("Type", "Link"); + map->insert("Icon", "metabar"); + map->insert("Name", "Metabar"); + map->insert("Open", "true"); + map->insert("X-KDE-KonqSidebarModule","konqsidebar_metabar"); + fn->setLatin1("metabar%1.desktop"); + return true; + } +} + +extern "C" +{ + void* create_konqsidebar_metabar(KInstance *instance,QObject *par,QWidget *widp,QString &desktopname,const char *name) + { + return new Metabar(instance,par,widp,desktopname,name); + } +} diff --git a/konq-plugins/sidebar/metabar/src/metabar.desktop b/konq-plugins/sidebar/metabar/src/metabar.desktop new file mode 100644 index 0000000..9ea7917 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabar.desktop @@ -0,0 +1,81 @@ +[Desktop Entry] +Type=Link +URL= +Icon=metabar +Comment=A konqueror navigation panel plugin called Metabar +Comment[bg]=Приставка за навигация в браузъра Konqueror +Comment[ca]=Un connector del plafó de navegació del konqueror anomenat Metabar +Comment[cs]=Navigační panel pro Konqueror - Metabar +Comment[da]=Et navigationspanel-plugin for konqueror der hedder Metabar +Comment[de]=Metabar - Ein Modul für den Navigationsbereich von Konqueror +Comment[el]=Ένα πρόσθετο πίνακα πλοήγησης του konqueror που ονομάζεται γραμμή μεταδεδομένων +Comment[en_GB]=A Konqueror navigation panel plugin called Metabar +Comment[eo]=Foliuma panela kromaĵo por Konkeranto nomata Metabar +Comment[es]=Un complemento del panel de navegación de konqueror llamado metabarra +Comment[et]=Konquerori navigeerimispaneeli plugin Metabar +Comment[eu]=Metabar izeneko Konqueror-en arakatze-panelaren plugina +Comment[fa]=وصلۀ تابلوی ناوش konqueror که فرامیله نام دارد +Comment[fi]=Konquerorin Metabar-niminen selauspaneelin liitännäinen +Comment[fr]=Un module pour le panneau de navigation de Konqueror appelé Metabar +Comment[fy]=In plugin foar Konqueror's navigaasjebalke, neamd Metabalke +Comment[ga]=Breiseán i bpainéal nascleanúna Konqueror darb ainm Metabar +Comment[gl]=Un plugin de navegación para konqueror chamado Metabar +Comment[hr]=Dodatak navigacijske ploče za Konqueror, zvan Metabar +Comment[hu]=Metabar, egy navigációs bővítőmodul a Konqueror böngészőhöz +Comment[is]=Konqueror leiðarstýrispjald íforrit sem kallast Metabar +Comment[it]=Plugin di navigazione di Konqueror chiamato Metabar +Comment[ja]=Konqueror メタバー ナビゲーションパネルプラグイン +Comment[ka]=konqueror ნავიგაციის მოდული სახელად Metabar +Comment[kk]=Metabar деген Konqueror панелінің плагин модулі +Comment[km]=កម្មវិធីជំនួយបន្ទះរុករករបស់ konqueror បានហៅរបារមេតា +Comment[lt]=Metabar - Konqueror navigacijos pulto priedas +Comment[mk]=Приклучок за панел за навигација во konqueror наречен Metabar +Comment[nb]=Et Konqueror programtillegg for navigasjonspanel, kalt Metabar +Comment[nds]=En Sietpaneelmoduul för Konqueror, nöömt "Metabar" +Comment[ne]=मेटाबार भनिने एउटा कन्क्वेरर नेभिगेसन प्यानल प्लगइन +Comment[nl]=Een plugin voor Konqueror's navigatiebalk, genaamd Metabalk +Comment[nn]=Eit programtillegg som gir Konqueror eit navigasjonpanel +Comment[pl]=Panel nawigacyjny Metabar dla Konquerora +Comment[pt]=Um 'plugin' de navegação do konqueror chamado Metabar +Comment[pt_BR]=Um plugin de navegação para o Konqueror chamado de Metabar +Comment[ru]=Панель сведений Konqueror +Comment[sk]=Modul navigačného panelu pre Konqueror nazývaný Metabar +Comment[sl]=Vstavek za Konqueror z navigacijskim pasom Metabar +Comment[sr]=Прикључак за навигациону таблу konqueror-а назван Метапалета +Comment[sr@Latn]=Priključak za navigacionu tablu konqueror-a nazvan Metapaleta +Comment[sv]=Ett sidopanelinsticksprogram för Konqueror kallad Metarad +Comment[tr]=Metabar isimli Konqueror gezinme paneli eklentisi +Comment[uk]=Втулок навігаційної панелі для konqueror - Metabar +Comment[vi]=Bổ sung bảng duyệt qua Konqueror tên Siêu Thanh +Comment[zh_CN]=称为 Metabar 的 Konqueror 导航面板插件 +Comment[zh_TW]=叫做 Metabar 的 Konqueror 導覽面板外掛程式 +Name=metabar +Name[de]=Metabar +Name[el]=Γραμμή μεταδεδομένων +Name[es]=metabarra +Name[et]=Metabar +Name[fa]=فرامیله +Name[fi]=metapalkki +Name[fr]=Metabar +Name[fy]=metabalke +Name[hu]=Metabar +Name[ja]=メタバー +Name[km]=របារមេតា +Name[ne]=मेटाबार +Name[nl]=metabalk +Name[pa]=ਮੈਟਾ-ਪੱਟੀ +Name[pl]=Metabar +Name[pt_BR]=MetaBar +Name[ru]=Сведения +Name[sk]=Metabar +Name[sl]=Metabar +Name[sr]=метапалета +Name[sr@Latn]=metapaleta +Name[sv]=Metarad +Name[tr]=Metabar +Name[vi]=siêu thanh +Name[zh_CN]=Metabar + +Open=false +X-KDE-KonqSidebarModule=konqsidebar_metabar + diff --git a/konq-plugins/sidebar/metabar/src/metabar.h b/konq-plugins/sidebar/metabar/src/metabar.h new file mode 100644 index 0000000..6d43592 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabar.h @@ -0,0 +1,32 @@ +#ifndef METABAR_H +#define METABAR_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <konqsidebarplugin.h> +#include <qstring.h> +#include <kconfig.h> + + +class Metabar : public KonqSidebarPlugin +{ + Q_OBJECT + + public: + Metabar(KInstance *inst,QObject *parent,QWidget *widgetParent, QString &desktopName, const char* name=0); + ~Metabar(); + + virtual QWidget *getWidget(){ return widget; } + virtual void *provides(const QString &) { return 0; } + + protected: + MetabarWidget *widget; + + void handleURL(const KURL &url); + void handlePreview(const KFileItemList &items); + +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/metabar_add.desktop b/konq-plugins/sidebar/metabar/src/metabar_add.desktop new file mode 100644 index 0000000..e7003e9 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabar_add.desktop @@ -0,0 +1,70 @@ +[Desktop Entry] +Comment=A konqueror navigation panel plugin called Metabar +Comment[bg]=Приставка за навигация в браузъра Konqueror +Comment[ca]=Un connector del plafó de navegació del konqueror anomenat Metabar +Comment[cs]=Navigační panel pro Konqueror - Metabar +Comment[da]=Et navigationspanel-plugin for konqueror der hedder Metabar +Comment[de]=Metabar - Ein Modul für den Navigationsbereich von Konqueror +Comment[el]=Ένα πρόσθετο πίνακα πλοήγησης του konqueror που ονομάζεται γραμμή μεταδεδομένων +Comment[en_GB]=A Konqueror navigation panel plugin called Metabar +Comment[eo]=Foliuma panela kromaĵo por Konkeranto nomata Metabar +Comment[es]=Un complemento del panel de navegación de konqueror llamado metabarra +Comment[et]=Konquerori navigeerimispaneeli plugin Metabar +Comment[eu]=Metabar izeneko Konqueror-en arakatze-panelaren plugina +Comment[fa]=وصلۀ تابلوی ناوش konqueror که فرامیله نام دارد +Comment[fi]=Konquerorin Metabar -niminen selauspaneelin liitännäinen +Comment[fr]=Un module pour le panneau de navigation de Konqueror appelé Metabar +Comment[fy]=In plugin foar Konqueror's navigaasjebalke, neamd Metabalke +Comment[ga]=Breiseán i bpainéal nascleanúna Konqueror darb ainm Metabar +Comment[gl]=Un plugin de navegación para konqueror chamado Metabar +Comment[hr]=Dodatak navigacijske trake za Konqueror, nazvan Metabar +Comment[hu]=Metabar, egy navigációs bővítőmodul a Konqueror böngészőhöz +Comment[is]=Konqueror leiðarstýrispjald íforrit sem kallast Metabar +Comment[it]=Plugin di navigazione di Konqueror chiamato Metabar +Comment[ja]=Konqueror メタバー ナビゲーションパネルプラグイン +Comment[ka]=konqueror ნავიგაციის მოდული სახელად Metabar +Comment[kk]=Metabar деген Konqueror панелінің плагин модулі +Comment[km]=កម្មវិធីជំនួយបន្ទះរុករករបស់ konqueror បានហៅរបារមេតា +Comment[lt]=Metabar - Konqueror navigacijos pulto priedas +Comment[mk]=Приклучок за панел за навигација во konqueror наречен Metabar +Comment[nb]=Et Konqueror programtillegg for navigasjonspanel, kalt Metabar +Comment[nds]=En Sietpaneel för Konqueror, nöömt "Metabar" +Comment[ne]=मेटाबार भनिने एउटा कन्क्वेरर नेभिगेसन प्यानल प्लगइन +Comment[nl]=Een plugin voor Konqueror's navigatiebalk, genaamd Metabalk +Comment[nn]=Eit programtillegg som gir Konqueror eit navigasjonspanel +Comment[pl]=Wtyczka panelu nawigacyjnego Metabar dla Konquerora +Comment[pt]=Um 'plugin' de navegação do konqueror chamado Metabar +Comment[pt_BR]=Um plugin de navegação para o Konqueror chamado de MetaBar +Comment[ru]=Панель сведений Konqueror +Comment[sk]=Modul navigačného panelu pre Konqueror nazývaný Metabar +Comment[sl]=Vstavek za Konqueror z navigacijskim pasom Metabar +Comment[sr]=Прикључак за навигациону таблу konqueror-а назван Метапалета +Comment[sr@Latn]=Priključak za navigacionu tablu konqueror-a nazvan Metapaleta +Comment[sv]=Ett sidopanelinsticksprogram för Konqueror kallad Metarad +Comment[tr]=Metabar isimli Konqueror gezinme paneli eklentisi +Comment[uk]=Втулок навігаційної панелі для konqueror - Metabar +Comment[vi]=Bổ sung bảng duyệt qua Konqueror tên Siêu Thanh +Comment[zh_CN]=称为 Metabar 的 Konqueror 导航面板插件 +Comment[zh_TW]=叫做 Metabar 的 Konqueror 導覽面板外掛程式 +Icon=metabar +Name=Metabar +Name[el]=Γραμμή μεταδεδομένων +Name[eo]=MetaCrawler +Name[es]=Metabarra +Name[fa]=فرامیله +Name[fy]=Metabalke +Name[ja]=メタバー +Name[km]=របារមេតា +Name[ne]=मेटाबार +Name[nl]=Metabalk +Name[pa]=ਮੈਟਾ-ਪੱਟੀ +Name[pt_BR]=MetaBar +Name[ru]=Сведения +Name[sr]=Метапалета +Name[sr@Latn]=Metapaleta +Name[sv]=Metarad +Name[vi]=Siêu Thanh +Open=false +Type=Link +URL= +X-KDE-KonqSidebarAddModule=konqsidebar_metabar diff --git a/konq-plugins/sidebar/metabar/src/metabarfunctions.cpp b/konq-plugins/sidebar/metabar/src/metabarfunctions.cpp new file mode 100644 index 0000000..2d16e29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabarfunctions.cpp @@ -0,0 +1,242 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "metabarfunctions.h" + +#include <html_element.h> +#include <html_document.h> +#include <css_value.h> + +#include <kconfig.h> + +#include <qrect.h> + +#define CSS_PRIORITY "important" +#define RESIZE_SPEED 5 +#define RESIZE_STEP 2 + +MetabarFunctions::MetabarFunctions(KHTMLPart *html, QObject *parent, const char* name) : QObject(parent, name), m_html(html) +{ + timer = new QTimer(this); + connect(timer, SIGNAL(timeout()), this, SLOT(animate())); +} + +MetabarFunctions::~MetabarFunctions() +{ + if(timer->isActive()){ + timer->stop(); + } +} + +void MetabarFunctions::handleRequest(const KURL &url) +{ + QString function = url.host(); + QStringList params = QStringList::split(',', url.filename()); + + if(function == "toggle"){ + if(params.size() == 1){ + toggle(params.first()); + } + } + + else if(function == "adjustSize"){ + if(params.size() == 1){ + adjustSize(params.first()); + } + } + + else if(function == "show"){ + if(params.size() == 1){ + show(params.first()); + } + } + + else if(function == "hide"){ + if(params.size() == 1){ + hide(params.first()); + } + } +} + +void MetabarFunctions::toggle(DOM::DOMString item) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById(item)); + + if(!node.isNull()){ + DOM::NodeList children = node.childNodes(); + DOM::CSSStyleDeclaration style = node.style(); + DOM::DOMString expanded = node.getAttribute("expanded"); + + bool isExpanded = expanded == "true"; + + int height = 0; + if(!isExpanded){ + height = getHeight(node); + } + + DOM::DOMString att = isExpanded ? "false" : "true"; + node.setAttribute("expanded", att); + + KConfig config("metabarrc"); + config.setGroup("General"); + + if(config.readBoolEntry("AnimateResize", false)){ + resizeMap[item.string()] = height; + + if(!timer->isActive()){ + timer->start(RESIZE_SPEED); + } + } + else{ + style.setProperty("height", QString("%1px").arg(height), CSS_PRIORITY); + } + } +} + +void MetabarFunctions::adjustSize(DOM::DOMString item) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById(item)); + + if(!node.isNull()){ + DOM::NodeList children = node.childNodes(); + DOM::CSSStyleDeclaration style = node.style(); + DOM::DOMString expanded = node.getAttribute("expanded"); + + bool isExpanded = expanded == "true"; + + if(isExpanded){ + int height = getHeight(node); + + KConfig config("metabarrc"); + config.setGroup("General"); + + if(config.readBoolEntry("AnimateResize", false)){ + resizeMap[item.string()] = height; + + if(!timer->isActive()){ + timer->start(RESIZE_SPEED); + } + } + else{ + style.setProperty("height", QString("%1px").arg(height), CSS_PRIORITY); + } + } + } +} + +void MetabarFunctions::animate() +{ + QMap<QString, int>::Iterator it; + for(it = resizeMap.begin(); it != resizeMap.end(); ++it ) { + QString id = it.key(); + int height = it.data(); + int currentHeight = 0; + + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById(id)); + DOM::CSSStyleDeclaration style = node.style(); + + QString currentHeightString = style.getPropertyValue("height").string(); + if(currentHeightString.endsWith("px")){ + currentHeight = currentHeightString.left(currentHeightString.length() - 2).toInt(); + } + + if(currentHeight == height){ + resizeMap.remove(id); + + if(resizeMap.isEmpty()){ + timer->stop(); + } + } + else{ + int diff = kAbs(currentHeight - height); + int changeValue = RESIZE_STEP; + + if(diff < RESIZE_STEP){ + changeValue = diff; + } + + int change = currentHeight < height ? changeValue : -changeValue; + style.setProperty("height", QString("%1px").arg(currentHeight + change), CSS_PRIORITY); + doc.updateRendering(); + } + } +} + +void MetabarFunctions::show(DOM::DOMString item) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById(item)); + if(!node.isNull()){ + DOM::HTMLElement parent = static_cast<DOM::HTMLElement>(node.parentNode()); + + DOM::CSSStyleDeclaration style = parent.style(); + style.setProperty("display", "block", CSS_PRIORITY); + } +} + +void MetabarFunctions::hide(DOM::DOMString item) +{ + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById(item)); + if(!node.isNull()){ + DOM::HTMLElement parent = static_cast<DOM::HTMLElement>(node.parentNode()); + + DOM::CSSStyleDeclaration style = parent.style(); + style.setProperty("display", "none", CSS_PRIORITY); + } +} + +int MetabarFunctions::getHeight(DOM::HTMLElement &element) +{ + int height = 0; + DOM::NodeList children = element.childNodes(); + for(uint i = 0; i < children.length(); i++){ + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(children.item(i)); + DOM::CSSStyleDeclaration style = node.style(); + + DOM::DOMString css_height = style.getPropertyValue("height"); + if(!css_height.isNull()){ + height += css_height.string().left(css_height.string().length() - 2).toInt(); + } + else{ + int h = 0; + if(!node.isNull()){ + h = node.getRect().height(); + } + + DOM::DOMString display = style.getPropertyValue("display"); + if(display == "none"){ + h = 0; + } + else if(h == 0){ + h = 20; + } + + height += h; + } + } + + return height; +} + +#include "metabarfunctions.moc" diff --git a/konq-plugins/sidebar/metabar/src/metabarfunctions.h b/konq-plugins/sidebar/metabar/src/metabarfunctions.h new file mode 100644 index 0000000..1c01998 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabarfunctions.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef METABAR_FUNCTIONS_H +#define METABAR_FUNCTIONS_H + +#include <dom_string.h> + +#include <qtimer.h> +#include <qmap.h> + +#include <kurl.h> +#include <khtml_part.h> + +class MetabarFunctions : public QObject +{ + Q_OBJECT + + public: + MetabarFunctions(KHTMLPart *html, QObject *parent = 0, const char* name=0); + ~MetabarFunctions(); + + void toggle(DOM::DOMString item); + void adjustSize(DOM::DOMString item); + void hide(DOM::DOMString item); + void show(DOM::DOMString item); + void handleRequest(const KURL &url); + + protected: + KHTMLPart *m_html; + + private: + QTimer *timer; + + QMap<QString, int> resizeMap; + int getHeight(DOM::HTMLElement &element); + + private slots: + void animate(); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/metabarwidget.cpp b/konq-plugins/sidebar/metabar/src/metabarwidget.cpp new file mode 100644 index 0000000..f794353 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabarwidget.cpp @@ -0,0 +1,592 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "metabarwidget.h" +#include "configdialog.h" + +#include "defaultplugin.h" +#include "settingsplugin.h" +#include "remoteplugin.h" +#include "httpplugin.h" + +#include <qwidget.h> +#include <qlayout.h> +#include <qdir.h> +#include <qfile.h> +#include <qtextstream.h> +#include <qvaluelist.h> +#include <qurl.h> +#include <qbuffer.h> + +#include <khtmlview.h> +#include <kapplication.h> +#include <kstandarddirs.h> +#include <kurl.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <kicontheme.h> +#include <ktrader.h> +#include <klocale.h> +#include <krun.h> +#include <kdesktopfile.h> +#include <kpropertiesdialog.h> +#include <kaction.h> +#include <kactioncollection.h> +#include <kshortcut.h> +#include <kmimetype.h> +#include <kcmoduleinfo.h> +#include <kmdcodec.h> + +#include <kparts/browserextension.h> + +#include <dom2_events.h> +#include <dom2_views.h> +#include <dom_doc.h> +#include <dom_element.h> +#include <dom_string.h> +#include <html_element.h> +#include <html_misc.h> +#include <html_image.h> +#include <css_value.h> + +#include <dcopref.h> +#include <dcopclient.h> + +#define EVENT_TYPE DOM::DOMString("click") +#define ACTIVATION 1 + +MetabarWidget::MetabarWidget(QWidget *parent, const char *name) : QWidget(parent, name) +{ + skip = false; + loadComplete = false; + + currentItems = new KFileItemList; + currentItems->setAutoDelete(true); + + config = new KConfig("metabarrc"); + + dir_watch = new KDirWatch(); + connect(dir_watch, SIGNAL(dirty(const QString&)), this, SLOT(slotUpdateCurrentInfo(const QString&))); + connect(dir_watch, SIGNAL(created(const QString&)), this, SLOT(slotUpdateCurrentInfo(const QString&))); + connect(dir_watch, SIGNAL(deleted(const QString&)), this, SLOT(slotDeleteCurrentInfo(const QString&))); + + html = new KHTMLPart(this, "metabarhtmlpart"); + html->setJScriptEnabled(true); + html->setPluginsEnabled(true); + html->setCaretVisible(false); + html->setDNDEnabled(false); + html->setJavaEnabled(false); + html->view()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + html->view()->hide(); + + connect(html->browserExtension(), SIGNAL(openURLRequest( const KURL &, const KParts::URLArgs & )), this, SLOT(handleURLRequest(const KURL &, const KParts::URLArgs &))); + connect(html, SIGNAL(completed()), this, SLOT(loadCompleted())); + connect(html, SIGNAL(popupMenu(const QString &, const QPoint &)), this, SLOT(slotShowPopup(const QString&, const QPoint &))); + + functions = new MetabarFunctions(html, this); + + currentPlugin = 0; + defaultPlugin = new DefaultPlugin(html, functions); + HTTPPlugin *httpPlugin = new HTTPPlugin(html, functions); + + //plugins.setAutoDelete(true); + plugins.insert("settings", new SettingsPlugin(html, functions)); + plugins.insert("remote", new RemotePlugin(html, functions)); + //plugins.insert("trash", new TrashPlugin(html, functions)); + plugins.insert("http", httpPlugin); + plugins.insert("https", httpPlugin); + + QVBoxLayout *layout = new QVBoxLayout(this); + layout->addWidget(html->view()); + + popup = new KPopupMenu(0); + KAction *configAction = new KAction(i18n("Configure %1...").arg("Metabar"), "configure", KShortcut(), this, SLOT(slotShowConfig()), html->actionCollection(), "configure"); + configAction->plug(popup); + + KAction *reloadAction = new KAction(i18n("Reload Theme"), "reload", KShortcut(), this, SLOT(setTheme()), html->actionCollection(), "reload"); + reloadAction->plug(popup); + + setTheme(); +} + +MetabarWidget::~MetabarWidget() +{ + config->sync(); + delete config; + + delete dir_watch; + delete currentItems; +} + +void MetabarWidget::setFileItems(const KFileItemList &items, bool check) +{ + if(!loadComplete){ + return; + } + + if(skip){ + skip = false; + return; + } + + if(check){ + int count = items.count(); + + KURL url(getCurrentURL()); + + KFileItem *newItem = items.getFirst(); + KFileItem *oldItem = currentItems->getFirst(); + + if(count == 0){ + if(oldItem){ + if(oldItem->url() == url){ + return; + } + } + + currentItems->clear(); + currentItems->append(new KFileItem(S_IFDIR, KFileItem::Unknown, url, true)); + } + + else if(count == 1){ + if(newItem){ + if(newItem->url().isEmpty()){ + return; + } + + if(currentItems->count() == items.count() && oldItem){ + if(newItem->url() == oldItem->url()){ + return; + } + } + } + + currentItems = new KFileItemList(items); + } + + else{ + if(currentItems && *currentItems == items){ + return; + } + currentItems = new KFileItemList(items); + } + } + else{ + currentItems = new KFileItemList(items); + } + + if(currentPlugin){ + currentPlugin->deactivate(); + } + + QString protocol = currentItems->getFirst()->url().protocol(); + currentPlugin = plugins[protocol]; + + if(!currentPlugin){ + currentPlugin = defaultPlugin; + } + + ProtocolPlugin::activePlugin = currentPlugin; + currentPlugin->setFileItems(*currentItems); +} + +QString MetabarWidget::getCurrentURL() +{ + DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name()); + DCOPReply reply = ref.call("currentURL()"); + + if (reply.isValid()) { + QString url; + reply.get(url, "QString"); + + if(!url.isNull() && !url.isEmpty()){ + return url; + } + } + return 0; +} + +void MetabarWidget::openURL(const QString &url) +{ + DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name()); + DCOPReply reply = ref.call("openURL", url); +} + +void MetabarWidget::openTab(const QString &url) +{ + DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name()); + DCOPReply reply = ref.call("newTab", url); +} + +void MetabarWidget::callAction(const QString &action) +{ + DCOPRef ref(kapp->dcopClient()->appId(), QString(this->topLevelWidget()->name()).append("/action/").append(action).utf8()); + if(ref.call("enabled()")){ + ref.call("activate()"); + } +} + +void MetabarWidget::loadLinks() +{ + config->setGroup("General"); + QStringList links = config->readListEntry("Links"); + + if(links.count() == 0){ + functions->hide("links"); + } + else{ + functions->show("links"); + + DOM::HTMLDocument doc = html->htmlDocument(); + DOM::HTMLElement node = doc.getElementById("links"); + + if(!node.isNull()){ + DOM::DOMString innerHTML; + + for(QStringList::Iterator it = links.begin(); it != links.end(); ++it){ + config->setGroup("Link_" + (*it)); + addEntry(innerHTML, config->readEntry("Name"), config->readEntry("URL"), config->readEntry("Icon", "folder")); + } + + node.setInnerHTML(innerHTML); + } + + functions->adjustSize("links"); + } +} + +void MetabarWidget::loadCompleted() +{ + DOM::HTMLDocument doc = html->htmlDocument(); + + DOM::NodeList i18n_a_list = doc.getElementsByTagName("a"); + for(uint i = 0; i < i18n_a_list.length(); i++){ + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(i18n_a_list.item(i)); + if(!node.isNull()){ + if(node.hasAttribute("i18n")){ + QString text = node.innerText().string(); + node.setInnerText(DOM::DOMString(i18n(text.utf8().data()))); + } + + if(node.hasAttribute("image")){ + QString icon = node.getAttribute("image").string(); + QString url = getIconPath(icon); + QString style = QString("background-image: url(%1);").arg(url); + + node.setAttribute("style", style); + } + } + } + + DOM::NodeList i18n_ul_list = doc.getElementsByTagName("ul"); + for(uint i = 0; i < i18n_ul_list.length(); i++){ + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(i18n_ul_list.item(i)); + if(!node.isNull()){ + if(node.hasAttribute("i18n")){ + QString text = node.innerText().string(); + node.setInnerText(DOM::DOMString(i18n(text.utf8().data()))); + } + } + } + + config->setGroup("General"); + QString file = locate("data", QString("metabar/themes/%1/default.css").arg(config->readEntry("Theme", "default"))); + if(file.isNull()){ + file = locate("data", QString("metabar/themes/default/default.css")); + } + + QFile cssfile(file); + if(cssfile.open(IO_ReadOnly)){ + QTextStream stream( &cssfile ); + QString tmp = stream.read(); + cssfile.close(); + + tmp.replace("./", KURL::fromPathOrURL(file).directory(false)); + html->setUserStyleSheet(tmp); + } + + loadComplete = true; + html->view()->setFrameShape(config->readBoolEntry("ShowFrame", true) ? QFrame::StyledPanel : QFrame::NoFrame); + html->view()->show(); + + if(currentItems && !currentItems->isEmpty()){ + setFileItems(*currentItems, false); + } + else{ + QString url = getCurrentURL(); + KFileItem *item = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, KURL(url), true); + KFileItemList list; + list.append(item); + setFileItems(list, false); + } + + loadLinks(); +} + +void MetabarWidget::handleURLRequest(const KURL &url, const KParts::URLArgs &args) +{ + if(!currentPlugin){ + return; + } + + QString protocol = url.protocol(); + + if(currentPlugin->handleRequest(url)){ + return; + } + + if(protocol == "desktop"){ + QString path = url.path(); + + if(KDesktopFile::isDesktopFile(path)){ + KRun::run(new KDesktopFile(path, true), KURL::List()); + } + } + + else if(protocol == "kcmshell"){ + QString module = url.path().remove('/'); + + KRun::runCommand("kcmshell " + module); + } + + else if(protocol == "action"){ + QString action = url.url().right(url.url().length() - 9); + if(action.startsWith("metabar/")){ + QString newact = action.right(action.length() - 8); + + if(newact == "share"){ + slotShowSharingDialog(); + } + } + else{ + callAction(action); + } + } + + else if(protocol == "preview"){ + if(currentItems && !currentItems->isEmpty()){ + KFileItem *item = currentItems->getFirst(); + + DOM::HTMLDocument doc = html->htmlDocument(); + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(doc.getElementById("preview")); + DOM::HTMLImageElement image = static_cast<DOM::HTMLImageElement>(doc.getElementById("previewimage")); + + if(!node.isNull()){ + skip = true; //needed to prevent some weired reload + + DOM::DOMString innerHTML; + innerHTML += QString("<ul style=\"width: %1px; height: %1px\">").arg(image.width(), image.height()); + innerHTML += "<object class=\"preview\" type=\""; + innerHTML += item->mimetype(); + innerHTML += "\" data=\""; + innerHTML += item->url().url(); + innerHTML += "\" width=\""; + innerHTML += QString().setNum(image.width()); + innerHTML += "\" height=\""; + innerHTML += QString().setNum(image.height()); + innerHTML += "\" /></ul>"; + node.setInnerHTML(innerHTML); + } + } + } + + else if(protocol == "more"){ + QString name = url.host(); + + DOM::HTMLDocument doc = html->htmlDocument(); + DOM::NodeList list = doc.getElementsByName(name); + DOM::HTMLElement element = static_cast<DOM::HTMLElement>(doc.getElementById(name)); + bool showMore = true; + + for(uint i = 0; i < list.length(); i++){ + DOM::HTMLElement node = static_cast<DOM::HTMLElement>(list.item(i)); + if(!node.isNull()){ + DOM::HTMLElement parent = static_cast<DOM::HTMLElement>(node.parentNode()); + DOM::CSSStyleDeclaration style = parent.style(); + DOM::DOMString display = style.getPropertyValue("display"); + DOM::DOMString newDisplay = display == "none" ? "block" : "none"; + + style.setProperty("display", newDisplay, "important"); + + showMore = display == "block"; + } + } + + if(element.id().string().startsWith("hidden")){ + QString style = QString("background-image: url(%1);").arg(getIconPath(showMore ? "1downarrow" : "1uparrow")); + element.setInnerText( showMore ? i18n("More") : i18n("Less") ); + element.setAttribute("style", style); + } + + DOM::HTMLElement parent = static_cast<DOM::HTMLElement>(element.parentNode().parentNode()); + functions->adjustSize(parent.id()); + } + + else if(protocol == "function"){ + functions->handleRequest(url); + } + + else if(protocol == "configure"){ + slotShowConfig(); + } + + else if(protocol == "openwith"){ + if(currentItems && !currentItems->isEmpty()){ + KFileItem *item = currentItems->getFirst(); + + KRun::displayOpenWithDialog(KURL::List(item->url()), false); + } + } + + else{ + if(args.newTab()){ + openTab(url.url()); + } + else{ + openURL(url.url()); + } + } +} + +QString MetabarWidget::getIconPath(const QString &name) +{ + QPixmap icon = SmallIcon(name); + + QByteArray data; + QBuffer buffer(data); + buffer.open(IO_WriteOnly); + icon.save(&buffer, "PNG"); + + return QString::fromLatin1("data:image/png;base64,%1").arg(KCodecs::base64Encode(data)); +} + +void MetabarWidget::slotShowSharingDialog() +{ + if(currentItems && currentItems->count() == 1){ + KPropertiesDialog *dialog = new KPropertiesDialog(currentItems->first(), 0, 0, true); + dialog->showFileSharingPage(); + } +} + +void MetabarWidget::slotShowConfig() +{ + ConfigDialog *config_dialog = new ConfigDialog(this); + if(config_dialog->exec() == QDialog::Accepted){ + config->reparseConfiguration(); + + setFileItems(*currentItems, false); + loadLinks(); + + setTheme(); + + html->view()->setFrameShape(config->readBoolEntry("ShowFrame", true) ? QFrame::StyledPanel : QFrame::NoFrame); + } + + delete config_dialog; +} + +void MetabarWidget::slotShowPopup(const QString &url, const QPoint &point) +{ + popup->exec(point); +} + +void MetabarWidget::slotUpdateCurrentInfo(const QString &path) +{ + if(currentItems){ + KFileItem *item = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, KURL(path), true); + + if(currentItems->count() == 1){ + currentItems->clear(); + currentItems->append(item); + } + + setFileItems(*currentItems, false); + } +} + +void MetabarWidget::slotDeleteCurrentInfo(const QString&) +{ + if(currentItems && currentItems->count() == 1){ + QString url = getCurrentURL(); + KURL currentURL; + + if(currentItems){ + currentURL = currentItems->getFirst()->url(); + } + + if(!currentURL.isEmpty() && KURL(url) != currentURL){ + if(dir_watch->contains(currentURL.path())){ + dir_watch->removeDir(currentURL.path()); + } + dir_watch->addDir(url); + + KFileItem *item = new KFileItem(KFileItem::Unknown, KFileItem::Unknown, url, true); + + currentItems->clear(); + currentItems->append(item); + + setFileItems(*currentItems, false); + } + } +} + +void MetabarWidget::addEntry(DOM::DOMString &html, const QString name, const QString url, const QString icon, const QString id, const QString nameatt, bool hidden) +{ + html += "<ul"; + + if(hidden){ + html += " style=\"display: none;\""; + } + + html += "><a"; + + if(!id.isNull() && !id.isEmpty()){ + html += " id=\""; + html += id; + html += "\""; + } + + if(!nameatt.isNull() && !nameatt.isEmpty()){ + html += " name=\""; + html += nameatt; + html += "\""; + } + + html += " href=\""; + html += url; + html += "\" onClick=\"this.blur();\" style=\"background-image: url("; + html += getIconPath(icon); + html += ");\">"; + html += name; + html += "</a></ul>"; +} + +void MetabarWidget::setTheme() +{ + loadComplete = false; + + config->setGroup("General"); + QString file = locate("data", QString("metabar/themes/%1/layout.html").arg(config->readEntry("Theme", "default"))); + + html->openURL(KURL(file)); +} + +#include "metabarwidget.moc" diff --git a/konq-plugins/sidebar/metabar/src/metabarwidget.h b/konq-plugins/sidebar/metabar/src/metabarwidget.h new file mode 100644 index 0000000..a0acb41 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/metabarwidget.h @@ -0,0 +1,88 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef METABAR_WIDGET_H +#define METABAR_WIDGET_H + +#include <khtml_part.h> + +#include <kconfig.h> +#include <kfileitem.h> +#include <kurl.h> +#include <kservice.h> +#include <kpopupmenu.h> +#include <kdirwatch.h> + +#include <qmap.h> + +#include "protocolplugin.h" +#include "metabarfunctions.h" + +class MetabarWidget : public QWidget +{ + Q_OBJECT + + public: + MetabarWidget(QWidget *parent = 0, const char* name=0); + ~MetabarWidget(); + + void setFileItems(const KFileItemList &items, bool check = true); + + static QString getIconPath(const QString &name); + static void addEntry(DOM::DOMString &html, const QString name, const QString url, const QString icon, const QString id = QString::null, const QString nameatt = QString::null, bool hidden = false); + + private: + KFileItemList *currentItems; + KConfig *config; + + KHTMLPart *html; + + ProtocolPlugin *currentPlugin; + ProtocolPlugin *defaultPlugin; + + MetabarFunctions *functions; + + KDirWatch *dir_watch; + KPopupMenu *popup; + + QDict<ProtocolPlugin> plugins; + + bool skip; + bool loadComplete; + + void callAction(const QString &action); + void openURL(const QString &url); + void openTab(const QString &url); + void loadLinks(); + + QString getCurrentURL(); + + private slots: + void loadCompleted(); + void slotShowSharingDialog(); + void slotShowConfig(); + void slotShowPopup(const QString &url, const QPoint &pos); + void handleURLRequest(const KURL &url, const KParts::URLArgs &args); + void slotUpdateCurrentInfo(const QString &path); + void slotDeleteCurrentInfo(const QString &path); + void setTheme(); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/protocolplugin.cpp b/konq-plugins/sidebar/metabar/src/protocolplugin.cpp new file mode 100644 index 0000000..10fd784 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/protocolplugin.cpp @@ -0,0 +1,157 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "protocolplugin.h" + +#include <qbuffer.h> + +#include <kimageio.h> +#include <kmdcodec.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <html_document.h> +#include <html_image.h> + +ProtocolPlugin* ProtocolPlugin::activePlugin = 0; + +ProtocolPlugin::ProtocolPlugin(KHTMLPart *html, MetabarFunctions *functions, const char* name) : QObject(html, name), m_html(html), m_functions(functions) +{ +} + +ProtocolPlugin::~ProtocolPlugin() +{ +} + +void ProtocolPlugin::setFileItems(const KFileItemList &items) +{ + m_items = items; + + killJobs(); + + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement actions = doc.getElementById("actions"); + DOM::HTMLElement applications = doc.getElementById("open"); + DOM::HTMLElement info = doc.getElementById("info"); + DOM::HTMLElement preview = doc.getElementById("preview"); + DOM::HTMLElement bookmarks = doc.getElementById("bookmarks"); + + DOM::HTMLImageElement icon = (DOM::HTMLImageElement) doc.getElementById("icon"); + DOM::HTMLElement name = doc.getElementById("name"); + DOM::HTMLElement type = doc.getElementById("type"); + DOM::HTMLElement size = doc.getElementById("size"); + + if(!icon.isNull()){ + QPixmap pix; + if(m_items.count() == 1){ + pix = m_items.getFirst()->pixmap(KIcon::SizeLarge); + } + else{ + pix = DesktopIcon("kmultiple", KIcon::SizeLarge); + } + + QByteArray data; + QBuffer buffer(data); + buffer.open(IO_WriteOnly); + pix.save(&buffer, "PNG"); + QString icondata = QString::fromLatin1("data:image/png;base64,%1").arg(KCodecs::base64Encode(data)); + + icon.setSrc(icondata); + } + + if(!name.isNull()){ + if(m_items.count() == 1){ + name.setInnerText(m_items.getFirst()->name()); + } + else{ + name.setInnerText(i18n("%1 Elements").arg(m_items.count())); + } + } + + if(!type.isNull()){ + if(m_items.count() == 1){ + KFileItem *item = m_items.getFirst(); + KFileItem *that = const_cast<KFileItem *>(item); + + type.setInnerText(that->determineMimeType()->comment()); + } + else{ + int files = 0; + int dirs = 0; + + for(KFileItemListIterator it(m_items); it.current(); ++it){ + if((*it)->isDir()){ + dirs++; + } + else{ + files++; + } + } + + type.setInnerText(i18n("%1 Folders, %2 Files").arg(dirs).arg(files)); + } + + + } + + if(!size.isNull()){ + KIO::filesize_t s = 0; + + for(KFileItemListIterator it(m_items); it.current(); ++it){ + s += (*it)->size(); + } + + size.setInnerText(KIO::convertSize(s)); + } + + if(!actions.isNull()){ + loadActions(actions); + m_functions->adjustSize("actions"); + } + + if(!applications.isNull()){ + loadApplications(applications); + m_functions->adjustSize("open"); + } + + if(!info.isNull()){ + loadInformation(info); + m_functions->adjustSize("info"); + } + + if(!preview.isNull()){ + loadPreview(preview); + m_functions->adjustSize("preview"); + } + + if(!bookmarks.isNull()){ + loadBookmarks(bookmarks); + m_functions->adjustSize("bookmarks"); + } + + doc.updateRendering(); +} + +bool ProtocolPlugin::isActive() +{ + return activePlugin == this; +} + +#include "protocolplugin.moc" diff --git a/konq-plugins/sidebar/metabar/src/protocolplugin.h b/konq-plugins/sidebar/metabar/src/protocolplugin.h new file mode 100644 index 0000000..9202df3 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/protocolplugin.h @@ -0,0 +1,60 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _PROTOCOL_PLUGIN_H +#define _PROTOCOL_PLUGIN_H + +#include <kfileitem.h> +#include <khtml_part.h> + +#include <html_element.h> + +#include "metabarfunctions.h" + +class ProtocolPlugin : public QObject{ + Q_OBJECT + + public: + static ProtocolPlugin* activePlugin; + + ProtocolPlugin(KHTMLPart *html, MetabarFunctions *functions, const char* name = 0); + ~ProtocolPlugin(); + + void setFileItems(const KFileItemList &items); + bool isActive(); + + virtual bool handleRequest(const KURL &url) = 0; + virtual void deactivate() = 0; + + protected: + virtual void killJobs() = 0; + + virtual void loadActions(DOM::HTMLElement node) = 0; + virtual void loadApplications(DOM::HTMLElement node) = 0; + virtual void loadInformation(DOM::HTMLElement node) = 0; + virtual void loadPreview(DOM::HTMLElement node) = 0; + virtual void loadBookmarks(DOM::HTMLElement node) = 0; + + KFileItemList m_items; + KHTMLPart *m_html; + MetabarFunctions *m_functions; +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/remoteplugin.cpp b/konq-plugins/sidebar/metabar/src/remoteplugin.cpp new file mode 100644 index 0000000..6d9a2dc --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/remoteplugin.cpp @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "remoteplugin.h" + +#include <kservice.h> +#include <klocale.h> +#include <kstandarddirs.h> + +RemotePlugin::RemotePlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name) : DefaultPlugin (html, functions, name) +{ +} + +RemotePlugin::~RemotePlugin() +{ +} + +void RemotePlugin::loadActions(DOM::HTMLElement node) +{ + KService::Ptr service = KService::serviceByDesktopName("knetattach"); + + if(service && service->isValid()){ + DOM::DOMString innerHTML; + MetabarWidget::addEntry(innerHTML, i18n("Add a Network Folder"), "desktop://" + locate("apps", service->desktopEntryPath()), "wizard"); + node.setInnerHTML(innerHTML); + + m_functions->show("actions"); + } + + else{ + m_functions->hide("actions"); + } +} + +#include "remoteplugin.moc" diff --git a/konq-plugins/sidebar/metabar/src/remoteplugin.h b/konq-plugins/sidebar/metabar/src/remoteplugin.h new file mode 100644 index 0000000..f77bbfd --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/remoteplugin.h @@ -0,0 +1,37 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _REMOTE_PLUGIN_H_ +#define _REMOTE_PLUGIN_H_ + +#include "defaultplugin.h" + +class RemotePlugin : public DefaultPlugin +{ + Q_OBJECT + + public: + RemotePlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name = 0); + ~RemotePlugin(); + + void loadActions(DOM::HTMLElement node); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/serviceloader.cpp b/konq-plugins/sidebar/metabar/src/serviceloader.cpp new file mode 100644 index 0000000..7c7e544 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/serviceloader.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "serviceloader.h" + +#include <qdir.h> +#include <qvaluelist.h> +#include <qptrlist.h> + +#include <dcopclient.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kactioncollection.h> +#include <kiconloader.h> +#include <kaction.h> +#include <kshortcut.h> +#include <ksimpleconfig.h> +#include <kglobal.h> +#include <kstandarddirs.h> + + +ServiceLoader::ServiceLoader(QWidget *parent, const char *name) : QObject(parent, name) +{ + popups.setAutoDelete(true); +} + +ServiceLoader::~ServiceLoader() +{ +} + +void ServiceLoader::loadServices(const KFileItem item, DOM::DOMString &html, int &count) +{ + popups.clear(); + + KURL url = item.url(); + QString mimeType = item.mimetype(); + QString mimeGroup = mimeType.left(mimeType.find('/')); + + urlList.clear(); + urlList.append(url); + + QStringList dirs = KGlobal::dirs()->findDirs( "data", "konqueror/servicemenus/" ); + KConfig config("metabarrc", true, false); + config.setGroup("General"); + int maxActions = config.readNumEntry("MaxActions"); + bool matchAll = false; // config.readBoolEntry("MatchAll"); + + int id = 0; + QString idString; + + for(QStringList::Iterator dit = dirs.begin(); dit != dirs.end(); ++dit){ + idString.setNum(id); + + QDir dir(*dit); + QStringList entries = dir.entryList("*.desktop", QDir::Files); + + for(QStringList::Iterator eit = entries.begin(); eit != entries.end(); ++eit){ + KSimpleConfig cfg( *dit + *eit, true ); + cfg.setDesktopGroup(); + + if(cfg.hasKey("X-KDE-ShowIfRunning" )){ + const QString app = cfg.readEntry( "X-KDE-ShowIfRunning" ); + if(!kapp->dcopClient()->isApplicationRegistered(app.utf8())){ + continue; + } + } + + if(cfg.hasKey("X-KDE-Protocol")){ + const QString protocol = cfg.readEntry( "X-KDE-Protocol" ); + if(protocol != url.protocol()){ + continue; + } + } + + else if(url.protocol() == "trash"){ + continue; + } + + if(cfg.hasKey("X-KDE-Require")){ + const QStringList capabilities = cfg.readListEntry( "X-KDE-Require" ); + if (capabilities.contains( "Write" )){ + continue; + } + } + + if ( cfg.hasKey( "Actions" ) && cfg.hasKey( "ServiceTypes" ) ){ + const QStringList types = cfg.readListEntry( "ServiceTypes" ); + const QStringList excludeTypes = cfg.readListEntry( "ExcludeServiceTypes" ); + bool ok = false; + + for (QStringList::ConstIterator it = types.begin(); it != types.end() && !ok; ++it){ + bool checkTheMimetypes = false; + + if(matchAll){ + // first check if we have an all mimetype + if (*it == "all/all" || *it == "allfiles"){ + checkTheMimetypes = true; + } + + // next, do we match all files? + if (!ok && !item.isDir() && *it == "all/allfiles"){ + checkTheMimetypes = true; + } + } + + // if we have a mimetype, see if we have an exact or a type globbed match + if(!ok && (!mimeType.isEmpty() && *it == mimeType) || + (!mimeGroup.isEmpty() && ((*it).right(1) == "*" && (*it).left((*it).find('/')) == mimeGroup))) + { + checkTheMimetypes = true; + } + + if(checkTheMimetypes){ + ok = true; + + for(QStringList::ConstIterator itex = excludeTypes.begin(); itex != excludeTypes.end(); ++itex){ + if( ((*itex).right(1) == "*" && (*itex).left((*itex).find('/')) == mimeGroup) || + ((*itex) == mimeType)) + { + ok = false; + break; + } + } + } + } + if (ok){ + const QString priority = cfg.readEntry("X-KDE-Priority"); + const QString submenuName = cfg.readEntry( "X-KDE-Submenu" ); + bool usePopup = false; + KPopupMenu *popup; + + if(!submenuName.isEmpty()){ + usePopup = true; + + if(popups[submenuName]){ + popup = popups[submenuName]; + } + else{ + MetabarWidget::addEntry(html, submenuName, "servicepopup://" + idString, "1rightarrow", "popup" + idString, count < maxActions ? QString::null : QString("hiddenaction"), count >= maxActions); + + popup = new KPopupMenu(); + popups.insert(idString, popup); + + count++; + } + } + + QValueList<KDEDesktopMimeType::Service> list = KDEDesktopMimeType::userDefinedServices( *dit + *eit, url.isLocalFile()); + + for (QValueList<KDEDesktopMimeType::Service>::iterator it = list.begin(); it != list.end(); ++it){ + + if(usePopup){ + KAction *action = new KAction((*it).m_strName, (*it).m_strIcon, KShortcut(), this, SLOT(runAction()), popup, idString.utf8()); + action->plug(popup); + } + else{ + MetabarWidget::addEntry(html, (*it).m_strName, "service://" + idString, (*it).m_strIcon, QString::null, count < maxActions ? QString::null : QString("hiddenaction"), count >= maxActions); + count++; + } + + services.insert(idString, *it); + id++; + idString.setNum(id); + } + } + } + } + } +} + +void ServiceLoader::runAction() +{ + KDEDesktopMimeType::Service s = services[sender()->name()]; + if(!s.isEmpty()){ + KDEDesktopMimeType::executeService(urlList, s); + } +} + +void ServiceLoader::runAction(const QString& name) +{ + KDEDesktopMimeType::Service s = services[name]; + if(!s.isEmpty()){ + KDEDesktopMimeType::executeService(urlList, s); + } +} + +void ServiceLoader::showPopup(const QString &popup, const QPoint &point) +{ + KPopupMenu *p = popups[popup]; + if(p){ + p->exec(point); + } +} + +#include "serviceloader.moc" diff --git a/konq-plugins/sidebar/metabar/src/serviceloader.h b/konq-plugins/sidebar/metabar/src/serviceloader.h new file mode 100644 index 0000000..293ae6b --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/serviceloader.h @@ -0,0 +1,59 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _SERVICELOADER_H_ +#define _SERVICELOADER_H_ + +#include <qstring.h> +#include <qdict.h> +#include <qmap.h> +#include <qwidget.h> + +#include <kpopupmenu.h> +#include <kfileitem.h> +#include <kmimetype.h> +#include <kurl.h> + +#include <dom_string.h> + +#include "metabarwidget.h" + +class ServiceLoader : public QObject +{ + Q_OBJECT + + public: + ServiceLoader(QWidget *parent, const char *name = 0); + ~ServiceLoader(); + + void loadServices(const KFileItem item, DOM::DOMString &html, int &count); + void runAction(const QString &name); + void showPopup(const QString &popup, const QPoint &point); + + private: + QDict<KPopupMenu> popups; + QMap<QString,KDEDesktopMimeType::Service> services; + KURL::List urlList; + + private slots: + void runAction(); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/src/settingsplugin.cpp b/konq-plugins/sidebar/metabar/src/settingsplugin.cpp new file mode 100644 index 0000000..1fb9e50 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/settingsplugin.cpp @@ -0,0 +1,201 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#include "metabarwidget.h" +#include "settingsplugin.h" + +#include <kcmoduleinfo.h> +#include <kservice.h> +#include <klocale.h> + +#include <html_document.h> +#include <html_element.h> +#include <dom_string.h> + +SettingsPlugin::SettingsPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name) : ProtocolPlugin (html, functions, name) +{ + list_job = 0; +} + +SettingsPlugin::~SettingsPlugin() +{ +} + +void SettingsPlugin::killJobs() +{ + if(list_job){ + list_job->kill(); + list_job = 0; + } +} + +void SettingsPlugin::deactivate() +{ + m_functions->hide("actions"); + m_functions->hide("info"); +} + +void SettingsPlugin::loadActions(DOM::HTMLElement node) +{ + KURL url = m_items.getFirst()->url(); + + if(url.path().endsWith("/")){ + list_job = KIO::listDir(url, true, false); + connect(list_job, SIGNAL(entries(KIO::Job *, const KIO::UDSEntryList &)), this, SLOT(slotGotEntries(KIO::Job *, const KIO::UDSEntryList &))); + connect(list_job, SIGNAL(result(KIO::Job *)), this, SLOT(slotJobFinished(KIO::Job *))); + + m_functions->show("actions"); + } + else{ + QString path = url.path(); + QString name = url.filename(); + + KService::Ptr service = KService::serviceByStorageId(name); + if(service && service->isValid()){ + KCModuleInfo kcminfo(service); + + DOM::DOMString innerHTML; + MetabarWidget::addEntry(innerHTML, i18n("Run"), "kcmshell:/" + name, kcminfo.icon()); + node.setInnerHTML(innerHTML); + + m_functions->show("actions"); + } + else{ + m_functions->hide("actions"); + } + } +} + +void SettingsPlugin::loadInformation(DOM::HTMLElement node) +{ + KURL url = m_items.getFirst()->url(); + if(url.path().endsWith("/")){ + m_functions->hide("info"); + } + else{ + QString path = url.path(); + QString name = url.filename(); + + KService::Ptr service = KService::serviceByStorageId(name); + if(service && service->isValid()){ + KCModuleInfo kcminfo(service); + + bool needsRoot = kcminfo.needsRootPrivileges(); + + DOM::DOMString innerHTML; + innerHTML += "<ul class=\"info\"><b>" + i18n("Name") + ": </b>"; + innerHTML += kcminfo.moduleName(); + innerHTML += "</ul><ul class=\"info\"><b>" + i18n("Comment") + ": </b>"; + innerHTML += kcminfo.comment(); + innerHTML += "</ul>"; + + if(needsRoot){ + innerHTML += "<ul class=\"info\"><b>"; + innerHTML += i18n("Needs root privileges"); + innerHTML += "</b></ul>"; + } + node.setInnerHTML(innerHTML); + + m_functions->show("info"); + } + else{ + m_functions->hide("info"); + } + } +} + +void SettingsPlugin::loadApplications(DOM::HTMLElement node) +{ + m_functions->hide("open"); +} + +void SettingsPlugin::loadPreview(DOM::HTMLElement node) +{ + m_functions->hide("preview"); +} + +void SettingsPlugin::loadBookmarks(DOM::HTMLElement node) +{ + m_functions->hide("bookmarks"); +} + +bool SettingsPlugin::handleRequest(const KURL &) +{ + return false; +} + +void SettingsPlugin::slotGotEntries(KIO::Job *job, const KIO::UDSEntryList &list) +{ + if(!job){ + return; + } + + DOM::HTMLDocument doc = m_html->htmlDocument(); + DOM::HTMLElement node = doc.getElementById("actions"); + DOM::DOMString innerHTML; + + KIO::UDSEntryList::ConstIterator it = list.begin(); + KIO::UDSEntryList::ConstIterator it_end = list.end(); + for(; it != it_end; ++it){ + QString name; + QString icon; + QString url; + long type; + + KIO::UDSEntry::ConstIterator atomit = (*it).begin(); + KIO::UDSEntry::ConstIterator atomit_end = (*it).end(); + for(; atomit != atomit_end; ++atomit){ + if((*atomit).m_uds == KIO::UDS_NAME){ + name = (*atomit).m_str; + } + else if((*atomit).m_uds == KIO::UDS_ICON_NAME){ + icon = (*atomit).m_str; + } + else if((*atomit).m_uds == KIO::UDS_URL){ + url = (*atomit).m_str; + } + + else if((*atomit).m_uds == KIO::UDS_FILE_TYPE){ + type = (*atomit).m_long; + } + } + + kdDebug() << url << endl; + + if(type == S_IFREG){ + url = "kcmshell:/" + KURL(url).filename(); + } + + MetabarWidget::addEntry(innerHTML, name, url, icon); + } + + node.setInnerHTML(innerHTML); +} + +void SettingsPlugin::slotJobFinished(KIO::Job *job) +{ + if(list_job && job == list_job){ + list_job = 0; + + m_functions->adjustSize("actions"); + } +} + +#include "settingsplugin.moc" diff --git a/konq-plugins/sidebar/metabar/src/settingsplugin.h b/konq-plugins/sidebar/metabar/src/settingsplugin.h new file mode 100644 index 0000000..27f1097 --- /dev/null +++ b/konq-plugins/sidebar/metabar/src/settingsplugin.h @@ -0,0 +1,56 @@ +/*************************************************************************** + * Copyright (C) 2005 by Florian Roth * + * florian@synatic.net * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ + +#ifndef _SETTINGS_PLUGIN_H_ +#define _SETTINGS_PLUGIN_H_ + +#include "protocolplugin.h" + +#include <kio/jobclasses.h> +#include <kio/job.h> + +class SettingsPlugin : public ProtocolPlugin +{ + Q_OBJECT + + public: + SettingsPlugin(KHTMLPart* html, MetabarFunctions *functions, const char *name = 0); + ~SettingsPlugin(); + + void deactivate(); + bool handleRequest(const KURL &url); + + protected: + void killJobs(); + void loadActions(DOM::HTMLElement node); + void loadApplications(DOM::HTMLElement node); + void loadInformation(DOM::HTMLElement node); + void loadPreview(DOM::HTMLElement node); + void loadBookmarks(DOM::HTMLElement node); + + private: + KIO::ListJob *list_job; + + private slots: + void slotGotEntries(KIO::Job *job, const KIO::UDSEntryList &list); + void slotJobFinished(KIO::Job *job); +}; + +#endif diff --git a/konq-plugins/sidebar/metabar/stamp-h.in b/konq-plugins/sidebar/metabar/stamp-h.in new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/konq-plugins/sidebar/metabar/stamp-h.in diff --git a/konq-plugins/sidebar/newsticker/Makefile.am b/konq-plugins/sidebar/newsticker/Makefile.am new file mode 100644 index 0000000..4dc9fae --- /dev/null +++ b/konq-plugins/sidebar/newsticker/Makefile.am @@ -0,0 +1,36 @@ +SUBDIRS = . pics + +AM_CPPFLAGS = $(all_includes) +METASOURCES = AUTO + + + +################################ +# these are the headers for your project +noinst_HEADERS = nspanel.h nsstacktabwidget.h sidebar_news.h norsswidget.h + +kde_module_LTLIBRARIES = konq_sidebarnews.la + +# the Part's source, library search path, and link libraries +konq_sidebarnews_la_SOURCES = sidebar_news.cpp sidebar_news.skel nsstacktabwidget.cpp \ + nspanel.cpp nspanel.skel norsswidget.cpp \ + sidebarsettings.kcfgc \ + configfeedsbase.ui configfeeds.cpp +konq_sidebarnews_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) +konq_sidebarnews_la_LIBADD = $(LIB_KPARTS) $(LIB_KFILE) -lkonqsidebarplugin + + +globaladddir = $(kde_datadir)/konqsidebartng/add +globaladd_DATA = news_add.desktop + +kde_kcfg_DATA = konq_sidebarnews.kcfg + + + +############################ +# +# i18n +# +messages: rc.cpp + $(XGETTEXT) *.cpp -o $(podir)/konqsidebar_news.pot + diff --git a/konq-plugins/sidebar/newsticker/README b/konq-plugins/sidebar/newsticker/README new file mode 100644 index 0000000..65d15e6 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/README @@ -0,0 +1,38 @@ +Konqsidebarnews is based on the rss DCOP service in +kdenetwork/dcoprss. So you most likely you want to +install it before using the sidebar applet. + + + +TODO +==== + +- better handling of starting up rssservice + +- less crashes (check for stupid user input, etc...) + +- cleanly recover from a crashing dcop service + +- documentation + +- accessibility aware UI + +- integration with kdenetwork/knewsticker + + + +THANKS TO +========= + +- Joseph Wenningen (jowenn@kde.org) + idea and original code + +- Frerich Raabe (raabe@kde.org) + for kdenonbeta/librss where all the magic happens + +- Ian Reinhard Geiser (geiseri@kde.org) + for maintaining the DCOP service + + +--- +Marcus Camen <mcamen@mcamen.de> diff --git a/konq-plugins/sidebar/newsticker/configfeeds.cpp b/konq-plugins/sidebar/newsticker/configfeeds.cpp new file mode 100644 index 0000000..c682ab3 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/configfeeds.cpp @@ -0,0 +1,38 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + configfeeds.cpp + Copyright: Marcus Camen <mcamen@mcamen.de> + Copyright: Nathan Toone <nathan@toonetown.com> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "sidebarsettings.h" +#include "configfeeds.h" + + +namespace KSB_News { + +ConfigFeeds::ConfigFeeds(QWidget* parent, const char* name) : ConfigFeedsBase(parent, name) +{ +} + +} // namespace KSB_News + +#include "configfeeds.moc" diff --git a/konq-plugins/sidebar/newsticker/configfeeds.h b/konq-plugins/sidebar/newsticker/configfeeds.h new file mode 100644 index 0000000..555b4f5 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/configfeeds.h @@ -0,0 +1,53 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + configfeeds.h + Copyright: Marcus Camen <mcamen@mcamen.de> + Copyright: Nathan Toone <nathan@toonetown.com> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _konq_sidebar_news_configfeedsh_ +#define _konq_sidebar_news_configfeedsh_ + +#include "configfeedsbase.h" + + +// +// +// ATM this is just a noop wrapper +// +// + + +namespace KSB_News { + + class ConfigFeeds : public ConfigFeedsBase { + + Q_OBJECT + + public: + ConfigFeeds(QWidget* parent, const char* name = 0); + + }; + +} // namespace KSB_News + + +#endif diff --git a/konq-plugins/sidebar/newsticker/configfeedsbase.ui b/konq-plugins/sidebar/newsticker/configfeedsbase.ui new file mode 100644 index 0000000..8389747 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/configfeedsbase.ui @@ -0,0 +1,26 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>ConfigFeedsBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigFeedsBase</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KEditListBox"> + <property name="name"> + <cstring>kcfg_Sources</cstring> + </property> + <property name="title"> + <string>RSS Feeds</string> + </property> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="0"/> +<includehints> + <includehint>keditlistbox.h</includehint> + <includehint>klineedit.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/sidebar/newsticker/konq_sidebarnews.kcfg b/konq-plugins/sidebar/newsticker/konq_sidebarnews.kcfg new file mode 100644 index 0000000..7641ab2 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/konq_sidebarnews.kcfg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<kcfg xmlns="http://www.kde.org/standards/kcfg/1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://www.kde.org/standards/kcfg/1.0 + http://www.kde.org/standards/kcfg/1.0/kcfg.xsd" > + <kcfgfile name="konq_sidebarnewsrc"/> + + <group name="RSS sources"> + <entry name="Sources" type="StringList"> + <label>List of RSS Sources</label> + <default>http://www.kde.org/dotkdeorg.rdf</default> + </entry> + </group> + +</kcfg> diff --git a/konq-plugins/sidebar/newsticker/news_add.desktop b/konq-plugins/sidebar/newsticker/news_add.desktop new file mode 100644 index 0000000..989abf3 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/news_add.desktop @@ -0,0 +1,44 @@ +[Desktop Entry] +Type=Link +URL= +Icon=konqsidebar_news +Name=Newsticker +Name[bs]=News Ticker +Name[ca]=Teletip de notícies +Name[da]=Nyhedstelegraf +Name[eo]=Novaĵprezentilo +Name[es]=Teletipo de noticias +Name[et]=Uudistejälgija +Name[fi]=Uutisnäyttäjä +Name[fr]=Téléscripteur de nouvelles +Name[gl]=Notícias +Name[he]=מציג חדשות +Name[hi]=न्यूज़टिकर +Name[hr]=Obavijesti o novostima +Name[hu]=Hírmegjelenítő +Name[is]=Fréttastrimill +Name[it]=NewsTicker +Name[ja]=ニュースティッカー +Name[ka]=სიახლეთა მიმღები +Name[lt]=Naujienų pranešiklis +Name[nb]=Nyhetstelegraf +Name[nds]=Narichtentelegraaf +Name[ne]=न्यूजटिकर +Name[nn]=Nyhendetelegraf +Name[pa]=ਖ਼ਬਰਸਾਰ +Name[pl]=Pasek wiadomości +Name[pt]=Notícias +Name[pt_BR]=Mostrador de Notícias +Name[ru]=Индикатор новостей +Name[sk]=Sledovanie správ +Name[sl]=Prikazovalnik novic +Name[sv]=Nyhetsövervakare +Name[ta]=புதிய நகரும் செய்தி +Name[tr]=Haber Bandı +Name[uk]=Стрічка новин +Name[vi]=Bộ theo dõi tin tức +Name[zh_CN]=新闻点点通 +Open=false +X-KDE-KonqSidebarAddModule=konq_sidebarnews +X-KDE-KonqSidebarUniversal=true +TryExec=rssservice diff --git a/konq-plugins/sidebar/newsticker/norsswidget.cpp b/konq-plugins/sidebar/newsticker/norsswidget.cpp new file mode 100644 index 0000000..d4c803a --- /dev/null +++ b/konq-plugins/sidebar/newsticker/norsswidget.cpp @@ -0,0 +1,100 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + norsswidget.cpp + Copyright: Marcus Camen <mcamen@mcamen.de> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qlayout.h> +#include <qsizepolicy.h> +#include <dcopref.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kdebug.h> +#include <kconfigdialog.h> +#include "sidebarsettings.h" +#include "configfeeds.h" +#include "norsswidget.h" + + +namespace KSB_News { + + NoRSSWidget::NoRSSWidget(QWidget *parent, const char *name) + : QWidget(parent, name) { + + QVBoxLayout *topLayout = new QVBoxLayout(this); + + topLayout->addStretch(); + + KPushButton *btn = new KPushButton(i18n("&Configure"), this); + btn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum); + connect(btn, SIGNAL(clicked()), this, SLOT(slotBtnClicked())); + topLayout->addWidget(btn, 0, Qt::AlignHCenter); + + topLayout->addStretch(); + } + + + void NoRSSWidget::slotBtnClicked() { + // An instance of your dialog could be already created and could be + // cached, in which case you want to display the cached dialog + // instead of creating another one + if (KConfigDialog::showDialog("settings")) + return; + + // KConfigDialog didn't find an instance of this dialog, so lets create it + m_confdlg = new KConfigDialog(this, "settings", SidebarSettings::self(), + KDialogBase::Plain, + KDialogBase::Ok|KDialogBase::Cancel|KDialogBase::Default, + KDialogBase::Ok, + true); + ConfigFeeds *conf_widget = new ConfigFeeds(0, "feedcfgdlg"); + m_confdlg->addPage(conf_widget, i18n("RSS Settings"), "pixmap_name"); + + // User edited the configuration - update your local copies of the + // configuration data + connect(m_confdlg, SIGNAL(settingsChanged()), this, + SLOT(slotConfigure_okClicked())); + + m_confdlg->show(); + } + + + void NoRSSWidget::slotConfigure_okClicked() { + DCOPRef rss_document("rssservice", "RSSService"); + + // read list of sources + QStringList m_our_rsssources = SidebarSettings::sources(); + + // add new sources + QStringList::iterator it; + for (it = m_our_rsssources.begin(); it != m_our_rsssources.end(); ++it) { + rss_document.call("add", ( *it )); + } + + // save configuration to disk + SidebarSettings::setSources(m_our_rsssources); + SidebarSettings::writeConfig(); + } + +} // namespace KSB_News + +#include "norsswidget.moc" diff --git a/konq-plugins/sidebar/newsticker/norsswidget.h b/konq-plugins/sidebar/newsticker/norsswidget.h new file mode 100644 index 0000000..cebac3b --- /dev/null +++ b/konq-plugins/sidebar/newsticker/norsswidget.h @@ -0,0 +1,51 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + Copyright: norsswidget.h + Marcus Camen <mcamen@mcamen.de> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NORSSWIDGET_H_ +#define _NORSSWIDGET_H_ + + +class KConfigDialog; + + +namespace KSB_News { + + class NoRSSWidget : public QWidget { + Q_OBJECT + + public: + NoRSSWidget(QWidget *parent = 0, const char *name = 0); + + private slots: + void slotBtnClicked(); + void slotConfigure_okClicked(); + + private: + KConfigDialog *m_confdlg; + }; + + +} // namespace KSB_News + +#endif diff --git a/konq-plugins/sidebar/newsticker/nspanel.cpp b/konq-plugins/sidebar/newsticker/nspanel.cpp new file mode 100644 index 0000000..8086b35 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/nspanel.cpp @@ -0,0 +1,181 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + Copyright: nspanel.cpp + Marcus Camen <mcamen@mcamen.de> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qlistview.h> +#include <qfontmetrics.h> +#include <qtimer.h> +#include <kdebug.h> +#include <klistbox.h> +#include "nspanel.h" + + +namespace KSB_News { + +//////////////////////////////////////////////////////////////// +// ListBox including ToolTip for item +//////////////////////////////////////////////////////////////// + TTListBox::TTListBox(QWidget *parent, const char *name, WFlags f) + : KListBox(parent, name, f), + QToolTip(this) { + } + + void TTListBox::clear() { + KListBox::clear(); + } + + void TTListBox::maybeTip(const QPoint &point) { + QListBoxItem *item = itemAt(point); + if (item) { + QString text = item->text(); + if (!text.isEmpty()) { + // Show ToolTip only if necessary + QFontMetrics fm(fontMetrics()); + int textWidth = fm.width(text); + int widgetSpace = visibleWidth(); + if ((textWidth > widgetSpace) || (contentsX() > 0)) + tip(itemRect(item), text); + } + } + } + + + + NSPanel::NSPanel(QObject *parent, const char *name, const QString &key, + DCOPRef *rssservice) + :QObject(parent, name) + ,DCOPObject(QString(QString("sidebar-newsticker-")+key).latin1()) + ,m_listbox() + ,m_pixmap() +{ + kdDebug(90140) << "NSPanel: CTOR " << key << " " << rssservice << endl; + + m_rssservice = rssservice; + m_key = key; + m_rssdocument = m_rssservice->call("document(QString)", m_key); + m_isValid = false; + + connectDCOPSignal("rssservice", m_rssdocument.obj(), + "documentUpdated(DCOPRef)", + "emitDocumentUpdated(DCOPRef)", false); + connectDCOPSignal("rssservice", m_rssdocument.obj(), + "documentUpdated(DCOPRef)", + "emitTitleUpdated(DCOPRef)", false); + connectDCOPSignal("rssservice", m_rssdocument.obj(), + "pixmapUpdated(DCOPRef)", + "emitPixmapUpdated(DCOPRef)", false); + + // updating of RSS documents + m_timeoutinterval = 10 * 60 * 1000; // 10 mins + m_timer = new QTimer(this); + connect(m_timer, SIGNAL(timeout()), this, SLOT(refresh())); + m_timer->start(m_timeoutinterval); + refresh(); + } + + + void NSPanel::refresh() { + m_rssdocument.call("refresh()"); + } + + + NSPanel::~NSPanel() { + } + + + void NSPanel::setTitle(const QString &tit) { + m_title = tit; + } + + + void NSPanel::setListbox(TTListBox *lb) { + m_listbox = lb; + } + + + void NSPanel::setPixmap(const QPixmap &pm) { + m_pixmap = pm; + } + + + TTListBox *NSPanel::listbox() const { + return m_listbox; + } + + + QPixmap NSPanel::pixmap() { + return m_pixmap; + } + + + QString NSPanel::key() const { + return m_key; + } + + QString NSPanel::title() const { + return m_title; + } + + QStringList NSPanel::articles() { + return m_articles; + } + + QStringList NSPanel::articleLinks() { + return m_articlelinks; + } + + bool NSPanel::isValid() const { + return m_isValid; + } + + + void NSPanel::emitDocumentUpdated(DCOPRef /*dcopref*/) { + kdDebug(90140) << "NSPanel::emitDocumentUpdated" << endl; + + m_articles.clear(); + m_articlelinks.clear(); + m_count = m_rssdocument.call("count()"); + QString temp = m_rssdocument.call("title()"); + m_title = temp; + m_isValid = true; + for (int idx = 0; idx < m_count; ++idx) { + DCOPRef rss_article = m_rssdocument.call("article(int)", idx); + m_articles.append(rss_article.call("title()")); + m_articlelinks.append(rss_article.call("link()")); + } + + emit documentUpdated(this); + } + + void NSPanel::emitPixmapUpdated(DCOPRef /*dcopref*/) { + if (m_rssdocument.call("pixmapValid()")) { + QPixmap tmp = m_rssdocument.call("pixmap()"); + m_pixmap = tmp; + + emit pixmapUpdated(this); + } + } + +} // namespace KSB_News + +#include "nspanel.moc" diff --git a/konq-plugins/sidebar/newsticker/nspanel.h b/konq-plugins/sidebar/newsticker/nspanel.h new file mode 100644 index 0000000..0f30152 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/nspanel.h @@ -0,0 +1,109 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + Copyright: nspanel.h + Marcus Camen <mcamen@mcamen.de> +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _konq_sidebar_news_nspanelh_ +#define _konq_sidebar_news_nspanelh_ + +#include <qstring.h> +#include <qpixmap.h> +#include <qtooltip.h> +#include <dcopref.h> +#include <dcopobject.h> +#include <kio/job.h> +#include <klistbox.h> + + +class QBuffer; +class QTimer; + +namespace KSB_News { + +//////////////////////////////////////////////////////////////// +// ListBox including ToolTip for item +//////////////////////////////////////////////////////////////// + class TTListBox : public KListBox, QToolTip { + public: + TTListBox (QWidget *parent = 0, const char *name = 0, WFlags f = 0); + void clear(); + + protected: + virtual void maybeTip(const QPoint &); + }; + + + + class NSPanel : public QObject, public DCOPObject { + Q_OBJECT + K_DCOP + + public: + NSPanel(QObject *parent, const char *name, const QString &key, + DCOPRef *rssservice); + ~NSPanel(); + + void setTitle(const QString &tit); + void setListbox(TTListBox *lb); + void setPixmap(const QPixmap &pm); + void setPixmapBuffer(QBuffer *buf); + void setJob(KIO::Job *kio_job); + + TTListBox *listbox() const; + QPixmap pixmap(); + QString key() const; + QString title() const; + QStringList articles(); + QStringList articleLinks(); + bool isValid() const; + + k_dcop: + virtual void emitDocumentUpdated(DCOPRef); + virtual void emitPixmapUpdated(DCOPRef); + + private: + DCOPRef *m_rssservice; + DCOPRef m_rssdocument; + QString m_key; + QString m_title; + TTListBox *m_listbox; + QPixmap m_pixmap; + int m_count; + QStringList m_articles; // TODO: use proper container + QStringList m_articlelinks; // TODO: use proper container + int m_timeoutinterval; + QTimer *m_timer; + bool m_isValid; + + signals: + void documentUpdated(NSPanel *); + void pixmapUpdated(NSPanel *); + + public slots: + void refresh(); + + }; + + +} // namespace KSB_News + +#endif diff --git a/konq-plugins/sidebar/newsticker/nsstacktabwidget.cpp b/konq-plugins/sidebar/newsticker/nsstacktabwidget.cpp new file mode 100644 index 0000000..74aa07e --- /dev/null +++ b/konq-plugins/sidebar/newsticker/nsstacktabwidget.cpp @@ -0,0 +1,365 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + nsstacktabwidget.cpp - description + ------------------- + begin : Sat 07.09.2002 + copyright : (C) 2002-2004 Marcus Camen + email : mcamen@mcamen.de +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qpushbutton.h> +#include <qlayout.h> +#include <qscrollview.h> +#include <qptrdict.h> +#include <qsizepolicy.h> +#include <qtooltip.h> +#include <qcursor.h> +#include <qimage.h> +#include <kdebug.h> +#include <kaboutdata.h> +#include <kaboutapplication.h> +#include <kpopupmenu.h> +#include <kiconloader.h> +#include <kstringhandler.h> +#include <kapplication.h> +#include <kbugreport.h> +#include <kstdguiitem.h> +#include <kconfigdialog.h> +#include "sidebarsettings.h" +#include "configfeeds.h" +#include "nsstacktabwidget.h" + + +namespace KSB_News { + + NSStackTabWidget::NSStackTabWidget(QWidget *parent, const char *name, + QPixmap appIcon) : QWidget(parent, name) { + currentPage = 0; + layout = new QVBoxLayout(this); + + pagesheader.setAutoDelete(TRUE); + pages.setAutoDelete(TRUE); + + // about dialog + m_aboutdata = new KAboutData("konq_sidebarnews", + I18N_NOOP("Newsticker"), + KDE::versionString(), + I18N_NOOP("RSS Feed Viewer"), + KAboutData::License_LGPL, + I18N_NOOP("(c) 2002-2004, the Sidebar Newsticker developers")); + m_aboutdata->addAuthor("Marcus Camen", I18N_NOOP("Maintainer"), + "mcamen@mcamen.de"); + m_aboutdata->addAuthor("Frerich Raabe", "librss", + "raabe@kde.org"); + m_aboutdata->addAuthor("Ian Reinhart Geiser", "dcoprss", + "geiseri@kde.org"); + m_aboutdata->addAuthor("Joseph Wenninger", + I18N_NOOP("Idea and former maintainer"), + "jowenn@kde.org"); + m_aboutdata->setProductName("konqueror/sidebar newsticker"); + m_about = new KAboutApplication(m_aboutdata, this); + + + // bugreport dialog + m_bugreport = new KBugReport(0, true, m_aboutdata); + + + // popup menu + popup = new KPopupMenu(this); + popup->insertItem(KStdGuiItem::configure().iconSet(), + i18n("&Configure Newsticker..."), this, + SLOT(slotConfigure())); + popup->insertItem(SmallIconSet("reload"), i18n("&Reload"), this, + SLOT(slotRefresh())); + popup->insertItem(KStdGuiItem::close().iconSet(), + KStdGuiItem::close().text(), this, SLOT(slotClose())); + popup->insertSeparator(); + + // help menu + helpmenu = new KPopupMenu(this); + helpmenu->insertItem(appIcon, i18n("&About Newsticker"), this, + SLOT(slotShowAbout())); + helpmenu->insertItem(i18n("&Report Bug..."), this, + SLOT(slotShowBugreport())); + + popup->insertItem(KStdGuiItem::help().iconSet(), + KStdGuiItem::help().text(), helpmenu); + + + // read configuration from disk and initialize widget + m_our_rsssources = SidebarSettings::sources(); + } + + + void NSStackTabWidget::addStackTab(NSPanel *nsp, QWidget *page) { + QPushButton *button = new QPushButton(this); + + button->setText(KStringHandler::rPixelSqueeze(nsp->title(), + button->fontMetrics(), + button->width() - 4 )); + button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, + QSizePolicy::Preferred)); + connect(button, SIGNAL(clicked()), this, SLOT(buttonClicked())); + QToolTip::add(button, nsp->title()); + + // eventFiler for the title button + button->installEventFilter(this); + + QScrollView *sv = new QScrollView(this); + sv->setResizePolicy(QScrollView::AutoOneFit); + sv->addChild(page); + sv->setFrameStyle(QFrame::NoFrame); + page->show(); + + pagesheader.insert(nsp, button); + pages.insert(nsp, sv); + + layout->addWidget(button); + layout->addWidget(sv); + button->show(); + if (pages.count() == 1) { + currentPage = sv; + sv->show(); + } else { + sv->hide(); + } + } + + + + void NSStackTabWidget::delStackTab(NSPanel *nsp) { + pages.remove(nsp); + pagesheader.remove(nsp); + + if (pages.count() >= 1) { + QPtrDictIterator<QWidget> it(pages); + QWidget *previousPage = currentPage; + currentPage = it.current(); + if (currentPage != previousPage) + currentPage->show(); + } + } + + + + void NSStackTabWidget::updateTitle(NSPanel *nsp) { + QPushButton *pb = (QPushButton *)pagesheader.find(nsp); + if (! pb->pixmap()) + pb->setText(nsp->title()); + } + + + + void NSStackTabWidget::updatePixmap(NSPanel *nsp) { + QPushButton *pb = (QPushButton *)pagesheader.find(nsp); + QPixmap pixmap = nsp->pixmap(); + if ((pixmap.width() > 88) || (pixmap.height() > 31)) { + QImage image = pixmap.convertToImage(); + pixmap.convertFromImage(image.smoothScale(88, 31, QImage::ScaleMin)); + } + pb->setPixmap(pixmap); + } + + + + + void NSStackTabWidget::buttonClicked() { + QPushButton *pb = (QPushButton*)sender(); + NSPanel *nsp = NULL; + + // Which NSPanel belongs to pb + QPtrDictIterator<QWidget> it(pagesheader); + for (; it.current(); ++it) { + QPushButton *currentWidget = (QPushButton *)it.current(); + if (currentWidget == pb) + nsp = (NSPanel *)it.currentKey(); + } + + if (! nsp) + return; + + // Find current ScrollView + QWidget *sv = pages.find(nsp); + + // Change visible page + if (currentPage != sv) { + nsp->refresh(); + if (currentPage) + currentPage->hide(); + currentPage = sv; + currentPage->show(); + } + } + + + + bool NSStackTabWidget::eventFilter(QObject *obj, QEvent *ev) { + if (ev->type() == QEvent::MouseButtonPress + && ((QMouseEvent *)ev)->button() == QMouseEvent::RightButton) { + m_last_button_rightclicked = (QPushButton *)obj; + popup->exec(QCursor::pos()); + return true; + } else if (ev->type() == QEvent::Resize) { + QPushButton *pb = (QPushButton *)obj; + + const QPixmap *pm = pb->pixmap(); + if ( ! pm ) { + // Which NSPanel belongs to pb + NSPanel *nsp = NULL; + QPtrDictIterator<QWidget> it(pagesheader); + for (; it.current(); ++it) { + QPushButton *currentWidget = (QPushButton *)it.current(); + if (currentWidget == pb) + nsp = (NSPanel *)it.currentKey(); + } + pb->setText(KStringHandler::rPixelSqueeze(nsp->title(), + pb->fontMetrics(), + pb->width() - 4 )); + } + return true; + } + return false; // pass through event + } + + + void NSStackTabWidget::slotConfigure() { + // An instance of your dialog could be already created and could be + // cached, in which case you want to display the cached dialog + // instead of creating another one + if (KConfigDialog::showDialog("settings")) + return; + + // KConfigDialog didn't find an instance of this dialog, so lets create it + m_confdlg = new KConfigDialog(this, "settings", SidebarSettings::self(), + KDialogBase::Plain, + KDialogBase::Ok|KDialogBase::Cancel| \ + KDialogBase::Default| \ + KDialogBase::Apply, + KDialogBase::Ok, + true); + ConfigFeeds *conf_widget = new ConfigFeeds(0, "feedcfgdlg"); + m_confdlg->addPage(conf_widget, i18n("RSS Settings"), QString()); + + // User edited the configuration - update your local copies of the + // configuration data + connect(m_confdlg, SIGNAL(settingsChanged()), this, + SLOT(slotConfigure_okClicked())); + + m_confdlg->show(); + } + + + void NSStackTabWidget::slotConfigure_okClicked() { + DCOPRef rss_document("rssservice", "RSSService"); + + // remove old sources and old stack tabs + QStringList::iterator it; + for (it = m_our_rsssources.begin(); it != m_our_rsssources.end(); ++it) { + rss_document.call("remove", (*it)); + } + + // read list of sources + m_our_rsssources = SidebarSettings::sources(); + + // add new sources and new stack tabs + for (it = m_our_rsssources.begin(); it != m_our_rsssources.end(); ++it) { + rss_document.call("add", (*it)); + } + + // save configuration to disk + SidebarSettings::setSources(m_our_rsssources); + SidebarSettings::writeConfig(); + } + + + void NSStackTabWidget::slotShowAbout() { + m_about->show(); + } + + + void NSStackTabWidget::slotShowBugreport() { + m_bugreport->show(); + } + + + void NSStackTabWidget::slotRefresh() { + NSPanel *nsp = NULL; + + // find appendant NSPanel + QPtrDictIterator<QWidget> it(pagesheader); + for (; it.current(); ++it) { + QPushButton *currentWidget = (QPushButton *)it.current(); + if (currentWidget == m_last_button_rightclicked) + nsp = (NSPanel *)it.currentKey(); + } + + if (! nsp) { + return; + } else { + nsp->refresh(); + } + } + + + void NSStackTabWidget::slotClose() { + NSPanel *nsp = NULL; + // find appendant NSPanel + QPtrDictIterator<QWidget> it(pagesheader); + for (; it.current(); ++it) { + QPushButton *currentWidget = (QPushButton *)it.current(); + if (currentWidget == m_last_button_rightclicked) + nsp = (NSPanel *)it.currentKey(); + } + + if (! nsp) { + return; + } else { + // TODO: check, if rssservice is available + + // deregister RSS source and save configuration to disk + m_our_rsssources.remove(nsp->key()); + SidebarSettings::setSources(m_our_rsssources); + SidebarSettings::writeConfig(); + + DCOPRef rss_document("rssservice", "RSSService"); + rss_document.call("remove", nsp->key()); + } + } + + + bool NSStackTabWidget::isEmpty() const { + return pagesheader.isEmpty(); + } + + + bool NSStackTabWidget::isRegistered(const QString &key) { + m_our_rsssources = SidebarSettings::sources(); + if (m_our_rsssources.findIndex(key) == -1) + return false; + else + return true; + } + + +} // namespace KSB_News; + + +#include "nsstacktabwidget.moc" diff --git a/konq-plugins/sidebar/newsticker/nsstacktabwidget.h b/konq-plugins/sidebar/newsticker/nsstacktabwidget.h new file mode 100644 index 0000000..7b84289 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/nsstacktabwidget.h @@ -0,0 +1,91 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + nsstacktabwidget.h - description + ------------------- + begin : Sat 07.09.2002 + copyright : (C) 2002-2004 Marcus Camen + email : mcamen@mcamen.de +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _NSSTACKTABWIDGET_H_ +#define _NSSTACKTABWIDGET_H_ + +#include <qptrdict.h> +#include "nspanel.h" + + +class QVBoxLayout; +class QPushButton; +class QStringList; +class KPopupMenu; +class KAboutData; +class KAboutApplication; +class KBugReport; +class KConfigDialog; + +namespace KSB_News { + + class NewRssSourceDlg; + + class NSStackTabWidget : public QWidget { + Q_OBJECT + + public: + NSStackTabWidget(QWidget *parent = 0, const char *name = 0, + QPixmap appIcon = QPixmap()); + void addStackTab(NSPanel *nsp, QWidget *page); + void delStackTab(NSPanel *nsp); + void updateTitle(NSPanel *nsp); + void updatePixmap(NSPanel *nsp); + bool isEmpty() const; + bool isRegistered(const QString &key); + + protected: + bool eventFilter(QObject *obj, QEvent *ev); + + private slots: + void buttonClicked(); + void slotShowAbout(); + void slotShowBugreport(); + void slotRefresh(); + void slotClose(); + void slotConfigure(); + void slotConfigure_okClicked(); + + private: + QPtrDict<QWidget> pages; + QPtrDict<QWidget> pagesheader; + QVBoxLayout *layout; + QWidget *currentPage; + KPopupMenu *popup, *helpmenu; + KAboutData *m_aboutdata; + KAboutApplication *m_about; + KBugReport *m_bugreport; + QPushButton *m_last_button_rightclicked; + KConfigDialog *m_confdlg; + QStringList m_our_rsssources; + }; + + +} // namespace KSB_News + + +#endif diff --git a/konq-plugins/sidebar/newsticker/pics/LICENSE b/konq-plugins/sidebar/newsticker/pics/LICENSE new file mode 100644 index 0000000..7108d2b --- /dev/null +++ b/konq-plugins/sidebar/newsticker/pics/LICENSE @@ -0,0 +1,16 @@ +cr16-app-konqsidebar_news.png is based on livemark-item.png + +You can find the original file in the mozilla AVIARY_1_0_20040515_BRANCH: +http://lxr.mozilla.org/aviarybranch/source/browser/themes/winstripe/browser/licemark-item.png, Version 1.1 + +According to +http://lxr.mozilla.org/aviarybranch/source/browser/themes/LICENSE +the file is MPL / GPL / LPGP (confirmed to me in private mail by +Stephen Horlander <stephen@noved.org>): + "All files in this directory are assumed to be licensed under the + tri-license (MPL/GPL/LGPL) used throughout this codebase." + +-- +Marcus <mcamen@mcamen.de> + +
\ No newline at end of file diff --git a/konq-plugins/sidebar/newsticker/pics/Makefile.am b/konq-plugins/sidebar/newsticker/pics/Makefile.am new file mode 100644 index 0000000..e5515a8 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/pics/Makefile.am @@ -0,0 +1 @@ +KDE_ICON = AUTO diff --git a/konq-plugins/sidebar/newsticker/pics/cr16-app-konqsidebar_news.png b/konq-plugins/sidebar/newsticker/pics/cr16-app-konqsidebar_news.png Binary files differnew file mode 100644 index 0000000..4a7321a --- /dev/null +++ b/konq-plugins/sidebar/newsticker/pics/cr16-app-konqsidebar_news.png diff --git a/konq-plugins/sidebar/newsticker/pics/livemark-item.png b/konq-plugins/sidebar/newsticker/pics/livemark-item.png Binary files differnew file mode 100644 index 0000000..91cb614 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/pics/livemark-item.png diff --git a/konq-plugins/sidebar/newsticker/sidebar_news.cpp b/konq-plugins/sidebar/newsticker/sidebar_news.cpp new file mode 100644 index 0000000..f96bcd6 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/sidebar_news.cpp @@ -0,0 +1,279 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + sidebar_news.cpp - The real sidebar plugin + ------------------- + begin : Sat June 23 13:35:30 CEST 2001 + copyright : (C) 2001,2002 Marcus Camen, Joseph Wenninger + copyright : (C) 2003,2004 Marcus Camen + email : Marcus Camen <mcamen@mcamen.de> + idea and original code: jowenn@kde.org +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <dcopclient.h> +#include <qtimer.h> +#include <qbuffer.h> +#include <qwidgetstack.h> +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kdesktopfile.h> +#include <kiconloader.h> +#include <kdemacros.h> +#include "sidebar_news.h" +#include "nsstacktabwidget.h" +#include "norsswidget.h" +#include "sidebarsettings.h" + + +namespace KSB_News { + + KonqSidebar_News::KonqSidebar_News(KInstance *inst, QObject *parent, + QWidget *widgetParent, + QString &desktopName, const char* name) + : KonqSidebarPlugin(inst, parent, widgetParent, desktopName, name), + DCOPObject("sidebar-newsticker") + { + // get the application icon + // FIXME: as konqueror knows the icon there might be a possibility to + // access the already present QPixmap + KDesktopFile desktopFile(desktopName, true); + QString iconName = desktopFile.readIcon(); + KIconLoader iconLoader; + m_appIcon = iconLoader.loadIcon(iconName, KIcon::Small); + + // create all sidebar widgets + widgets = new QWidgetStack(widgetParent, "main_widgetstack"); + newswidget = new NSStackTabWidget(widgets, "feedbrowser_stackchld", + m_appIcon); + noRSSwidget = new NoRSSWidget(widgets, "nofeed_stackchld"); + widgets->addWidget(newswidget); + widgets->addWidget(noRSSwidget); + widgets->raiseWidget(noRSSwidget); + noRSSwidget->show(); + + // try to connect to the DCOP service + if (checkDcopService() > 0) { + KMessageBox::sorry(widgets, + i18n("<qt>Cannot connect to RSS service. Please make " + "sure the <strong>rssservice</strong> program " + "is available (usually distributed as part " + "of kdenetwork).</qt>"), + i18n("Sidebar Newsticker")); + noRSSwidget->setEnabled(false); + } else { + m_rssservice = DCOPRef("rssservice", "RSSService"); + + QStringList reslist = SidebarSettings::sources(); + QStringList::iterator it; + for (it = reslist.begin(); it != reslist.end(); ++it) { + addedRSSSource(*it); + } + + // fetch added and removed RSS sources + connectDCOPSignal("rssservice", m_rssservice.obj(), "added(QString)", + "addedRSSSource(QString)", false); + connectDCOPSignal("rssservice", m_rssservice.obj(), "removed(QString)", + "removedRSSSource(QString)", false); + + // show special widget if there are no RSS sources available + if (newswidget->isEmpty()) { + widgets->raiseWidget(noRSSwidget); + noRSSwidget->show(); + } else { + widgets->raiseWidget(newswidget); + } + } + } + + + KonqSidebar_News::~KonqSidebar_News() { + } + + + + void *KonqSidebar_News::provides(const QString &) {return 0;} + + void KonqSidebar_News::emitStatusBarText (const QString &) {;} + + QWidget *KonqSidebar_News::getWidget(){return widgets;} + + void KonqSidebar_News::handleURL(const KURL &/*url*/) {;} + + +///////// startup of the DCOP servce /////////////////////////////////////// + + int KonqSidebar_News::checkDcopService() { + QString rdfservice_error; + int err = 0; + + if (! kapp->dcopClient()->isApplicationRegistered("rssservice")) + if (KApplication::startServiceByDesktopName("rssservice", QString(), + &rdfservice_error) > 0) + err = 1; + + return err; + } + + + +///////// helper methods /////////////////////////////////////////////////// + + NSPanel *KonqSidebar_News::getNSPanelByKey(QString key) { + NSPanel *nsp = NULL, *current_nsp; + + for (current_nsp = nspanelptrlist.first(); current_nsp; + current_nsp = nspanelptrlist.next()) { + if (current_nsp->key() == key) + nsp = current_nsp; + } + + return nsp; + } + + + void KonqSidebar_News::addedRSSSource(QString key) { + kdDebug(90140) << "KonqSidebar_News::addedRSSSource: " << key << endl; + + // Only add RSS source if we have registered the URI before in + // NSStackTabWidget. + if (newswidget->isRegistered(key)) { + NSPanel *nspanel = new NSPanel(this, + QString(QString("sidebar-newsticker-")+key).latin1(), + key, &m_rssservice); + nspanel->setTitle(key); + nspanelptrlist.append(nspanel); + + // add preliminary widgets for this newssource + if (! nspanel->listbox()) { + TTListBox *listbox = new TTListBox(newswidget, "article_lb"); + newswidget->addStackTab(nspanel, listbox); + connect(listbox, SIGNAL(executed(QListBoxItem *)), + this, SLOT(slotArticleItemExecuted(QListBoxItem *))); + listbox->insertItem(i18n("Connecting..." )); + nspanel->setListbox(listbox); + } + + // listen to updates + connect(nspanel, SIGNAL(documentUpdated(NSPanel *)), + this, SLOT(updateArticles(NSPanel *))); + connect(nspanel, SIGNAL(documentUpdated(NSPanel *)), + this, SLOT(updateTitle(NSPanel *))); + connect(nspanel, SIGNAL(pixmapUpdated(NSPanel *)), + this, SLOT(updatePixmap(NSPanel *))); + + if (widgets->visibleWidget() != newswidget) + widgets->raiseWidget(newswidget); + } + } + + + void KonqSidebar_News::removedRSSSource(QString key) { + kdDebug(90140) << "inside KonqSidebar_News::removedSource " << key << endl; + + if (NSPanel *nsp = getNSPanelByKey(key)) { + newswidget->delStackTab(nsp); + delete nspanelptrlist.take(nspanelptrlist.findRef(nsp)); + } else + kdWarning() << "removedSource called for non-existing id" << endl; + + if (newswidget->isEmpty()) + widgets->raiseWidget(noRSSwidget); + } + + +///////////////////////////////////////////////////////////////////// + + void KonqSidebar_News::slotArticleItemExecuted(QListBoxItem *item) { + if (!item) return; + + NSPanel *current_nspanel, *nspanel = NULL; + for (current_nspanel = nspanelptrlist.first(); current_nspanel; + current_nspanel = nspanelptrlist.next()) { + if (current_nspanel->listbox() == item->listBox()) + nspanel = current_nspanel; + } + + int subid = nspanel->listbox()->index(item); + QString link = nspanel->articleLinks()[subid]; + + emit openURLRequest(KURL(link)); + + } + + + +//////////// update article headlines //////////// + + void KonqSidebar_News::updateArticles(NSPanel *nsp) { + nsp->listbox()->clear(); + + QStringList articleList = nsp->articles(); + QStringList::iterator it; + for (it = articleList.begin(); it != articleList.end(); ++it) + nsp->listbox()->insertItem((*it)); + } + + +/////////// Title stuff ///////////////////////////////////// + + void KonqSidebar_News::updateTitle(NSPanel *nsp) { + newswidget->updateTitle(nsp); + } + + +/////////// Pixmap stuff ///////////////////////////////////// + + void KonqSidebar_News::updatePixmap(NSPanel *nsp) { + newswidget->updatePixmap(nsp); + } + + + +///////////////////////////////////////////////////////// + + + extern "C" { + KDE_EXPORT void* create_konq_sidebarnews(KInstance *instance, QObject *par, + QWidget *widp, + QString &desktopname, + const char *name) { + KGlobal::locale()->insertCatalogue("konqsidebar_news"); + return new KonqSidebar_News(instance, par, widp, desktopname, name); + } + } + + extern "C" { + KDE_EXPORT bool add_konq_sidebarnews(QString* fn, QString*, + QMap<QString,QString> *map) { + map->insert("Type", "Link"); + map->insert("Icon", "konqsidebar_news"); + map->insert("Name", i18n("Newsticker")); + map->insert("Open", "false"); + map->insert("X-KDE-KonqSidebarModule", "konq_sidebarnews"); + fn->setLatin1("news%1.desktop"); + return true; + } + } + +} // namespace KSB_News + +#include "sidebar_news.moc" diff --git a/konq-plugins/sidebar/newsticker/sidebar_news.h b/konq-plugins/sidebar/newsticker/sidebar_news.h new file mode 100644 index 0000000..e6da786 --- /dev/null +++ b/konq-plugins/sidebar/newsticker/sidebar_news.h @@ -0,0 +1,89 @@ +// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8; -*- + +/*************************************************************************** + sidebar_news.h - The real sidebar plugin + ------------------- + begin : Sat July 23 20:35:30 CEST 2001 + copyright : (C) 2001,2002 Marcus Camen, Joseph Wenninger + copyright : (C) 2003,2004 Marcus Camen + email : Marcus Camen <mcamen@mcamen.de> + idea and original code: jowenn@kde.org +***************************************************************************/ + +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _konq_sidebar_news_h_ +#define _konq_sidebar_news_h_ + +#include <konqsidebarplugin.h> +#include "nspanel.h" + + +class QPixmap; +class QWidgetStack; + +namespace KSB_News { + + class NSStackTabWidget; + class NoRSSWidget; + + class KonqSidebar_News : public KonqSidebarPlugin, DCOPObject { + Q_OBJECT + K_DCOP + + public: + KonqSidebar_News(KInstance *instance, QObject *parent, + QWidget *widgetParent, QString &desktopName_, + const char* name=0); + ~KonqSidebar_News(); + virtual void *provides(const QString &); + void emitStatusBarText (const QString &); + virtual QWidget *getWidget(); + + k_dcop: + virtual void addedRSSSource(QString); + virtual void removedRSSSource(QString); + + protected: + virtual void handleURL(const KURL &url); + + private: + int checkDcopService(); + QWidgetStack *widgets; + NSStackTabWidget *newswidget; + NoRSSWidget *noRSSwidget; + QPtrList<NSPanel> nspanelptrlist; + NSPanel *getNSPanelByKey(QString key); + DCOPRef m_rssservice; + QPixmap m_appIcon; + + signals: + // see <konqsidebarplugin.h> + void openURLRequest(const KURL &url, + const KParts::URLArgs &args = KParts::URLArgs()); + + private slots: + void slotArticleItemExecuted(QListBoxItem *item); + void updateArticles(NSPanel *nsp); + void updateTitle(NSPanel *nsp); + void updatePixmap(NSPanel *nsp); + }; + +} // namespace KSB_News + +#endif diff --git a/konq-plugins/sidebar/newsticker/sidebarsettings.kcfgc b/konq-plugins/sidebar/newsticker/sidebarsettings.kcfgc new file mode 100644 index 0000000..6e24cde --- /dev/null +++ b/konq-plugins/sidebar/newsticker/sidebarsettings.kcfgc @@ -0,0 +1,5 @@ +File=konq_sidebarnews.kcfg +ClassName=SidebarSettings +Singleton=true +Mutators=true +NameSpace=KSB_News diff --git a/konq-plugins/smbmounter/Readme b/konq-plugins/smbmounter/Readme new file mode 100644 index 0000000..0ccf41c --- /dev/null +++ b/konq-plugins/smbmounter/Readme @@ -0,0 +1,19 @@ +This directory existed until kde 3.3, if you're interested to revive it, you +can get it back from cvs. It has been removed because the smbro-ioslave has also +been removed, and this plugin doesn't work without it. + +This plugin for konqy works together with the smbro ioslave. +It uses the special() function of the smbro ioslave to mount and unmount smb +shares. This is done by the ioslave by executing smbmount and smbumount. +Therefor both have to be installed suid root. +If you consider this a security risk, don't use this plugin. +Move with konqy into a smb share (e.g. smb://host/my_files) and then select +Tools->smbmount current share. The share "my_files" will be mounted under +"~/smb_network/host/my_files". Once you mounted the share, the menu item +"smbumount current share" becomes active, so that you can unmount it again. + +AFAIK smbmount is linux-only, so it won't work on other systems. + +If you have suggestions, wishes or find bugs, send me an email. + +Alexander Neundorf <neundorf@kde.org> diff --git a/konq-plugins/uachanger/Makefile.am b/konq-plugins/uachanger/Makefile.am new file mode 100644 index 0000000..80e2c2b --- /dev/null +++ b/konq-plugins/uachanger/Makefile.am @@ -0,0 +1,17 @@ +kde_module_LTLIBRARIES = libuachangerplugin.la + +AM_CPPFLAGS = $(all_includes) +METASOURCES = AUTO + +libuachangerplugin_la_SOURCES = uachangerplugin.cpp +libuachangerplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +libuachangerplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = uachangerplugin.rc uachangerplugin.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = uachangerplugin.desktop + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/uachangerplugin.pot diff --git a/konq-plugins/uachanger/uachangerplugin.cpp b/konq-plugins/uachanger/uachangerplugin.cpp new file mode 100644 index 0000000..b929930 --- /dev/null +++ b/konq-plugins/uachanger/uachangerplugin.cpp @@ -0,0 +1,436 @@ +/* + Copyright (c) 2001 Dawit Alemayehu <adawit@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <sys/utsname.h> + +#include <qregexp.h> + +#include <krun.h> +#include <kdebug.h> +#include <kaction.h> +#include <klocale.h> +#include <kglobal.h> +#include <ktrader.h> +#include <kconfig.h> +#include <kio/job.h> +#include <kservice.h> +#include <kinstance.h> +#include <kpopupmenu.h> +#include <dcopref.h> +#include <khtml_part.h> +#include <kgenericfactory.h> +#include <kprotocolmanager.h> +#include <kaboutdata.h> + +#include "uachangerplugin.h" + +typedef KGenericFactory<UAChangerPlugin> UAChangerPluginFactory; +static const KAboutData aboutdata("uachangerplugin", I18N_NOOP("Change Browser Identification") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY (libuachangerplugin, UAChangerPluginFactory (&aboutdata)) + + +#define UA_PTOS(x) (*it)->property(x).toString() +#define QFL1(x) QString::fromLatin1(x) + + +UAChangerPlugin::UAChangerPlugin( QObject* parent, const char* name, + const QStringList & ) + :KParts::Plugin( parent, name ), + m_bSettingsLoaded(false), m_part(0L), m_config(0L) +{ + setInstance(UAChangerPlugin::instance()); + + m_pUAMenu = new KActionMenu( i18n("Change Browser &Identification"), "agent", + actionCollection(), "changeuseragent" ); + m_pUAMenu->setDelayed( false ); + connect( m_pUAMenu->popupMenu(), SIGNAL( aboutToShow() ), + this, SLOT( slotAboutToShow() ) ); + + m_pUAMenu->setEnabled ( false ); + + if ( parent && parent->inherits( "KHTMLPart" ) ) + { + m_part = static_cast<KHTMLPart*>(parent); + connect( m_part, SIGNAL(started(KIO::Job*)), this, + SLOT(slotStarted(KIO::Job*)) ); + } +} + +UAChangerPlugin::~UAChangerPlugin() +{ + saveSettings(); + slotReloadDescriptions(); +} + +void UAChangerPlugin::slotReloadDescriptions() +{ + delete m_config; + m_config = 0L; +} + +void UAChangerPlugin::parseDescFiles() +{ + KTrader::OfferList list = KTrader::self()->query("UserAgentStrings"); + if ( list.count() == 0 ) + return; + + m_mapAlias.clear(); + m_lstAlias.clear(); + m_lstIdentity.clear(); + + struct utsname utsn; + uname( &utsn ); + + QStringList languageList = KGlobal::locale()->languageList(); + if ( languageList.count() ) + { + QStringList::Iterator it = languageList.find(QFL1("C")); + if( it != languageList.end() ) + { + if( languageList.contains( QFL1("en") ) > 0 ) + languageList.remove( it ); + else + (*it) = QFL1("en"); + } + } + + KTrader::OfferList::ConstIterator it = list.begin(); + KTrader::OfferList::ConstIterator lastItem = list.end(); + + for ( ; it != lastItem; ++it ) + { + QString tmp = UA_PTOS("X-KDE-UA-FULL"); + QString tag = UA_PTOS("X-KDE-UA-TAG"); + + if(tag != "IE" && tag != "NN" && tag != "MOZ") + tag = "OTHER"; + + if ( (*it)->property("X-KDE-UA-DYNAMIC-ENTRY").toBool() ) + { + tmp.replace( QFL1("appSysName"), QFL1(utsn.sysname) ); + tmp.replace( QFL1("appSysRelease"), QFL1(utsn.release) ); + tmp.replace( QFL1("appMachineType"), QFL1(utsn.machine) ); + tmp.replace( QFL1("appLanguage"), languageList.join(QFL1(", ")) ); + tmp.replace( QFL1("appPlatform"), QFL1("X11") ); + } + + if ( m_lstIdentity.contains(tmp) ) + continue; // Ignore dups! + + m_lstIdentity << tmp; + tmp = QString("%1 %2").arg(UA_PTOS("X-KDE-UA-SYSNAME")).arg(UA_PTOS("X-KDE-UA-SYSRELEASE")); + + if ( tmp.stripWhiteSpace().isEmpty() ) + { + if(tag == "NN" || tag == "IE" || tag == "MOZ") + tmp = i18n("Version %1").arg(UA_PTOS("X-KDE-UA-VERSION")); + else + tmp = QString("%1 %2").arg(UA_PTOS("X-KDE-UA-NAME")).arg(UA_PTOS("X-KDE-UA-VERSION")); + } + else + { + if(tag == "NN" || tag == "IE" || tag == "MOZ") + tmp = i18n("Version %1 on %2").arg(UA_PTOS("X-KDE-UA-VERSION")).arg(tmp); + else + tmp = i18n("%1 %2 on %3").arg(UA_PTOS("X-KDE-UA-NAME")).arg(UA_PTOS("X-KDE-UA-VERSION")).arg(tmp); + } + + m_lstAlias << tmp; + + /* sort in this UA Alias alphabetically */ + BrowserGroup ualist = m_mapAlias[tag]; + BrowserGroup::Iterator e = ualist.begin(); + while ( !tmp.isEmpty() && e != ualist.end() ) + { + if ( m_lstAlias[(*e)] > tmp ) { + ualist.insert( e, m_lstAlias.count()-1 ); + tmp = QString::null; + } + ++e; + } + + if ( !tmp.isEmpty() ) + ualist.append( m_lstAlias.count()-1 ); + + m_mapAlias[tag] = ualist; + + if(tag == "OTHER") + m_mapBrowser[tag] = i18n("Other"); + else + m_mapBrowser[tag] = UA_PTOS("X-KDE-UA-NAME"); + + } +} + +void UAChangerPlugin::slotStarted( KIO::Job* ) +{ + m_currentURL = m_part->url(); + + // This plugin works on local files, http[s], and webdav[s]. + QString proto = m_currentURL.protocol(); + if (m_currentURL.isLocalFile() || + proto.startsWith("http") || proto.startsWith("webdav")) + { + if (!m_pUAMenu->isEnabled()) + m_pUAMenu->setEnabled ( true ); + } + else + { + m_pUAMenu->setEnabled ( false ); + } +} + +void UAChangerPlugin::slotAboutToShow() +{ + if (!m_config) + { + m_config = new KConfig( "kio_httprc" ); + parseDescFiles(); + } + + if (!m_bSettingsLoaded) + loadSettings(); + + int count = 0; + m_pUAMenu->popupMenu()->clear(); + m_pUAMenu->popupMenu()->insertTitle(i18n("Identify As")); // imho title doesn't need colon.. + + QString host = m_currentURL.isLocalFile() ? QFL1("localhost") : m_currentURL.host(); + m_currentUserAgent = KProtocolManager::userAgentForHost(host); + //kdDebug(90130) << "User Agent: " << m_currentUserAgent << endl; + + int id = m_pUAMenu->popupMenu()->insertItem( i18n("Default Identification"), this, + SLOT(slotDefault()), 0, ++count ); + if( m_currentUserAgent == KProtocolManager::defaultUserAgent() ) + m_pUAMenu->popupMenu()->setItemChecked(id, true); + + m_pUAMenu->popupMenu()->insertSeparator(); + + AliasConstIterator map = m_mapAlias.begin(); + for( ; map != m_mapAlias.end(); ++map ) + { + KPopupMenu *browserMenu = new KPopupMenu; + BrowserGroup::ConstIterator e = map.data().begin(); + for( ; e != map.data().end(); ++e ) + { + int id = browserMenu->insertItem( m_lstAlias[*e], this, SLOT(slotItemSelected(int)), 0, *e ); + if (m_lstIdentity[(*e)] == m_currentUserAgent) + browserMenu->setItemChecked(id, true); + } + m_pUAMenu->popupMenu()->insertItem( m_mapBrowser[map.key()], browserMenu ); + } + + m_pUAMenu->popupMenu()->insertSeparator(); + + /* useless here, imho.. + m_pUAMenu->popupMenu()->insertItem( i18n("Reload Identifications"), this, + SLOT(slotReloadDescriptions()), + 0, ++count );*/ + + m_pUAMenu->popupMenu()->insertItem( i18n("Apply to Entire Site"), this, + SLOT(slotApplyToDomain()), + 0, ++count ); + m_pUAMenu->popupMenu()->setItemChecked(count, m_bApplyToDomain); + + m_pUAMenu->popupMenu()->insertItem( i18n("Configure..."), this, + SLOT(slotConfigure())); + +} + +void UAChangerPlugin::slotConfigure() +{ + KService::Ptr service = KService::serviceByDesktopName ("useragent"); + if (service) + KRun::runCommand (service->exec ()); +} + +void UAChangerPlugin::slotItemSelected( int id ) +{ + if (m_lstIdentity[id] == m_currentUserAgent) return; + + QString host; + m_currentUserAgent = m_lstIdentity[id]; + host = m_currentURL.isLocalFile() ? QFL1("localhost") : filterHost( m_currentURL.host() ); + + m_config->setGroup( host.lower() ); + m_config->writeEntry( "UserAgent", m_currentUserAgent ); + m_config->sync(); + + // Update the io-slaves... + updateIOSlaves (); + + // Reload the page with the new user-agent string + m_part->openURL( m_currentURL ); +} + +void UAChangerPlugin::slotDefault() +{ + if( m_currentUserAgent == KProtocolManager::defaultUserAgent() ) return; // don't flicker! + // We have no choice but delete all higher domain level settings here since it + // affects what will be matched. + QStringList partList = QStringList::split('.', m_currentURL.host(), false); + + if ( !partList.isEmpty() ) + { + partList.remove(partList.begin()); + + QStringList domains; + // Remove the exact name match... + domains << m_currentURL.host (); + + while (partList.count()) + { + if (partList.count() == 2) + if (partList[0].length() <=2 && partList[1].length() ==2) + break; + + if (partList.count() == 1) + break; + + domains << partList.join(QFL1(".")); + partList.remove(partList.begin()); + } + + for (QStringList::Iterator it = domains.begin(); it != domains.end(); it++) + { + //kdDebug () << "Domain to remove: " << *it << endl; + if ( m_config->hasGroup(*it) ) + m_config->deleteGroup(*it); + else if( m_config->hasKey(*it) ) + m_config->deleteEntry(*it); + } + } + else + if ( m_currentURL.isLocalFile() && m_config->hasGroup( "localhost" ) ) + m_config->deleteGroup( "localhost" ); + + m_config->sync(); + + // Reset some internal variables and inform the http io-slaves of the changes. + m_currentUserAgent = KProtocolManager::defaultUserAgent(); + + // Update the http io-slaves. + updateIOSlaves(); + + // Reload the page with the default user-agent + m_part->openURL( m_currentURL ); +} + +void UAChangerPlugin::updateIOSlaves () +{ + // Inform running http(s) io-slaves about the change... + if (!DCOPRef("*", "KIO::Scheduler").send("reparseSlaveConfiguration", QString::null)) + kdWarning() << "UAChangerPlugin::updateIOSlaves: Unable to update running application!" << endl; +} + +QString UAChangerPlugin::filterHost(const QString &hostname) +{ + QRegExp rx; + + // Check for IPv4 address + rx.setPattern ("[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}"); + if (rx.exactMatch (hostname)) + return hostname; + + // Check for IPv6 address here... + rx.setPattern ("^\\[.*\\]$"); + if (rx.exactMatch (hostname)) + return hostname; + + // Return the TLD if apply to domain or + return (m_bApplyToDomain ? findTLD(hostname): hostname); +} + +QString UAChangerPlugin::findTLD (const QString &hostname) +{ + QStringList domains; + QStringList partList = QStringList::split('.', hostname, false); + + if (partList.count()) + partList.remove(partList.begin()); // Remove hostname + + while(partList.count()) + { + // We only have a TLD left. + if (partList.count() == 1) + break; + + if( partList.count() == 2 ) + { + // The .name domain uses <name>.<surname>.name + // Although the TLD is striclty speaking .name, for our purpose + // it should be <surname>.name since people should not be able + // to set cookies for everyone with the same surname. + // Matches <surname>.name + if( partList[1].lower() == QFL1("name") ) + { + break; + } + else if( partList[1].length() == 2 ) + { + // If this is a TLD, we should stop. (e.g. co.uk) + // We assume this is a TLD if it ends with .xx.yy or .x.yy + if (partList[0].length() <= 2) + break; // This is a TLD. + + // Catch some TLDs that we miss with the previous check + // e.g. com.au, org.uk, mil.co + QCString t = partList[0].lower().utf8(); + if ((t == "com") || (t == "net") || (t == "org") || (t == "gov") || + (t == "edu") || (t == "mil") || (t == "int")) + break; + } + } + + domains.append(partList.join(QFL1("."))); + partList.remove(partList.begin()); // Remove part + } + + if( domains.isEmpty() ) + return hostname; + + return domains[0]; +} + +void UAChangerPlugin::saveSettings() +{ + if(!m_bSettingsLoaded) return; + + KConfig cfg ("uachangerrc", false, false); + cfg.setGroup ("General"); + + cfg.writeEntry ("applyToDomain", m_bApplyToDomain); +} + +void UAChangerPlugin::loadSettings() +{ + KConfig cfg ("uachangerrc", false, false); + cfg.setGroup ("General"); + + m_bApplyToDomain = cfg.readBoolEntry ("applyToDomain", true); + m_bSettingsLoaded = true; +} + +void UAChangerPlugin::slotApplyToDomain() +{ + m_bApplyToDomain = !m_bApplyToDomain; +} + +#include "uachangerplugin.moc" diff --git a/konq-plugins/uachanger/uachangerplugin.desktop b/konq-plugins/uachanger/uachangerplugin.desktop new file mode 100644 index 0000000..9b15127 --- /dev/null +++ b/konq-plugins/uachanger/uachangerplugin.desktop @@ -0,0 +1,121 @@ +[Desktop Entry] +X-KDE-Library=UserAgentChanger +X-KDE-PluginInfo-Author=Dawit Alemayehu +X-KDE-PluginInfo-Email=adawit@kde.org +X-KDE-PluginInfo-Name=UserAgentChanger +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=UserAgent Changer +Name[bs]=Promjena identifikacije preglednika +Name[ca]=Canvia l'agent d'usuari +Name[cs]=Změna uživatelského agenta +Name[da]=Ændring af brugeragent +Name[de]=Browserkennung ändern +Name[el]=Αλλαγή πράκτορα χρήστη +Name[eo]=Uzantagenta ŝanĝilo +Name[es]=Cambiador de la identificación del agente usuario +Name[et]=Identifikaatori muutja +Name[eu]=Erabiltzaile agentearen aldatzailea +Name[fa]=تغییردهندۀ عامل کاربر +Name[fi]=Käyttäjäagenttimuuttaja +Name[fr]=Changeur d'identité du navigateur +Name[fy]=Brûkersagint wizigje +Name[ga]=Clár Athraithe UserAgent +Name[gl]=Cámbio de Identificación do Navegador +Name[he]=משנה זיהוי דפדפן +Name[hi]=यूज़रएजेंट परिवर्तक +Name[hr]=Izmjenjivač korisničkog agenta +Name[hu]=A böngészőazonosító átváltása +Name[is]=Auðkenni vafra +Name[it]=Modificatore di User Agent +Name[ja]=ユーザエージェント チェンジャー +Name[ka]=UserAgent შემცვლელი +Name[kk]=UserAgent ауыстырғышы +Name[km]=កម្មវិធីផ្លាស់ប្ដូរភ្នាក់ងារអ្នកប្រើ +Name[lt]=Naudotojo agento keitiklis +Name[mk]=Менувач на кориснички агент +Name[nb]=Brukeragent-endring +Name[nds]=Nettkieker-Kennen ännern +Name[ne]=प्रयोगकर्ता अभिकर्ता परिवर्तक +Name[nl]=Gebruikersagent wijzigen +Name[nn]=Endring av brukaragent +Name[pa]=ਉਪਭੋਗੀ ਏਜੰਟ ਤਬਦੀਲੀਕਾਰ +Name[pl]=Zmiana identyfikacji przeglądarki +Name[pt]=Mudança de Agente do Utilizador +Name[pt_BR]=Modificar de Agente de Usuários +Name[ru]=Смена идентификации браузера (UserAgent) +Name[sk]=Zmena identifikácie prehliadača +Name[sl]=Spreminjanje uporabniškega agenta +Name[sr]=Измењивач корисничког агента +Name[sr@Latn]=Izmenjivač korisničkog agenta +Name[sv]=Ändring av användaragent +Name[ta]=பயனர் முகவர் மாற்றி +Name[tg]=Ивазкунии нишондиҳандаҳои воқеанигор (UserAgent) +Name[tr]=KullanıcıAjanı Değiştiricisi +Name[uk]=Селектор агента користувача +Name[vi]=Bộ đổi UserAgent +Name[zh_CN]=用户代理更换器 +Comment=Plugin for changing the user agent +Comment[af]=Inplak vir verandering die gebruiker agent +Comment[az]=İstifadəçi alıcısını dəyişdirmək üçün əlavə +Comment[bg]=Приставка за смяна на идентификацията на браузъра +Comment[bs]=Dodatak za promijenju identifikacije preglednika +Comment[ca]=Connector per a modificar l'agent d'usuari +Comment[cs]=Modul pro změnu uživatelského agenta +Comment[cy]=Ategyn i newid asiant y defnyddiwr +Comment[da]=Plugin til at ændre brugeragenten +Comment[de]=Modul zum Ändern der Browserkennung +Comment[el]=Πρόσθετο για την αλλαγή του πράκτορα χρήστη +Comment[eo]=Kromaĵo por ŝanĝi la uzantan agenton +Comment[es]=Complemento para cambiar el agente usuario +Comment[et]=Brauseri identifikaatori muutmise plugin +Comment[eu]=Erabiltzaile agentea aldatzeko plugina +Comment[fa]=وصله برای تغییر عامل کاربر +Comment[fi]=Sovelma käyttäjäagentin muuttamiseen +Comment[fr]=Module externe pour changer l'identification du navigateur +Comment[fy]=Plugin foar it wizigjen fan de brûkersagint +Comment[ga]=Breiseán a athraíonn an gníomhaire úsáideora +Comment[gl]=Un plugin para alterar o axente do usuário +Comment[he]=תוסף לשינוי זיהוי הדפדפן +Comment[hi]=यूज़रएजेंट बदलने के लिए प्लगइन +Comment[hr]=Dodatak za izmjenu korisničkog agenta +Comment[hu]=Bővítőmodul a böngészőazonosító megváltoztatásához +Comment[is]=Íforrit til að breyta auðkenni vafra +Comment[it]=Plugin per modificare lo user agent +Comment[ja]=ユーザエージェント変更用プラグイン +Comment[ka]=მომხმარებლის აგენტის შეცვლის მოდული +Comment[kk]=Пайдаланушы агентін ауыстыру плагин модулі +Comment[km]=កម្មវិធីជំនួយសម្រាប់ផ្លាស់ប្ដូរភ្នាក់ងារអ្នកប្រើ +Comment[lt]=Priedas naudotojo agentui keisti +Comment[mk]=Приклучок за менување на корисничкиот агент +Comment[ms]=Plugin untuk mengubah ejen pengguna +Comment[nb]=Tilleggsmodul for å endre brukeragent +Comment[nds]=Moduul för't Ännern vun de Nettkieker-Kennen +Comment[ne]=प्रयोगकर्ता अभिकर्ता परिवर्तनका लागि प्लगइन +Comment[nl]=Plugin voor het wijzigen van de gebruikersagent +Comment[nn]=Programtillegg som kan endra brukaragenten +Comment[pl]=Wtyczka zmiany identyfikacji przeglądarki +Comment[pt]=Um 'plugin' para alterar o agente do utilizador +Comment[pt_BR]=Plug-in para modificar o agente de usuário +Comment[ro]=Modul pentru modificarea identificării "User Agent" a Konqueror +Comment[ru]=Модуль настройки описания браузера +Comment[sk]=Modul pre zmenu UserAgent-a +Comment[sl]=Vstavek za spreminjanje uporabniškega agenta +Comment[sr]=Прикључак за мењање корисничког агента +Comment[sr@Latn]=Priključak za menjanje korisničkog agenta +Comment[sv]=Insticksprogram för att ändra användaragent +Comment[ta]=பயனர் செயலியை மாற்றுவதற்கான சொருகுப் பொருள் +Comment[tg]=Модули танзимоти тахаллуси воқеанигор +Comment[tr]=Kullanıcı ajanını değiştirmek için bir eklenti +Comment[uk]=Втулок для зміни агента користувача +Comment[vi]=Bổ sung thay đổi tác nhân người dùng +Comment[xh]=Plagela ngaphakathi utshintsho lomsebenzisiwomntu omele omnye +Comment[zh_CN]=用来更换用户代理的插件 +Comment[zh_TW]=改變使用者代理人的外掛程式 +X-KDE-ParentApp=konqueror +Icon=agent +DocPath=konq-plugins/uachanger/index.html diff --git a/konq-plugins/uachanger/uachangerplugin.h b/konq-plugins/uachanger/uachangerplugin.h new file mode 100644 index 0000000..eb70704 --- /dev/null +++ b/konq-plugins/uachanger/uachangerplugin.h @@ -0,0 +1,95 @@ +/* + Copyright (c) 2001 Dawit Alemayehu <adawit@kde.org> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License (LGPL) as published by the Free Software Foundation; + either version 2 of the License, or (at your option) any later + version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __UACHANGER_PLUGIN_H +#define __UACHANGER_PLUGIN_H + +#include <qmap.h> +#include <qvaluelist.h> +#include <qstringlist.h> + +#include <kurl.h> +#include <klibloader.h> +#include <kparts/plugin.h> + +class KHTMLPart; +class KActionMenu; +class KConfig; + +namespace KIO +{ + class Job; +} + +class UAChangerPlugin : public KParts::Plugin +{ + Q_OBJECT + +public: + UAChangerPlugin( QObject* parent, const char* name, + const QStringList & ); + ~UAChangerPlugin(); + +protected slots: + void slotDefault(); + void parseDescFiles(); + void updateIOSlaves(); + + void slotConfigure(); + void slotAboutToShow(); + void slotApplyToDomain(); + void slotItemSelected(int); + void slotStarted(KIO::Job*); + void slotReloadDescriptions(); + +protected: + QString findTLD (const QString &hostname); + QString filterHost (const QString &hostname); + +private: + void loadSettings(); + void saveSettings(); + + int m_selectedItem; + bool m_bApplyToDomain; + bool m_bSettingsLoaded; + + KHTMLPart* m_part; + KActionMenu* m_pUAMenu; + KConfig* m_config; + + KURL m_currentURL; + QString m_currentUserAgent; + + QStringList m_lstAlias; + QStringList m_lstIdentity; + + typedef QValueList<int> BrowserGroup; + typedef QMap<QString,BrowserGroup> AliasMap; + typedef QMap<QString,QString> BrowserMap; + + typedef AliasMap::Iterator AliasIterator; + typedef AliasMap::ConstIterator AliasConstIterator; + + BrowserMap m_mapBrowser; + AliasMap m_mapAlias; +}; + +#endif diff --git a/konq-plugins/uachanger/uachangerplugin.rc b/konq-plugins/uachanger/uachangerplugin.rc new file mode 100644 index 0000000..91535bf --- /dev/null +++ b/konq-plugins/uachanger/uachangerplugin.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartplugin> +<kpartplugin name="UserAgentChanger" library="libuachangerplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="changeuseragent"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="changeuseragent"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/uninstall.desktop b/konq-plugins/uninstall.desktop new file mode 100644 index 0000000..e1e3e17 --- /dev/null +++ b/konq-plugins/uninstall.desktop @@ -0,0 +1,2 @@ +[Desktop Entry] +Hidden=true diff --git a/konq-plugins/validators/Makefile.am b/konq-plugins/validators/Makefile.am new file mode 100644 index 0000000..3c09508 --- /dev/null +++ b/konq-plugins/validators/Makefile.am @@ -0,0 +1,24 @@ +INCLUDES = $(all_includes) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libvalidatorsplugin.la + +libvalidatorsplugin_la_SOURCES = plugin_validators.cpp validatorsdialog.cpp +libvalidatorsplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +libvalidatorsplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = plugin_validators.rc plugin_validators.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = plugin_validators.desktop + +install-data-local: $(srcdir)/../uninstall.desktop + $(mkinstalldirs) $(DESTDIR)$(pluginsdir) + $(INSTALL_DATA) $(srcdir)/../uninstall.desktop $(DESTDIR)$(pluginsdir)/validatorsplugin.desktop + +KDE_ICON = validators cssvalidator htmlvalidator + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/validatorsplugin.pot diff --git a/konq-plugins/validators/cr16-action-cssvalidator.png b/konq-plugins/validators/cr16-action-cssvalidator.png Binary files differnew file mode 100644 index 0000000..63bbee6 --- /dev/null +++ b/konq-plugins/validators/cr16-action-cssvalidator.png diff --git a/konq-plugins/validators/cr16-action-htmlvalidator.png b/konq-plugins/validators/cr16-action-htmlvalidator.png Binary files differnew file mode 100644 index 0000000..b4a0acc --- /dev/null +++ b/konq-plugins/validators/cr16-action-htmlvalidator.png diff --git a/konq-plugins/validators/cr16-action-validators.png b/konq-plugins/validators/cr16-action-validators.png Binary files differnew file mode 100644 index 0000000..b4a0acc --- /dev/null +++ b/konq-plugins/validators/cr16-action-validators.png diff --git a/konq-plugins/validators/cr22-action-cssvalidator.png b/konq-plugins/validators/cr22-action-cssvalidator.png Binary files differnew file mode 100644 index 0000000..a6dec2b --- /dev/null +++ b/konq-plugins/validators/cr22-action-cssvalidator.png diff --git a/konq-plugins/validators/cr22-action-htmlvalidator.png b/konq-plugins/validators/cr22-action-htmlvalidator.png Binary files differnew file mode 100644 index 0000000..ff67d1e --- /dev/null +++ b/konq-plugins/validators/cr22-action-htmlvalidator.png diff --git a/konq-plugins/validators/cr22-action-validators.png b/konq-plugins/validators/cr22-action-validators.png Binary files differnew file mode 100644 index 0000000..ff67d1e --- /dev/null +++ b/konq-plugins/validators/cr22-action-validators.png diff --git a/konq-plugins/validators/plugin_validators.cpp b/konq-plugins/validators/plugin_validators.cpp new file mode 100644 index 0000000..69f07cd --- /dev/null +++ b/konq-plugins/validators/plugin_validators.cpp @@ -0,0 +1,202 @@ +/* This file is part of Validators + * + * It's a merge of the HTML- and the CSSValidator + * + * Copyright (C) 2001 by Richard Moore <rich@kde.org> + * Andreas Schlapbach <schlpbch@iam.unibe.ch> + * + * for information how to write your own plugin see: + * http://developer.kde.org/documentation/tutorials/dot/writing-plugins.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +/* $Id$ */ + +#include <kinstance.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kaction.h> +#include <khtml_part.h> +#include <kgenericfactory.h> +#include <kdebug.h> +#include <kaboutdata.h> + +#include "plugin_validators.h" +#include "validatorsdialog.h" + + +typedef KGenericFactory<PluginValidators> PluginValidatorsFactory; +static const KAboutData aboutdata("validatorsplugin", I18N_NOOP("Validate Web Page") , "1.0" ); +K_EXPORT_COMPONENT_FACTORY( libvalidatorsplugin, + PluginValidatorsFactory( &aboutdata ) ) + +PluginValidators::PluginValidators( QObject* parent, const char* name, + const QStringList & ) + : Plugin( parent, name ), m_configDialog(0), m_part(0) +{ + setInstance(PluginValidatorsFactory::instance()); + + m_menu = new KActionMenu ( i18n( "&Validate Web Page" ), "validators", + actionCollection(), "validateWebpage" ); + m_menu->setDelayed( false ); + + m_menu->insert( new KAction( i18n( "Validate &HTML" ), + "htmlvalidator", 0, + this, SLOT(slotValidateHTML()), + actionCollection(), "validateHTML") ); + + m_menu->insert( new KAction( i18n( "Validate &CSS" ), + "cssvalidator", 0, + this, SLOT(slotValidateCSS()), + actionCollection(), "validateCSS") ); + + m_menu->insert( new KAction( i18n( "Validate &Links" ), + 0, + this, SLOT(slotValidateLinks()), + actionCollection(), "validateLinks") ); + + m_menu->setEnabled( false ); + + if ( parent && parent->inherits( "KHTMLPart" )) + { + m_menu->insert( new KAction( i18n( "C&onfigure Validator..." ), + "configure", 0, + this, SLOT(slotConfigure()), + actionCollection(), "configure") ); + + m_part = static_cast<KHTMLPart *>( parent ); + m_configDialog = new ValidatorsDialog( m_part->widget() ); + setURLs(); + + connect( m_part, SIGNAL(started(KIO::Job*)), this, + SLOT(slotStarted(KIO::Job*)) ); + } +} + +PluginValidators::~PluginValidators() +{ + delete m_configDialog; +// Dont' delete the action. KActionCollection as parent does the job already +// and not deleting it at this point also ensures that in case we are not unplugged +// from the GUI yet and the ~KXMLGUIClient destructor will do so it won't hit a +// dead pointer. The kxmlgui factory keeps references to the actions, but it does not +// connect to their destroyed() signal, yet (need to find an elegant solution for that +// as it can easily increase the memory usage significantly) . That's why actions must +// persist as long as the plugin is plugged into the GUI. +// delete m_menu; +} + +void PluginValidators::setURLs() +{ + m_WWWValidatorUrl = KURL(m_configDialog->getWWWValidatorUrl()); + m_CSSValidatorUrl = KURL(m_configDialog->getCSSValidatorUrl()); + m_WWWValidatorUploadUrl = KURL(m_configDialog->getWWWValidatorUploadUrl()); + m_CSSValidatorUploadUrl = KURL(m_configDialog->getCSSValidatorUploadUrl()); + m_linkValidatorUrl = KURL(m_configDialog->getLinkValidatorUrl()); +} + +void PluginValidators::slotStarted( KIO::Job* ) +{ + // The w3c validator can only access http URLs, and upload local files. + // No https, probably no webdav either. + m_menu->setEnabled( m_part->url().isLocalFile() + || m_part->url().protocol().lower() == "http" ); +} + +void PluginValidators::slotValidateHTML() +{ + validateURL(m_WWWValidatorUrl, m_WWWValidatorUploadUrl); +} + +void PluginValidators::slotValidateCSS() +{ + validateURL(m_CSSValidatorUrl, m_CSSValidatorUploadUrl); +} + +void PluginValidators::slotValidateLinks() +{ + validateURL(m_linkValidatorUrl, KURL()); +} + +void PluginValidators::slotConfigure() +{ + m_configDialog->show(); + setURLs(); +} + +void PluginValidators::validateURL(const KURL &url, const KURL &uploadUrl) +{ + // The parent is assumed to be a KHTMLPart + if ( !parent()->inherits("KHTMLPart") ) + { + QString title = i18n( "Cannot Validate Source" ); + QString text = i18n( "You cannot validate anything except web pages with " + "this plugin." ); + + KMessageBox::sorry( 0, text, title ); + return; + } + + KURL validatorUrl(url); + + // Get URL + KURL partUrl = m_part->url(); + if ( !partUrl.isValid() ) // Just in case ;) + { + QString title = i18n( "Malformed URL" ); + QString text = i18n( "The URL you entered is not valid, please " + "correct it and try again." ); + KMessageBox::sorry( 0, text, title ); + return; + } + + if (partUrl.isLocalFile()) + { + if ( validatorUrl.isEmpty() ) { + QString title = i18n( "Upload Not Possible" ); + QString text = i18n( "Validating links is not possible for local " + "files." ); + KMessageBox::sorry( 0, text, title ); + return; + } + validatorUrl = uploadUrl; + } + else + { + if (partUrl.hasPass()) + { + KMessageBox::sorry( + m_part->widget(), + i18n("<qt>The selected URL cannot be verified because it contains " + "a password. Sending this URL to <b>%1</b> would put the security " + "of <b>%2</b> at risk.</qt>") + .arg(validatorUrl.host()).arg(partUrl.host())); + return; + } + // Set entered URL as a parameter + QString q = partUrl.url(); + q = KURL::encode_string( q ); + QString p = "uri="; + p += q; + validatorUrl.setQuery( p ); + } + kdDebug(90120) << "final URL: " << validatorUrl.url() << endl; + + emit m_part->browserExtension()->openURLRequest( validatorUrl ); +} + +#include <plugin_validators.moc> diff --git a/konq-plugins/validators/plugin_validators.desktop b/konq-plugins/validators/plugin_validators.desktop new file mode 100644 index 0000000..f326863 --- /dev/null +++ b/konq-plugins/validators/plugin_validators.desktop @@ -0,0 +1,128 @@ +[Desktop Entry] +X-KDE-Library=validators +X-KDE-PluginInfo-Author=Richard Moore, Andreas Schlapbach +X-KDE-PluginInfo-Email=rich@kde.org, schlpbch@iam.unibe.ch +X-KDE-PluginInfo-Name=validators +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=false +Name=Website Validators +Name[bg]=Валидатори за уеб сайтове +Name[bs]=Validatori za Web stranice +Name[ca]=Validadors de pàgines web +Name[cs]=Validátory webových stránek +Name[da]=Gyldighedstjekkere af netsider +Name[de]=Webseiten-Überprüfung +Name[el]=Ελεγκτές εγκυρότητας ιστοσελίδων +Name[eo]=Retsituo kontroliloj +Name[es]=Validadores de sitios web +Name[et]=Veebilehe süntaksi kontrollijad +Name[eu]=Weblekuen balidatzailea +Name[fa]=اعتبارسنجهای وبگاه +Name[fi]=WWW-validaattorit +Name[fr]=Validateur de sites Internet +Name[fy]=Webstee-falidaasjeprogramma +Name[ga]=Bailíochtóirí Suímh Ghréasáin +Name[gl]=Validación de Páxinas Web +Name[he]=מוודאי אתרי אינטרנט +Name[hi]=वेबसाइट वेलिडेटर्स +Name[hr]=Provjera valjanosti web-lokacije +Name[hu]=Weboldal-ellenőrző +Name[is]=Villuleitun vefa +Name[it]=Validatore di Siti Web +Name[ja]=ウェブサイト検証 +Name[ka]=ვებგვერდის დამმოწმებელი +Name[kk]=Вебсайт тексергіші +Name[km]=កម្មវិធីធ្វើឲ្យតំបន់បណ្ដាញមានសុពលភាព +Name[lt]=Web sričių tikrinimo priemonės +Name[mk]=Валидатори на веб-страници +Name[ms]=Pengesah Laman Web +Name[nb]=Nettsted-validator +Name[nds]=Nettsieden-Prööv +Name[ne]=वेबसाइट प्रमाणितकर्ता +Name[nl]=Website-validatieprogramma +Name[nn]=Nettstadvalidering +Name[pl]=Sprawdzanie poprawności witryn internetowych +Name[pt]=Validação de Páginas Web +Name[pt_BR]=Validadores de Sites Web +Name[ru]=Проверка правильности сайтов +Name[sk]=Kontrola web stránky +Name[sl]=Potrdilniki spletnih strani +Name[sr]=Оверивачи веб сајтова +Name[sr@Latn]=Overivači veb sajtova +Name[sv]=Validering av webbplatser +Name[ta]=வலைதள மதிப்பீடுகள் +Name[tg]=Тафтиши дурустии сайтҳо +Name[tr]=İnternet Sitesi Denetleyicisi +Name[uk]=Служби перевірки сайтів +Name[uz]=Veb-sahifa toʻgʻriligini tekshirish +Name[uz@cyrillic]=Веб-саҳифа тўғрилигини текшириш +Name[vi]=Bộ thẩm tra chỗ Mạng +Name[zh_CN]=网站校验器 +Name[zh_TW]=網站驗證器 +Comment=CSS and HTML validator plugins +Comment[af]=Css en Html geldighiedstoetser inprop modules +Comment[ar]=ملحقات للتأكد من صلاحية ملفات HTML و CSS +Comment[az]=CSS və HTML doğrulayıcı əlavələri +Comment[bg]=Приставка за валидиране на CSS и HTML +Comment[bs]=CSS i HTML validator dodaci +Comment[ca]=Connectors de validació CSS i HTML +Comment[cs]=Moduly pro validaci CSS a HTML +Comment[cy]=Ategynnau dilysydd CSS a HTML +Comment[da]=Gyldighedstjekker-plugin for CSS og HTML +Comment[de]=CSS- und HTML-Module zur Syntaxüberprüfung +Comment[el]=Πρόσθετα ελέγχου εγκυρότητας CSS και HTML +Comment[eo]=CSS kaj HTML kontrolaj kromaĵoj +Comment[es]=Complementos para validar CSS y HTML +Comment[et]=CSS ja HTML süntaksi kontrollimise plugin +Comment[eu]=CSS eta HTML balidatzeko pluginak +Comment[fa]=وصلههای اعتبارسنج زنگام و CSS +Comment[fi]=CSS ja HTML validointisovelmat +Comment[fr]=Module de validation CSS et HTML +Comment[fy]=Plugins foar it falidearjen fan HTML en CSS +Comment[ga]=Breiseáin Bhailíochtaithe CSS agus HTML +Comment[gl]=Plugins de validación de CSS e HTML +Comment[he]=תוספים לווידוא CSS ו־HTML +Comment[hi]=सीएसएस तथा एचटीएमएल वेलिडेटर प्लगइन्स +Comment[hr]=Dodatak za provjeravanje valjanosti CSS-a i HTML-a +Comment[hu]=CSS- és HTML-ellenőrző bővítőmodul +Comment[is]=CSS og HTML gildir +Comment[it]=Plugin per validare CSS e HTML +Comment[ja]=CSS と HTML を検証するプラグイン +Comment[ka]=CSS და HTML დამოწმების მოდული +Comment[kk]=CSS және HTML тексергіш плагин модулі +Comment[km]=កម្មវិធីជំនួយរបស់កម្មវិធីធ្វើឲ្យ CSS និង HTML មានសុពលភាព +Comment[lt]=CSS ir HTML tikrinimo priedai +Comment[mk]=Приклучоци за валидирање на CSS и HTML +Comment[ms]=Plugin pengesah CSS dan HTML +Comment[nb]=Tilleggsmoduler for validering av CSS og HTML +Comment[nds]=CSS- un HTML-Pröövmodulen +Comment[ne]=सीएसएस र एचटीएमएल प्रमाणितकर्ता प्लगइनहरू +Comment[nl]=Plugins voor het valideren van HTML en CSS +Comment[nn]=Programtillegg for validering av CSS og HTML +Comment[pl]=Wtyczka sprawdzania poprawności HTML i CSS +Comment[pt]='Plugins' de validação de CSS e HTML +Comment[pt_BR]=Plug-Ins validador para CSS e HTML +Comment[ro]=Module de validare CSS şi HTML +Comment[ru]=Модули проверки правильности HTML и CSS +Comment[sk]=Modul pre kontrolu CSS a HTML +Comment[sl]=Vstavki za potrjevanje CSS in HTML +Comment[sr]=Прикључци за оверавање CSS-а и HTML-а +Comment[sr@Latn]=Priključci za overavanje CSS-a i HTML-a +Comment[sv]=Insticksprogram för CSS- och HTML-validering +Comment[ta]=CSS மற்றும் HTML மதிப்பீட்டாளர் சொருகுப்பொருள்கள் +Comment[tg]=Модули тафтиши дурустии HTML ва CSS +Comment[tr]=CSS ve HTML denetleme eklentileri +Comment[uk]=Втулки перевірки CSS і HTML +Comment[uz]=HTML va CSS toʻgʻriligini tekshirish vositalari +Comment[uz@cyrillic]=HTML ва CSS тўғрилигини текшириш воситалари +Comment[vi]=Bổ sung thẩm tra HTML và CSS +Comment[xh]=Iiplagi zangaphakathi zomqinisekisi we CSS ne HTML +Comment[zh_CN]=CSS 和 HTML 校验插件 +Comment[zh_TW]=CSS 與 HTML 驗證外掛程式 +Icon=validators +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/validators/index.html diff --git a/konq-plugins/validators/plugin_validators.h b/konq-plugins/validators/plugin_validators.h new file mode 100644 index 0000000..448e77f --- /dev/null +++ b/konq-plugins/validators/plugin_validators.h @@ -0,0 +1,72 @@ +/* This file is part of Validators + * + * It's a merge of the HTML- and the CSSValidator + * + * Copyright (C) 2001 by Richard Moore <rich@kde.org> + * Andreas Schlapbach <schlpbch@iam.unibe.ch> + * + * for information how to write your own plugin see: + * http://developer.kde.org/documentation/tutorials/dot/writing-plugins.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +/* $Id$ */ + +#ifndef __plugin_validators_h +#define __plugin_validators_h + +#include <kparts/plugin.h> +#include <klibloader.h> + +#include "validatorsdialog.h" +#include <qguardedptr.h> + +class KAction; +class KURL; + +class PluginValidators : public KParts::Plugin +{ + Q_OBJECT +public: + PluginValidators( QObject* parent, const char* name, + const QStringList & ); + virtual ~PluginValidators(); + +public slots: + void slotValidateHTML(); + void slotValidateCSS(); + void slotValidateLinks(); + void slotConfigure(); + +private slots: + void slotStarted( KIO::Job* ); + +private: + KActionMenu *m_menu; + QGuardedPtr<ValidatorsDialog> m_configDialog; // | + // +-> Order dependency. + KHTMLPart* m_part; // | + + KURL m_WWWValidatorUrl, m_WWWValidatorUploadUrl; + KURL m_CSSValidatorUrl, m_CSSValidatorUploadUrl; + KURL m_linkValidatorUrl; + + void setURLs(); + void validateURL(const KURL &url, const KURL &uploadUrl = KURL()); +}; + +#endif diff --git a/konq-plugins/validators/plugin_validators.rc b/konq-plugins/validators/plugin_validators.rc new file mode 100644 index 0000000..5207ee8 --- /dev/null +++ b/konq-plugins/validators/plugin_validators.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="validators" library="libvalidatorsplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="validateWebpage"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="validateWebpage"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/validators/validatorsdialog.cpp b/konq-plugins/validators/validatorsdialog.cpp new file mode 100644 index 0000000..0c524e2 --- /dev/null +++ b/konq-plugins/validators/validatorsdialog.cpp @@ -0,0 +1,176 @@ +/* This file is part of the KDE project + + Copyright (C) 2001 Andreas Schlapbach <schlpbch@iam.unibe.ch> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include <qlabel.h> +#include <qvbox.h> +#include <qgroupbox.h> +#include <qlayout.h> +#include <qcombobox.h> +#include <kconfig.h> + +#include <klocale.h> + +#include "validatorsdialog.h" +#include "validatorsdialog.moc" + +ValidatorsDialog::ValidatorsDialog(QWidget *parent, const char *name ) + : KDialogBase( parent, name, false, i18n("Configure"), Ok|Cancel, Ok, true ) +{ + setCaption(i18n("Configure Validating Servers")); + setMinimumWidth(300); + + QVBox *page = makeVBoxMainWidget (); + + QGroupBox *tgroup = new QGroupBox( i18n("HTML/XML Validator"), page ); + QVBoxLayout *vlay = new QVBoxLayout( tgroup, spacingHint() ); + vlay->addSpacing( fontMetrics().lineSpacing()); + + vlay->addWidget(new QLabel( i18n("URL:"), tgroup)); + + m_WWWValidatorCB = new QComboBox(true, tgroup); + m_WWWValidatorCB->setDuplicatesEnabled(false); + vlay->addWidget( m_WWWValidatorCB ); + + vlay->addWidget(new QLabel( i18n("Upload:"), tgroup)); + + m_WWWValidatorUploadCB = new QComboBox(true, tgroup); + m_WWWValidatorUploadCB->setDuplicatesEnabled(false); + vlay->addWidget( m_WWWValidatorUploadCB ); + + /// + + QGroupBox *group2= new QGroupBox( i18n("CSS Validator"), page ); + QVBoxLayout *vlay2 = new QVBoxLayout( group2, spacingHint() ); + vlay2->addSpacing( fontMetrics().lineSpacing()); + + vlay2->addWidget(new QLabel( i18n("URL:"), group2)); + + m_CSSValidatorCB = new QComboBox(true, group2); + m_CSSValidatorCB->setDuplicatesEnabled(false); + vlay2->addWidget( m_CSSValidatorCB ); + + vlay2->addWidget(new QLabel( i18n("Upload:"), group2)); + + m_CSSValidatorUploadCB = new QComboBox(true, group2); + m_CSSValidatorUploadCB->setDuplicatesEnabled(false); + vlay2->addWidget( m_CSSValidatorUploadCB ); + + /// + + QGroupBox *group3= new QGroupBox( i18n("Link Validator"), page ); + QVBoxLayout *vlay3 = new QVBoxLayout( group3, spacingHint() ); + vlay3->addSpacing( fontMetrics().lineSpacing()); + + vlay3->addWidget(new QLabel( i18n("URL:"), group3)); + + m_linkValidatorCB = new QComboBox(true, group3); + m_linkValidatorCB->setDuplicatesEnabled(false); + vlay3->addWidget( m_linkValidatorCB ); + + load(); +} + +ValidatorsDialog::~ValidatorsDialog() +{ + delete m_config; +} + +void ValidatorsDialog::load() +{ + m_config = new KConfig("validatorsrc"); + m_config->setGroup("Addresses"); + + m_WWWValidatorCB->insertStringList(m_config->readListEntry("WWWValidatorUrl")); + if (m_WWWValidatorCB->count()==0) { + m_WWWValidatorCB->insertItem("http://validator.w3.org/check"); + } + m_WWWValidatorCB->setCurrentItem(m_config->readNumEntry("WWWValidatorUrlIndex",0)); + + m_CSSValidatorCB->insertStringList(m_config->readListEntry("CSSValidatorUrl")); + if (m_CSSValidatorCB->count()==0) { + m_CSSValidatorCB->insertItem("http://jigsaw.w3.org/css-validator/validator"); + } + m_CSSValidatorCB->setCurrentItem(m_config->readNumEntry("CSSValidatorUrlIndex",0)); + + m_linkValidatorCB->insertStringList(m_config->readListEntry("LinkValidatorUrl")); + if (m_linkValidatorCB->count()==0) { + m_linkValidatorCB->insertItem("http://validator.w3.org/checklink"); + } + m_linkValidatorCB->setCurrentItem(m_config->readNumEntry("LinkValidatorUrlIndex",0)); + + m_WWWValidatorUploadCB->insertStringList(m_config->readListEntry("WWWValidatorUploadUrl")); + if (m_WWWValidatorUploadCB->count()==0) { + m_WWWValidatorUploadCB->insertItem("http://validator.w3.org/file-upload.html"); + } + m_WWWValidatorUploadCB->setCurrentItem(m_config->readNumEntry("WWWValidatorUploadUrlIndex",0)); + + m_CSSValidatorUploadCB->insertStringList(m_config->readListEntry("CSSValidatorUploadUrl")); + if (m_CSSValidatorUploadCB->count()==0) { + m_CSSValidatorUploadCB->insertItem("http://jigsaw.w3.org/css-validator/validator-upload.html" ); + } + m_CSSValidatorUploadCB->setCurrentItem(m_config->readNumEntry("CSSValidatorUploadUrlIndex",0)); +} + +void ValidatorsDialog::save() +{ + QStringList strList; + for (int i = 0; i < m_WWWValidatorCB->count(); i++) { + strList.append(m_WWWValidatorCB->text(i)); + } + m_config->writeEntry( "WWWValidatorUrl", strList ); + strList.clear(); + for (int i = 0; i < m_CSSValidatorCB->count(); i++) { + strList.append(m_CSSValidatorCB->text(i)); + } + m_config->writeEntry( "CSSValidatorUrl", strList ); + strList.clear(); + for (int i = 0; i < m_linkValidatorCB->count(); i++) { + strList.append(m_linkValidatorCB->text(i)); + } + m_config->writeEntry( "LinkValidatorUrl", strList ); + strList.clear(); + for (int i = 0; i < m_WWWValidatorUploadCB->count(); i++) { + strList.append(m_WWWValidatorUploadCB->text(i)); + } + m_config->writeEntry( "WWWValidatorUploadUrl", strList ); + strList.clear(); + for (int i = 0; i < m_CSSValidatorUploadCB->count(); i++) { + strList.append(m_CSSValidatorUploadCB->text(i)); + } + m_config->writeEntry( "CSSValidatorUploadUrl", strList ); + + m_config->writeEntry( "WWWValidatorUrlIndex", m_WWWValidatorCB->currentItem() ); + m_config->writeEntry( "CSSValidatorUrlIndex", m_CSSValidatorCB->currentItem() ); + m_config->writeEntry( "LinkValidatorUrlIndex", m_linkValidatorCB->currentItem() ); + m_config->writeEntry( "WWWValidatorUploadUrlIndex", m_WWWValidatorUploadCB->currentItem() ); + m_config->writeEntry( "CSSValidatorUploadUrlIndex", m_CSSValidatorUploadCB->currentItem() ); + m_config->sync(); +} + +void ValidatorsDialog::slotOk() +{ + save(); + hide(); +} + +void ValidatorsDialog::slotCancel() +{ + load(); + hide(); +} diff --git a/konq-plugins/validators/validatorsdialog.h b/konq-plugins/validators/validatorsdialog.h new file mode 100644 index 0000000..79684f5 --- /dev/null +++ b/konq-plugins/validators/validatorsdialog.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + + Copyright (C) 2001 Andreas Schlapbach <schlpbch@iam.unibe.ch> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef __validatorsdialog_h +#define __validatorsdialog_h + +#include <qcombobox.h> + +#include <kconfig.h> +#include <kdialogbase.h> + +class ValidatorsDialog : public KDialogBase +{ + Q_OBJECT + + public: + ValidatorsDialog(QWidget *parent=0, const char *name=0 ); + ~ValidatorsDialog(); + + const QString getWWWValidatorUrl() const {return m_WWWValidatorCB->currentText();} + const QString getCSSValidatorUrl() const {return m_CSSValidatorCB->currentText();} + const QString getWWWValidatorUploadUrl() const {return m_WWWValidatorUploadCB->currentText();} + const QString getCSSValidatorUploadUrl() const {return m_CSSValidatorUploadCB->currentText();} + const QString getLinkValidatorUrl() const {return m_linkValidatorCB->currentText();} + + protected slots: + void slotOk(); + void slotCancel(); + + private: + void load(); + void save(); + + QComboBox *m_WWWValidatorCB; + QComboBox *m_WWWValidatorUploadCB; + QComboBox *m_CSSValidatorCB; + QComboBox *m_CSSValidatorUploadCB; + QComboBox *m_linkValidatorCB; + KConfig *m_config; +}; + +#endif diff --git a/konq-plugins/webarchiver/Makefile.am b/konq-plugins/webarchiver/Makefile.am new file mode 100644 index 0000000..53d519e --- /dev/null +++ b/konq-plugins/webarchiver/Makefile.am @@ -0,0 +1,32 @@ +INCLUDES = $(all_includes) +KDE_CXXFLAGS = $(USE_EXCEPTIONS) +METASOURCES = AUTO + +# Install this plugin in the KDE modules directory +kde_module_LTLIBRARIES = libwebarchiverplugin.la webarchivethumbnail.la + +libwebarchiverplugin_la_SOURCES = plugin_webarchiver.cpp archiveviewbase.ui archivedialog.cpp +libwebarchiverplugin_la_LIBADD = $(LIB_KPARTS) $(LIB_KHTML) +libwebarchiverplugin_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) + +pluginsdir = $(kde_datadir)/khtml/kpartplugins +plugins_DATA = plugin_webarchiver.rc plugin_webarchiver.desktop + +appsdir = $(kde_appsdir)/.hidden +apps_DATA = plugin_webarchiver.desktop + +install-data-local: $(srcdir)/../uninstall.desktop + $(mkinstalldirs) $(DESTDIR)$(pluginsdir) + $(INSTALL_DATA) $(srcdir)/../uninstall.desktop $(DESTDIR)$(pluginsdir)/webarchiverplugin.desktop + +webarchivethumbnail_la_SOURCES = webarchivecreator.cpp +webarchivethumbnail_la_LIBADD = $(LIB_KHTML) +webarchivethumbnail_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + +servicesdir = $(kde_servicesdir) +services_DATA = webarchivethumbnail.desktop + +KDE_ICON = webarchiver + +messages: rc.cpp + $(XGETTEXT) *.cpp *.h -o $(podir)/webarchiver.pot diff --git a/konq-plugins/webarchiver/archivedialog.cpp b/konq-plugins/webarchiver/archivedialog.cpp new file mode 100644 index 0000000..71390c2 --- /dev/null +++ b/konq-plugins/webarchiver/archivedialog.cpp @@ -0,0 +1,565 @@ +/* + Copyright (C) 2001 Andreas Schlapbach <schlpbch@iam.unibe.ch> + Copyright (C) 2003 Antonio Larrosa <larrosa@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "archivedialog.h" +#include <qwidget.h> +#include <khtml_part.h> +#include "archiveviewbase.h" +#include <kinstance.h> +#include <ktempfile.h> +#include <ktar.h> + +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <kpassivepopup.h> +#include <klocale.h> +#include <kio/netaccess.h> +#include <khtml_part.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kactivelabel.h> +#include <qstylesheet.h> +#include <qiodevice.h> +#include <klistview.h> +#include <kio/job.h> +#include <kapplication.h> +#include <kurllabel.h> +#include <kprogress.h> +#include <kstringhandler.h> +#include <qpushbutton.h> + +#undef DEBUG_WAR + +#define CONTENT_TYPE "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\">" + +ArchiveDialog::ArchiveDialog(QWidget *parent, const QString &filename, + KHTMLPart *part) : + KDialogBase(parent, "WebArchiveDialog", false, i18n("Web Archiver"), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::User1 ), + m_bPreserveWS(false), m_tmpFile(0), m_url(part->url()) +{ + m_widget=new ArchiveViewBase(this); + setMainWidget(m_widget); + setWFlags(getWFlags() | WDestructiveClose); + + m_widget->urlLabel->setText(QString("<a href=\"")+m_url.url()+"\">"+KStringHandler::csqueeze( m_url.url(), 80 )+"</a>"); + m_widget->targetLabel->setText(QString("<a href=\"")+filename+"\">"+KStringHandler::csqueeze( filename, 80 )+"</a>"); + + if(part->document().ownerDocument().isNull()) + m_document = part->document(); + else + m_document = part->document().ownerDocument(); + + enableButtonOK( false ); + showButton( KDialogBase::User1, false ); + setButtonOK( KStdGuiItem::close() ); + + m_tarBall = new KTar(filename,"application/x-gzip"); +} + +void ArchiveDialog::archive() +{ + m_iterator=0; + m_currentLVI=0; + if (m_tarBall->open(IO_WriteOnly)) { +#ifdef DEBUG_WAR + kdDebug(90110) << "Web Archive opened " << endl; +#endif + + m_linkDict.insert(QString("index.html"), QString("")); + saveFile("index.html"); + + } else { + const QString title = i18n( "Unable to Open Web-Archive" ); + const QString text = i18n( "Unable to open \n %1 \n for writing." ).arg(m_tarBall->fileName()); + KMessageBox::sorry( 0L, text, title ); + } +} + +ArchiveDialog::~ArchiveDialog() +{ + delete m_tarBall; +} + +/* Store the HTMLized DOM-Tree to a temporary file and add it to the Tar-Ball */ + +void ArchiveDialog::saveFile( const QString&) +{ + KTempFile tmpFile; + if (!(tmpFile.status())) { + + QString temp; + + m_state=Retrieving; + QTextStream *tempStream = new QTextStream(&temp, IO_ReadOnly); + + saveToArchive(tempStream); + + delete tempStream; + + m_downloadedURLDict.clear(); + + m_state=Downloading; + m_widget->progressBar->setTotalSteps(m_urlsToDownload.count()); + m_widget->progressBar->setProgress(0); + downloadNext(); + + } else { + const QString title = i18n( "Could Not Open Temporary File" ); + const QString text = i18n( "Could not open a temporary file" ); + KMessageBox::sorry( 0, text, title ); + } +} + +void ArchiveDialog::setSavingState() +{ + KTempFile tmpFile; + QTextStream* textStream = tmpFile.textStream(); + textStream->setEncoding(QTextStream::UnicodeUTF8); + + m_widget->progressBar->setProgress(m_widget->progressBar->totalSteps()); + + m_state=Saving; + saveToArchive(textStream); + + tmpFile.close(); + + QString fileName="index.html"; + QFile file(tmpFile.name()); + file.open(IO_ReadOnly); + m_tarBall->writeFile(fileName, QString::null, QString::null, file.size(), file.readAll()); +#ifdef DEBUG_WAR + kdDebug(90110) << "HTML-file written: " << fileName << endl; +#endif + file.close(); + + // Cleaning up + file.remove(); + m_tarBall->close(); + + KPassivePopup::message( m_url.prettyURL() , i18n( "Archiving webpage completed." ), this ); + + enableButtonOK(true); + setEscapeButton(Ok); + actionButton(Ok)->setFocus(); + enableButtonCancel(false); +} + +/* Recursively travers the DOM-Tree */ + +void ArchiveDialog::saveToArchive(QTextStream* _textStream) +{ + if (!_textStream) return; + + // Add a doctype + + (*_textStream) <<"<!-- saved from:" << endl << m_url.url() << " -->" << endl; + + try + { + saveArchiveRecursive(m_document.documentElement(), m_url, _textStream, 0); + } + catch (...) + { + kdDebug(90110) << "exception" << endl; + } +} + +static bool hasAttribute(const DOM::Node &pNode, const QString &attrName, const QString &attrValue) +{ + const DOM::Element element = (const DOM::Element) pNode; + DOM::Attr attr; + DOM::NamedNodeMap attrs = element.attributes(); + unsigned long lmap = attrs.length(); + for( unsigned int j=0; j<lmap; j++ ) { + attr = static_cast<DOM::Attr>(attrs.item(j)); + if ((attr.name().string().upper() == attrName) && + (attr.value().string().upper() == attrValue)) + return true; + } + return false; +} + +static bool hasChildNode(const DOM::Node &pNode, const QString &nodeName) +{ + DOM::Node child; + try + { + // We might throw a DOM exception + child = pNode.firstChild(); + } + catch (...) + { + // No children, stop recursion here + child = DOM::Node(); + } + + while(!child.isNull()) { + if (child.nodeName().string().upper() == nodeName) + return true; + child = child.nextSibling(); + } + return false; +} + +/* Transform DOM-Tree to HTML */ + +void ArchiveDialog::saveArchiveRecursive(const DOM::Node &pNode, const KURL& baseURL, + QTextStream* _textStream, int indent) +{ + const QString nodeNameOrig(pNode.nodeName().string()); + const QString nodeName(pNode.nodeName().string().upper()); + QString text; + QString strIndent; + strIndent.fill(' ', indent); + const DOM::Element element = (const DOM::Element) pNode; + DOM::Node child; + + if ( !element.isNull() ) { + if (nodeName.at(0)=='-') { + /* Don't save khtml internal tags '-konq..' + * Approximating it with <DIV> + */ + text += "<DIV> <!-- -KONQ_BLOCK -->"; + } else if (nodeName == "BASE") { + /* Skip BASE, everything is relative to index.html + * Saving SCRIPT but they can cause trouble! + */ + } else if ((nodeName == "META") && hasAttribute(pNode, "HTTP-EQUIV", "CONTENT-TYPE")) { + /* Skip content-type meta tag, we provide our own. + */ + } else { + if (!m_bPreserveWS) { + if (nodeName == "PRE") { + m_bPreserveWS = true; + } + text = strIndent; + } + text += "<" + nodeNameOrig; + QString attributes; + QString attrNameOrig, attrName, attrValue; + DOM::Attr attr; + DOM::NamedNodeMap attrs = element.attributes(); + unsigned long lmap = attrs.length(); + for( unsigned int j=0; j<lmap; j++ ) { + attr = static_cast<DOM::Attr>(attrs.item(j)); + attrNameOrig = attr.name().string(); + attrName = attrNameOrig.upper(); + attrValue = attr.value().string(); + +#if 0 + if ((nodeName == "FRAME" || nodeName == "IFRAME") && attrName == "SRC") { + //attrValue = handleLink(baseURL, attrValue); + + /* Going recursively down creating a DOM-Tree for the Frame, second Level of recursion */ + //## Add Termination criteria, on the other hand frames are not indefinetly nested, are they :) + + KHTMLPart* part = new KHTMLPart(); + KURL absoluteURL = getAbsoluteURL(baseURL, attrValue); + part->openURL(absoluteURL); + saveFile(getUniqueFileName(absoluteURL.fileName()), part); + delete part; + + } else if +#endif + if ((nodeName == "LINK" && attrName == "HREF") || // Down load stylesheets, js-script, .. + ((nodeName == "FRAME" || nodeName == "IFRAME") && attrName == "SRC") || + ((nodeName == "IMG" || nodeName == "INPUT" || nodeName == "SCRIPT") && attrName == "SRC") || + ((nodeName == "BODY" || nodeName == "TABLE" || nodeName == "TH" || nodeName == "TD") && attrName == "BACKGROUND")) { + // Some people use carriage return in file names and browsers support that! + attrValue = handleLink(baseURL, attrValue.replace(QRegExp("\\s"), "")); + } + /* + * ## Make recursion level configurable + */ + /* + } else if (nodeName == "A" && attrName == "HREF") { + attrValue = handleLink(baseURL, attrValue); + */ + + attributes += " " + attrName + "=\"" + attrValue + "\""; + } + if (!(attributes.isEmpty())){ + text += " "; + } + text += attributes.simplifyWhiteSpace(); + text += ">"; + + if (nodeName == "HTML") { + /* Search for a HEAD tag, if not found, generate one. + */ + if (!hasChildNode(pNode, "HEAD")) + text += "\n" + strIndent + " <HEAD>" CONTENT_TYPE "</HEAD>"; + } + else if (nodeName == "HEAD") { + text += "\n" + strIndent + " " + CONTENT_TYPE; + } + } + } else { + const QString& nodeValue(pNode.nodeValue().string()); + if (!(nodeValue.isEmpty())) { + // Don't escape < > in JS or CSS + QString parentNodeName = pNode.parentNode().nodeName().string().upper(); + if (parentNodeName == "STYLE") { + text = analyzeInternalCSS(baseURL, pNode.nodeValue().string()); + } else if (m_bPreserveWS) { + text = QStyleSheet::escape(pNode.nodeValue().string()); + } else if (parentNodeName == "SCRIPT") { + text = pNode.nodeValue().string(); + } else { + text = strIndent + QStyleSheet::escape(pNode.nodeValue().string()); + } + } + } + +#ifdef DEBUG_WAR + kdDebug(90110) << "text:" << text << endl; +#endif + if (!(text.isEmpty())) { + (*_textStream) << text; + if (!m_bPreserveWS) { + (*_textStream) << endl; + } + } + + try + { + // We might throw a DOM exception + child = pNode.firstChild(); + } + catch (...) + { + // No children, stop recursion here + child = DOM::Node(); + } + + while(!child.isNull()) { + saveArchiveRecursive(child, baseURL, _textStream, indent+2); + child = child.nextSibling(); + } + + if (!(element.isNull())) { + if (nodeName == "AREA" || nodeName == "BASE" || nodeName == "BASEFONT" || + nodeName == "BR" || nodeName == "COL" || nodeName == "FRAME" || + nodeName == "HR" || nodeName == "IMG" || nodeName == "INPUT" || + nodeName == "ISINDEX" || nodeName == "META" || nodeName == "PARAM") { + + /* Closing Tag is forbidden, see HTML 4.01 Specs: Index of Elements */ + + } else { + if (!m_bPreserveWS) { + text = strIndent; + } else { + text =""; + } + if (nodeName.at(0)=='-') { + text += "</DIV> <!-- -KONQ_BLOCK -->"; + } else { + text += "</" + pNode.nodeName().string() + ">"; + if (nodeName == "PRE") { + m_bPreserveWS = false; + } + } +#ifdef DEBUG_WAR + kdDebug(90110) << text << endl; +#endif + if (!(text.isEmpty())) { + (*_textStream) << text; + if (!m_bPreserveWS) { + (*_textStream) << endl; + } + } + } + } +} + +/* Extract the URL, download it's content and return an unique name for the link */ + +QString ArchiveDialog::handleLink(const KURL& _url, const QString& _link) +{ + KURL url(getAbsoluteURL(_url, _link)); + + QString tarFileName; + if (kapp->authorizeURLAction("redirect", _url, url)) + { + if (m_state==Retrieving) + m_urlsToDownload.append(url); + else if (m_state==Saving) + tarFileName = m_downloadedURLDict[url.url()]; + } + + return tarFileName; +} + +void ArchiveDialog::downloadNext() +{ + if (m_iterator>=m_urlsToDownload.count()) + { + // We've already downloaded all the files we wanted, let's save them + setSavingState(); + return; + } + + KURL url=m_urlsToDownload[m_iterator]; + +#ifdef DEBUG_WAR + kdDebug(90110) << "URL : " << url.url() << endl; +#endif + QString tarFileName; + + // Only download file once + if (m_downloadedURLDict.contains(url.url())) { + tarFileName = m_downloadedURLDict[url.url()]; +#ifdef DEBUG_WAR + kdDebug(90110) << "File already downloaded: " << url.url() + << m_downloadedURLDict.count() << endl; +#endif + m_iterator++; + downloadNext(); + return; + } else { + + // Gets the name of a temporary file into m_tmpFileName + delete m_tmpFile; + m_tmpFile=new KTempFile(); + m_tmpFile->close(); + QFile::remove(m_tmpFile->name()); + kdDebug(90110) << "downloading: " << url.url() << " to: " << m_tmpFile->name() << endl; + KURL dsturl; + dsturl.setPath(m_tmpFile->name()); + KIO::Job *job=KIO::file_copy(url, dsturl, -1, false, false, false); + job->addMetaData("cache", "cache"); // Use entry from cache if available. + connect(job, SIGNAL(result( KIO::Job *)), this, SLOT(finishedDownloadingURL( KIO::Job *)) ); + + m_currentLVI=new QListViewItem(m_widget->listView, url.prettyURL()); + m_widget->listView->insertItem( m_currentLVI ); + m_currentLVI->setText(1,i18n("Downloading")); + } +#ifdef DEBUG_WAR + kdDebug(90110) << "TarFileName: [" << tarFileName << "]" << endl << endl; +#endif +} + +void ArchiveDialog::finishedDownloadingURL( KIO::Job *job ) +{ + if ( job->error() ) + { +// QString s=job->errorString(); + m_currentLVI->setText(1,i18n("Error")); + } + else + m_currentLVI->setText(1,i18n("Ok")); + + m_widget->progressBar->advance(1); + + + KURL url=m_urlsToDownload[m_iterator]; + + QString tarFileName = getUniqueFileName(url.fileName()); + + // Add file to Tar-Ball + QFile file(m_tmpFile->name()); + file.open(IO_ReadOnly); + m_tarBall->writeFile(tarFileName, QString::null, QString::null, file.size(), file.readAll()); + file.close(); + m_tmpFile->unlink(); + delete m_tmpFile; + m_tmpFile=0; + + // Add URL to downloaded URLs + + m_downloadedURLDict.insert(url.url(), tarFileName); + m_linkDict.insert(tarFileName, QString("")); + + m_iterator++; + downloadNext(); +} + +/* Create an absolute URL for download */ + +KURL ArchiveDialog::getAbsoluteURL(const KURL& _url, const QString& _link) +{ + // Does all the magic for me + return KURL(_url, _link); +} + +/* Adds an id to a fileName to make it unique relative to the Tar-Ball */ + +QString ArchiveDialog::getUniqueFileName(const QString& fileName) +{ + // Name clash -> add unique id + static int id=2; + QString uniqueFileName(fileName); + +#ifdef DEBUG_WAR + kdDebug(90110) << "getUniqueFileName(..): [" << fileName << "]" << endl; +#endif + + while (uniqueFileName.isEmpty() || m_linkDict.contains(uniqueFileName)) + uniqueFileName = QString::number(id++) + fileName; + + return uniqueFileName; +} + +/* Search for Images in CSS, extract them and adjust CSS */ + +QString ArchiveDialog::analyzeInternalCSS(const KURL& _url, const QString& string) +{ +#ifdef DEBUG_WAR + kdDebug () << "analyzeInternalCSS" << endl; +#endif + + QString str(string); + int pos = 0; + int startUrl = 0; + int endUrl = 0; + int length = string.length(); + while (pos < length && pos >= 0) { + pos = str.find("url(", pos); + if (pos!=-1) { + pos += 4; // url( + + if (str[pos]=='"' || str[pos]=='\'') // CSS 'feature' + pos++; + startUrl = pos; + pos = str.find(")",startUrl); + endUrl = pos; + if (str[pos-1]=='"' || str[pos-1]=='\'') // CSS 'feature' + endUrl--; + QString url = str.mid(startUrl, endUrl-startUrl); + +#ifdef DEBUG_WAR + kdDebug () << "url: " << url << endl; +#endif + + url = handleLink(_url, url); + +#ifdef DEBUG_WAR + kdDebug () << "url: " << url << endl; +#endif + + str = str.replace(startUrl, endUrl-startUrl, url); + pos++; + } + } + return str; +} + +#include "archivedialog.moc" diff --git a/konq-plugins/webarchiver/archivedialog.h b/konq-plugins/webarchiver/archivedialog.h new file mode 100644 index 0000000..1dc5ff8 --- /dev/null +++ b/konq-plugins/webarchiver/archivedialog.h @@ -0,0 +1,82 @@ +/* + Copyright (C) 2003 Antonio Larrosa <larrosa@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef _ARCHIVEDIALOG_H_ +#define _ARCHIVEDIALOG_H_ + +#include <dom/dom_core.h> +#include <dom/html_document.h> + +#include <kdialogbase.h> +#include <ktempfile.h> +#include <kio/job.h> + +#include <qstring.h> +#include <qmap.h> +#include <qvaluelist.h> + +class QWidget; +class KHTMLPart; +class ArchiveViewBase; +class KURL; +class KTar; +class QTextStream; +class QListViewItem; + +class ArchiveDialog : public KDialogBase +{ + Q_OBJECT +public: + ArchiveDialog(QWidget *parent, const QString &targetFilename, KHTMLPart *part); + ~ArchiveDialog(); + + void archive(); + +public slots: + void finishedDownloadingURL( KIO::Job *job ); + void setSavingState(); +protected: + void saveFile( const QString& fileName); + void saveToArchive(QTextStream* _textStream); + void saveArchiveRecursive(const DOM::Node &node, const KURL& baseURL, + QTextStream* _textStream, int ident); + QString handleLink(const KURL& _url, const QString & _link); + KURL getAbsoluteURL(const KURL& _url, const QString& _link); + QString getUniqueFileName(const QString& fileName); + QString stringToHTML(const QString& string); + QString analyzeInternalCSS(const KURL& _url, const QString& string); + void downloadNext(); + + ArchiveViewBase *m_widget; + QMap<QString, QString> m_downloadedURLDict; + QMap<QString, QString> m_linkDict; + KTar* m_tarBall; + bool m_bPreserveWS; + QListViewItem *m_currentLVI; + unsigned int m_iterator; + enum State { Retrieving=0, Downloading, Saving }; + State m_state; + QValueList <KURL>m_urlsToDownload; + KTempFile *m_tmpFile; + KURL m_url; + DOM::Document m_document; + +}; + +#endif // _ARCHIVEDIALOG_H_ diff --git a/konq-plugins/webarchiver/archiveviewbase.ui b/konq-plugins/webarchiver/archiveviewbase.ui new file mode 100644 index 0000000..a2aceb2 --- /dev/null +++ b/konq-plugins/webarchiver/archiveviewbase.ui @@ -0,0 +1,128 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ArchiveViewBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ArchiveViewBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>483</height> + </rect> + </property> + <property name="caption"> + <string>Web Archiver</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KActiveLabel" row="1" column="1"> + <property name="name"> + <cstring>targetLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Local File</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>To:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Archiving:</string> + </property> + </widget> + <widget class="KActiveLabel" row="0" column="1"> + <property name="name"> + <cstring>urlLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Original URL</string> + </property> + </widget> + </grid> + </widget> + <widget class="KProgress"> + <property name="name"> + <cstring>progressBar</cstring> + </property> + </widget> + <widget class="KListView"> + <column> + <property name="text"> + <string>URL</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <column> + <property name="text"> + <string>State</string> + </property> + <property name="clickable"> + <bool>true</bool> + </property> + <property name="resizable"> + <bool>true</bool> + </property> + </column> + <property name="name"> + <cstring>listView</cstring> + </property> + <property name="resizeMode"> + <enum>AllColumns</enum> + </property> + <property name="fullWidth"> + <bool>true</bool> + </property> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kactivelabel.h</includehint> + <includehint>kactivelabel.h</includehint> + <includehint>klistview.h</includehint> +</includehints> +</UI> diff --git a/konq-plugins/webarchiver/cr16-action-webarchiver.png b/konq-plugins/webarchiver/cr16-action-webarchiver.png Binary files differnew file mode 100644 index 0000000..aa60f00 --- /dev/null +++ b/konq-plugins/webarchiver/cr16-action-webarchiver.png diff --git a/konq-plugins/webarchiver/cr22-action-webarchiver.png b/konq-plugins/webarchiver/cr22-action-webarchiver.png Binary files differnew file mode 100644 index 0000000..ddf14ac --- /dev/null +++ b/konq-plugins/webarchiver/cr22-action-webarchiver.png diff --git a/konq-plugins/webarchiver/plugin_webarchiver.cpp b/konq-plugins/webarchiver/plugin_webarchiver.cpp new file mode 100644 index 0000000..fca9bc7 --- /dev/null +++ b/konq-plugins/webarchiver/plugin_webarchiver.cpp @@ -0,0 +1,116 @@ +/* This file is part of Webarchiver + * Copyright (C) 2001 by Andreas Schlapbach <schlpbch@iam.unibe.ch> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +/* $Id$ */ + +/* + * There are two recursions within this code: + * - Recursively create DOM-Tree for referenced links which get recursively + * converted to HTML + * + * => This code has the potential to download whole sites to a TarGz-Archive + */ + +//#define DEBUG_WAR + +#include <qdir.h> +#include <qfile.h> + +#include <kaction.h> +#include <kinstance.h> + +#include <kfiledialog.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <khtml_part.h> +#include <kdebug.h> +#include <kgenericfactory.h> +#include <kglobalsettings.h> + +#include "plugin_webarchiver.h" +#include "archivedialog.h" + +typedef KGenericFactory<PluginWebArchiver> PluginWebArchiverFactory; +K_EXPORT_COMPONENT_FACTORY( libwebarchiverplugin, + PluginWebArchiverFactory( "webarchiver" ) ) + +PluginWebArchiver::PluginWebArchiver( QObject* parent, const char* name, + const QStringList & ) + : Plugin( parent, name ) +{ + (void) new KAction( i18n("Archive &Web Page..."), + "webarchiver", 0, + this, SLOT(slotSaveToArchive()), + actionCollection(), "archivepage" ); +} + +PluginWebArchiver::~PluginWebArchiver() +{ +} + +void PluginWebArchiver::slotSaveToArchive() +{ + // ## Unicode ok? + if( !parent() || !parent()->inherits("KHTMLPart")) + return; + KHTMLPart *part = static_cast<KHTMLPart *>( parent() ); + + QString archiveName = QString::fromUtf8(part->htmlDocument().title().string().utf8()); + + if (archiveName.isEmpty()) + archiveName = i18n("Untitled"); + + // Replace space with underscore, proposed Frank Pieczynski <pieczy@knuut.de> + + archiveName = archiveName.simplifyWhiteSpace(); + archiveName.replace( "\\s:", " "); + archiveName.replace( "?", ""); + archiveName.replace( ":", ""); + archiveName.replace( "/", ""); + archiveName = archiveName.replace( QRegExp("\\s+"), " "); + + archiveName = KGlobalSettings::documentPath() + "/" + archiveName + ".war" ; + + KURL url = KFileDialog::getSaveURL(archiveName, i18n("*.war *.tgz|Web Archives"), part->widget(), + i18n("Save Page as Web-Archive") ); + + if (url.isEmpty()) { return; } + + if (!(url.isValid())) { + const QString title = i18n( "Invalid URL" ); + const QString text = i18n( "The URL\n%1\nis not valid." ).arg(url.prettyURL()); + KMessageBox::sorry(part->widget(), text, title ); + return; + } + + const QFile file(url.path()); + if (file.exists()) { + const QString title = i18n( "File Exists" ); + const QString text = i18n( "Do you really want to overwrite:\n%1?" ).arg(url.prettyURL()); + if (KMessageBox::Continue != KMessageBox::warningContinueCancel( part->widget(), text, title, i18n("Overwrite") ) ) { + return; + } + } + + ArchiveDialog *dialog=new ArchiveDialog(0L, url.path(), part); + dialog->show(); + dialog->archive(); +} + +#include "plugin_webarchiver.moc" diff --git a/konq-plugins/webarchiver/plugin_webarchiver.desktop b/konq-plugins/webarchiver/plugin_webarchiver.desktop new file mode 100644 index 0000000..3e8f55b --- /dev/null +++ b/konq-plugins/webarchiver/plugin_webarchiver.desktop @@ -0,0 +1,130 @@ +[Desktop Entry] +X-KDE-Library=webarchiver +X-KDE-PluginInfo-Author=Andreas Schlapbach +X-KDE-PluginInfo-Email=schlpbch@iam.unibe.ch +X-KDE-PluginInfo-Name=webarchiver +X-KDE-PluginInfo-Version=3.3 +X-KDE-PluginInfo-Website= +X-KDE-PluginInfo-Category=Tools +X-KDE-PluginInfo-Depends= +X-KDE-PluginInfo-License=GPL +X-KDE-PluginInfo-EnabledByDefault=true +Name=Web Archiver +Name[bg]=Уеб архиватор +Name[br]=Dieller ar gwiad +Name[bs]=Web arhiver +Name[ca]=Arxivador de webs +Name[cs]=Archivátor webu +Name[cy]=Archifydd Gwe +Name[da]=Netarkivør +Name[de]=Web-Archivierung +Name[el]=Δημιουργός αρχειοθήκης Ιστού +Name[eo]=TTT-arĥivilo +Name[es]=Archivador Web +Name[et]=Veebiarhiivid +Name[eu]=Web artxibalaria +Name[fa]=بایگانیکنندۀ وب +Name[fi]=WWW arkistot +Name[fr]=Archiveur Internet +Name[fy]=Webargiven +Name[ga]=Cartlannaí Gréasáin +Name[gl]=Arquivador Web +Name[he]=ארכיוני רשת +Name[hi]=वेब अभिलेखागार +Name[hr]=Web-arhiviranje +Name[hu]=Weboldal-archiváló +Name[is]=Safnvistuð vefgögn +Name[it]=Immagazzinatore Web +Name[ja]=ウェブアーカイバ +Name[ka]=ვებ არქივატორი +Name[kk]=Веб архивтеуіші +Name[km]=កម្មវិធីទុកបណ្ដាញជាប័ណ្ណសារ +Name[lt]=Žiniatinklių puslapių archyvavimo priemonė +Name[mk]=Веб-архивер +Name[ms]=Pengarkib Web +Name[nb]=Nett-arkivar +Name[nds]=Nettarchiv-Maker +Name[ne]=वेब सङ्ग्रहकर्ता +Name[nl]=Webarchieven +Name[nn]=Vevarkiverar +Name[pa]=ਵੈਬ ਆਰਚੀਵਰ +Name[pl]=Archiwizator stron WWW +Name[pt]=Arquivos Web +Name[pt_BR]=Arquivador Web +Name[ru]=Web-архиватор +Name[sk]=Web archívy +Name[sl]=Spletni arhivirnik +Name[sr]=Веб архивер +Name[sr@Latn]=Veb arhiver +Name[sv]=Webbarkiv +Name[ta]=வலை காப்பு +Name[tg]=Веб-архивчӣ +Name[tr]=Web Arşivleyici +Name[uk]=Архіватор Тенет +Name[uz]=Veb-arxivlagich +Name[uz@cyrillic]=Веб-архивлагич +Name[vi]=Bộ lưu trữ Mạng +Name[zh_CN]=Web 存档器 +Name[zh_TW]=Web 檔案館 +Comment=Creates archives of websites +Comment[ar]=يقوم بإنشاء أرشيفات للمواقع الشبكة +Comment[az]=Veb saytlarını arxivləyir +Comment[bg]=Създаване на архиви от уеб сайтове +Comment[bs]=Pravi arhive web stranica +Comment[ca]=Crea arxius de les pàgines web +Comment[cs]=Vytvoří archív webové stránky +Comment[cy]=Creu archifau o wefannau +Comment[da]=Opretter arkiver af netsider +Comment[de]=Erstellt ein Archiv von Webseiten +Comment[el]=Δημιουργεί αρχειοθήκες από ιστοσελίδες +Comment[eo]=Kreas arĥivojn el retsituojn +Comment[es]=Crea copias de sitios web +Comment[et]=Loob veebilehtede arhiivi +Comment[eu]=Weblekuen artxiboak sortzen ditu +Comment[fa]=بایگانیهای وبگاهها را ایجاد میکند +Comment[fi]=Luo webbisivustojen arkistoja +Comment[fr]=Crée des archives de sites Internet +Comment[fy]=Makket argiven fan websteën oan +Comment[ga]=Cruthaigh cartlann de shuímh Ghréasáin +Comment[gl]=Cria ficheiros de páxinas web +Comment[he]=יצירת ארכיונים של אתרי אינטרנט +Comment[hi]=वेबसाइटों के अभिलेखागार बनाए +Comment[hr]=Izrada arhiva od web-lokacija +Comment[hu]=Website-archiválás +Comment[is]=Býr til safnskrár af vefsetrum +Comment[it]=Crea archivi dei siti web +Comment[ja]=ウェブサイトのアーカイブを作成 +Comment[ka]=ვებ გვერდების არქივებს ქმნის +Comment[kk]=Вебсайттың архивін құру +Comment[km]=បង្កើតប័ណ្ណសាររបស់តំបន់បណ្ដាញ +Comment[lt]=Sukuria archyvus iš žiniatinklio puslapių +Comment[mk]=Креира архиви од веб-страници +Comment[ms]=Bina arkib laman web +Comment[nb]=Lager arkiver av nettsteder +Comment[nds]=Stellt Nettsiedenarchiven op +Comment[ne]=वेबसाइटहरूको सङ्ग्रह सिर्जना गर्छ +Comment[nl]=Maakt archieven van websites aan +Comment[nn]=Lagar arkiv av nettstader +Comment[pl]=Tworzy archiwa stron WWW +Comment[pt]=Cria arquivos de páginas web +Comment[pt_BR]=Cria arquivos de sites web +Comment[ro]=Creează arhive ale site-urilor web +Comment[ru]=Создание архивов web-сайтов +Comment[sk]=Vytvára archívy webových stránok +Comment[sl]=Ustvari arhive spletnih strani +Comment[sr]=Прави архиве од веб сајтова +Comment[sr@Latn]=Pravi arhive od veb sajtova +Comment[sv]=Skapar arkiv av webbplatser +Comment[ta]=வலைதளங்களின் காப்பகத்தை உருவாக்குகிறது +Comment[tg]=Эҷод кардани архивҳои веб-сайтҳо +Comment[tr]=Web sayfalarının arşivini oluşturur +Comment[uk]=Створює архіви сайтів Тенет +Comment[uz]=Veb-saytlarning arxivini yaratish +Comment[uz@cyrillic]=Веб-сайтларнинг архивини яратиш +Comment[vi]=Tạo kho lưu chỗ Mạng +Comment[xh]=Yenza iindawo zokugcina ze websites +Comment[zh_CN]=创建网站存档 +Comment[zh_TW]=建立網站的檔案 +Icon=webarchiver +X-KDE-ParentApp=konqueror +DocPath=konq-plugins/webarchiver/index.html diff --git a/konq-plugins/webarchiver/plugin_webarchiver.h b/konq-plugins/webarchiver/plugin_webarchiver.h new file mode 100644 index 0000000..2353fe1 --- /dev/null +++ b/konq-plugins/webarchiver/plugin_webarchiver.h @@ -0,0 +1,42 @@ +/* This file is part of Webarchiver + * Copyright (C) 2001 by Andreas Schlapbach <schlpbch@iam.unibe.ch> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + **/ + +/* $Id$ */ + +#ifndef plugin_webarchiver_h +#define plugin_webarchiver_h + +#include <kparts/plugin.h> +#include <klibloader.h> + +class PluginWebArchiver : public KParts::Plugin +{ + Q_OBJECT + + public: + PluginWebArchiver( QObject* parent, const char* name, + const QStringList & ); + virtual ~PluginWebArchiver(); + + public slots: + void slotSaveToArchive(); + +}; + +#endif diff --git a/konq-plugins/webarchiver/plugin_webarchiver.rc b/konq-plugins/webarchiver/plugin_webarchiver.rc new file mode 100644 index 0000000..d0369c8 --- /dev/null +++ b/konq-plugins/webarchiver/plugin_webarchiver.rc @@ -0,0 +1,11 @@ +<!DOCTYPE kpartgui> +<kpartplugin name="webarchiver" library="libwebarchiverplugin"> +<MenuBar> + <Menu name="tools"><Text>&Tools</Text> + <Action name="archivepage"/> + </Menu> +</MenuBar> +<ToolBar name="extraToolBar"><text>Extra Toolbar</text> + <Action name="archivepage"/> +</ToolBar> +</kpartplugin> diff --git a/konq-plugins/webarchiver/webarchivecreator.cpp b/konq-plugins/webarchiver/webarchivecreator.cpp new file mode 100644 index 0000000..cba7f18 --- /dev/null +++ b/konq-plugins/webarchiver/webarchivecreator.cpp @@ -0,0 +1,117 @@ +/* + Copyright (C) 2001 Malte Starostik <malte@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// $Id$ + +#include <time.h> + +#include <qpixmap.h> +#include <qimage.h> +#include <qpainter.h> + +#include <kapplication.h> +#include <khtml_part.h> + +#include "webarchivecreator.moc" + +extern "C" +{ + ThumbCreator * KDE_EXPORT new_creator() + { + return new WebArchiveCreator; + } +} + +WebArchiveCreator::WebArchiveCreator() + : m_html(0) +{ +} + +WebArchiveCreator::~WebArchiveCreator() +{ + delete m_html; +} + +bool WebArchiveCreator::create(const QString &path, int width, int height, QImage &img) +{ + if (!m_html) + { + m_html = new KHTMLPart; + connect(m_html, SIGNAL(completed()), SLOT(slotCompleted())); + m_html->setJScriptEnabled(false); + m_html->setJavaEnabled(false); + m_html->setPluginsEnabled(false); + } + KURL url; + url.setProtocol( "tar" ); + url.setPath( path ); + url.addPath( "index.html" ); + m_html->openURL( url ); + m_completed = false; + startTimer(5000); + while (!m_completed) + kapp->processOneEvent(); + killTimers(); + + // render the HTML page on a bigger pixmap and use smoothScale, + // looks better than directly scaling with the QPainter (malte) + QPixmap pix; + if (width > 400 || height > 600) + { + if (height * 3 > width * 4) + pix.resize(width, width * 4 / 3); + else + pix.resize(height * 3 / 4, height); + } + else + pix.resize(400, 600); + // light-grey background, in case loadind the page failed + pix.fill( QColor( 245, 245, 245 ) ); + + int borderX = pix.width() / width, + borderY = pix.height() / height; + QRect rc(borderX, borderY, pix.width() - borderX * 2, pix.height() - borderY * +2); + + QPainter p; + p.begin(&pix); + m_html->paint(&p, rc); + p.end(); + + img = pix.convertToImage(); + return true; +} + +void WebArchiveCreator::timerEvent(QTimerEvent *) +{ + m_html->closeURL(); + m_completed = true; +} + +void WebArchiveCreator::slotCompleted() +{ + m_completed = true; +} + +ThumbCreator::Flags WebArchiveCreator::flags() const +{ + return DrawFrame; +} + +// vim: ts=4 sw=4 et diff --git a/konq-plugins/webarchiver/webarchivecreator.h b/konq-plugins/webarchiver/webarchivecreator.h new file mode 100644 index 0000000..eae653b --- /dev/null +++ b/konq-plugins/webarchiver/webarchivecreator.h @@ -0,0 +1,51 @@ +/* + Copyright (C) 2001 Malte Starostik <malte@kde.org> + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +// $Id$ +// +#ifndef __webarchivecreator_h__ +#define __webarchivecreator_h__ + +#include <kio/thumbcreator.h> + +class KHTMLPart; + +class WebArchiveCreator : public QObject, public ThumbCreator +{ + Q_OBJECT +public: + WebArchiveCreator(); + virtual ~WebArchiveCreator(); + virtual bool create(const QString &path, int width, int height, QImage &img); + virtual Flags flags() const; + +protected: + virtual void timerEvent(QTimerEvent *); + +private slots: + void slotCompleted(); + +private: + KHTMLPart *m_html; + bool m_completed; +}; + +#endif + +// vim: ts=4 sw=4 et diff --git a/konq-plugins/webarchiver/webarchivethumbnail.desktop b/konq-plugins/webarchiver/webarchivethumbnail.desktop new file mode 100644 index 0000000..171ed05 --- /dev/null +++ b/konq-plugins/webarchiver/webarchivethumbnail.desktop @@ -0,0 +1,76 @@ +[Desktop Entry] +Type=Service +Name=Web Archives +Name[af]=Web Argiewe +Name[ar]=أرشيفات الشبكة +Name[az]=Veb Arxivləri +Name[bg]=Уеб архиви +Name[br]=Dielloù ar gwiad +Name[bs]=Web arhive +Name[ca]=Arxius web +Name[cs]=Webové archívy +Name[cy]=Archifau Wefannau +Name[da]=Netarkiver +Name[de]=Web-Archive +Name[el]=Αρχειοθήκες ιστού +Name[eo]=TTT-arĥivoj +Name[es]=Sitios web guardados +Name[et]=Veebiarhiivid +Name[eu]=Web artxiboak +Name[fa]=بایگانیهای وب +Name[fi]=WWW arkistot +Name[fo]=Vevskjalasavn +Name[fr]=Archives Internet +Name[fy]=Webargiven +Name[ga]=Cartlanna Gréasáin +Name[gl]=Arquivos Web +Name[he]=ארכיוני רשת +Name[hi]=वेब अभिलेखागार +Name[hr]=Web arhive +Name[hu]=Webes archívumok +Name[is]=Safnvistuð vefgögn +Name[it]=Archivi Web +Name[ja]=ウェブアーカイブ +Name[ka]=ვებ არქივატორები +Name[kk]=Веб ахивтеуіші +Name[km]=ប័ណ្ណសារបណ្ដាញ +Name[ko]=웹 저장고 +Name[lt]=Žiniatinklio archyvai +Name[lv]=Web Arhīvi +Name[mk]=Веб-архиви +Name[ms]=Arkib Web +Name[mt]=Arkivji webb +Name[nb]=Vev-arkiver +Name[nds]=Nettarchiven +Name[ne]=वेब सङ्ग्रह +Name[nl]=Webarchieven +Name[nn]=Vevarkiv +Name[nso]=Dipolokelo tsa Web +Name[pa]=ਵੈਬ ਆਰਚੀਵ +Name[pl]=Archiwa WWW +Name[pt]=Arquivos Web +Name[pt_BR]=Arquivos Web +Name[ro]=Arhive web +Name[ru]=Web-архивы +Name[sk]=Web archívy +Name[sl]=Spletni arhivi +Name[sr]=Веб архиве +Name[sr@Latn]=Veb arhive +Name[sv]=Webbarkiv +Name[ta]=வலை காப்புகள் +Name[tg]=Веб-архивҳо +Name[th]=แฟ้มบีบอัดของเว็บ +Name[tr]=Web Arşivleri +Name[uk]=Архіви Тенет +Name[uz]=Veb-arxivlar +Name[uz@cyrillic]=Веб-архивлар +Name[ven]=Dziwebu dzau vhulunga zwa kale +Name[vi]=Kho lưu Mạng +Name[xh]=Iindawo zokugcina ze web +Name[zh_CN]=Web 存档 +Name[zh_TW]=Web 檔案館 +Name[zu]=Ushicilelo lukawonke umuntu kanye nemiqulu emidala yeWeb +ServiceTypes=ThumbCreator +MimeTypes=application/x-webarchive +X-KDE-Library=webarchivethumbnail +CacheThumbnail=true |