You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeaddons/konq-plugins/sidebar/metabar/src/metabarwidget.cpp

593 lines
17 KiB

/***************************************************************************
* 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., *
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include "metabarwidget.h"
#include "configdialog.h"
#include "defaultplugin.h"
#include "settingsplugin.h"
#include "remoteplugin.h"
#include "httpplugin.h"
#include <tqwidget.h>
#include <tqlayout.h>
#include <tqdir.h>
#include <tqfile.h>
#include <tqtextstream.h>
#include <tqvaluelist.h>
#include <tqurl.h>
#include <tqbuffer.h>
#include <tdehtmlview.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 <tdecmoduleinfo.h>
#include <kmdcodec.h>
#include <tdeparts/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(TQWidget *parent, const char *name) : TQWidget(parent, name)
{
skip = false;
loadComplete = false;
currentItems = new KFileItemList;
currentItems->setAutoDelete(true);
config = new TDEConfig("metabarrc");
dir_watch = new KDirWatch();
connect(dir_watch, TQT_SIGNAL(dirty(const TQString&)), this, TQT_SLOT(slotUpdateCurrentInfo(const TQString&)));
connect(dir_watch, TQT_SIGNAL(created(const TQString&)), this, TQT_SLOT(slotUpdateCurrentInfo(const TQString&)));
connect(dir_watch, TQT_SIGNAL(deleted(const TQString&)), this, TQT_SLOT(slotDeleteCurrentInfo(const TQString&)));
html = new KHTMLPart(this, "metabarhtmlpart");
html->setJScriptEnabled(true);
html->setPluginsEnabled(true);
html->setCaretVisible(false);
html->setDNDEnabled(false);
html->setJavaEnabled(false);
html->view()->setSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding);
html->view()->hide();
connect(html->browserExtension(), TQT_SIGNAL(openURLRequest( const KURL &, const KParts::URLArgs & )), this, TQT_SLOT(handleURLRequest(const KURL &, const KParts::URLArgs &)));
connect(html, TQT_SIGNAL(completed()), this, TQT_SLOT(loadCompleted()));
connect(html, TQT_SIGNAL(popupMenu(const TQString &, const TQPoint &)), this, TQT_SLOT(slotShowPopup(const TQString&, const TQPoint &)));
functions = new MetabarFunctions(html, TQT_TQOBJECT(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);
TQVBoxLayout *layout = new TQVBoxLayout(this);
layout->addWidget(html->view());
popup = new KPopupMenu(0);
KAction *configAction = new KAction(i18n("Configure %1...").arg("Metabar"), "configure", KShortcut(), TQT_TQOBJECT(this), TQT_SLOT(slotShowConfig()), html->actionCollection(), "configure");
configAction->plug(popup);
KAction *reloadAction = new KAction(i18n("Reload Theme"), "reload", KShortcut(), TQT_TQOBJECT(this), TQT_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();
}
TQString protocol = currentItems->getFirst()->url().protocol();
currentPlugin = plugins[protocol];
if(!currentPlugin){
currentPlugin = defaultPlugin;
}
ProtocolPlugin::activePlugin = currentPlugin;
currentPlugin->setFileItems(*currentItems);
}
TQString MetabarWidget::getCurrentURL()
{
DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name());
DCOPReply reply = ref.call("currentURL()");
if (reply.isValid()) {
TQString url;
reply.get(url, TQSTRING_OBJECT_NAME_STRING);
if(!url.isNull() && !url.isEmpty()){
return url;
}
}
return 0;
}
void MetabarWidget::openURL(const TQString &url)
{
DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name());
DCOPReply reply = ref.call("openURL", url);
}
void MetabarWidget::openTab(const TQString &url)
{
DCOPRef ref(kapp->dcopClient()->appId(), this->topLevelWidget()->name());
DCOPReply reply = ref.call("newTab", url);
}
void MetabarWidget::callAction(const TQString &action)
{
DCOPRef ref(kapp->dcopClient()->appId(), TQString(TQString(this->topLevelWidget()->name()).append("/action/").append(action)).utf8());
if(ref.call("enabled()")){
ref.call("activate()");
}
}
void MetabarWidget::loadLinks()
{
config->setGroup("General");
TQStringList 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(TQStringList::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")){
TQString text = node.innerText().string();
node.setInnerText(DOM::DOMString(i18n(text.utf8().data())));
}
if(node.hasAttribute("image")){
TQString icon = node.getAttribute("image").string();
TQString url = getIconPath(icon);
TQString style = TQString("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")){
TQString text = node.innerText().string();
node.setInnerText(DOM::DOMString(i18n(text.utf8().data())));
}
}
}
config->setGroup("General");
TQString file = locate("data", TQString("metabar/themes/%1/default.css").arg(config->readEntry("Theme", "default")));
if(file.isNull()){
file = locate("data", TQString("metabar/themes/default/default.css"));
}
TQFile cssfile(file);
if(cssfile.open(IO_ReadOnly)){
TQTextStream stream( &cssfile );
TQString tmp = stream.read();
cssfile.close();
tmp.replace("./", KURL::fromPathOrURL(file).directory(false));
html->setUserStyleSheet(tmp);
}
loadComplete = true;
html->view()->setFrameShape(config->readBoolEntry("ShowFrame", true) ? TQFrame::StyledPanel : TQFrame::NoFrame);
html->view()->show();
if(currentItems && !currentItems->isEmpty()){
setFileItems(*currentItems, false);
}
else{
TQString 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;
}
TQString protocol = url.protocol();
if(currentPlugin->handleRequest(url)){
return;
}
if(protocol == "desktop"){
TQString path = url.path();
if(KDesktopFile::isDesktopFile(path)){
KRun::run(new KDesktopFile(path, true), KURL::List());
}
}
else if(protocol == "tdecmshell"){
TQString module = url.path().remove('/');
KRun::runCommand("tdecmshell " + module);
}
else if(protocol == "action"){
TQString action = url.url().right(url.url().length() - 9);
if(action.startsWith("metabar/")){
TQString 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 += TQString("<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 += TQString(TQString().setNum(image.width()));
innerHTML += "\" height=\"";
innerHTML += TQString(TQString().setNum(image.height()));
innerHTML += "\" /></ul>";
node.setInnerHTML(innerHTML);
}
}
}
else if(protocol == "more"){
TQString 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")){
TQString style = TQString("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());
}
}
}
TQString MetabarWidget::getIconPath(const TQString &name)
{
TQPixmap icon = SmallIcon(name);
TQByteArray data;
TQBuffer buffer(data);
buffer.open(IO_WriteOnly);
icon.save(&buffer, "PNG");
return TQString::fromLatin1("data:image/png;base64,%1").arg(KCodecs::base64Encode(data).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() == TQDialog::Accepted){
config->reparseConfiguration();
setFileItems(*currentItems, false);
loadLinks();
setTheme();
html->view()->setFrameShape(config->readBoolEntry("ShowFrame", true) ? TQFrame::StyledPanel : TQFrame::NoFrame);
}
delete config_dialog;
}
void MetabarWidget::slotShowPopup(const TQString &url, const TQPoint &point)
{
popup->exec(point);
}
void MetabarWidget::slotUpdateCurrentInfo(const TQString &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 TQString&)
{
if(currentItems && currentItems->count() == 1){
TQString 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 TQString name, const TQString url, const TQString icon, const TQString id, const TQString 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");
TQString file = locate("data", TQString("metabar/themes/%1/layout.html").arg(config->readEntry("Theme", "default")));
html->openURL(KURL(file));
}
#include "metabarwidget.moc"