diff options
Diffstat (limited to 'kftpgrabber/src/widgets')
83 files changed, 17190 insertions, 0 deletions
diff --git a/kftpgrabber/src/widgets/Makefile.am b/kftpgrabber/src/widgets/Makefile.am new file mode 100644 index 0000000..fa99f84 --- /dev/null +++ b/kftpgrabber/src/widgets/Makefile.am @@ -0,0 +1,28 @@ +INCLUDES = -I$(srcdir)/.. \ + -I$(srcdir)/../engine \ + -I$(srcdir)/../misc \ + -I$(srcdir)/../widgets/browser \ + -I.. \ + -I../ui \ + $(all_includes) + +METASOURCES = AUTO + +noinst_LTLIBRARIES = +noinst_LIBRARIES = libwidgets.a +libwidgets_a_SOURCES = logview.cpp kftpselectserverdialog.cpp \ + kftpselectserverdialog.h kftpserverlineedit.cpp kftpserverlineedit.h listview.cpp \ + quickconnect.cpp systemtray.cpp balloon.cpp searchdialog.cpp \ + kftpzeroconflistview.cpp trafficgraph.cpp kftptabwidget.cpp failedtransfers.cpp \ + listviewitem.cpp sidebar.cpp multitabbar.cpp configdialog.cpp \ + configfilter.cpp verifier.cpp filtereditor.cpp widgetlister.cpp overlaywidget.cpp \ + popupmessage.cpp + +SUBDIRS = queueview browser bookmarks + +noinst_HEADERS = listview.h quickconnect.h systemtray.h searchdialog.h \ + kftpzeroconflistview.h trafficgraph.h kftptabwidget.h \ + logview.h failedtransfers.h listviewitem.h sidebar.h multitabbar.h \ + multitabbar_p.h configdialog.h configfilter.h verifier.h balloon.h filtereditor.h \ + widgetlister.h overlaywidget.h popupmessage.h + diff --git a/kftpgrabber/src/widgets/balloon.cpp b/kftpgrabber/src/widgets/balloon.cpp new file mode 100644 index 0000000..eb10432 --- /dev/null +++ b/kftpgrabber/src/widgets/balloon.cpp @@ -0,0 +1,145 @@ +/*
+ * This file is part of the KFTPGrabber project
+ *
+ * Copyright (C) 2003-2005 by the KFTPGrabber developers
+ * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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
+ * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied
+ * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and
+ * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * In addition, as a special exception, the copyright holders give
+ * permission to link the code of portions of this program with the
+ * OpenSSL library under certain conditions as described in each
+ * individual source file, and distribute linked combinations
+ * including the two.
+ *
+ * You must obey the GNU General Public License in all respects
+ * for all of the code used other than OpenSSL. If you modify
+ * file(s) with this exception, you may extend this exception to your
+ * version of the file(s), but you are not obligated to do so. If you
+ * do not wish to do so, delete this exception statement from your
+ * version. If you delete this exception statement from all source
+ * files in the program, then also delete it here.
+ */
+
+#include <qpointarray.h>
+#include <qpushbutton.h>
+#include <qtooltip.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include <kapplication.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kstandarddirs.h>
+#include <kactivelabel.h>
+#include <kglobalsettings.h>
+
+#include "widgets/balloon.h"
+#include "misc.h"
+
+using namespace KFTPGrabberBase;
+
+namespace KFTPWidgets {
+
+Balloon::Balloon(const QString &text, const QString &pix)
+ : QWidget(0L, "KFTPBalloon", WStyle_StaysOnTop | WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WX11BypassWM)
+{
+ setCaption("");
+
+ QVBoxLayout *BalloonLayout = new QVBoxLayout(this, 22, KDialog::spacingHint(), "BalloonLayout");
+
+ // BEGIN Layout1
+ QHBoxLayout *Layout1 = new QHBoxLayout(BalloonLayout, KDialog::spacingHint(), "Layout1");
+ KActiveLabel *caption = new KActiveLabel(text, this, "caption");
+ caption->setPalette(QToolTip::palette());
+ caption->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
+
+ if (!pix.isEmpty()) {
+ QLabel *image = new QLabel(this, "mImage");
+ image->setScaledContents(FALSE);
+ image->setPixmap(loadSmallPixmap(pix));
+
+ Layout1->addWidget(image);
+ }
+
+ Layout1->addWidget(caption);
+ // END Layout1
+
+ setPalette(QToolTip::palette());
+ setAutoMask(true);
+
+ connect(caption, SIGNAL(clicked(int, int)), this, SIGNAL(signalBalloonClicked()));
+ connect(caption, SIGNAL(linkClicked(const QString &)), this, SIGNAL(signalIgnoreButtonClicked()));
+ connect(caption, SIGNAL(linkClicked(const QString &)), this, SLOT(deleteLater()));
+}
+
+void Balloon::mousePressEvent(QMouseEvent *e)
+{
+ emit signalBalloonClicked();
+ e->accept();
+}
+
+void Balloon::setAnchor(const QPoint &anchor)
+{
+ m_anchor = anchor;
+ updateMask();
+}
+
+void Balloon::updateMask()
+{
+ QRegion mask(10, 10, width() - 20, height() - 20);
+
+ QPoint corners[8] = {
+ QPoint(width() - 50, 10),
+ QPoint(10, 10),
+ QPoint(10, height() - 50),
+ QPoint(width() - 50, height() - 50),
+ QPoint(width() - 10, 10),
+ QPoint(10, 10),
+ QPoint(10, height() - 10),
+ QPoint(width() - 10, height() - 10)
+ };
+
+ for (int i = 0; i < 4; ++i) {
+ QPointArray corner;
+ corner.makeArc(corners[i].x(), corners[i].y(), 40, 40, i * 16 * 90, 16 * 90);
+ corner.resize(corner.size() + 1);
+ corner.setPoint(corner.size() - 1, corners[i + 4]);
+ mask -= corner;
+ }
+
+ // get screen-geometry for screen our anchor is on
+ // (geometry can differ from screen to screen!)
+ QRect deskRect = KGlobalSettings::desktopGeometry(m_anchor);
+
+ bool bottom = (m_anchor.y() + height()) > (deskRect.height() - 48);
+ bool right = (m_anchor.x() + width()) > (deskRect.width() - 48);
+
+ QPointArray arrow(4);
+ arrow.setPoint(0, QPoint(right ? width() : 0, bottom ? height() : 0));
+ arrow.setPoint(1, QPoint(right ? width() - 10 : 10, bottom ? height() - 30 : 30));
+ arrow.setPoint(2, QPoint(right ? width() - 30 : 30, bottom ? height() - 10 : 10));
+ arrow.setPoint(3, arrow[0]);
+ mask += arrow;
+ setMask(mask);
+
+ move(right ? m_anchor.x() - width() : m_anchor.x(), bottom ? m_anchor.y() - height() : m_anchor.y());
+}
+
+}
+
+#include "balloon.moc"
+
diff --git a/kftpgrabber/src/widgets/balloon.h b/kftpgrabber/src/widgets/balloon.h new file mode 100644 index 0000000..c123ae7 --- /dev/null +++ b/kftpgrabber/src/widgets/balloon.h @@ -0,0 +1,86 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSBALLOON_H +#define KFTPWIDGETSBALLOON_H + +#include <qwidget.h> + +namespace KFTPWidgets { + +/** + * A little balloon for notifications taken from Kopete with some modifications + * for KFTPGrabber. + * + * @author Malte Starostik <malte@kde.org> + * @author Duncan Mac-Vicar Prett <duncan@kde.org> + */ +class Balloon : public QWidget +{ +Q_OBJECT +public: + /** + * Class constructor. + * + * @param text The text to display inside the balloon + * @param pic Name of the pixmap to display inside the balloon + */ + Balloon(const QString &text, const QString &pic); + + /** + * Set widget anchor. + * + * @param anchor Anchor coordinates + */ + void setAnchor(const QPoint &anchor); + + /** + * Intercept mouse press events. + */ + void mousePressEvent(QMouseEvent *e); +signals: + void signalButtonClicked(); + void signalIgnoreButtonClicked(); + void signalBalloonClicked(); +protected: + void updateMask(); +private: + QPoint m_anchor; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/bookmarks/Makefile.am b/kftpgrabber/src/widgets/bookmarks/Makefile.am new file mode 100644 index 0000000..d735a01 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = -I$(top_builddir)/kftpgrabber/src \ + -I$(srcdir)/../.. \ + -I$(srcdir)/../../engine \ + -I$(srcdir)/../../misc \ + -I$(srcdir)/../../widgets \ + -I$(srcdir)/../../widgets/browser \ + -I$(srcdir)/../../ui \ + -I$(top_builddir)/kftpgrabber/src/ui \ + $(all_includes) +METASOURCES = AUTO +noinst_LIBRARIES = libbookmarkwidgets.a +noinst_HEADERS = editor.h editortls.h listview.h importwizard.h sidebar.h +libbookmarkwidgets_a_SOURCES = editor.cpp editortls.cpp listview.cpp importwizard.cpp sidebar.cpp diff --git a/kftpgrabber/src/widgets/bookmarks/editor.cpp b/kftpgrabber/src/widgets/bookmarks/editor.cpp new file mode 100644 index 0000000..88ba05c --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/editor.cpp @@ -0,0 +1,492 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include <qlayout.h> +#include <qpushbutton.h> +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qspinbox.h> +#include <qsplitter.h> +#include <qtextedit.h> +#include <qtabwidget.h> + +#include <kglobal.h> +#include <kcharsets.h> +#include <klocale.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <kpassdlg.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kcombobox.h> +#include <kurlrequester.h> +#include <kguiitem.h> +#include <kfiledialog.h> +#include <kio/job.h> + +#include "kftpapi.h" +#include "kftpbookmarks.h" +#include "misc/config.h" +#include "misc.h" + +#include "editor.h" +#include "listview.h" +#include "importwizard.h" +#include "editortls.h" + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Bookmarks { + +KActionCollection *BookmarkEditor::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +BookmarkEditor::BookmarkEditor(QWidget *parent, const char *name) + : KDialogBase(parent, name, true, "FTP Bookmark Editor", User2|User1|Ok|Apply|Cancel, Ok, true, KGuiItem(i18n("Import...")), KGuiItem(i18n("Export..."))), + m_activeSite(0), + m_activeItem(0L), + m_portChanged(false) +{ + // We operate on a copy of the bookmarks + m_bookmarks = new KFTPBookmarks::Manager(*KFTPBookmarks::Manager::self()); + + QHBoxLayout *winLayout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + QSplitter *splitter = new QSplitter(this); + setMainWidget(splitter); + winLayout->addWidget(splitter); + + // Create the list view for editing bookmarks + m_tree = new ListView(m_bookmarks, splitter); + + m_properties = new BookmarkProperties(splitter); + + initDialog(); + + connect(this, SIGNAL(user1Clicked()), this, SLOT(slotImportWizard())); + connect(this, SIGNAL(user2Clicked()), this, SLOT(slotExportWizard())); + + connect(m_tree, SIGNAL(bookmarkClicked(QListViewItem*)), this, SLOT(slotTreeClicked(QListViewItem*))); + connect(m_tree, SIGNAL(bookmarkNew(ListViewItem*, KFTPBookmarks::Site*)), this, SLOT(slotNewAction(ListViewItem*, KFTPBookmarks::Site*))); + connect(m_tree, SIGNAL(bookmarkDuplicated(ListViewItem*, KFTPBookmarks::Site*)), this, SLOT(slotDuplicateAction(ListViewItem*, KFTPBookmarks::Site*))); + connect(m_tree, SIGNAL(bookmarkDeleted()), this, SLOT(slotDeleteAction())); + connect(m_tree, SIGNAL(bookmarkMoved()), this, SLOT(refresh())); + connect(m_tree, SIGNAL(categoryRenamed()), this, SLOT(refresh())); + + // Get the new bookmark data + m_tree->fillBookmarkData(); +} + +BookmarkEditor::BookmarkEditor(ListViewItem *item, QWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("FTP Bookmark Editor"), Ok|Apply|Cancel, Ok, true), + m_activeSite(0), + m_activeItem(item), + m_tree(0L), + m_portChanged(false) +{ + setCaption(m_activeItem->text(0)); + + // We operate on a copy of the bookmarks + m_bookmarks = new KFTPBookmarks::Manager(*KFTPBookmarks::Manager::self()); + + QHBoxLayout *winLayout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_properties = new BookmarkProperties(this); + setMainWidget(m_properties); + winLayout->addWidget(m_properties); + + initDialog(); + + m_activeSite = m_activeItem->m_site; + + showActiveNode(); +} + +BookmarkEditor::~BookmarkEditor() +{ + delete m_bookmarks; +} + +void BookmarkEditor::initDialog() +{ + m_properties->tabList->setTabIconSet(m_properties->general, loadSmallIcon("kfm")); + m_properties->tabList->setTabIconSet(m_properties->advanced, loadSmallIcon("contents")); + m_properties->tabList->setTabIconSet(m_properties->keepalive, loadSmallIcon("clock")); + m_properties->protoAdvanced->setIconSet(loadSmallIcon("configure")); + m_properties->retryGroup->setEnabled(false); + m_properties->defLocalDir->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly ); + + connect(m_properties->anonLogin, SIGNAL(clicked()), this, SLOT(slotChangeAnonLogin())); + connect(m_properties->doRetry, SIGNAL(clicked()), this, SLOT(slotChangeActiveRetryGroup())); + connect(m_properties->doKeepalive, SIGNAL(clicked()), this, SLOT(slotChangeActiveKeepaliveGroup())); + connect(m_properties->protoAdvanced, SIGNAL(clicked()), this, SLOT(slotProtoAdvancedClicked())); + connect(m_properties->serverProtocol, SIGNAL(activated(int)), this, SLOT(slotChangeServerProtocol(int))); + connect(m_properties->serverPort, SIGNAL(valueChanged(int)), this, SLOT(slotPortChanged())); + + connect(this, SIGNAL(applyClicked()), this, SLOT(slotSaveActiveNode())); + connect(this, SIGNAL(okClicked()), this, SLOT(slotSaveActiveNode())); + + // Populate charsets + QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames(); + m_properties->serverEncoding->insertStringList(charsets); + + // Deactivate everything until an item gets selected + m_properties->setEnabled(false); +} + +void BookmarkEditor::refresh() +{ + m_tree->clear(); + m_tree->fillBookmarkData(); +} + +void BookmarkEditor::slotImportWizard() +{ + ImportWizard *wizard = new ImportWizard(this); + + if (wizard->exec() == QDialog::Accepted) { + // Refresh bookmarks + m_bookmarks->setBookmarks(KFTPBookmarks::Manager::self()); + + m_tree->clear(); + m_tree->fillBookmarkData(); + } + + delete wizard; +} + +void BookmarkEditor::slotExportWizard() +{ + if (KMessageBox::questionYesNo(0, i18n("<qt>You are about to export your KFTPGrabber bookmarks. They may contain passwords or sensitive X509 certificates; exporting your bookmarks may compromise their safety.<br><br>Are you sure?</qt>"), i18n("Export Bookmarks")) == KMessageBox::No) { + return; + } + + QString savePath = KFileDialog::getSaveFileName(QString::null, "*.xml|KFTPGrabber Bookmarks", 0, i18n("Export Bookmarks")); + + if (!savePath.isEmpty()) { + // Save and copy the bookmarks + KFTPBookmarks::Manager::self()->save(); + KIO::copy(KURL(getStoreDir("bookmarks.xml")), KURL(savePath), false); + } +} + +void BookmarkEditor::slotNewAction(ListViewItem *item, KFTPBookmarks::Site *site) +{ + // Display the new server's properties + m_activeItem = item; + m_activeSite = site; + + showActiveNode(); + + // Set Focus to servername + m_properties->serverName->selectAll(); + m_properties->serverName->setFocus(); +} + +void BookmarkEditor::slotDuplicateAction(ListViewItem *item, KFTPBookmarks::Site *site) +{ + m_activeItem = item; + + // Display its properties + m_activeSite = site; + + showActiveNode(); +} + +void BookmarkEditor::slotDeleteAction() +{ + m_activeItem = 0L; + m_properties->setEnabled(false); +} + +void BookmarkEditor::slotSaveActiveNode() +{ + if (!m_activeItem) { + KFTPBookmarks::Manager::self()->setBookmarks(m_bookmarks); + return; + } + + m_activeSite->setAttribute("name", m_properties->serverName->text()); + m_activeSite->setProperty("host", m_properties->serverAddress->text()); + m_activeSite->setProperty("port", m_properties->serverPort->value()); + m_activeSite->setProperty("protocol", m_properties->serverProtocol->currentItem() == SP_SFTP ? "sftp" : "ftp"); + m_activeSite->setProperty("use_tls", m_properties->serverProtocol->currentItem() == SP_SSL_EXPLICIT); + m_activeSite->setProperty("use_implicit", m_properties->serverProtocol->currentItem() == SP_SSL_IMPLICIT); + m_activeSite->setProperty("anonlogin", m_properties->anonLogin->isChecked()); + + m_activeSite->setProperty("username", m_properties->downUser->text()); + m_activeSite->setProperty("password", encodePassword(m_properties->downPass->password())); + + m_activeSite->setProperty("encoding", KGlobal::charsets()->encodingForName(m_properties->serverEncoding->currentText())); + + // Only save the local dir if it differs from the default one + if (m_properties->defLocalDir->url() != KFTPCore::Config::defLocalDir()) + m_activeSite->setProperty("deflocalpath", m_properties->defLocalDir->url()); + + m_activeSite->setProperty("defremotepath", m_properties->defRemoteDir->text()); + m_activeSite->setProperty("description", m_properties->description->text()); + + m_activeSite->setProperty("doRetry", m_properties->doRetry->isChecked()); + m_activeSite->setProperty("retrytime", m_properties->retryDelay->value()); + m_activeSite->setProperty("retrycount", m_properties->retryCount->value()); + + m_activeSite->setProperty("doKeepalive", m_properties->doKeepalive->isChecked()); + m_activeSite->setProperty("keepaliveTimeout", m_properties->keepaliveTimeout->value()); + + m_activeSite->setProperty("disablePASV", m_properties->disablePASV->isChecked()); + m_activeSite->setProperty("disableEPSV", m_properties->disableEPSV->isChecked()); + m_activeSite->setProperty("pasvSiteIp", m_properties->pasvSiteIp->isChecked()); + m_activeSite->setProperty("disableForceIp", m_properties->disableForceIp->isChecked()); + m_activeSite->setProperty("disableThreads", m_properties->threadsDisable->isChecked()); + m_activeSite->setProperty("statListings", m_properties->statListings->isChecked()); + + // Update the ListView node + m_activeItem->setText(0, m_properties->serverName->text()); + + if (m_tree) + KFTPBookmarks::Manager::self()->setBookmarks(m_bookmarks); + + showActiveNode(); + + // Save the bookmarks + KFTPBookmarks::Manager::self()->save(); +} + +void BookmarkEditor::showActiveNode() +{ + if (m_activeItem->m_type == BT_CATEGORY || !m_activeSite) { + m_properties->setEnabled(false); + return; + } + + m_properties->setEnabled(true); + + // Show all the data for the active node + m_properties->serverName->setText(m_activeSite->getAttribute("name")); + m_properties->serverAddress->setText(m_activeSite->getProperty("host")); + + if (m_activeSite->getProperty("protocol") == "sftp") m_properties->serverProtocol->setCurrentItem(SP_SFTP); + else if (m_activeSite->getIntProperty("use_tls")) m_properties->serverProtocol->setCurrentItem(SP_SSL_EXPLICIT); + else if (m_activeSite->getIntProperty("use_implicit")) m_properties->serverProtocol->setCurrentItem(SP_SSL_IMPLICIT); + else m_properties->serverProtocol->setCurrentItem(SP_FTP); + + slotChangeServerProtocol(m_properties->serverProtocol->currentItem()); + + + m_properties->serverPort->setValue(m_activeSite->getIntProperty("port")); + m_portChanged = false; + + m_properties->downUser->erase(); + m_properties->downPass->erase(); + m_properties->anonLogin->setChecked(m_activeSite->getIntProperty("anonlogin")); + + slotChangeAnonLogin(); + + m_properties->downUser->setText(m_activeSite->getProperty("username")); + m_properties->downPass->insert(m_activeSite->getProperty("password")); + + QString defLocalPath = m_activeSite->getProperty("deflocalpath"); + if (defLocalPath.isEmpty()) + defLocalPath = KFTPCore::Config::defLocalDir(); + + m_properties->defLocalDir->setURL(defLocalPath); + m_properties->defRemoteDir->setText(m_activeSite->getProperty("defremotepath")); + m_properties->description->setText(m_activeSite->getProperty("description")); + + int retryTime = m_activeSite->getIntProperty("retrytime"); + int retryCount = m_activeSite->getIntProperty("retrycount"); + + m_properties->doRetry->setChecked(m_activeSite->getIntProperty("doRetry")); + + if (m_properties->doRetry->isChecked()) { + m_properties->retryGroup->setEnabled(true); + m_properties->retryDelay->setValue(retryTime); + m_properties->retryCount->setValue(retryCount); + } else { + m_properties->retryGroup->setEnabled(false); + m_properties->retryDelay->setValue(KFTPCore::Config::retryTime()); + m_properties->retryCount->setValue(KFTPCore::Config::retryCount()); + } + + m_properties->doKeepalive->setChecked(m_activeSite->getIntProperty("doKeepalive")); + + if (m_properties->doKeepalive->isChecked()) { + m_properties->keepaliveGroup->setEnabled(true); + m_properties->keepaliveTimeout->setValue(m_activeSite->getIntProperty("keepaliveTimeout")); + } else { + m_properties->keepaliveGroup->setEnabled(false); + m_properties->keepaliveTimeout->setValue(60); + } + + QString serverEncoding = m_activeSite->getProperty("encoding"); + if (serverEncoding.isEmpty()) + serverEncoding = KFTPCore::Config::defEncoding(); + + serverEncoding = QString("%1 ( %2 )").arg(KGlobal::charsets()->languageForEncoding(serverEncoding)).arg(serverEncoding); + m_properties->serverEncoding->setCurrentText(serverEncoding); + + m_properties->disablePASV->setChecked(m_activeSite->getIntProperty("disablePASV")); + m_properties->disableEPSV->setChecked(m_activeSite->getIntProperty("disableEPSV")); + m_properties->pasvSiteIp->setChecked(m_activeSite->getIntProperty("pasvSiteIp")); + m_properties->disableForceIp->setChecked(m_activeSite->getIntProperty("disableForceIp")); + m_properties->threadsDisable->setChecked(m_activeSite->getIntProperty("disableThreads")); + m_properties->statListings->setChecked(m_activeSite->getIntProperty("statListings")); +} + +void BookmarkEditor::slotTreeClicked(QListViewItem *item) +{ + m_activeItem = static_cast<ListViewItem*>(item); + + if ( !m_activeItem || m_activeItem->m_type == BT_CATEGORY ) { + // Deactivate all controls + m_properties->setEnabled(false); + return; + } + + // Find the node and set it active + if (m_activeItem->m_type == BT_CATEGORY) { + // Category + m_activeSite = 0L; + } else { + // Server + m_activeSite = m_activeItem->m_site; + } + + // Show the active node (if any) + showActiveNode(); +} + +void BookmarkEditor::slotChangeActiveRetryGroup() +{ + m_properties->retryGroup->setEnabled(m_properties->doRetry->isChecked()); +} + +void BookmarkEditor::slotChangeActiveKeepaliveGroup() +{ + m_properties->keepaliveGroup->setEnabled(m_properties->doKeepalive->isChecked()); +} + +void BookmarkEditor::slotChangeAnonLogin() +{ + static QString tmpUser, tmpPass; + + if (m_properties->anonLogin->isChecked()) { + m_properties->downUser->setEnabled(false); + m_properties->downPass->setEnabled(false); + tmpUser = m_properties->downUser->text(); + tmpPass = m_properties->downPass->text(); + m_properties->downUser->setText("anonymous"); + + // Use the appropriate e-mail address for anonymous accounts + if (!KFTPCore::Config::anonMail().isEmpty()) + m_properties->downPass->setText(KFTPCore::Config::anonMail()); + else + m_properties->downPass->setText("userlogin@anonymo.us"); + } else { + m_properties->downUser->setEnabled(true); + m_properties->downPass->setEnabled(true); + m_properties->downUser->setText(tmpUser); + m_properties->downPass->setText(tmpPass); + } +} + +void BookmarkEditor::slotProtoAdvancedClicked() +{ + BookmarkEditorTLS *tlsDialog = new BookmarkEditorTLS(this); + + // Initialize dialog + int mode = m_activeSite->getIntProperty("tls_data_mode"); + bool useCert = m_activeSite->getIntProperty("use_cert"); + QString certPath = m_activeSite->getProperty("tls_cert_path"); + + tlsDialog->setTLSMode(mode); + tlsDialog->setCertChecked(useCert); + if (useCert) + tlsDialog->setCertPath(certPath); + tlsDialog->slotChangeActiveX509Group(); + + if (tlsDialog->exec()) { + // Save the modifications + m_activeSite->setProperty("tls_data_mode", tlsDialog->getTLSMode()); + m_activeSite->setProperty("use_cert", tlsDialog->isCertChecked()); + + if (tlsDialog->isCertChecked()) + m_activeSite->setProperty("tls_cert_path", tlsDialog->getCertPath()); + } + + delete tlsDialog; +} + +void BookmarkEditor::slotPortChanged() +{ + m_portChanged = true; +} + +void BookmarkEditor::slotChangeServerProtocol(int item) +{ + // Enable/Disable the SSL/TLS settings if needed + m_properties->protoAdvanced->setEnabled( item == 1 || item == 2 ); + + // Set the default port + if (!m_portChanged) { + switch (item) { + case SP_SSL_IMPLICIT: + if (m_properties->serverPort->value() == 21 || m_properties->serverPort->value() == 22) + m_properties->serverPort->setValue(993); + break; + case SP_SFTP: + if (m_properties->serverPort->value() == 21 || m_properties->serverPort->value() == 993) + m_properties->serverPort->setValue(22); + break; + default: + if (m_properties->serverPort->value() == 22 || m_properties->serverPort->value() == 993) + m_properties->serverPort->setValue(21); + break; + } + + m_portChanged = false; + } +} + +} + +} + +#include "editor.moc" diff --git a/kftpgrabber/src/widgets/bookmarks/editor.h b/kftpgrabber/src/widgets/bookmarks/editor.h new file mode 100644 index 0000000..50b04aa --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/editor.h @@ -0,0 +1,133 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPBOOKMARKEDITOR_H +#define KFTPBOOKMARKEDITOR_H + +#include "ui/bookmark_properties.h" + +#include <kaction.h> +#include <kdialogbase.h> + +#include <qlistview.h> +#include <qdom.h> + +namespace KFTPBookmarks { + class Manager; + class Site; +} + +namespace KFTPWidgets { + +namespace Bookmarks { + +class ListViewItem; +class ListView; + +/** +@author Jernej Kos +*/ +class BookmarkEditor : public KDialogBase +{ +Q_OBJECT +public: + BookmarkEditor(QWidget *parent = 0, const char *name = 0); + BookmarkEditor(ListViewItem *item, QWidget *parent = 0, const char *name = 0); + ~BookmarkEditor(); +private: + enum BookmarkType { + BT_CATEGORY = 0, + BT_SERVER + }; + + enum ServerProtocol { + SP_FTP = 0, + SP_SSL_EXPLICIT, + SP_SSL_IMPLICIT, + SP_SFTP + }; + + KFTPBookmarks::Manager *m_bookmarks; + KFTPBookmarks::Site *m_activeSite; + + ListViewItem *m_activeItem; + + BookmarkProperties *m_properties; + ListView *m_tree; + + bool m_portChanged; + + /* Actions */ + KAction *m_newAction; + KAction *m_renameAction; + KAction *m_deleteAction; + KAction *m_subCatAction; + KAction *m_copyAction; + KActionCollection *actionCollection(); + + // Some common stuff for the constructors + void initDialog(); + + void showActiveNode(); +public slots: + void refresh(); +private slots: + /* Action slots */ + void slotNewAction(ListViewItem *item, KFTPBookmarks::Site *site); + void slotDeleteAction(); + void slotDuplicateAction(ListViewItem *item, KFTPBookmarks::Site *site); + + /* Other slots */ + void slotChangeAnonLogin(); + void slotProtoAdvancedClicked(); + void slotChangeActiveRetryGroup(); + void slotChangeActiveKeepaliveGroup(); + void slotChangeServerProtocol(int item); + void slotPortChanged(); + + void slotTreeClicked(QListViewItem *item); + + void slotImportWizard(); + void slotExportWizard(); + + void slotSaveActiveNode(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/bookmarks/editortls.cpp b/kftpgrabber/src/widgets/bookmarks/editortls.cpp new file mode 100644 index 0000000..c299288 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/editortls.cpp @@ -0,0 +1,115 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include <qcheckbox.h> + +#include <kcombobox.h> +#include <klocale.h> +#include <kurlrequester.h> + +#include "kftpapi.h" +#include "editortls.h" +#include "kftpbookmarkeditortlswidget.h" +#include "misc.h" + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Bookmarks { + +KActionCollection *BookmarkEditorTLS::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +BookmarkEditorTLS::BookmarkEditorTLS(QWidget *parent, const char *name) + : KDialogBase(parent, name) +{ + m_mainWidget = new KFTPBookmarkEditorTLSWidget(this); + setMainWidget(m_mainWidget); + + setCaption(i18n("SSL/TLS Settings")); + showButtonApply(false); + + connect(m_mainWidget->useCert, SIGNAL(clicked()), this, SLOT(slotChangeActiveX509Group())); +} + +BookmarkEditorTLS::~BookmarkEditorTLS() +{ + delete m_mainWidget; +} + +void BookmarkEditorTLS::slotChangeActiveX509Group() +{ + m_mainWidget->certPath->setEnabled(m_mainWidget->useCert->isChecked()); +} + +int BookmarkEditorTLS::getTLSMode() +{ + return m_mainWidget->tlsMode->currentItem(); +} + +bool BookmarkEditorTLS::isCertChecked() +{ + return m_mainWidget->useCert->isChecked(); +} + +QString BookmarkEditorTLS::getCertPath() +{ + return m_mainWidget->certPath->url(); +} + +void BookmarkEditorTLS::setTLSMode(int mode) +{ + m_mainWidget->tlsMode->setCurrentItem(mode); +} + +void BookmarkEditorTLS::setCertChecked(const bool checked) +{ + m_mainWidget->useCert->setChecked(checked); +} + +void BookmarkEditorTLS::setCertPath(const QString &path) +{ + m_mainWidget->certPath->setURL(path); +} + +} + +} + +#include "editortls.moc" diff --git a/kftpgrabber/src/widgets/bookmarks/editortls.h b/kftpgrabber/src/widgets/bookmarks/editortls.h new file mode 100644 index 0000000..3325946 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/editortls.h @@ -0,0 +1,85 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPBOOKMARKEDITORTLS_H +#define KFTPBOOKMARKEDITORTLS_H + +#include "editor.h" +#include "kftpbookmarkeditortlswidget.h" + +#include <kaction.h> +#include <kdialogbase.h> + +#include <qlistview.h> +#include <qdom.h> + +namespace KFTPWidgets { + +namespace Bookmarks { + +/** +@author Jernej Kos +*/ +class BookmarkEditorTLS : public KDialogBase +{ +Q_OBJECT +public: + BookmarkEditorTLS(QWidget *parent = 0, const char *name = 0); + ~BookmarkEditorTLS(); + + int getTLSMode(); + bool isCertChecked(); + QString getCertPath(); + + void setTLSMode(int mode); + void setCertChecked(const bool checked); + void setCertPath(const QString &path); +private: + QDomNode m_activeNode; + QDomNode m_activeCategory; + + KFTPBookmarkEditorTLSWidget *m_mainWidget; + + KActionCollection *actionCollection(); +public slots: + void slotChangeActiveX509Group(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/bookmarks/importwizard.cpp b/kftpgrabber/src/widgets/bookmarks/importwizard.cpp new file mode 100644 index 0000000..aa30bee --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/importwizard.cpp @@ -0,0 +1,167 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "importwizard.h" +#include "kftpapi.h" +#include "kftppluginmanager.h" +#include "interfaces/kftpbookmarkimportplugin.h" +#include "misc.h" +#include "kftpbookmarks.h" + +#include <qfileinfo.h> +#include <qlabel.h> + +#include <kurlrequester.h> +#include <kmessagebox.h> +#include <klocale.h> +#include <kprogress.h> +#include <kstandarddirs.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Bookmarks { + +PluginListItem::PluginListItem(KListView *parent, KService::Ptr service) + : KListViewItem(parent, service->name(), service->comment()), m_service(service) +{ + setPixmap(0, loadSmallPixmap("filter")); +} + +ImportWizard::ImportWizard(QWidget *parent, const char *name) + : KFTPBookmarkImportLayout(parent, name) +{ + m_pluginList->setFullWidth(true); + m_pluginList->setAllColumnsShowFocus(true); + + connect(m_pluginList, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotPluginsSelectionChanged(QListViewItem*))); + + setNextEnabled(Step1, false); + + // Set pixmap + QString pixmapPath = locate("appdata", "kftpgrabber-bi-wizard.png"); + if (!pixmapPath.isNull()) { + QPixmap pix(pixmapPath); + + m_wizardPixmap->setPixmap(pix); + m_wizardPixmap_2->setPixmap(pix); + m_wizardPixmap_3->setPixmap(pix); + } + + // Disable useless help buttons + setHelpEnabled(Step1, false); + setHelpEnabled(Step2, false); + setHelpEnabled(Step3, false); + + displayPluginList(); +} + +void ImportWizard::next() +{ + if (currentPage() == Step1) { + // Load the plugin + m_plugin = KFTPAPI::getInstance()->pluginManager()->loadImportPlugin(m_service); + + if (!m_plugin) { + KMessageBox::error(0, i18n("Unable to load the selected import plugin.")); + return; + } else { + // Get the default plugin path + m_importUrl->setURL("~/" + m_plugin->getDefaultPath()); + } + } else if (currentPage() == Step2) { + // Check if the file exists + if (!QFileInfo(m_importUrl->url()).exists() || !QFileInfo(m_importUrl->url()).isReadable()) { + KMessageBox::error(0, i18n("The selected file does not exist or is not readable.")); + return; + } + } + + QWizard::next(); + + if (currentPage() == Step3) { + // Start the import + setBackEnabled(Step3, false); + + connect(m_plugin, SIGNAL(progress(int)), this, SLOT(slotImportProgress(int))); + m_plugin->import(m_importUrl->url()); + } +} + +void ImportWizard::slotImportProgress(int progress) +{ + m_progressBar->setProgress(progress); + + if (progress == 100) { + // Import complete + KMessageBox::information(0, i18n("Bookmark importing is complete.")); + + // Add the imported stuff to the current bookmarks + KFTPBookmarks::Manager::self()->importSites(m_plugin->getImportedXml().documentElement()); + + accept(); + } +} + +void ImportWizard::displayPluginList() +{ + KTrader::OfferList plugins = KFTPAPI::getInstance()->pluginManager()->getImportPlugins(); + + KTrader::OfferList::ConstIterator end(plugins.end()); + for (KTrader::OfferList::ConstIterator i(plugins.begin()); i != end; ++i) { + KService::Ptr service = *i; + + new PluginListItem(m_pluginList, service); + } +} + +void ImportWizard::slotPluginsSelectionChanged(QListViewItem *i) +{ + if (i) { + PluginListItem *item = static_cast<PluginListItem*>(i); + m_service = item->m_service; + + setNextEnabled(Step1, true); + } else { + setNextEnabled(Step1, false); + } +} + +} + +} + +#include "importwizard.moc" diff --git a/kftpgrabber/src/widgets/bookmarks/importwizard.h b/kftpgrabber/src/widgets/bookmarks/importwizard.h new file mode 100644 index 0000000..9b74dd3 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/importwizard.h @@ -0,0 +1,85 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPBOOKMARKIMPORTWIZARD_H +#define KFTPBOOKMARKIMPORTWIZARD_H + +#include "kftpbookmarkimportlayout.h" + +#include <kparts/componentfactory.h> +#include <klistview.h> + +class KFTPBookmarkImportPlugin; + +namespace KFTPWidgets { + +namespace Bookmarks { + +class PluginListItem : public KListViewItem +{ +friend class ImportWizard; +public: + PluginListItem(KListView *parent, KService::Ptr service); +private: + KService::Ptr m_service; +}; + +/** + * This is a wizard used to import bookmarks via detected KParts plugins. + * + * @author Jernej Kos + */ +class ImportWizard : public KFTPBookmarkImportLayout +{ +Q_OBJECT +public: + ImportWizard(QWidget *parent = 0, const char *name = 0); +private: + KService::Ptr m_service; + KFTPBookmarkImportPlugin *m_plugin; + + void displayPluginList(); +private slots: + virtual void next(); + + void slotImportProgress(int progress); + void slotPluginsSelectionChanged(QListViewItem *i); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/bookmarks/listview.cpp b/kftpgrabber/src/widgets/bookmarks/listview.cpp new file mode 100644 index 0000000..4349604 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/listview.cpp @@ -0,0 +1,532 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "kftpapi.h" +#include "listview.h" +#include "kftpbookmarks.h" +#include "kftpsession.h" +#include "misc.h" + +#include <qdragobject.h> + +#include <kaction.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kdebug.h> +#include <kio/passdlg.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Bookmarks { + +ListViewItem::ListViewItem(QListView *parent, const QString &t1) + : KListViewItem(parent, t1) +{ +} + +ListViewItem::ListViewItem(QListViewItem *parent, const QString &t1) + : KListViewItem(parent, t1) +{ +} + +int ListViewItem::compare(QListViewItem *i, int col, bool) const +{ + if (m_type != static_cast<ListViewItem*>(i)->m_type) { + if (m_type == 0) + return -1; // category + else + return 1; // server + } + + return KListViewItem::compare(i, col, false); +} + +ListView::ListView(KFTPBookmarks::Manager *bookmarks, QWidget *parent, const char *name) + : KFTPWidgets::ListView(parent, name), + m_autoUpdate(false), + m_connectBookmark(false), + m_editMenuItem(false), + m_bookmarks(bookmarks), + m_activeSite(0), + m_activeCategory(0), + m_activeItem(0) +{ + // Set some stuff + setMinimumWidth(150); + setFullWidth(true); + addColumn(i18n("Bookmarks")); + setRootIsDecorated(true); + setEmptyListText(i18n("No bookmarks.")); + setItemsRenameable(false); + + // Drag & drop + setDragEnabled(true); + setAcceptDrops(true); + setDropVisualizer(false); + + // Init auto open timer + m_openTimer = new QTimer(this); + + connect(this, SIGNAL(dropped(QDropEvent*, QListViewItem*)), this, SLOT(slotDropped(QDropEvent*, QListViewItem*))); + connect(this, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotClicked(QListViewItem*))); + connect(this, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(slotDoubleClicked(QListViewItem*))); + connect(this, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)), this, SLOT(slotContextMenu(QListViewItem*, const QPoint&, int))); + + /* Init the actions */ + m_newAction = new KAction(i18n("&New..."), "filenew", KShortcut(), this, SLOT(slotNewAction()), actionCollection(), "bookmark_new"); + m_renameAction = new KAction(i18n("&Rename"), KShortcut(), this, SLOT(slotRenameAction()), actionCollection(), "bookmark_rename"); + m_deleteAction = new KAction(i18n("&Delete"), "editdelete", KShortcut(), this, SLOT(slotDeleteAction()), actionCollection(), "bookmark_delete"); + m_subCatAction = new KAction(i18n("&Create Subcategory..."), "folder_new", KShortcut(), this, SLOT(slotSubCatAction()), actionCollection(), "bookmark_subcat"); + m_copyAction = new KAction(i18n("&Duplicate"), KShortcut(), this, SLOT(slotDuplicateAction()), actionCollection(), "bookmark_duplicate"); +} + +KActionCollection *ListView::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +void ListView::setAutoUpdate(bool value) +{ + m_autoUpdate = value; + + if (value) + connect(m_bookmarks, SIGNAL(update()), this, SLOT(slotAutoUpdate())); + + slotAutoUpdate(); +} + +void ListView::setConnectBookmark(bool value) +{ + m_connectBookmark = value; + + if (value) + connect(this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotBookmarkExecuted(QListViewItem*))); +} + +void ListView::setEditMenuItem(bool value) +{ + m_editMenuItem = value; +} + +void ListView::slotBookmarkExecuted(QListViewItem *item) +{ + if (!item || !m_connectBookmark || static_cast<ListViewItem*>(item)->m_type == BT_CATEGORY) + return; + + KFTPBookmarks::Site *site = static_cast<ListViewItem*>(item)->m_site; + KURL siteUrl = site->getUrl(); + + // Handle empty usernames and passwords for non-anonymous sites + if (!siteUrl.hasUser() || !siteUrl.hasPass() && siteUrl.user() != "anonymous") { + KIO::PasswordDialog *dlg = new KIO::PasswordDialog(i18n("Please provide your username and password for connecting to this site."), siteUrl.user(), true); + dlg->addCommentLine(i18n("Site:"), QString("%1:%2").arg(siteUrl.host()).arg(siteUrl.port())); + + if (dlg->exec() == KDialogBase::Accepted) { + siteUrl.setUser(dlg->username()); + siteUrl.setPass(dlg->password()); + + if (dlg->keepPassword()) { + // Save password to the bookmarked site + site->setProperty("username", dlg->username()); + site->setProperty("password", encodePassword(dlg->password())); + } + + delete dlg; + } else { + // Abort connection attempt + delete dlg; + return; + } + } + + // Just spawn a new session + KFTPSession::Session *session = KFTPSession::Manager::self()->spawnRemoteSession(KFTPSession::IgnoreSide, siteUrl, site); + m_bookmarks->setupClient(site, session->getClient()); +} + +void ListView::slotAutoUpdate() +{ + if (m_autoUpdate) { + // Update the bookmark list + fillBookmarkData(); + } +} + +QDragObject *ListView::dragObject() +{ + // Determine hotspot and pixmap + QPoint hotspot; + QPixmap pixmap = *selectedItem()->pixmap(0); + hotspot.setX(pixmap.width() / 2); + hotspot.setY(pixmap.height() / 2); + + QString id = static_cast<ListViewItem*>(selectedItem())->m_site->id(); + m_dragObject = new QStoredDrag("application/x-qlistviewitem", this); + QByteArray data; + QDataStream arg(data, IO_WriteOnly); + arg << id; + + // Start the drag + static_cast<QStoredDrag*>(m_dragObject)->setEncodedData(data); + m_dragObject->setPixmap(pixmap, hotspot); + + return m_dragObject; +} + +bool ListView::acceptDrag(QDropEvent *e) const +{ + // If it is a local drag, accept it + return e->source() == static_cast<QWidget*>(const_cast<ListView*>(this)); +} + +void ListView::contentsDragEnterEvent(QDragEnterEvent *e) +{ + if (!acceptDrag(e)) { + e->ignore(); + return; + } + e->acceptAction(); + + m_currentBeforeDropItem = selectedItem(); + QListViewItem *item = itemAt(contentsToViewport(e->pos())); + + if (item) { + m_dropItem = item; + m_openTimer->start(750); + } else { + m_dropItem = 0L; + } +} + +void ListView::contentsDragMoveEvent(QDragMoveEvent *e) +{ + if (!acceptDrag(e)) { + e->ignore(); + return; + } + e->acceptAction(); + + QListViewItem *item = itemAt(contentsToViewport(e->pos())); + if (item) { + setSelected(item, true); + if (item != m_dropItem) { + m_openTimer->stop(); + m_dropItem = item; + m_openTimer->start(750); + } + } else { + if (selectedItem()) { + setSelected(selectedItem(), false); + } + + m_openTimer->stop(); + m_dropItem = 0L; + } +} + +void ListView::contentsDragLeaveEvent(QDragLeaveEvent*) +{ + if (m_currentBeforeDropItem) { + setSelected(m_currentBeforeDropItem, true); + ensureItemVisible(m_currentBeforeDropItem); + } else { + setSelected(m_dropItem, false); + } + + m_openTimer->stop(); + m_dropItem = 0L; +} + +void ListView::slotOpenTimer() +{ + m_openTimer->stop(); + if (m_dropItem && m_dropItem->isExpandable()) { + // Expand the category + m_dropItem->setOpen(true); + } +} + +void ListView::slotDropped(QDropEvent *e, QListViewItem*) +{ + KFTPBookmarks::Site *parentSite = 0L; + + if (selectedItem()) { + QListViewItem *newParent = 0L; + + // Get the new path + if (static_cast<ListViewItem*>(selectedItem())->m_type == 0) + newParent = selectedItem(); + else + newParent = selectedItem()->parent(); + + if (newParent) + parentSite = static_cast<ListViewItem*>(newParent)->m_site; + else + parentSite = m_bookmarks->findCategory("root"); + } else { + parentSite = m_bookmarks->findCategory("root"); + } + + QString id; + + // Decode the data + QDataStream arg(e->encodedData("application/x-qlistviewitem"), IO_ReadOnly); + arg >> id; + + // Move the site + KFTPBookmarks::Site *originalSite = m_bookmarks->findSite(id); + parentSite->reparentSite(originalSite); + + emit bookmarkMoved(); + + // Notify the bookmark manager + m_bookmarks->emitUpdate(); +} + +void ListView::fillBookmarkData() +{ + // Fill the tree with data + m_bookmarks->guiPopulateBookmarksTree(this); +} + +void ListView::slotClicked(QListViewItem *item) +{ + m_activeItem = static_cast<ListViewItem*>(item); + + if (m_activeItem) { + if (m_activeItem->m_type == BT_CATEGORY) { + // Category + m_activeCategory = m_activeItem->m_site; + m_activeSite = 0L; + } else { + // Server + m_activeSite = m_activeItem->m_site; + m_activeCategory = m_activeSite->getParentSite(); + } + } + + emit bookmarkClicked(item); +} + +void ListView::slotDoubleClicked(QListViewItem *item) +{ + if (!item) + return; + + setOpen(item, !item->isOpen()); +} + +KFTPBookmarks::Manager *ListView::getBookmarks() +{ + return m_bookmarks; +} + +void ListView::slotRenameAction() +{ + // Rename a subcategory + ListViewItem *item = static_cast<ListViewItem*>(selectedItems().at(0)); + KFTPBookmarks::Site *site = item->m_site; + + bool ok; + QString newName = KInputDialog::getText(i18n("Category Name"), i18n("Rename category:"), item->text(0), &ok, this); + + if (ok) { + // Ok, let's rename it + site->setAttribute("name", newName); + item->setText(0, newName); + } +} + +void ListView::slotSubCatAction() +{ + // Create a subcategory + ListViewItem *item = static_cast<ListViewItem*>(selectedItems().at(0)); + KFTPBookmarks::Site *site = item ? item->m_site : m_bookmarks->findCategory("root"); + + bool ok; + QString newName = KInputDialog::getText(i18n("New Category Name"), i18n("New category:"), "", &ok, this); + + if (ok) { + // Let's create the sub category + site->addCategory(newName); + + emit categoryRenamed(); + m_bookmarks->emitUpdate(); + } +} + +void ListView::slotNewAction() +{ + if (!m_activeCategory) { + // Set the starting category to document root + m_activeCategory = m_bookmarks->findCategory("root"); + } + + // Create the new node + KFTPBookmarks::Site *site = m_activeCategory->addSite(); + site->setAttribute("name", i18n("New server")); + site->setProperty("port", 21); + + // Create the ListViewItem + ListViewItem *serv = 0L; + if (!m_activeItem || (!m_activeItem->parent() && m_activeItem->m_type == BT_SERVER)) { + serv = new ListViewItem(this, i18n("New Server")); + } else if (m_activeItem->m_type == BT_CATEGORY) { + serv = new ListViewItem(m_activeItem, i18n("New Server")); + m_activeItem->setOpen(true); + } else { + serv = new ListViewItem(m_activeItem->parent(), i18n("New Server")); + } + + serv->m_type = BT_SERVER; + serv->m_site = site; + + serv->setPixmap(0, loadSmallPixmap("ftp")); + + // Set the new ListViewItem as active + setSelected(serv, true); + m_activeItem = serv; + + // Display its properties + m_activeSite = site; + + emit bookmarkNew(serv, site); +} + +void ListView::slotDuplicateAction() +{ + // Copy a bookmark + ListViewItem *item = static_cast<ListViewItem*>(selectedItems().at(0)); + + // Clone the node + KFTPBookmarks::Site *copy = item->m_site->duplicate(); + + // Create the ListViewItem + ListViewItem *serv = 0L; + if (item->parent()) + serv = new ListViewItem(item->parent(), copy->getAttribute("name")); + else + serv = new ListViewItem(this, copy->getAttribute("name")); + + serv->m_type = BT_SERVER; + serv->m_site = copy; + + serv->setPixmap(0, loadSmallPixmap("ftp")); + + // Set the new ListViewItem as active + setSelected(serv, true); + m_activeItem = serv; + + // Display its properties + m_activeSite = copy; + + emit bookmarkDuplicated(serv, copy); + + // Update the bookmarks + m_bookmarks->emitUpdate(); +} + +void ListView::slotDeleteAction() +{ + // Delete a server or a category + ListViewItem *item = static_cast<ListViewItem*>(selectedItems().at(0)); + + // What do we have here ? + if (item->m_type == BT_CATEGORY) { + // Category + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove this category?")) == KMessageBox::Yes) { + m_bookmarks->delSite(item->m_site); + } else { + return; + } + } else { + // Server + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove this server?")) == KMessageBox::Yes) { + m_bookmarks->delSite(item->m_site); + } else { + return; + } + } + + if ( !m_autoUpdate ) + delete item; + + m_activeItem = 0L; + emit bookmarkDeleted(); +} + +void ListView::slotContextMenu(QListViewItem *item, const QPoint &pos, int) +{ + slotClicked(item); + + KPopupMenu *context = new KPopupMenu(this); + + if (item) { + context->insertTitle(item->text(0)); + + // Server or category + if (static_cast<ListViewItem*>(item)->m_type == BT_CATEGORY) { + m_newAction->plug(context); + m_deleteAction->plug(context); + m_subCatAction->plug(context); + m_renameAction->plug(context); + } else { + if (m_editMenuItem) + actionCollection()->action("bookmark_edit2")->plug(context); + + m_newAction->plug(context); + m_copyAction->plug(context); + m_deleteAction->plug(context); + } + } else { + // Nothing selected + m_newAction->plug(context); + m_subCatAction->plug(context); + } + + context->exec(pos); + + delete context; +} + +} + +} + +#include "listview.moc" diff --git a/kftpgrabber/src/widgets/bookmarks/listview.h b/kftpgrabber/src/widgets/bookmarks/listview.h new file mode 100644 index 0000000..213ec03 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/listview.h @@ -0,0 +1,193 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPBOOKMARKEDITORLISTVIEW_H +#define KFTPBOOKMARKEDITORLISTVIEW_H + +#include <qdom.h> +#include <qtimer.h> + +#include "../listview.h" + +class KAction; +class KActionCollection; +class Sidebar; +class KFTPSelectServerDialog; + +namespace KFTPBookmarks { + class Site; + class Manager; + class BookmarkEditor; + class Sidebar; +} + +namespace KFTPWidgets { + +namespace Bookmarks { + +class ListView; + +class ListViewItem : public KListViewItem +{ +friend class BookmarkEditor; +friend class KFTPWidgets::Bookmarks::ListView; +friend class Sidebar; +friend class ::KFTPSelectServerDialog; +public: + ListViewItem(QListView *parent, const QString &t1); + ListViewItem(QListViewItem *parent, const QString &t1); + + int compare(QListViewItem *i, int col, bool) const; + + void setSite(KFTPBookmarks::Site *site) { m_site = site; } + void setType(int type) { m_type = type; } +private: + int m_type; + KFTPBookmarks::Site *m_site; +}; + +/** +@author Jernej Kos +*/ +class ListView : public KFTPWidgets::ListView +{ +Q_OBJECT +public: + ListView(KFTPBookmarks::Manager *bookmarks, QWidget *parent = 0, const char *name = 0); + + /** + * Fill current treeview with all the bookmarks. + */ + void fillBookmarkData(); + + /** + * This changes the auto-update behaviour of the ListView. If set to true, this + * list view will automaticly update when bookmarks are changed. Defaults + * to false. + * + * @param value True to enable auto update, false otherwise + */ + void setAutoUpdate(bool value); + + /** + * This changes the connect-on-click behaviour of the ListView. If set to true, + * a new remote session will be spawned whenever the users double clicks the + * bookmark. + * + * @param value True to enable connect on click, false otherwise + */ + void setConnectBookmark(bool value); + + /** + * Get the bookmarks, the listview operates on + */ + KFTPBookmarks::Manager *getBookmarks(); + + /** + * Specifiy, whether an edit menuitem should be placed in the contextmenu + * + * @param value True to enable the edit menuitem, false otherwise + */ + void setEditMenuItem(bool value); + +private: + enum BookmarkType { + BT_CATEGORY = 0, + BT_SERVER + }; + + bool m_autoUpdate; + bool m_connectBookmark; + bool m_editMenuItem; + QDragObject *m_dragObject; + + /* Actions */ + KAction *m_newAction; + KAction *m_renameAction; + KAction *m_deleteAction; + KAction *m_subCatAction; + KAction *m_copyAction; + + /* Auto open categories support */ + QListViewItem *m_dropItem; + QListViewItem* m_currentBeforeDropItem; + QTimer *m_openTimer; + + /* Specifies, on which bookmarks we operate */ + KFTPBookmarks::Manager *m_bookmarks; + + KFTPBookmarks::Site *m_activeSite; + KFTPBookmarks::Site *m_activeCategory; + KFTPWidgets::Bookmarks::ListViewItem *m_activeItem; + + KActionCollection *actionCollection(); + + /* Drag & drop support */ + QDragObject *dragObject(); + bool acceptDrag(QDropEvent *e) const; + void contentsDragEnterEvent(QDragEnterEvent *e); + void contentsDragMoveEvent(QDragMoveEvent *e); + void contentsDragLeaveEvent(QDragLeaveEvent*); +private slots: + void slotDropped(QDropEvent *e, QListViewItem*); + void slotDoubleClicked(QListViewItem *item); + void slotOpenTimer(); + + void slotClicked(QListViewItem*); + void slotNewAction(); + void slotRenameAction(); + void slotDeleteAction(); + void slotSubCatAction(); + void slotDuplicateAction(); + void slotContextMenu(QListViewItem*, const QPoint&, int col); + + void slotAutoUpdate(); + void slotBookmarkExecuted(QListViewItem*); +signals: + void bookmarkMoved(); + void bookmarkNew(ListViewItem*, KFTPBookmarks::Site*); + void bookmarkDeleted(); + void bookmarkDuplicated(ListViewItem*, KFTPBookmarks::Site*); + void bookmarkClicked(QListViewItem*); + + void categoryRenamed(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/bookmarks/sidebar.cpp b/kftpgrabber/src/widgets/bookmarks/sidebar.cpp new file mode 100644 index 0000000..21ee0d9 --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/sidebar.cpp @@ -0,0 +1,158 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include <qlayout.h> +#include <qsplitter.h> +#include <qvbox.h> + +#include <kaction.h> +#include <klocale.h> +#include <ktoolbar.h> + +#include "kftpapi.h" +#include "kftpbookmarks.h" +#include "editor.h" +#include "listview.h" +#include "misc.h" + +#include "sidebar.h" + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Bookmarks { + +KActionCollection *Sidebar::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +Sidebar::Sidebar(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + m_toolBar = new KToolBar(this, "bookmarkToolBar"); + m_toolBar->setIconSize(16); + layout->addWidget(m_toolBar); + + // Create the list view for editing bookmarks + m_tree = new ListView(KFTPBookmarks::Manager::self(), this); + m_tree->setAutoUpdate(true); + m_tree->setConnectBookmark(true); + m_tree->setEditMenuItem(true); + + layout->addWidget(m_tree); + + m_editAction = new KAction(i18n("&Edit..."), "edit", KShortcut(), this, SLOT(slotEditAction()), actionCollection(), "bookmark_edit2"); + connect(m_tree, SIGNAL(bookmarkClicked(QListViewItem*)), this, SLOT(slotClicked(QListViewItem*))); + connect(m_tree, SIGNAL(bookmarkNew(ListViewItem*, KFTPBookmarks::Site*)), this, SLOT(slotNewAction(ListViewItem*, KFTPBookmarks::Site*))); + + // Get the new bookmark data + m_tree->fillBookmarkData(); + + // Init the Actions + slotClicked(0L); + + setMinimumWidth(200); +} + +Sidebar::~Sidebar() +{ +} + +void Sidebar::refresh() +{ + m_tree->clear(); + m_tree->fillBookmarkData(); +} + +void Sidebar::slotEditAction() +{ + ListViewItem* item = static_cast<ListViewItem*>(m_tree->selectedItems().at(0)); + + if (item) { + BookmarkEditor *editor = new BookmarkEditor(item, this); + + editor->exec(); + delete editor; + + // Update the bookmarks globaly + KFTPBookmarks::Manager::self()->emitUpdate(); + } +} + +void Sidebar::slotNewAction(ListViewItem*, KFTPBookmarks::Site *site) +{ + BookmarkEditor *editor = new BookmarkEditor(static_cast<ListViewItem*>(m_tree->selectedItems().at(0)), this); + + if (!editor->exec()) { + // If the user clicks Abort, remove the newly created server + KFTPBookmarks::Manager::self()->delSite(site); + } + + delete editor; +} + +void Sidebar::slotClicked(QListViewItem *item) +{ + // When nodes are expanded, item is 0, although an item is still selected, so grab it here + item = m_tree->selectedItems().at(0); + + // Enable/Disable actions for the toolbar + if (!item) { + actionCollection()->action("bookmark_delete")->setEnabled(false); + actionCollection()->action("bookmark_subcat")->setEnabled(true); + m_editAction->setEnabled(false); + return; + } + + actionCollection()->action("bookmark_delete")->setEnabled(true); + + if (static_cast<ListViewItem*>(item)->m_type == BT_CATEGORY) { + m_editAction->setEnabled(false); + actionCollection()->action("bookmark_subcat")->setEnabled(true); + } else { + m_editAction->setEnabled(true); + actionCollection()->action("bookmark_subcat")->setEnabled(false); + } +} + +} + +} + +#include "sidebar.moc" diff --git a/kftpgrabber/src/widgets/bookmarks/sidebar.h b/kftpgrabber/src/widgets/bookmarks/sidebar.h new file mode 100644 index 0000000..ef08d3e --- /dev/null +++ b/kftpgrabber/src/widgets/bookmarks/sidebar.h @@ -0,0 +1,88 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPBOOKMARKSIDEBAR_H +#define KFTPBOOKMARKSIDEBAR_H + +namespace KFTPBookmarks { + class Site; +} + +class KAction; +class KToolBar; + +namespace KFTPWidgets { + +namespace Bookmarks { + +class ListViewItem; +class ListView; + +/** +@author Markus Brueffer +*/ +class Sidebar : public QWidget +{ +Q_OBJECT +public: + Sidebar(QWidget *parent = 0, const char *name = 0); + ~Sidebar(); + +private: + enum BookmarkType { + BT_CATEGORY = 0, + BT_SERVER + }; + + KToolBar *m_toolBar; + ListView *m_tree; + + KAction *m_editAction; + KActionCollection *actionCollection(); +public slots: + void refresh(); +private slots: + void slotClicked(QListViewItem*); + + /* Action slots */ + void slotEditAction(); + void slotNewAction(ListViewItem *item, KFTPBookmarks::Site *site); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/Makefile.am b/kftpgrabber/src/widgets/browser/Makefile.am new file mode 100644 index 0000000..2b9c987 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = -I$(srcdir)/../.. -I../.. \ + -I$(srcdir)/../../engine \ + -I$(srcdir)/../../misc \ + -I$(srcdir)/.. \ + -I$(srcdir)/../../ui -I../../ui \ + $(all_includes) + +METASOURCES = AUTO +noinst_LIBRARIES = libbrowser.a +noinst_HEADERS = view.h actions.h treeview.h propsplugin.h \ + filterwidget.h detailsview.h locationnavigator.h dirlister.h +libbrowser_a_SOURCES = view.cpp actions.cpp treeview.cpp \ + propsplugin.cpp filterwidget.cpp detailsview.cpp locationnavigator.cpp dirlister.cpp diff --git a/kftpgrabber/src/widgets/browser/actions.cpp b/kftpgrabber/src/widgets/browser/actions.cpp new file mode 100644 index 0000000..cc9fc8c --- /dev/null +++ b/kftpgrabber/src/widgets/browser/actions.cpp @@ -0,0 +1,764 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "browser/actions.h" +#include "browser/view.h" +#include "browser/detailsview.h" +#include "browser/propsplugin.h" +#include "browser/filterwidget.h" + +#include "widgets/quickconnect.h" +#include "widgets/popupmessage.h" + +#include "kftpbookmarks.h" +#include "kftpqueue.h" +#include "kftpapi.h" +#include "kftpsession.h" +#include "verifier.h" +#include "mainactions.h" + +#include "misc.h" +#include "misc/config.h" +#include "misc/filter.h" +#include "misc/customcommands/manager.h" + +#include <kglobal.h> +#include <kcharsets.h> +#include <kapplication.h> +#include <kmainwindow.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kinputdialog.h> +#include <kpropertiesdialog.h> +#include <kio/job.h> +#include <kshred.h> +#include <klineedit.h> +#include <kfiledialog.h> +#include <kstandarddirs.h> + +#include <qdir.h> +#include <qclipboard.h> + +using namespace KFTPGrabberBase; +using namespace KFTPEngine; +using namespace KFTPCore; +using namespace KFTPCore::Filter; + +namespace KFTPWidgets { + +namespace Browser { + +Actions::Actions(View *parent) + : QObject(parent), + m_view(parent) +{ +} + +void Actions::initActions() +{ + m_actionCollection = new KActionCollection(m_view, this); + + // Create all the actions + m_goUpAction = KStdAction::up(this, SLOT(slotGoUp()), m_actionCollection, "go_up"); + m_goBackAction = KStdAction::back(this, SLOT(slotGoBack()), m_actionCollection, "go_back"); + m_goForwardAction = KStdAction::forward(this, SLOT(slotGoForward()), m_actionCollection, "go_forward"); + m_goHomeAction = KStdAction::home(this, SLOT(slotGoHome()), m_actionCollection, "go_home"); + + m_reloadAction = KStdAction::redisplay(this, SLOT(slotReload()), m_actionCollection, "reload"); + m_reloadAction->setText(i18n("&Reload")); + m_reloadAction->setShortcut(KShortcut(Qt::Key_F5)); + + m_abortAction = new KAction(i18n("&Abort"), "stop", KShortcut(), this, SLOT(slotAbort()), m_actionCollection, "abort"); + m_toggleTreeViewAction = new KToggleAction(i18n("&Show Tree View"), "view_tree", KShortcut(), this, SLOT(slotShowHideTree()), m_actionCollection, "toggle_tree_view"); + m_toggleFilterAction = new KToggleAction(i18n("Show &Filter"), "filter", KShortcut(), this, SLOT(slotShowHideFilter()), m_actionCollection, "toggle_filter"); + + m_renameAction = new KAction(i18n("&Rename"), KShortcut(Qt::Key_F2), this, SLOT(slotRename()), m_actionCollection, "edit_rename"); + m_deleteAction = new KAction(i18n("&Delete"), "editdelete", KShortcut(Qt::Key_Delete), this, SLOT(slotDelete()), m_actionCollection, "edit_delete"); + m_propsAction = new KAction(i18n("&Properties"), KShortcut(), this, SLOT(slotProps()), m_actionCollection, "edit_properties"); + m_shredAction = new KAction(i18n("&Shred"), "editshred", KShortcut(), this, SLOT(slotShred()), m_actionCollection, "edit_shred"); + + m_copyAction = KStdAction::copy(this, SLOT(slotCopy()), m_actionCollection, "edit_copy"); + m_pasteAction = KStdAction::paste(this, SLOT(slotPaste()), m_actionCollection, "edit_paste"); + + m_filterActions = new KActionMenu(i18n("&Filter Options"), "", m_actionCollection, "edit_filter_options"); + m_alwaysSkipAction = new KAction(i18n("Always &skip this file when queuing"), KShortcut(), this, SLOT(slotAlwaysSkip()), m_actionCollection); + m_topPriorityAction = new KAction(i18n("Make this file &top priority"), KShortcut(), this, SLOT(slotTopPriority()), m_actionCollection); + m_lowPriorityAction = new KAction(i18n("Make this file &lowest priority"), KShortcut(), this, SLOT(slotLowPriority()), m_actionCollection); + + m_filterActions->insert(m_alwaysSkipAction); + m_filterActions->insert(m_topPriorityAction); + m_filterActions->insert(m_lowPriorityAction); + + m_transferAction = new KAction(i18n("&Transfer"), KShortcut(), this, SLOT(slotTransfer()), m_actionCollection, "transfer"); + m_queueTransferAction = new KAction(i18n("&Queue Transfer"), "queue", KShortcut(), this, SLOT(slotQueueTransfer()), m_actionCollection, "queue_transfer"); + m_createDirAction = new KAction(i18n("&Create Directory..."), "folder_new", KShortcut(), this, SLOT(slotCreateDir()), m_actionCollection, "create_dir"); + m_fileEditAction = new KAction(i18n("&Open file"), "fileopen", KShortcut(), this, SLOT(slotFileEdit()), m_actionCollection, "open_file"); + m_verifyAction = new KAction(i18n("&Verify..."), "ok", KShortcut(), this, SLOT(slotVerify()), m_actionCollection, "verify"); + + populateEncodings(); + + m_moreActions = new KActionMenu(i18n("&More Actions"), "configure", this); + m_rawCmdAction = new KAction(i18n("&Manual Command Entry..."), "openterm", KShortcut(), this, SLOT(slotRawCmd()), m_actionCollection, "send_raw_cmd"); + m_exportListingAction = new KAction(i18n("&Export Directory Listing..."), "", KShortcut(), this, SLOT(slotExportListing()), m_actionCollection, "export_listing"); + m_showHiddenFilesAction = new KToggleAction(i18n("Show &Hidden Files && Directories"), KShortcut(), this, SLOT(slotShowHiddenFiles()), m_actionCollection, "show_hidden"); + m_openExternalAction = new KAction(i18n("Open current directory in &Konqueror..."), "konqueror", KShortcut(), this, SLOT(slotOpenExternal()), m_actionCollection, "open_konqi"); + + m_markItemsAction = new KAction(i18n("Compare &selected items"), "", KShortcut(Qt::Key_Space), this, SLOT(slotMarkItems()), m_actionCollection, "compare_selected"); + m_compareAction = new KAction(i18n("Compare &directories"), "", KShortcut(), this, SLOT(slotCompare()), m_actionCollection, "compare_dirs"); + + m_showHiddenFilesAction->setChecked(KFTPCore::Config::showHiddenFiles()); + + m_rawCommandsMenu = CustomCommands::Manager::self()->categories(i18n("Send &Raw Command"), m_view->getSession()); + m_rawCommandsMenu->insert(m_rawCmdAction, 0); + m_rawCommandsMenu->popupMenu()->insertSeparator(1); + + m_moreActions->insert(m_rawCommandsMenu); + m_moreActions->insert(m_changeEncodingAction); + m_moreActions->popupMenu()->insertSeparator(); + m_moreActions->insert(m_exportListingAction); + m_moreActions->insert(m_openExternalAction); + m_moreActions->insert(m_markItemsAction); + m_moreActions->insert(m_compareAction); + m_moreActions->popupMenu()->insertSeparator(); + m_moreActions->insert(m_showHiddenFilesAction); + + m_moreActions->setStickyMenu(true); + m_moreActions->setDelayed(false); + + m_siteChangeAction = new KActionMenu(i18n("&Change Site"), "goto", this); + m_quickConnectAction = new KAction(i18n("&Quick Connect..."), "connect_creating", KShortcut(), this, SLOT(slotQuickConnect()), m_actionCollection, "quick_connect"); + m_connectAction = new KActionMenu(i18n("&Connect To"), this); + m_disconnectAction = new KAction(i18n("&Disconnect"), "connect_no", KShortcut(), this, SLOT(slotDisconnect()), m_actionCollection, "disconnect"); + + m_siteChangeAction->insert(m_quickConnectAction); + m_siteChangeAction->insert(m_connectAction); + m_siteChangeAction->insert(m_disconnectAction); + m_siteChangeAction->setStickyMenu(true); + m_siteChangeAction->setDelayed(false); + + // Populate bookmarks + KFTPBookmarks::Manager::self()->guiPopulateBookmarksMenu(m_connectAction, QDomNode(), false, m_view->m_session); +} + +void Actions::populateEncodings() +{ + // Charsets + m_changeEncodingAction = new KActionMenu(i18n("Change Remote &Encoding"), "charset", m_actionCollection, "changeremoteencoding"); + m_changeEncodingAction->setDelayed(false); + + KPopupMenu *menu = m_changeEncodingAction->popupMenu(); + menu->clear(); + + QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames(); + int count = 0; + for (QStringList::iterator i = charsets.begin(); i != charsets.end(); ++i) + menu->insertItem(*i, this, SLOT(slotCharsetChanged(int)), 0, ++count); + + menu->insertSeparator(); + menu->insertItem(i18n("Default"), this, SLOT(slotCharsetReset(int)), 0, ++count); + menu->setItemChecked(count, true); + + m_defaultCharsetOption = count; + m_curCharsetOption = count; +} + +void Actions::updateActions() +{ + m_goUpAction->setEnabled(m_view->url().upURL() != m_view->url()); + + // History + int index = 0; + const QValueList<LocationNavigator::Element> list = m_view->history(index); + + m_goBackAction->setEnabled(index < static_cast<int>(list.count()) - 1); + m_goForwardAction->setEnabled(index > 0); + + m_abortAction->setEnabled(m_view->m_ftpClient->socket()->isBusy()); + m_toggleTreeViewAction->setEnabled(true); + m_toggleFilterAction->setEnabled(true); + + m_quickConnectAction->setEnabled(m_view->url().isLocalFile()); + m_connectAction->setEnabled(true); + m_disconnectAction->setEnabled(m_view->m_ftpClient->socket()->isConnected()); + + const KFileItemList *selectedItems = m_view->selectedItems(); + + if (selectedItems->count() == 1) { + m_fileEditAction->setEnabled(!selectedItems->getFirst()->isDir()); + m_verifyAction->setEnabled(selectedItems->getFirst()->isLocalFile() && selectedItems->getFirst()->name(true).right(3) == "sfv"); + } else { + m_fileEditAction->setEnabled(false); + m_verifyAction->setEnabled(false); + } + + // Check if we can transfer anything + KFTPSession::Session *session = m_view->m_session; + KFTPSession::Session *opposite = KFTPSession::Manager::self()->getActive(oppositeSide(m_view->m_session->getSide())); + + m_renameAction->setEnabled(session->isConnected()); + m_deleteAction->setEnabled(session->isConnected()); + m_propsAction->setEnabled(true); + m_shredAction->setEnabled(!session->isRemote()); + m_copyAction->setEnabled(true); + m_pasteAction->setEnabled(true); + + if ((!session->isRemote() && !opposite->isRemote()) || + ( + (session->isRemote() && opposite->isRemote()) && + ( + session->getClient()->socket()->protocolName() != opposite->getClient()->socket()->protocolName() || + !(session->getClient()->socket()->features() & SF_FXP_TRANSFER) + ) + ) + ) { + m_queueTransferAction->setEnabled(false); + m_transferAction->setEnabled(false); + } else { + m_queueTransferAction->setEnabled(true); + m_transferAction->setEnabled(true); + } + + if (!session->isRemote() || session->getClient()->socket()->isConnected()) + m_createDirAction->setEnabled(true); + else + m_createDirAction->setEnabled(false); + + m_changeEncodingAction->setEnabled(session->isRemote()); + m_rawCmdAction->setEnabled(!m_view->url().isLocalFile() && m_view->m_ftpClient->socket()->features() & SF_RAW_COMMAND); + m_rawCommandsMenu->setEnabled(m_rawCmdAction->isEnabled()); + m_openExternalAction->setEnabled(!session->isRemote()); +} + +void Actions::slotGoUp() +{ + m_view->goUp(); +} + +void Actions::slotGoBack() +{ + m_view->goBack(); +} + +void Actions::slotGoForward() +{ + m_view->goForward(); +} + +void Actions::slotReload() +{ + m_view->reload(); +} + +void Actions::slotGoHome() +{ + m_view->goHome(); +} + +void Actions::slotQuickConnect() +{ + // Create/get the new dialog + QuickConnectDialog *quickConnect = new QuickConnectDialog(m_view); + + if (quickConnect->exec() == KDialogBase::Accepted) { + // Get the url and connect + if (m_view->m_ftpClient->socket()->isConnected()) { + if (KFTPCore::Config::confirmDisconnects() && KMessageBox::warningYesNo(0, i18n("Do you want to drop current connection?")) == KMessageBox::No) + return; + + m_view->m_session->disconnectAllConnections(); + } + + m_view->m_session->setSite(0); + + quickConnect->setupClient(m_view->m_ftpClient); + m_view->m_ftpClient->connect(quickConnect->getUrl()); + } + + delete quickConnect; +} + +void Actions::slotDisconnect() +{ + if (m_view->m_ftpClient->socket()->isConnected()) { + if (KFTPCore::Config::confirmDisconnects() && KMessageBox::warningYesNo(0, i18n("Do you want to drop current connection?")) == KMessageBox::No) + return; + + m_view->m_session->disconnectAllConnections(); + } +} + +void Actions::slotShred() +{ + // Shred the file + if (KMessageBox::warningContinueCancel(0, i18n("Are you sure you want to SHRED this file?"), i18n("Shred File"),KGuiItem(i18n("&Shred"), "editshred")) == KMessageBox::Cancel) + return; + + KShred::shred(m_view->selectedItems()->getFirst()->url().path()); +} + +void Actions::slotRename() +{ + KFTPWidgets::Browser::DetailsView *view = m_view->getDetailsView(); + + // Rename the first file in the current selection + view->rename(view->KListView::selectedItems().at(0), 0); + + // Enhanced rename: Don't highlight the file extension. (from Konqueror) + KLineEdit *le = view->renameLineEdit(); + + if (le) { + const QString txt = le->text(); + QString pattern; + KMimeType::diagnoseFileName(txt, pattern); + + if (!pattern.isEmpty() && pattern.at(0) == '*' && pattern.find('*',1) == -1) + le->setSelection(0, txt.length()-pattern.stripWhiteSpace().length()+1); + else { + int lastDot = txt.findRev('.'); + + if (lastDot > 0) + le->setSelection(0, lastDot); + } + } +} + +void Actions::slotDelete() +{ + KFTPSession::Session *session = m_view->getSession(); + + // Delete a file or directory + KURL::List selection = m_view->selectedURLs(); + KURL::List::ConstIterator i = selection.begin(); + QStringList prettyList; + for (; i != selection.end(); ++i) { + prettyList.append((*i).pathOrURL()); + } + + if (KMessageBox::warningContinueCancelList(0, + i18n("Do you really want to delete this item?", "Do you really want to delete these %n items?", prettyList.count()), + prettyList, + i18n("Delete Files"), + KStdGuiItem::del(), + QString::null, + KMessageBox::Dangerous) == KMessageBox::Cancel) + return; + + // Go trough all files and delete them + if (!session->isRemote()) { + KIO::del(selection); + } else { + KURL::List::Iterator end(selection.end()); + + for (KURL::List::Iterator i(selection.begin()); i != end; ++i) { + if (!(*i).isLocalFile()) + session->getClient()->remove(KURL((*i).url())); + } + } +} + +void Actions::slotCopy() +{ + QClipboard *cb = QApplication::clipboard(); + cb->setData(m_view->getDetailsView()->dragObject(), QClipboard::Clipboard); +} + +void Actions::slotPaste() +{ + // Decode the data and try to init transfer + KIO::MetaData p_meta; + KURL::List p_urls; + + if (KURLDrag::decode(QApplication::clipboard()->data(), p_urls, p_meta)) { + // Add destination url and call the QueueManager + p_meta.insert("DestURL", m_view->url().url()); + KURLDrag *drag = new KURLDrag(p_urls, p_meta, m_view, name()); + KFTPQueue::Manager::self()->insertTransfer(drag); + } +} + +void Actions::slotProps() +{ + // Show file properties + const KFileItemList *selectedItems = m_view->selectedItems(); + KFileItem *item = selectedItems->getFirst(); + + if (selectedItems->count() == 0) { + if (m_view->url().isLocalFile()) + item = new KFileItem(m_view->url(), 0, 0); + else + return; + } + + // Show the dialog + KPropertiesDialog *propsDialog; + + if (item->isLocalFile()) { + if (selectedItems->count() == 0) + propsDialog = new KPropertiesDialog(item); + else + propsDialog = new KPropertiesDialog(*selectedItems); + } else { + propsDialog = new KPropertiesDialog(item->name()); + propsDialog->insertPlugin(new KFTPWidgets::Browser::PropsPlugin(propsDialog, *selectedItems)); + propsDialog->insertPlugin(new KFTPWidgets::Browser::PermissionsPropsPlugin(propsDialog, *selectedItems, m_view->getSession())); + } + + propsDialog->exec(); +} + +void Actions::addPriorityItems(int priority) +{ + // Add the files to skiplist + KURL::List selection = m_view->selectedURLs(); + KURL::List::Iterator end(selection.end()); + + for (KURL::List::Iterator i(selection.begin()); i != end; ++i) { + Rule *rule = new Rule(); + + if (priority == 0) { + rule->setName(i18n("Skip '%1'").arg((*i).filename())); + const_cast<ConditionChain*>(rule->conditions())->append(new Condition(Filename, Condition::Is, (*i).filename())); + const_cast<ActionChain*>(rule->actions())->append(new Action(Action::Skip, QVariant())); + } else { + rule->setName(i18n("Priority '%1'").arg((*i).filename())); + const_cast<ConditionChain*>(rule->conditions())->append(new Condition(Filename, Condition::Is, (*i).filename())); + const_cast<ActionChain*>(rule->actions())->append(new Action(Action::Priority, priority)); + } + + Filters::self()->append(rule); + } +} + +void Actions::slotAlwaysSkip() +{ + addPriorityItems(0); +} + +void Actions::slotTopPriority() +{ + addPriorityItems(1); +} + +void Actions::slotLowPriority() +{ + addPriorityItems(-1); +} + +void Actions::slotTransfer() +{ + // Queue a transfer + KFileItemList list(*m_view->selectedItems()); + KFileItemListIterator i(list); + KFileItem *item; + KFTPSession::Session *opposite = KFTPSession::Manager::self()->getActive(oppositeSide(m_view->m_session->getSide())); + KFTPQueue::Transfer *transfer = 0L; + + while ((item = i.current()) != 0) { + KURL destinationUrl = opposite->getFileView()->url(); + destinationUrl.addPath(item->name()); + + transfer = KFTPQueue::Manager::self()->spawnTransfer( + item->url(), + destinationUrl, + item->size(), + item->isDir(), + list.count() == 1, + true, + 0L, + true + ); + + ++i; + } + + // Execute transfer + if (transfer) + static_cast<KFTPQueue::Site*>(transfer->parentObject())->delayedExecute(); +} + +void Actions::slotQueueTransfer() +{ + // Queue a transfer + KFileItemList list(*m_view->selectedItems()); + KFileItemListIterator i(list); + KFileItem *item; + KFTPSession::Session *opposite = KFTPSession::Manager::self()->getActive(oppositeSide(m_view->m_session->getSide())); + + while ((item = i.current()) != 0) { + KURL destinationUrl = opposite->getFileView()->url(); + destinationUrl.addPath(item->name()); + + KFTPQueue::Manager::self()->spawnTransfer( + item->url(), + destinationUrl, + item->size(), + item->isDir(), + list.count() == 1, + true, + 0L, + list.count() > 1 + ); + + ++i; + } +} + +void Actions::slotCreateDir() +{ + // Create new directory + bool ok; + QString newDirName = KInputDialog::getText(i18n("Create Directory"), i18n("Directory name:"), "", &ok); + + if (ok) { + KURL url = m_view->url(); + url.addPath(newDirName); + + if (url.isLocalFile()) + KIO::mkdir(url); + else + m_view->m_ftpClient->mkdir(url); + } +} + +void Actions::slotFileEdit() +{ + KFileItem *item = m_view->selectedItems()->getFirst(); + + if (!item->isDir()) { + if (item->isLocalFile()) { + item->run(); + } else { + // Create a new transfer to download the file and open it + KFTPQueue::TransferFile *transfer = new KFTPQueue::TransferFile(KFTPQueue::Manager::self()); + transfer->setSourceUrl(item->url()); + transfer->setDestUrl(KURL(KGlobal::dirs()->saveLocation("tmp") + QString("%1-%2").arg(KApplication::randomString(7)).arg(item->name()))); + transfer->addSize(item->size()); + transfer->setTransferType(KFTPQueue::Download); + transfer->setOpenAfterTransfer(true); + KFTPQueue::Manager::self()->insertTransfer(transfer); + + // Execute the transfer + transfer->delayedExecute(); + } + } +} + +void Actions::slotAbort() +{ + KFTPSession::Session *session = KFTPSession::Manager::self()->find(m_view); + + // Abort the session + if (session) + session->abort(); +} + +void Actions::slotRawCmd() +{ + bool ok; + QString rawCmd = KInputDialog::getText(i18n("Send Raw Command"), i18n("Command:"), "", &ok); + + if (ok) + m_view->m_ftpClient->raw(rawCmd); +} + +void Actions::slotShowHideTree() +{ + m_view->setTreeVisible(m_toggleTreeViewAction->isChecked()); +} + +void Actions::slotShowHideFilter() +{ + if (m_toggleFilterAction->isChecked()) { + m_view->m_searchToolBar->show(); + m_view->m_searchFilter->clear(); + m_view->m_searchFilter->setFocus(); + } else { + m_view->m_searchFilter->clear(); + m_view->m_searchToolBar->hide(); + } +} + +void Actions::slotCharsetChanged(int id) +{ + if (!m_changeEncodingAction->popupMenu()->isItemChecked(id)) { + QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames(); + QString charset = KGlobal::charsets()->encodingForName(charsets[id - 1]); + + // Set the current socket's charset + m_view->m_ftpClient->socket()->changeEncoding(charset); + + // Update checked items + m_changeEncodingAction->popupMenu()->setItemChecked(id, true); + m_changeEncodingAction->popupMenu()->setItemChecked(m_curCharsetOption, false); + m_curCharsetOption = id; + } +} + +void Actions::slotCharsetReset(int id) +{ + // Revert to default charset if possible + KFTPBookmarks::Site *site = m_view->m_session->getSite(); + + if (site) { + // Set the current socket's charset + m_view->m_ftpClient->socket()->changeEncoding(site->getProperty("encoding")); + + // Update checked items + m_changeEncodingAction->popupMenu()->setItemChecked(id, true); + m_changeEncodingAction->popupMenu()->setItemChecked(m_curCharsetOption, false); + m_curCharsetOption = id; + } +} + +void Actions::slotExportListing() +{ + QString savePath = KFileDialog::getSaveFileName(QString::null, "*.txt|Directory Dump", 0, i18n("Export Directory Listing")); + + if (!savePath.isEmpty()) { + QFile file(savePath); + + if (!file.open(IO_WriteOnly)) + return; + + QTextStream stream(&file); + + KFileItemList list(*m_view->items()); + KFileItemListIterator i(list); + KFileItem *item; + + while ((item = i.current()) != 0) { + stream << item->permissionsString() << "\t"; + stream << item->user() << "\t" << item->group() << "\t"; + stream << item->timeString() << "\t"; + stream << item->name() << "\t"; + stream << "\n"; + + ++i; + } + + file.flush(); + file.close(); + } +} + +void Actions::slotVerify() +{ + KFTPWidgets::Verifier *verifier = new KFTPWidgets::Verifier(); + verifier->setFile(m_view->selectedItems()->getFirst()->url().path()); + verifier->exec(); + + delete verifier; +} + +void Actions::slotShowHiddenFiles() +{ + m_view->setShowHidden(m_showHiddenFilesAction->isChecked()); + m_view->reload(); +} + +void Actions::slotOpenExternal() +{ + KFileItem *folder = new KFileItem(m_view->url(), "inode/directory", S_IFDIR); + folder->run(); +} + +void Actions::slotMarkItems() +{ + KFileItemList list(*m_view->selectedItems()); + KFileItemListIterator i(list); + KFileItem *item; + KFTPSession::Session *opposite = KFTPSession::Manager::self()->getActive(oppositeSide(m_view->m_session->getSide())); + + DetailsView *tView = m_view->getDetailsView(); + DetailsView *oView = opposite->getFileView()->getDetailsView(); + + while ((item = i.current()) != 0) { + tView->markItem(item); + oView->markItem(item->name()); + ++i; + } +} + +void Actions::slotCompare() +{ + KFTPSession::Session *opposite = KFTPSession::Manager::self()->getActive(oppositeSide(m_view->m_session->getSide())); + + DetailsView *tView = m_view->getDetailsView(); + DetailsView *oView = opposite->getFileView()->getDetailsView(); + + // All items in the other list view should be visible by default + QListViewItemIterator j(oView); + while (j.current()) { + KFileItem *oItem = static_cast<KFileListViewItem*>(*j)->fileInfo(); + oView->setItemVisibility(oItem, true); + + ++j; + } + + // Compare the two listviews + QListViewItemIterator i(tView); + while (i.current()) { + KFileItem *tItem = static_cast<KFileListViewItem*>(*i)->fileInfo(); + + if (tItem) { + KFileItem *oItem = oView->fileItem(tItem->name()); + + if (oItem && (oItem->size() == tItem->size() || oItem->isDir())) { + tView->setItemVisibility(tItem, false); + oView->setItemVisibility(oItem, false); + } else { + tView->setItemVisibility(tItem, true); + } + } + + ++i; + } + + PopupMessage *popup = new PopupMessage(m_view->getStatusLabel(), m_view); + popup->setText(i18n("Identical files on both sides have been hidden. Only <b>different files</b> are now visible.")); + popup->setImage(SmallIcon("info")); + popup->setShowCloseButton(false); + popup->setShowCounter(false); + + popup->reposition(); + popup->display(); +} + +} + +} + +#include "actions.moc" diff --git a/kftpgrabber/src/widgets/browser/actions.h b/kftpgrabber/src/widgets/browser/actions.h new file mode 100644 index 0000000..69434e4 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/actions.h @@ -0,0 +1,189 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPFILEDIRVIEWACTIONS_H +#define KFTPFILEDIRVIEWACTIONS_H + +#include <qobject.h> +#include <kaction.h> +#include <krun.h> +#include <kservice.h> +#include <kuserprofile.h> + +namespace KFTPWidgets { + +namespace Browser { + +class View; + +/** + * This class contains all per-view actions. + * + * @author Jernej Kos + */ +class Actions : public QObject +{ +Q_OBJECT +friend class View; +friend class DetailsView; +public: + /** + * Class constructor. + * + * @param parent Parent view widget + */ + Actions(View *parent); + + /** + * Initialize view's action collection and it's actions. + */ + void initActions(); + + /** + * Properly enable/disable the available actions. + */ + void updateActions(); +private: + KActionCollection *m_actionCollection; + View *m_view; + + int m_curCharsetOption; + int m_defaultCharsetOption; + + KAction *m_goUpAction; + KAction *m_goBackAction; + KAction *m_goForwardAction; + KAction *m_goHomeAction; + KAction *m_reloadAction; + + KAction *m_abortAction; + KToggleAction *m_toggleTreeViewAction; + KToggleAction *m_toggleFilterAction; + + KAction *m_renameAction; + KAction *m_deleteAction; + KAction *m_propsAction; + KAction *m_shredAction; + + KAction *m_copyAction; + KAction *m_pasteAction; + + KActionMenu *m_filterActions; + KAction *m_alwaysSkipAction; + KAction *m_topPriorityAction; + KAction *m_lowPriorityAction; + + KAction *m_transferAction; + KAction *m_queueTransferAction; + KAction *m_createDirAction; + KAction *m_fileEditAction; + KAction *m_verifyAction; + + KActionMenu *m_moreActions; + KActionMenu *m_rawCommandsMenu; + KAction *m_rawCmdAction; + KActionMenu *m_changeEncodingAction; + KAction *m_exportListingAction; + KToggleAction *m_showHiddenFilesAction; + KAction *m_openExternalAction; + + KAction *m_markItemsAction; + KAction *m_compareAction; + + KActionMenu *m_siteChangeAction; + KAction *m_quickConnectAction; + KActionMenu *m_connectAction; + KAction *m_disconnectAction; +private: + /** + * Populates the encodings list. + */ + void populateEncodings(); + + /** + * A helper function to add the currently selected item(s) to the + * priority list with the given priority. + * + * @param priority The priority to use + */ + void addPriorityItems(int priority); +private slots: + void slotGoUp(); + void slotGoBack(); + void slotGoForward(); + void slotGoHome(); + void slotReload(); + + void slotAbort(); + void slotShowHideTree(); + void slotShowHideFilter(); + + void slotRename(); + void slotDelete(); + void slotProps(); + void slotShred(); + + void slotCopy(); + void slotPaste(); + + void slotAlwaysSkip(); + void slotTopPriority(); + void slotLowPriority(); + + void slotTransfer(); + void slotQueueTransfer(); + void slotCreateDir(); + void slotFileEdit(); + void slotVerify(); + + void slotRawCmd(); + void slotCharsetChanged(int); + void slotCharsetReset(int); + void slotExportListing(); + void slotShowHiddenFiles(); + void slotOpenExternal(); + + void slotMarkItems(); + void slotCompare(); + + void slotQuickConnect(); + void slotDisconnect(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/detailsview.cpp b/kftpgrabber/src/widgets/browser/detailsview.cpp new file mode 100644 index 0000000..5206d3d --- /dev/null +++ b/kftpgrabber/src/widgets/browser/detailsview.cpp @@ -0,0 +1,596 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "browser/detailsview.h" +#include "browser/treeview.h" +#include "browser/view.h" +#include "browser/locationnavigator.h" +#include "browser/dirlister.h" +#include "browser/actions.h" + +#include "misc/config.h" +#include "misc/kftpapi.h" +#include "misc/filter.h" + +#include "kftpqueue.h" + +#include <qheader.h> +#include <qpainter.h> + +#include <kpopupmenu.h> +#include <kurldrag.h> + +using namespace KFTPCore::Filter; + +namespace KFTPWidgets { + +namespace Browser { + +DetailsView::DetailsView(QWidget *parent, View *view, KFTPSession::Session *session) + : KFileDetailView(parent, 0), + m_view(view), + m_treeView(0), + m_refreshing(false), + m_shouldDisableResize(true), + m_autoResizeEnabled(true) +{ + m_resizeTimer = new QTimer(this); + connect(m_resizeTimer, SIGNAL(timeout()), this, SLOT(updateColumnWidths())); + + m_dirLister = new DirLister(this); + m_dirLister->setSession(session); + + connect(m_dirLister, SIGNAL(clear()), this, SLOT(slotClear())); + connect(m_dirLister, SIGNAL(completed()), this, SLOT(slotCompleted())); + connect(m_dirLister, SIGNAL(deleteItem(KFileItem*)), this, SLOT(slotDeleteItem(KFileItem*))); + connect(m_dirLister, SIGNAL(refreshItems()), this, SLOT(slotRefreshItems())); + connect(m_dirLister, SIGNAL(siteChanged(const KURL&)), this, SLOT(slotSiteChanged(const KURL&))); + + m_navigator = new LocationNavigator(this); + + connect(m_navigator, SIGNAL(urlChanged(const KURL&)), this, SLOT(slotUrlChanged(const KURL&))); + + connect(this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotItemExecuted())); + connect(this, SIGNAL(returnPressed(QListViewItem*)), this, SLOT(slotItemExecuted())); + connect(this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(slotContextMenu(KListView*, QListViewItem*, const QPoint&))); + connect(this, SIGNAL(itemRenamed(QListViewItem*, const QString&, int)), this, SLOT(slotItemRenamed(QListViewItem*, const QString&))); + + // Setup the header + QHeader *viewHeader = header(); + viewHeader->setResizeEnabled(true); + viewHeader->setMovingEnabled(false); + + connect(viewHeader, SIGNAL(sizeChange(int, int, int)), this, SLOT(slotHeaderResized(int))); + + // Set column width + setColumnWidthMode(NameColumn, QListView::Manual); + setColumnWidthMode(SizeColumn, QListView::Manual); + setColumnWidthMode(DateColumn, QListView::Manual); + setColumnWidthMode(PermissionsColumn, QListView::Manual); + + // Set column alignments + setColumnAlignment(SizeColumn, Qt::AlignRight); + setColumnAlignment(DateColumn, Qt::AlignHCenter); + setColumnAlignment(PermissionsColumn, Qt::AlignHCenter); + + if (KFTPCore::Config::showOwnerGroup()) { + setColumnAlignment(OwnerColumn, Qt::AlignHCenter); + setColumnAlignment(GroupColumn, Qt::AlignHCenter); + } else { + // Only show owner/group if set in the config + removeColumn(4); + removeColumn(4); + } + + setColumnWidth(NameColumn, 140); + setColumnWidth(DateColumn, 100); + + setAcceptDrops(true); + setSelectionMode(KFile::Extended); + setHScrollBarMode(QScrollView::AlwaysOff); + + // Set the defaults + setHomeUrl(KURL(KFTPCore::Config::defLocalDir())); + setShowHidden(KFTPCore::Config::showHiddenFiles()); +} + +DetailsView::~DetailsView() +{ +} + +const KURL &DetailsView::url() const +{ + return m_navigator->url(); +} + +const QValueList<LocationNavigator::Element> DetailsView::history(int &index) const +{ + return m_navigator->history(index); +} + +bool DetailsView::isSelected(const KFileItem *i) const +{ + if (!i) + return false; + + const KFileListViewItem *item = static_cast<const KFileListViewItem*>(i->extraData(this)); + return (item && item->isSelected() && item->isVisible()); +} + +void DetailsView::setTreeView(TreeView *tree) +{ + m_treeView = tree; + + connect(m_treeView, SIGNAL(pathChanged(const KURL&)), this, SLOT(openUrl(const KURL&))); +} + +void DetailsView::setHomeUrl(const KURL &url) +{ + m_navigator->setHomeUrl(url); +} + +void DetailsView::goBack() +{ + m_navigator->goBack(); +} + +void DetailsView::goForward() +{ + m_navigator->goForward(); +} + +void DetailsView::goUp() +{ + m_navigator->goUp(); +} + +void DetailsView::goHome() +{ + m_navigator->goHome(); +} + +void DetailsView::endItemUpdates() +{ + const KFileListViewItem *item = static_cast<const KFileListViewItem*>(firstChild()); + if (item) + setCurrentItem(item->fileInfo()); + + int index = 0; + const QValueList<LocationNavigator::Element> history = m_navigator->history(index); + if (!history.isEmpty()) { + KFileView::setCurrentItem(history[index].currentFilename()); + KFileDetailView::setSelected(currentFileItem(), true); + + // Scroll the contents to last known coordinates + setContentsPos(history[index].contentsX(), history[index].contentsY()); + } + + m_treeView->openUrl(m_navigator->url()); + m_treeView->endUpdate(m_navigator->url()); + setFocus(); +} + +void DetailsView::openUrl(const KURL &url) +{ + m_navigator->setUrl(url); +} + +void DetailsView::slotClear() +{ + clearView(); +} + +void DetailsView::slotDeleteItem(KFileItem *item) +{ + removeItem(item); + + if (item->isDir()) + m_treeView->removeFolder(item->url()); +} + +void DetailsView::slotCompleted() +{ + m_refreshing = true; + + clearView(); + + KFileItemList items(m_dirLister->items()); + KFileItemListIterator i(items); + + KFileItem *item = 0; + while ((item = i.current()) != 0) { + insertItem(item); + + if (item->isDir()) + m_treeView->createFolder(item->url(), item->pixmap(16)); + + ++i; + } + + endItemUpdates(); + m_refreshing = false; + + m_view->updateActions(); +} + +void DetailsView::slotRefreshItems() +{ + QTimer::singleShot(0, this, SLOT(reload())); +} + +void DetailsView::reload() +{ + fetchLocation(m_navigator->url(), true); +} + +void DetailsView::slotUrlChanged(const KURL &url) +{ + fetchLocation(url); +} + +void DetailsView::slotSiteChanged(const KURL &url) +{ + m_navigator->clear(); + m_treeView->resetView(url); +} + +void DetailsView::fetchLocation(const KURL &url, bool reload) +{ + m_dirLister->setShowingDotFiles(m_showHidden); + m_dirLister->fetchLocation(url, reload); +} + +void DetailsView::slotContentsMoving(int x, int y) +{ + if (!m_refreshing) + emit contentsMoved(x, y); +} + +void DetailsView::slotItemExecuted() +{ + KFileItem *item = currentFileItem(); + + if (item) { + if (item->isDir()) + openUrl(item->url()); + } +} + +void DetailsView::slotHeaderResized(int section) +{ + if (m_autoResizeEnabled && m_shouldDisableResize && section == 0) { + setHScrollBarMode(QScrollView::Auto); + m_autoResizeEnabled = false; + } +} + +void DetailsView::resizeContents(int width, int height) +{ + m_shouldDisableResize = false; + + KFileDetailView::resizeContents(width, height); + + // Update the column widths + if (m_autoResizeEnabled) { + m_resizeTimer->stop(); + m_resizeTimer->start(50, true); + } +} + +void DetailsView::resizeEvent(QResizeEvent *event) +{ + m_shouldDisableResize = false; + + KFileDetailView::resizeEvent(event); + + // Update the column widths + if (m_autoResizeEnabled) { + m_resizeTimer->stop(); + m_resizeTimer->start(50, true); + } +} + +void DetailsView::updateColumnWidths() +{ + // The code below is based on Dolphin, Copyright (C) 2006 by Peter Penz + const int columnCount = columns(); + int requiredWidth = 0; + + for (int i = 1; i < columnCount; ++i) { + // When a directory contains no items, a minimum width for + // the column must be available, so that the header is readable. + int columnWidth = 64; + QFontMetrics fontMetrics(font()); + + for (QListViewItem* item = firstChild(); item != 0; item = item->nextSibling()) { + const int width = item->width(fontMetrics, this, i); + + if (width > columnWidth) { + columnWidth = width; + } + } + + // Add custom margin + columnWidth += 16; + setColumnWidth(i, columnWidth); + requiredWidth += columnWidth; + } + + // Resize the first column in a way that the whole available width is used + int firstColumnWidth = visibleWidth() - requiredWidth; + if (firstColumnWidth < 128) { + firstColumnWidth = 128; + } + + setColumnWidth(0, firstColumnWidth); + m_shouldDisableResize = true; +} + +void DetailsView::insertItem(KFileItem *fileItem) +{ + const ActionChain *actionChain = Filters::self()->process(fileItem->url(), fileItem->size(), fileItem->isDir()); + const Action *action; + + if ((actionChain && actionChain->getAction(Action::Hide))) + return; + + KFileView::insertItem(fileItem); + + ListViewItem *item = new ListViewItem(this, fileItem); + + if (actionChain && (action = actionChain->getAction(Action::Colorize))) + item->setColor(action->value().toColor()); + + QDir::SortSpec spec = KFileView::sorting(); + if (spec & QDir::Time) { + item->setKey(sortingKey(fileItem->time(KIO::UDS_MODIFICATION_TIME), fileItem->isDir(), spec)); + } else if (spec & QDir::Size) { + item->setKey(sortingKey(fileItem->size(), fileItem->isDir(), spec)); + } else { + item->setKey(sortingKey(fileItem->text(), fileItem->isDir(), spec)); + } + + fileItem->setExtraData(this, item); +} + +void DetailsView::slotContextMenu(KListView*, QListViewItem *i, const QPoint &p) +{ + m_view->updateActions(); + + // Create the popup menu + KPopupMenu *menu = new KPopupMenu(this); + + Actions *actions = m_view->m_actions; + + // Always show create directory + actions->m_createDirAction->plug(menu); + menu->insertSeparator(); + + // If nothing is selected, show the navigation menus + if (!i) { + actions->m_goUpAction->plug(menu); + actions->m_goBackAction->plug(menu); + actions->m_goForwardAction->plug(menu); + actions->m_reloadAction->plug(menu); + } else { + actions->m_transferAction->plug(menu); + actions->m_queueTransferAction->plug(menu); + actions->m_renameAction->plug(menu); + actions->m_deleteAction->plug(menu); + actions->m_shredAction->plug(menu); + actions->m_fileEditAction->plug(menu); + actions->m_verifyAction->plug(menu); + menu->insertSeparator(); + actions->m_copyAction->plug(menu); + actions->m_pasteAction->plug(menu); + menu->insertSeparator(); + actions->m_filterActions->plug(menu); + } + + // Always show properties + menu->insertSeparator(); + actions->m_propsAction->plug(menu); + + menu->exec(p); +} + +void DetailsView::slotItemRenamed(QListViewItem *item, const QString &name) +{ + KFileItem *fileItem = static_cast<KFileListViewItem*>(item)->fileInfo(); + m_view->rename(fileItem->url(), name); +} + +QDragObject *DetailsView::dragObject() +{ + KURLDrag *object = static_cast<KURLDrag*>(KFileDetailView::dragObject()); + + // Add some metadata + const KFileItemList *list = KFileView::selectedItems(); + + if (list) { + KFileItemListIterator i(*list); + KFileItem *item; + + while ((item = i.current()) != 0) { + QString type = item->isDir() ? "D" : "F"; + object->metaData().insert(item->url().htmlURL().local8Bit(), type + ":" + KIO::number(item->size())); + ++i; + } + } + + return object; +} + +bool DetailsView::acceptDrag(QDropEvent *event) const +{ + return KURLDrag::canDecode(event) && + (event->action() == QDropEvent::Copy || + event->action() == QDropEvent::Move || + event->action() == QDropEvent::Link) && + event->source() != this; +} + +void DetailsView::contentsDropEvent(QDropEvent *event) +{ + if (!acceptDrag(event)) + return; + + KIO::MetaData meta; + KURL::List urls; + KURLDrag::decode(event, urls, meta); + + meta.insert("DestURL", url().url()); + KFTPQueue::Manager::self()->insertTransfer(new KURLDrag(urls, meta, this, name())); +} + +KFileItem *DetailsView::fileItem(const QString &filename) +{ + if (!filename.isNull()) { + KFileItem *item; + + for (item = firstFileItem(); item; item = nextItem(item)) { + if (item->name() == filename) + return item; + } + } + + return 0; +} + +void DetailsView::setItemVisibility(KFileItem *item, int visibility) +{ + ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this)); + + if (i) { + if (visibility != 0 && visibility != 1) + visibility = !i->isVisible(); + + i->setVisible(visibility); + } +} + +void DetailsView::setItemColor(KFileItem *item, const QColor &text, const QColor &background) +{ + ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this)); + + if (i) { + i->setColor(text); + i->setBackground(background); + i->repaint(); + } +} + +void DetailsView::markItem(KFileItem *item) +{ + ListViewItem *i = static_cast<ListViewItem*>(item->extraData(this)); + + if (i) { + i->markItem(!i->marked()); + } +} + +void DetailsView::markItem(const QString &filename) +{ + if (KFileItem *item = fileItem(filename)) + markItem(item); +} + +void DetailsView::unmarkItems() +{ + KFileItem *item; + + for (item = firstFileItem(); item; item = nextItem(item)) { + static_cast<ListViewItem*>(item->extraData(this))->markItem(false); + } +} + +DetailsView::ListViewItem::ListViewItem(QListView *parent, KFileItem *fileItem) + : KFileListViewItem(parent, fileItem), + m_marked(false) +{ + if (fileItem->isDir() && !KFTPCore::Config::showDirectorySize()) { + setText(SizeColumn, " - "); + } else { + QString sizeText; + sizeText = KFTPCore::Config::showSizeInBytes() ? KIO::number(fileItem->size()) : KIO::convertSize(fileItem->size()); + sizeText.append(" "); + + setText(SizeColumn, sizeText); + } +} + +void DetailsView::ListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup colorGroup(cg); + QColor textColor = colorGroup.text(); + + // Set custom file item color if set + if (m_textColor.isValid()) + colorGroup.setColor(QColorGroup::Text, m_textColor); + + // Set custom file item font + QFont font = p->font(); + font.setBold(m_marked); + p->setFont(font); + + if (m_backgroundColor.isValid()) { + colorGroup.setColor(QColorGroup::Base, m_backgroundColor); + + // Override the KListViewItem since it resets the background color + QListViewItem::paintCell(p, colorGroup, column, width, alignment); + } else { + KFileListViewItem::paintCell(p, colorGroup, column, width, alignment); + } + + if (column < listView()->columns() - 1) { + // Draw a separator between columns + p->setPen(KGlobalSettings::buttonBackground()); + p->drawLine(width - 1, 0, width - 1, height() - 1); + } +} + +void DetailsView::ListViewItem::markItem(bool marked) +{ + if (m_marked != marked) { + m_marked = marked; + repaint(); + } +} + +} + +} + +#include "detailsview.moc" diff --git a/kftpgrabber/src/widgets/browser/detailsview.h b/kftpgrabber/src/widgets/browser/detailsview.h new file mode 100644 index 0000000..eb60b70 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/detailsview.h @@ -0,0 +1,374 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETS_BROWSERDETAILSVIEW_H +#define KFTPWIDGETS_BROWSERDETAILSVIEW_H + +#include "browser/locationnavigator.h" + +#include <kfiledetailview.h> +#include <kdirlister.h> + +namespace KFTPSession { + class Session; +} + +namespace KFTPWidgets { + +namespace Browser { + +class DirLister; +class TreeView; +class View; + +/** + * This class represents a detailed list view for displaying local and + * remote directory contents. It is based upon KFileDetailView but uses + * a custom (wrapped) DirLister for actual listings. + * + * @author Jernej Kos + */ +class DetailsView : public KFileDetailView { +Q_OBJECT +public: + /** + * Maps the column indices of KFileDetailView to a + * descriptive column name. + */ + enum ColumnName { + NameColumn = 0, + SizeColumn = 1, + DateColumn = 2, + PermissionsColumn = 3, + OwnerColumn = 4, + GroupColumn = 5 + }; + + /** + * Class constructor. + * + * @param parent Parent widget + * @param view Main view container + * @param session Current session + */ + DetailsView(QWidget *parent, View *view, KFTPSession::Session *session); + + /** + * Class destructor. + */ + ~DetailsView(); + + /** + * Returns the navigator object for navigating this view. + */ + const LocationNavigator *locationNavigator() const { return m_navigator; } + + /** + * Returns the current URL. + */ + const KURL &url() const; + + /** + * Returns the current history elements. + * + * @param index Variable to save the current history position to + * @return Current history element list + */ + const QValueList<LocationNavigator::Element> history(int &index) const; + + /** + * @overload + * Reimplemented from KFileView to support filtered views. + */ + bool isSelected(const KFileItem *i) const; + + /** + * Set the tree view widget to use for the tree. + * + * @param tree A valid tree view widget + */ + void setTreeView(TreeView *tree); + + /** + * Set the home URL. + * + * @param url URL to use as home URL + */ + void setHomeUrl(const KURL &url); + + /** + * Changes the "show hidden files" setting. + * + * @param value True to enable showing hidden files, false otherwise + */ + void setShowHidden(bool value) { m_showHidden = value; } + + /** + * Go one history hop back. + */ + void goBack(); + + /** + * Go one history hop forward. + */ + void goForward(); + + /** + * Go up in the directory structure. + */ + void goUp(); + + /** + * Go the the predefined home URL. + */ + void goHome(); + + /** + * Do item post-processing. + */ + void endItemUpdates(); + + /** + * @overload + * Reimplemented from KFileDetailView. + */ + void insertItem(KFileItem *fileItem); + + /** + * Fetch a file item by its filename. + * + * @param file Item's filename + */ + KFileItem *fileItem(const QString &filename); + + /** + * Changes item's colors in the list view. Note that this overrides any + * highlight colors predefined by user filters. + * + * @param item The item to change colors for + * @param text Text color + * @param background Background color + */ + void setItemColor(KFileItem *item, const QColor &text, const QColor &background); + + /** + * Changes item's visibility in the list view. + * + * @param item The item tho change visiblity for + * @param visibility 1 if the item should be visible, 0 if it should be hidden, reverse otherwise + */ + void setItemVisibility(KFileItem *item, int visibility = -1); + + /** + * Mark or unmark the item. If the item is already marked it will be + * unmarked and vice-versa. + * + * @param item The item to mark + */ + void markItem(KFileItem *item); + + /** + * Mark or unmark the item identified by its filename. If the item is + * already marked it will be unmarked and vice-versa. + * + * @param filename Item's filename + */ + void markItem(const QString &filename); + + /** + * Unmark all items. + */ + void unmarkItems(); +public slots: + /** + * Open an URL. Note that if a remote URL is specified the session needs to + * be connected to the specified host! + * + * @param url URL to open + */ + void openUrl(const KURL &url); + + /** + * Reload the current directory listing. + */ + void reload(); + + /** + * Calculates new widths for all the columns. + */ + void updateColumnWidths(); + + /** + * This method gets called when the widget is resized. It is used for automatic + * resize handling. + * + * @param width The new width + * @param height The new height + */ + void resizeContents(int width, int height); + + /** + * Returns the drag object to use for copy/paste and "drag and drop". + */ + QDragObject *dragObject(); +protected: + /** + * Instruct the directory lister object to fetch the specified URL. + * + * @param url URL to fetch + * @param reload Should the cache be invalidated + */ + void fetchLocation(const KURL &url, bool reload = false); + + /** + * This method gets called when the widget is resized. It is used for automatic + * resize handling. + */ + void resizeEvent(QResizeEvent *event); + + /** + * Returns true if the drop event should be accepted. + */ + bool acceptDrag(QDropEvent *event) const; + + /** + * Called when something acceptable gets dropped on us. + */ + void contentsDropEvent(QDropEvent *event); +private: + class ListViewItem : public KFileListViewItem { + public: + ListViewItem(QListView *parent, KFileItem *fileItem); + + /** + * @overload + * Reimplemented from KListView to implement nicer items. + */ + void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + + /** + * Set a text color for this item. + * + * @param color Text color + */ + void setColor(QColor color) { m_textColor = color; } + + /** + * Set a background color for this item. + * + * @param color Background color + */ + void setBackground(QColor color) { m_backgroundColor = color; } + + /** + * Set marked state for this item. + * + * @param marked True if this item should be marked, false otherwise + */ + void markItem(bool marked); + + /** + * Returns true if this item is marked. + */ + bool marked() const { return m_marked; } + private: + QColor m_textColor; + QColor m_backgroundColor; + bool m_marked; + }; + + View *m_view; + DirLister *m_dirLister; + LocationNavigator *m_navigator; + TreeView *m_treeView; + QTimer *m_resizeTimer; + + bool m_refreshing; + bool m_showHidden; + bool m_shouldDisableResize; + bool m_autoResizeEnabled; +protected slots: + void slotClear(); + void slotCompleted(); + void slotDeleteItem(KFileItem *item); + void slotRefreshItems(); + void slotSiteChanged(const KURL &url); + + void slotUrlChanged(const KURL &url); + + /** + * This slot gets called when an item has been renamed. + */ + void slotItemRenamed(QListViewItem *item, const QString &name); + + void slotContentsMoving(int x, int y); + + /** + * This slot gets called when a context menu should be displayed. + */ + void slotContextMenu(KListView*, QListViewItem *i, const QPoint &p); + + /** + * This slot gets called when an item has been clicked. + */ + void slotItemExecuted(); + + /** + * This slot gets called when a section in listview's header is resized. This + * is needed for proper automatic resize handling. + * + * @param section The section that was resized + */ + void slotHeaderResized(int section); +signals: + /** + * This signals gets emitted when user scrolls the widget. + * + * @param x New X position + * @param y New Y position + */ + void contentsMoved(int x, int y); + + /** + * This signal is emitted when items change. + */ + void itemsChanged(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/dirlister.cpp b/kftpgrabber/src/widgets/browser/dirlister.cpp new file mode 100644 index 0000000..4d539e4 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/dirlister.cpp @@ -0,0 +1,169 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "dirlister.h" + +#include "engine/thread.h" +#include "engine/cache.h" + +#include "kftpsession.h" + +#include <kmessagebox.h> +#include <klocale.h> + +using namespace KFTPEngine; + +namespace KFTPWidgets { + +namespace Browser { + +DirLister::DirLister(QObject *parent) + : QObject(parent) +{ + m_localLister = new KDirLister(); + m_localLister->setAutoUpdate(true); + + enableLocal(); +} + +DirLister::~DirLister() +{ + delete m_localLister; +} + +void DirLister::setSession(KFTPSession::Session *session) +{ + m_remoteSession = session; +} + +void DirLister::fetchLocation(const KURL &url, bool reload) +{ + if (m_url.isLocalFile() != url.isLocalFile()) + emit siteChanged(url); + + m_url = url; + + if (url.isLocalFile()) { + enableLocal(); + + m_localLister->stop(); + m_localLister->setShowingDotFiles(m_showHidden); + m_localLister->openURL(url, false, reload); + } else { + enableRemote(); + + if (reload) { + KURL tmp = url; + Cache::self()->invalidateEntry(tmp); + } + + emit clear(); + m_remoteSession->getClient()->list(url); + } +} + +void DirLister::enableLocal() +{ + m_localLister->stop(); + m_localLister->QObject::disconnect(this); + + connect(m_localLister, SIGNAL(clear()), this, SIGNAL(clear())); + connect(m_localLister, SIGNAL(completed()), this, SIGNAL(completed())); + connect(m_localLister, SIGNAL(deleteItem(KFileItem*)), this, SIGNAL(deleteItem(KFileItem*))); + connect(m_localLister, SIGNAL(refreshItems(const KFileItemList&)), this, SIGNAL(refreshItems())); +} + +void DirLister::enableRemote() +{ + m_localLister->stop(); + m_localLister->QObject::disconnect(this); + m_remoteSession->getClient()->eventHandler()->QObject::disconnect(this); + + connect(m_remoteSession->getClient()->eventHandler(), SIGNAL(engineEvent(KFTPEngine::Event*)), this, SLOT(slotRemoteEngineEvent(KFTPEngine::Event*))); +} + +void DirLister::disableRemote() +{ + m_remoteSession->getClient()->eventHandler()->QObject::disconnect(this); +} + +void DirLister::stop() +{ + if (m_url.isLocalFile()) + m_localLister->stop(); +} + +KFileItemList DirLister::items() const +{ + if (m_url.isLocalFile()) + return m_localLister->items(); + else + return m_items; +} + +void DirLister::slotRemoteEngineEvent(KFTPEngine::Event *event) +{ + switch (event->type()) { + case Event::EventError: { + KMessageBox::error(0, i18n("Could not enter folder %1.").arg(m_url.path()), i18n("Error")); + disableRemote(); + break; + } + case Event::EventDirectoryListing: { + m_items.clear(); + + // Populate the item list + QValueList<DirectoryEntry> list = event->getParameter(0).asDirectoryListing().list(); + QValueList<DirectoryEntry>::ConstIterator end(list.end()); + for (QValueList<DirectoryEntry>::ConstIterator i(list.begin()); i != end; ++i) { + if (!m_showHidden && (*i).filename().at(0) == '.') + continue; + + m_items.append(new KFileItem((*i).toUdsEntry(), m_url, false, true)); + } + + disableRemote(); + emit completed(); + break; + } + default: break; + } +} + +} + +} + +#include "dirlister.moc" diff --git a/kftpgrabber/src/widgets/browser/dirlister.h b/kftpgrabber/src/widgets/browser/dirlister.h new file mode 100644 index 0000000..730704f --- /dev/null +++ b/kftpgrabber/src/widgets/browser/dirlister.h @@ -0,0 +1,157 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETS_BROWSERDIRLISTER_H +#define KFTPWIDGETS_BROWSERDIRLISTER_H + +#include <qobject.h> + +#include <kurl.h> +#include <kdirlister.h> + +namespace KFTPSession { + class Session; +} + +namespace KFTPEngine { + class Event; +} + +namespace KFTPWidgets { + +namespace Browser { + +/** + * This class is a wrapper around KDirLister to support remote listings + * via engine sockets. + * + * @author Jernej Kos + */ +class DirLister : public QObject { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent object + */ + DirLister(QObject *parent); + + /** + * Class destructor. + */ + ~DirLister(); + + /** + * Set the remote session. You have to call this method before anything else + * in this class! + * + * @param session A valid session + */ + void setSession(KFTPSession::Session *session); + + /** + * Changes the "show hidden files" setting. + * + * @param value True to enable showing hidden files, false otherwise + */ + void setShowingDotFiles(bool value) { m_showHidden = value; } + + /** + * Fetch a specific location. + * + * @param url The URL to fetch (can be local or remote) + * @param reload If set to true listing cache will be invalidated + */ + void fetchLocation(const KURL &url, bool reload); + + /** + * Stop the current listing operation. + */ + void stop(); + + /** + * Returns the items listed for the current URL. You should call this when receiving + * the finished() signal. + * + * @return The items listed for the current URL + */ + KFileItemList items() const; +protected: + void enableLocal(); + void enableRemote(); + void disableRemote(); +private: + KDirLister *m_localLister; + KFTPSession::Session *m_remoteSession; + KFileItemList m_items; + KURL m_url; + bool m_showHidden; +private slots: + void slotRemoteEngineEvent(KFTPEngine::Event *event); +signals: + /** + * Emitted when all items should be cleared. + */ + void clear(); + + /** + * Emitted when the listing operation has been completed. + */ + void completed(); + + /** + * Emitted when an item has to be removed. + */ + void deleteItem(KFileItem *item); + + /** + * Emitted when items should be refreshed. + */ + void refreshItems(); + + /** + * Emitted when site changes from local to remote or vice-versa. + * + * @param url New site URL + */ + void siteChanged(const KURL &url); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/filterwidget.cpp b/kftpgrabber/src/widgets/browser/filterwidget.cpp new file mode 100644 index 0000000..47f88d9 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/filterwidget.cpp @@ -0,0 +1,118 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "browser/filterwidget.h" +#include "browser/detailsview.h" + +#include <qlistview.h> +#include <qregexp.h> +#include <qpopupmenu.h> + +#include <klocale.h> + +namespace KFTPWidgets { + +namespace Browser { + +FilterWidget::FilterWidget(QWidget *parent, DetailsView *view) + : KListViewSearchLine(parent, view), + m_filterDirectories(true), + m_filterSymlinks(true), + m_caseSensitive(false) +{ + connect(view, SIGNAL(itemsChanged()), this, SLOT(updateSearch())); +} + +bool FilterWidget::itemMatches(const QListViewItem *item, const QString &pattern) const +{ + if (!pattern.isEmpty()) { + const KFileListViewItem *i = dynamic_cast<const KFileListViewItem*>(item); + + if (i) { + if (i->fileInfo()->isDir() && !m_filterDirectories) + return true; + else if (i->fileInfo()->isLink() && !m_filterSymlinks) + return true; + } + + QRegExp filter(pattern); + filter.setCaseSensitive(m_caseSensitive); + filter.setWildcard(true); + + return filter.search(item->text(0)) > -1; + } + + return true; +} + +QPopupMenu *FilterWidget::createPopupMenu() +{ + QPopupMenu *popup = KLineEdit::createPopupMenu(); + + QPopupMenu *subMenu = new QPopupMenu(popup); + connect(subMenu, SIGNAL(activated(int)), this, SLOT(slotOptionsMenuActivated(int))); + + popup->insertSeparator(); + popup->insertItem(i18n("Filter Options"), subMenu); + + subMenu->insertItem(i18n("Filter Directories"), FilterWidget::FilterDirectories); + subMenu->setItemChecked(FilterWidget::FilterDirectories, m_filterDirectories); + + subMenu->insertItem(i18n("Filter Symlinks"), FilterWidget::FilterSymlinks); + subMenu->setItemChecked(FilterWidget::FilterSymlinks, m_filterSymlinks); + + subMenu->insertItem(i18n("Case Sensitive"), FilterWidget::CaseSensitive); + subMenu->setItemChecked(FilterWidget::CaseSensitive, m_caseSensitive); + + return popup; +} + +void FilterWidget::slotOptionsMenuActivated(int id) +{ + switch (id) { + case FilterDirectories: m_filterDirectories = !m_filterDirectories; break; + case FilterSymlinks: m_filterSymlinks = !m_filterSymlinks; break; + case CaseSensitive: m_caseSensitive = !m_caseSensitive; break; + default: break; + } + + updateSearch(); +} + +} + +} + +#include "filterwidget.moc" diff --git a/kftpgrabber/src/widgets/browser/filterwidget.h b/kftpgrabber/src/widgets/browser/filterwidget.h new file mode 100644 index 0000000..f5429cf --- /dev/null +++ b/kftpgrabber/src/widgets/browser/filterwidget.h @@ -0,0 +1,97 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETS_BROWSERFILTERWIDGET_H +#define KFTPWIDGETS_BROWSERFILTERWIDGET_H + +#include <klistviewsearchline.h> + +namespace KFTPWidgets { + +namespace Browser { + +class DetailsView; + +/** + * This class is a simple filtering widget that accepts wildcard + * patterns and filters listviews. Note that this widget only + * filters on the first column. + * + * @author Jernej Kos <kostko@jweb-network.net> + */ +class FilterWidget : public KListViewSearchLine { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent The parent widget + * @param view The view you want to filter + */ + FilterWidget(QWidget *parent, DetailsView *view); +protected: + enum { + FilterDirectories = 1, + FilterSymlinks = 2, + CaseSensitive = 3 + }; + + /** + * @overload + * Reimplemented from KListViewSearchLine to support wildcard + * matching schemes. + */ + bool itemMatches(const QListViewItem *item, const QString &pattern) const; + + /** + * @overload + * Reimplemented from KListViewSearchLine to remove multiple + * columns selection, since this widget only operates on the + * first column. + */ + QPopupMenu *createPopupMenu(); +private: + bool m_filterDirectories; + bool m_filterSymlinks; + bool m_caseSensitive; +private slots: + void slotOptionsMenuActivated(int id); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/locationnavigator.cpp b/kftpgrabber/src/widgets/browser/locationnavigator.cpp new file mode 100644 index 0000000..5be8004 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/locationnavigator.cpp @@ -0,0 +1,173 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "locationnavigator.h" +#include "detailsview.h" + +namespace KFTPWidgets { + +namespace Browser { + +LocationNavigator::Element::Element() + : m_url(), + m_currentFilename(), + m_contentsX(0), + m_contentsY(0) +{ +} + +LocationNavigator::Element::Element(const KURL &url) + : m_url(url), + m_currentFilename(), + m_contentsX(0), + m_contentsY(0) +{ +} + +LocationNavigator::LocationNavigator(DetailsView *view) + : m_view(view), + m_historyIndex(0) +{ + connect(view, SIGNAL(contentsMoved(int, int)), this, SLOT(slotContentsMoved(int, int))); +} + +void LocationNavigator::setUrl(const KURL &url) +{ + if (m_historyIndex > 0) { + const KURL &nextUrl = m_history[m_historyIndex - 1].url(); + + if (url == nextUrl) { + goForward(); + return; + } + } + + // Check for duplicates + const KURL ¤tUrl = m_history[m_historyIndex].url(); + if (currentUrl == url) + return; + + updateCurrentElement(); + + const QValueListIterator<LocationNavigator::Element> i = m_history.at(m_historyIndex); + m_history.insert(i, Element(url)); + + emit urlChanged(url); + emit historyChanged(); + + // Cleanup history when it becomes too big + if (m_historyIndex > 100) { + m_history.erase(m_history.begin()); + m_historyIndex--; + } +} + +const KURL& LocationNavigator::url() const +{ + return m_history[m_historyIndex].url(); +} + +const QValueList<LocationNavigator::Element> LocationNavigator::history(int &index) const +{ + index = m_historyIndex; + return m_history; +} + +void LocationNavigator::goBack() +{ + updateCurrentElement(); + const int count = m_history.count(); + + if (m_historyIndex < count - 1) { + m_historyIndex++; + + emit urlChanged(url()); + emit historyChanged(); + } +} + +void LocationNavigator::goForward() +{ + if (m_historyIndex > 0) { + m_historyIndex--; + + emit urlChanged(url()); + emit historyChanged(); + } +} + +void LocationNavigator::goUp() +{ + setUrl(url().upURL()); +} + +void LocationNavigator::goHome() +{ + setUrl(m_homeUrl); +} + +void LocationNavigator::clear() +{ + Element element = m_history[m_historyIndex]; + + m_history.clear(); + m_historyIndex = 0; + + m_history.append(element); +} + +void LocationNavigator::slotContentsMoved(int x, int y) +{ + m_history[m_historyIndex].setContentsX(x); + m_history[m_historyIndex].setContentsY(y); +} + +void LocationNavigator::updateCurrentElement() +{ + const KFileItem *item = m_view->currentFileItem(); + + if (item) + m_history[m_historyIndex].setCurrentFilename(item->name()); + + m_history[m_historyIndex].setContentsX(m_view->contentsX()); + m_history[m_historyIndex].setContentsY(m_view->contentsY()); +} + +} + +} + +#include "locationnavigator.moc" + diff --git a/kftpgrabber/src/widgets/browser/locationnavigator.h b/kftpgrabber/src/widgets/browser/locationnavigator.h new file mode 100644 index 0000000..475a3af --- /dev/null +++ b/kftpgrabber/src/widgets/browser/locationnavigator.h @@ -0,0 +1,210 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETS_BROWSERLOCATIONNAVIGATOR_H +#define KFTPWIDGETS_BROWSERLOCATIONNAVIGATOR_H + +#include <qobject.h> +#include <qvaluelist.h> + +#include <kurl.h> + +namespace KFTPWidgets { + +namespace Browser { + +class DetailsView; + +/** + * This class contains the current navigational history and enables + * moving through it. + * + * @author Jernej Kos + */ +class LocationNavigator : public QObject { +Q_OBJECT +public: + /** + * An Element instance represents one history element. The class contains + * information about the URL, the selected item and the contents position. + */ + class Element { + public: + /** + * Class constructor. + */ + Element(); + + /** + * Class constructor. + * + * @param url Element's URL + */ + Element(const KURL &url); + + /** + * Returns the element's URL. + */ + const KURL &url() const { return m_url; } + + /** + * Set currently selected filename. + * + * @param filename The filename of the currently selected item + */ + void setCurrentFilename(const QString &filename) { m_currentFilename = filename; } + + /** + * Returns the selected filename. + */ + const QString ¤tFilename() const { return m_currentFilename; } + + /** + * Set current contents X position. + * + * @param x Contents X position + */ + void setContentsX(int x) { m_contentsX = x; } + + /** + * Returns the saved contents X position. + */ + int contentsX() const { return m_contentsX; } + + /** + * Set current contents Y position. + * + * @param y Contents Y position + */ + void setContentsY(int y) { m_contentsY = y; } + + /** + * Returns the saved contents Y position. + */ + int contentsY() const { return m_contentsY; } + private: + KURL m_url; + QString m_currentFilename; + + int m_contentsX; + int m_contentsY; + }; + + /** + * Class constructor. + * + * @param view Parent view + */ + LocationNavigator(DetailsView *view); + + /** + * Set a new current URL. Calling this will emit the urlChanged signal. + * + * @param url Wanted URL + */ + void setUrl(const KURL &url); + + /** + * Returns the current URL. + */ + const KURL &url() const; + + /** + * Returns the current history elements. + * + * @param index Variable to save the current history position to + * @return Current history element list + */ + const QValueList<Element> history(int &index) const; + + /** + * Go one history hop back. + */ + void goBack(); + + /** + * Go one history hop forward. + */ + void goForward(); + + /** + * Go up in the directory structure. + */ + void goUp(); + + /** + * Go the the predefined home URL. + */ + void goHome(); + + /** + * Set the home URL. + * + * @param url URL to use as home URL + */ + void setHomeUrl(const KURL &url) { m_homeUrl = url; } + + /** + * Clear current history. + */ + void clear(); +signals: + /** + * This signal is emitted whenever the current URL changes. + * + * @param url The new URL + */ + void urlChanged(const KURL &url); + + /** + * This signal is emitted whenever the history is updated. + */ + void historyChanged(); +private slots: + void slotContentsMoved(int x, int y); +private: + DetailsView *m_view; + int m_historyIndex; + QValueList<Element> m_history; + KURL m_homeUrl; + + void updateCurrentElement(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/propsplugin.cpp b/kftpgrabber/src/widgets/browser/propsplugin.cpp new file mode 100644 index 0000000..b6e688d --- /dev/null +++ b/kftpgrabber/src/widgets/browser/propsplugin.cpp @@ -0,0 +1,360 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "browser/propsplugin.h" +#include "kftpsession.h" + +#include <qlayout.h> +#include <qlabel.h> +#include <qstyle.h> +#include <qgroupbox.h> + +#include <klocale.h> +#include <kiconloader.h> +#include <kseparator.h> +#include <ksqueezedtextlabel.h> + +using namespace KFTPEngine; + +namespace KFTPWidgets { + +namespace Browser { + +PropsPlugin::PropsPlugin(KPropertiesDialog *props, KFileItemList items) + : KPropsDlgPlugin(props) +{ + QFrame *frame = properties->addPage(i18n("&General")); + frame->setMinimumWidth(320); + frame->setMinimumHeight(300); + + // Some differences between a single file and multiple files + KFileItem *item = items.at(0); + KURL fileUrl = item->url(); + filesize_t fileSize = item->size(); + QString nameText; + QString iconText; + QString mimeComment; + + if (items.count() == 1) { + bool isDir = false; + + // Guess file type + if (item->isDir()) { + iconText = "folder"; + isDir = true; + mimeComment = i18n("Remote folder"); + } else if (item->isLink()) { + // We can't know if the sym-linked file is realy a directory, but most of + // the time it is. So if we can't determine the MIME type, set it to directory. + KMimeType::Ptr mimeType = KMimeType::findByURL(fileUrl, 0, false, true); + + if (mimeType->name() == KMimeType::defaultMimeType()) { + iconText = "folder"; + isDir = true; + mimeComment = i18n("Remote folder"); + } else { + iconText = mimeType->icon(QString::null, false); + mimeComment = mimeType->comment(); + } + } else { + KMimeType::Ptr mimeType = KMimeType::findByURL(fileUrl, 0, false, true); + iconText = mimeType->icon(QString::null, false); + mimeComment = mimeType->comment(); + } + + if (mimeComment.isEmpty()) { + mimeComment = i18n("Unknown"); + } + + nameText = item->name(); + } else { + // Count files and folders selected + int countFiles = 0; + int countFolders = 0; + fileSize = 0; + + KFileItemListIterator i(items); + for (; i.current(); ++i) { + if ((*i)->isDir()) + countFolders++; + else + countFiles++; + + fileSize += (*i)->size(); + } + + iconText = "kmultiple"; + nameText = KIO::itemsSummaryString(countFiles + countFolders, countFiles, countFolders, 0, false); + } + + QVBoxLayout *vbl = new QVBoxLayout(frame, 0, KDialog::spacingHint(), "vbl"); + QGridLayout *grid = new QGridLayout(0, 3); + grid->setColStretch(0, 0); + grid->setColStretch(1, 0); + grid->setColStretch(2, 1); + grid->addColSpacing(1, KDialog::spacingHint()); + vbl->addLayout(grid); + + // Display file name and icon + QLabel *iconLabel = new QLabel(frame); + int bsize = 66 + 2 * iconLabel->style().pixelMetric(QStyle::PM_ButtonMargin); + iconLabel->setFixedSize(bsize, bsize); + iconLabel->setPixmap(DesktopIcon(iconText)); + grid->addWidget(iconLabel, 0, 0, AlignLeft); + + QLabel *nameLabel = new QLabel(frame); + nameLabel->setText(nameText); + grid->addWidget(nameLabel, 0, 2); + + KSeparator *sep = new KSeparator(KSeparator::HLine, frame); + grid->addMultiCellWidget(sep, 2, 2, 0, 2); + + // Display file information + QLabel *l; + int currentRow = 3; + + if (items.count() == 1) { + l = new QLabel(i18n("Type:"), frame); + grid->addWidget(l, currentRow, 0); + + l = new QLabel(mimeComment, frame); + grid->addWidget(l, currentRow++, 2); + } + + l = new QLabel(i18n("Location:"), frame); + grid->addWidget(l, currentRow, 0); + + l = new KSqueezedTextLabel(frame); + l->setText(fileUrl.directory()); + grid->addWidget(l, currentRow++, 2); + + l = new QLabel(i18n("Size:"), frame); + grid->addWidget(l, currentRow, 0); + + l = new QLabel(frame); + grid->addWidget(l, currentRow++, 2); + + l->setText(QString::fromLatin1("%1 (%2)").arg(KIO::convertSize(fileSize)) + .arg(KGlobal::locale()->formatNumber(fileSize, 0))); + + sep = new KSeparator(KSeparator::HLine, frame); + grid->addMultiCellWidget(sep, currentRow, currentRow, 0, 2); + currentRow++; + + // Display modification time + if (items.count() == 1) { + l = new QLabel(i18n("Created:"), frame); + grid->addWidget(l, currentRow, 0); + + QDateTime dt; + dt.setTime_t(item->time(KIO::UDS_MODIFICATION_TIME)); + l = new QLabel(KGlobal::locale()->formatDateTime(dt), frame); + grid->addWidget(l, currentRow++, 2); + } + + vbl->addStretch(1); +} + +void PropsPlugin::applyChanges() +{ +} + +mode_t PermissionsPropsPlugin::fperm[3][4] = { + {S_IRUSR, S_IWUSR, S_IXUSR, S_ISUID}, + {S_IRGRP, S_IWGRP, S_IXGRP, S_ISGID}, + {S_IROTH, S_IWOTH, S_IXOTH, S_ISVTX} +}; + +PermissionsPropsPlugin::PermissionsPropsPlugin(KPropertiesDialog *_props, KFileItemList items, KFTPSession::Session *session) + : KPropsDlgPlugin(_props), + m_items(items), + m_session(session), + m_cbRecursive(0) +{ + QFrame *frame = properties->addPage(i18n("&Permissions")); + frame->setMinimumWidth(320); + frame->setMinimumHeight(300); + + // Some differences between a single file and multiple files + KFileItem *item = items.at(0); + KURL fileUrl = item->url(); + bool isDir = false; + + if (items.count() == 1) { + // Guess file type + if (item->isDir()) { + isDir = true; + } else if (item->isLink()) { + // We can't know if the sym-linked file is realy a directory, but most of + // the time it is. So if we can't determine the MIME type, set it to directory. + KMimeType::Ptr mimeType = KMimeType::findByURL(fileUrl, 0, false, true); + + if (mimeType->name() == KMimeType::defaultMimeType()) + isDir = true; + } + } else { + // Check for directories + KFileItemListIterator i(items); + for (; i.current(); ++i) { + if ((*i)->isDir()) { + isDir = true; + break; + } + } + } + + QBoxLayout *box = new QVBoxLayout(frame, 0, KDialog::spacingHint()); + + QGroupBox *gb = new QGroupBox(0, Qt::Vertical, i18n("Access Permissions"), frame); + gb->layout()->setSpacing(KDialog::spacingHint()); + gb->layout()->setMargin(KDialog::marginHint()); + box->addWidget(gb); + + QGridLayout *gl = new QGridLayout(gb->layout(), 6, 6, 15); + + QLabel *l = new QLabel(i18n("Class"), gb); + gl->addWidget(l, 1, 0); + + if (isDir) + l = new QLabel(i18n("Show\nEntries"), gb); + else + l = new QLabel(i18n("Read"), gb); + gl->addWidget(l, 1, 1); + + if (isDir) + l = new QLabel(i18n("Write\nEntries"), gb); + else + l = new QLabel(i18n("Write"), gb); + gl->addWidget(l, 1, 2); + + if (isDir) + l = new QLabel(i18n("Enter folder", "Enter"), gb); + else + l = new QLabel(i18n("Exec"), gb); + + QSize size = l->sizeHint(); + size.setWidth(size.width() + 15); + l->setFixedSize(size); + gl->addWidget(l, 1, 3); + + l = new QLabel(i18n("Special"), gb); + gl->addMultiCellWidget(l, 1, 1, 4, 5); + + l = new QLabel(i18n("User"), gb); + gl->addWidget(l, 2, 0); + + l = new QLabel(i18n("Group"), gb); + gl->addWidget(l, 3, 0); + + l = new QLabel(i18n("Others"), gb); + gl->addWidget(l, 4, 0); + + l = new QLabel(i18n("Set UID"), gb); + gl->addWidget(l, 2, 5); + + l = new QLabel(i18n("Set GID"), gb); + gl->addWidget(l, 3, 5); + + l = new QLabel(i18n("Sticky"), gb); + gl->addWidget(l, 4, 5); + + mode_t permissions = item->permissions(); + + // Display checkboxes + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 4; ++col) { + QCheckBox *cb = new QCheckBox(gb); + connect(cb, SIGNAL(clicked()), this, SLOT(setDirty())); + m_permsCheck[row][col] = cb; + cb->setChecked(permissions & fperm[row][col]); + + gl->addWidget(cb, row + 2, col + 1); + } + } + + gl->setColStretch(6, 10); + box->addStretch(10); + + if (isDir) { + m_cbRecursive = new QCheckBox(i18n("Apply changes to all subfolders and their contents"), frame); + connect(m_cbRecursive, SIGNAL(clicked()), this, SLOT(changed())); + box->addWidget(m_cbRecursive); + } +} + +void PermissionsPropsPlugin::applyChanges() +{ + // Generate new permissions =) + int newPerms[4] = {0,}; + + for (int row = 0; row < 3; ++row) { + for (int col = 0; col < 4; ++col) { + if (!m_permsCheck[row][col]->isChecked()) continue; + + int x = col < 3 ? col : row; + int c = 0; + + switch (x) { + case 0: c = 4; break; + case 1: c = 2; break; + case 2: c = 1; break; + } + + if (col < 3) { + newPerms[row + 1] += c; + } else { + newPerms[0] += c; + } + } + } + + // Actually do a chmod + int mode = newPerms[0] * 1000 + newPerms[1] * 100 + newPerms[2] * 10 + newPerms[3]; + bool recursive = m_cbRecursive && m_cbRecursive->isChecked(); + + KFileItemListIterator i(m_items); + for (; i.current(); ++i) { + if ((*i)->isDir()) + m_session->getClient()->chmod((*i)->url(), mode, recursive); + else + m_session->getClient()->chmod((*i)->url(), mode); + } +} + +} + +} + +#include "propsplugin.moc" diff --git a/kftpgrabber/src/widgets/browser/propsplugin.h b/kftpgrabber/src/widgets/browser/propsplugin.h new file mode 100644 index 0000000..9283f85 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/propsplugin.h @@ -0,0 +1,98 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPFILEPROPSPLUGIN_H +#define KFTPFILEPROPSPLUGIN_H + +#include "engine/directorylisting.h" + +#include <qcheckbox.h> +#include <kpropertiesdialog.h> + +namespace KFTPSession { + class Session; +} + +namespace KFTPEngine { + class Thread; +} + +namespace KFTPWidgets { + +namespace Browser { + +/** + * This is a plugin for displaying remote file properties using the + * standard KDE file properties dialog. + * + * @author Jernej Kos + */ +class PropsPlugin : public KPropsDlgPlugin +{ +Q_OBJECT +public: + PropsPlugin(KPropertiesDialog *props, KFileItemList items); + + void applyChanges(); +}; + +/** + * This is a plugin for displaying remote file permissions and their + * changing using the standard KDE file properties dialog. + * + * @author Jernej Kos + */ +class PermissionsPropsPlugin : public KPropsDlgPlugin +{ +Q_OBJECT +public: + PermissionsPropsPlugin(KPropertiesDialog *props, KFileItemList items, KFTPSession::Session *session); + + void applyChanges(); +private: + KFileItemList m_items; + KFTPSession::Session *m_session; + + static mode_t fperm[3][4]; + QString m_perms[3]; + QCheckBox *m_permsCheck[3][4]; + QCheckBox *m_cbRecursive; +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/treeview.cpp b/kftpgrabber/src/widgets/browser/treeview.cpp new file mode 100644 index 0000000..0f2a824 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/treeview.cpp @@ -0,0 +1,520 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "browser/treeview.h" +#include "browser/view.h" + +#include "engine/thread.h" + +#include "misc.h" + +#include <qheader.h> +#include <qtimer.h> + +#include <kio/job.h> +#include <kurl.h> +#include <kurldrag.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +namespace Browser { + +/* + * TreeViewItem class + */ + +TreeViewItem::TreeViewItem(TreeView *parent, const KURL &url) + : QListViewItem(parent), + m_tree(parent), + m_url(url), + m_dirty(false) +{ + // Set the name + setText(0, path2Name(url.path(-1))); +} + +TreeViewItem::TreeViewItem(TreeView *tree, QListViewItem *parent, const KURL &url) + : QListViewItem(parent), + m_tree(tree), + m_url(url), + m_dirty(false) +{ + // Set the name + setText(0, path2Name(url.path(-1))); +} + +TreeViewItem::~TreeViewItem() +{ + // The item should be removed from the list as well + m_tree->m_treeItems.remove(m_url.path()); +} + +int TreeViewItem::compare(QListViewItem *i, int col, bool) const +{ + // Hidden files must be on top + if (m_url.fileName().at(0) == '.') + return -1; + + return QListViewItem::compare(i, col, false); +} + +/* + * TreeView class + */ + +TreeView::TreeView(QWidget *parent) + : KListView(parent) +{ + // Create the columns + addColumn(i18n("Directory")); + + // General tree settings + setDragEnabled(true); + setAcceptDrops(true); + setMinimumWidth(150); + setRootIsDecorated(false); + header()->hide(); + + // Reset the view + resetView(KURL("/")); + m_noItemOpen = false; + + // Connect signals + connect(this, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotClicked(QListViewItem*))); + connect(this, SIGNAL(doubleClicked(QListViewItem*)), this, SLOT(slotDoubleClicked(QListViewItem*))); + + // Drag and drop + m_dropItem = 0L; +} + + +TreeView::~TreeView() +{ + // Free the item index + m_treeItems.clear(); +} + +void TreeView::resetView(const KURL &url) +{ + // Free the item index + m_treeItems.clear(); + + // Clear the view + clear(); + header()->resizeSection(0, 0); + + // Create the root item + TreeViewItem *rootItem = new TreeViewItem(this, remoteUrl("/", url)); + rootItem->setText(0, url.isLocalFile() ? i18n("Root directory") : url.host()); + rootItem->setPixmap(0, loadSmallPixmap("folder_red")); + setOpen(rootItem, true); +} + +int TreeView::openUrl(const KURL &url, QListViewItem *parent) +{ + // Root item should always be open + setOpen(firstChild(), true); + + // Go trough all items in the list and try to find the url + QListViewItem *item; + if (!parent) + item = firstChild(); + else + item = parent; + + while (item) { + // Check if the item is correct + if (static_cast<TreeViewItem*>(item)->m_url.path(-1) == url.path(-1)) { + // We have found it + ensureItemVisible(item); + setCurrentItem(item); + setSelected(item, true); + + // Change viewport + QRect r = itemRect(item); + if (r.isValid()) { + int x, y; + viewportToContents(contentsX(), r.y(), x, y); + setContentsPos(x, y); + } + + return 1; + } + + if (item->firstChild()) { + // If item has children, go after them + if (openUrl(url, item->firstChild()) == 1) + return 1; + } + + item = item->nextSibling(); + } + + return 0; +} + +QListViewItem *TreeView::findItem(QListViewItem *parent, const QString &name) +{ + QListViewItem *item = parent->firstChild(); + + while (item) { + if (item->text(0) == name) + return item; + + item = item->nextSibling(); + } + + // If nothing is found, parent should be returned + return parent; +} + +void TreeView::createFolder(const KURL &url, QPixmap icon) +{ + int numDirs = url.path(1).contains('/', false); + QListViewItem *item = firstChild(); + + for (int i = 1; i < numDirs; i++) { + QString itemUrl = url.path().section('/', 0, i); + + if (m_treeItems[itemUrl]) { + // Item exists for this URL + item = m_treeItems[itemUrl]; + } else { + // Item not yet created + KURL tmp = url; + tmp.setPath(itemUrl); + + item = new TreeViewItem(this, item, tmp); + if (i == numDirs - 1) + item->setPixmap(0, icon); + else + item->setPixmap(0, loadSmallPixmap("folder")); + + m_treeItems.insert(itemUrl, static_cast<TreeViewItem*>(item)); + } + + // Mark it as dirty + static_cast<TreeViewItem*>(item)->m_dirty = true; + + // Open it + if (!m_noItemOpen) + setOpen(item, true); + } + + // Root item should always be open + setOpen(firstChild(), true); +} + +void TreeView::endUpdate(const KURL &url) +{ + // Remove all items in the selected dir, not marked as dirty + TreeViewItem *top = static_cast<TreeViewItem*>(firstChild()); + TreeViewItem *tmp = 0L; + int numDirs = url.path(1).contains('/', false); + + if (url.path() == "/") { + TreeViewItem *i = static_cast<TreeViewItem*>(top->firstChild()); + + while (i) { + tmp = static_cast<TreeViewItem*>(i->nextSibling()); + + if (!i->m_dirty) { + // Remove item from the index + delete i; + } else { + i->m_dirty = false; + } + + i = tmp; + } + + return; + } + + // URL for items + KURL itemURL = url; + itemURL.setPath("/"); + + for (int i = 1; i < numDirs; i++) { + QString sect = url.path().section('/', i, i); + itemURL.setPath(url.path().section('/', 0, i)); + + if (!m_treeItems[itemURL.path()]) { + // Item not yet created + return; + } else { + // Item is already present + top = m_treeItems[itemURL.path()]; + + // Check for URL match + if (itemURL.path(-1) == url.path(-1)) { + // URL match, delete the item's children + TreeViewItem *i = static_cast<TreeViewItem*>(top->firstChild()); + + while (i) { + tmp = static_cast<TreeViewItem*>(i->nextSibling()); + + if (!i->m_dirty) { + // Remove item from the index + delete i; + } else { + i->m_dirty = false; + } + + i = tmp; + } + return; + } + } + } +} + +void TreeView::clearFolder(const KURL &url) +{ + // Remove url's children + QListViewItem *top = firstChild(); + int numDirs = url.path(1).contains('/', false); + + if (url.path() == "/") { + QListViewItem *i = top->firstChild(); + + while (i) { + // Remove item from the index + delete i; + + i = top->firstChild(); + } + + return; + } + + // URL for items + KURL itemURL = url; + itemURL.setPath("/"); + + for (int i = 1; i < numDirs; i++) { + QString sect = url.path().section('/', i, i); + itemURL.setPath(url.path().section('/', 0, i)); + + if (!m_treeItems[itemURL.path()]) { + // Item not yet created + return; + } else { + // Item is already present + top = m_treeItems[itemURL.path()]; + + // Check for URL match + if (itemURL.path(-1) == url.path(-1)) { + // URL match, delete the item's children + QListViewItem *i = top->firstChild(); + + while (i) { + // Remove item from the index + delete i; + + i = top->firstChild(); + } + return; + } + } + } +} + +void TreeView::removeFolder(const KURL &url) +{ + // Removes a folder at url + QListViewItem *top = firstChild(); + int numDirs = url.path(1).contains('/', false); + + // URL for items + KURL itemURL = url; + itemURL.setPath("/"); + + for (int i = 1; i < numDirs; i++) { + QString sect = url.path().section('/', i, i); + itemURL.setPath(url.path().section('/', 0, i)); + + if (!m_treeItems[itemURL.path()]) { + // Item not yet created + return; + } else { + // Item is already present + top = m_treeItems[itemURL.path()]; + + // Check for URL match + if (itemURL.path(-1) == url.path(-1)) { + // Remove item from the index + delete top; + + return; + } + } + } +} + +void TreeView::slotClicked(QListViewItem *item) +{ + if (!item) + return; + + m_noItemOpen = true; + emit pathChanged(static_cast<TreeViewItem*>(item)->m_url); + m_noItemOpen = false; +} + +void TreeView::slotDoubleClicked(QListViewItem *item) +{ + if (!item) + return; + + setOpen(item, !item->isOpen()); +} + +void TreeView::startDrag() +{ + dragObject()->drag(); +} + +bool TreeView::acceptDrag(QDropEvent *e) +{ + return KURLDrag::canDecode(e) && + ( e->action() == QDropEvent::Copy + || e->action() == QDropEvent::Move + || e->action() == QDropEvent::Link ) + && acceptDrops() + && dragEnabled(); +} + +QDragObject *TreeView::dragObject() +{ + TreeViewItem *item = static_cast<TreeViewItem*>(selectedItem()); + + // Set the correct pixmap + QPixmap pix = *item->pixmap(0); + + KURL::List urls; + urls.append(item->m_url); + + KIO::MetaData meta; + meta.insert(item->m_url.htmlURL().local8Bit(), "D:0"); + + m_dragObject = new KURLDrag(urls, meta, this, name()); + m_dragObject->setPixmap(pix, QPoint(pix.width() / 2, pix.height() / 2)); + + return m_dragObject; +} + +void TreeView::contentsDragEnterEvent(QDragEnterEvent *e) +{ + if (!acceptDrag(e)) { + e->accept(false); + return; + } + + e->acceptAction(); + QListViewItem *i = itemAt(contentsToViewport(e->pos())); + if (i) + m_dropItem = i; +} + +void TreeView::contentsDragMoveEvent(QDragMoveEvent *e) +{ + if (!acceptDrag(e)) { + e->accept(false); + return; + } + + e->acceptAction(); + QListViewItem *i = itemAt(contentsToViewport(e->pos())); + + if (i && i != m_dropItem) + m_dropItem = i; +} + +void TreeView::contentsDragLeaveEvent(QDragLeaveEvent*) +{ + m_dropItem = 0L; +} + +void TreeView::contentsDropEvent(QDropEvent *e) +{ + if (!m_dropItem) + return; + + if (!acceptDrag(e)) { + e->acceptAction(false); + return; + } + e->acceptAction(); + + // Decode the data and try to init transfer + KIO::MetaData meta; + KURL::List urls; + KURLDrag::decode(e, urls, meta); + + // Move the specified file(s) + for (KURL::List::iterator i = urls.begin(); i != urls.end(); ++i) { + KURL destUrl = static_cast<TreeViewItem*>(m_dropItem)->m_url; + + if (destUrl != (*i)) { + if (destUrl.isLocalFile() != (*i).isLocalFile()) { + // TODO Queue up a transfer + } else { + // Rename/move the file + destUrl.addPath((*i).fileName()); + + if ((*i).isLocalFile()) { + KIO::move((*i), destUrl, false); + + // Reload the listing + static_cast<View*>(parent()->parent())->reload(); + } else { + static_cast<View*>(parent()->parent())->m_ftpClient->rename((*i), destUrl); + } + } + } + } + + // Invalidate the drop item + m_dropItem = 0L; +} + +} + +} + +#include "treeview.moc" diff --git a/kftpgrabber/src/widgets/browser/treeview.h b/kftpgrabber/src/widgets/browser/treeview.h new file mode 100644 index 0000000..220ac88 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/treeview.h @@ -0,0 +1,189 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPFILEDIRTREEVIEW_H +#define KFTPFILEDIRTREEVIEW_H + +#include <klistview.h> +#include <klocale.h> +#include <kurl.h> + +#include <qpixmap.h> +#include <qdict.h> + +namespace KFTPWidgets { + +namespace Browser { + +class TreeViewItem; + +/** + * This class represents a tree view showing the directory structure. It + * should usually be used together with a ListView. + * + * @author Jernej Kos + */ +class TreeView : public KListView +{ +Q_OBJECT +friend class ListView; +friend class TreeViewItem; +public: + /** + * Class constructor. + * + * @param parent The parent widget + */ + TreeView(QWidget *parent); + + /** + * Class destructor. + */ + ~TreeView(); + + /** + * Open an URL. + * + * @param url The url to open + */ + int openUrl(const KURL &url, QListViewItem *parent = 0); + + /** + * Remove the folder's child items. + * + * @param url The folder's URL + */ + void clearFolder(const KURL &url); + + /** + * Remove the folder and it's child items. + * + * @param url The folder's URL + */ + void removeFolder(const KURL &url); + + /** + * Create a new folder identified by it's URL and any folders missing + * in the hierarchy. + * + * @param url The folder's URL + * @param icon The icon to use + */ + void createFolder(const KURL &url, QPixmap icon); + + /** + * Clear all items in the view and create a new root item. + * + * @param url The root's new URL + */ + void resetView(const KURL &url); + + /** + * End item update and clear all non-dirty items. + * + * @param url The url to purge + */ + void endUpdate(const KURL &url); +private: + QDict<TreeViewItem> m_treeItems; + bool m_noItemOpen; + + /* Drag & drop support */ + QListViewItem *m_dropItem; + QDragObject *m_dragObject; + + QDragObject *dragObject(); + void startDrag(); + bool acceptDrag(QDropEvent *e); + void contentsDragEnterEvent(QDragEnterEvent *e); + void contentsDragMoveEvent(QDragMoveEvent *e); + void contentsDragLeaveEvent(QDragLeaveEvent*); + void contentsDropEvent(QDropEvent *e); +protected: + QListViewItem *findItem(QListViewItem *parent, const QString &name); +private slots: + void slotClicked(QListViewItem *item); + void slotDoubleClicked(QListViewItem *item); +signals: + void pathChanged(const KURL &url); +}; + +/** + * This class represents an item in the tree view. + * + * @author Jernej Kos + */ +class TreeViewItem : public QListViewItem +{ +friend class TreeView; +public: + /** + * Class constructor. + * + * @param parent The parent tree view + * @param url This item's URL + */ + TreeViewItem(TreeView *parent, const KURL &url); + + /** + * Class constructor. + * + * @param tree The tree view instance + * @param parent The parent list view item + * @param url This item's URL + */ + TreeViewItem(TreeView *tree, QListViewItem *parent, const KURL &url); + + /** + * Class destructor. + */ + ~TreeViewItem(); +protected: + /** + * @overload + * Reimplemented from QListViewItem to provide proper comparation. + */ + int compare(QListViewItem *i, int col, bool) const; +private: + TreeView *m_tree; + KURL m_url; + bool m_dirty; +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/browser/view.cpp b/kftpgrabber/src/widgets/browser/view.cpp new file mode 100644 index 0000000..4b3b0e5 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/view.cpp @@ -0,0 +1,456 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "browser/view.h" +#include "browser/detailsview.h" +#include "browser/treeview.h" +#include "browser/actions.h" +#include "browser/filterwidget.h" + +#include "kftpbookmarks.h" +#include "misc/config.h" +#include "kftpsession.h" +#include "ftpsocket.h" + +#include "misc.h" + +#include <klocale.h> +#include <ktoolbar.h> +#include <kstatusbar.h> +#include <kcombobox.h> +#include <kaction.h> +#include <kmessagebox.h> +#include <ksslinfodlg.h> +#include <klineedit.h> +#include <kpixmapprovider.h> + +#include <kio/job.h> + +#include <qdir.h> +#include <qlabel.h> +#include <qlayout.h> + +using namespace KFTPGrabberBase; +using namespace KFTPEngine; + +namespace KFTPWidgets { + +namespace Browser { + +class HistoryPixmapProvider : public KPixmapProvider +{ +public: + QPixmap pixmapFor(const QString&, int) + { + return loadSmallPixmap("folder"); + } +}; + +View::View(QWidget *parent, const char *name, KFTPEngine::Thread *client, KFTPSession::Session *session) + : QWidget(parent, name), + m_session(session), + m_ftpClient(client) +{ + m_connTimer = new QTimer(this); + + // Create the GUI + init(); + populateToolbar(); + + // Hide/show the tree acoording to configuration + setTreeVisible(KFTPCore::Config::showTree()); + + // Let us be up to date with bookmark changes + connect(KFTPBookmarks::Manager::self(), SIGNAL(update()), this, SLOT(updateBookmarks())); + + // Some other stuff + connect(m_ftpClient->eventHandler(), SIGNAL(engineEvent(KFTPEngine::Event*)), this, SLOT(slotEngineEvent(KFTPEngine::Event*))); + connect(m_connTimer, SIGNAL(timeout()), this, SLOT(slotDurationUpdate())); + + // Config updates to hide/show the tree + connect(KFTPCore::Config::self(), SIGNAL(configChanged()), this, SLOT(slotConfigUpdate())); +} + +View::~View() +{ +} + +void View::init() +{ + // Init actions + m_actions = new Actions(this); + m_actions->initActions(); + + // Layout + QVBoxLayout *layout = new QVBoxLayout(this); + + // Create the toolbars + m_toolBarFirst = new KToolBar(this, "first toolbar", false, false); + m_toolBarSecond = new KToolBar(this, "second toolbar", false, false); + m_searchToolBar = new KToolBar(this, "search toolbar", false, false); + + m_toolBarFirst->setEnableContextMenu(false); + m_toolBarFirst->setMovingEnabled(false); + m_toolBarFirst->setFullSize(true); + + m_toolBarSecond->setEnableContextMenu(false); + m_toolBarSecond->setMovingEnabled(false); + m_toolBarSecond->setFullSize(true); + + m_searchToolBar->setEnableContextMenu(false); + m_searchToolBar->setMovingEnabled(false); + m_searchToolBar->setFullSize(true); + + QLabel *filterLabel = new QLabel(i18n("Filter: "), m_searchToolBar); + m_searchToolBar->insertWidget(1, 35, filterLabel); + + // Create the erase button + m_toolBarSecond->insertButton(QApplication::reverseLayout() ? "clear_left" :"locationbar_erase", 0, SIGNAL(clicked()), this, SLOT(slotHistoryEraseClicked()), true); + + // Create the labels + QLabel *pathLabel = new QLabel(i18n("Path: "), m_toolBarSecond); + m_toolBarSecond->insertWidget(1, 35, pathLabel); + + // Create the history combo + m_historyCombo = new KHistoryCombo(true, m_toolBarSecond); + m_toolBarSecond->insertWidget(2, 0, m_historyCombo); + m_historyCombo->setPixmapProvider(new HistoryPixmapProvider()); + m_historyCombo->setMaxCount(25); + m_historyCombo->setSizeLimit(25); + m_historyCombo->setDuplicatesEnabled(false); + m_historyCombo->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed)); + + connect(m_historyCombo, SIGNAL(activated(const QString&)), this, SLOT(slotHistoryActivated(const QString&))); + + // Do some more stuff + m_toolBarSecond->setItemAutoSized(1, true); + m_toolBarSecond->setStretchableWidget(m_historyCombo); + m_toolBarSecond->updateRects(true); + m_toolBarFirst->updateRects(true); + + // Create a splitter + m_splitter = new QSplitter(this); + m_splitter->setOpaqueResize(true); + m_splitter->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding)); + + // Create a status bar + QHBoxLayout *statusLayout = new QHBoxLayout(this); + + m_connDurationMsg = new QLabel(this); + m_connDurationMsg->setAlignment(AlignAuto | AlignVCenter | AlignHCenter | ExpandTabs); + m_connDurationMsg->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + m_connDurationMsg->setMinimumWidth(100); + + m_sslIcon = new QPushButton(this); + m_sslIcon->setFlat(true); + m_sslIcon->setIconSet(SmallIconSet("decrypted")); + m_sslIcon->setEnabled(false); + + connect(m_sslIcon, SIGNAL(clicked()), this, SLOT(slotDisplayCertInfo())); + + m_statusMsg = new QLabel(this); + m_statusMsg->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); + m_statusMsg->setText(i18n("Idle.")); + + statusLayout->addWidget(m_statusMsg, 1); + statusLayout->addWidget(m_connDurationMsg); + statusLayout->addWidget(m_sslIcon); + + // Add toolbars to the layout + layout->addWidget(m_toolBarFirst); + layout->addWidget(m_toolBarSecond); + layout->addWidget(m_splitter, 10); + layout->addWidget(m_searchToolBar); + layout->addLayout(statusLayout); + + // Now add some stuff to the splitter + m_detailsView = new DetailsView(m_splitter, this, m_session); + m_splitter->moveToLast(m_detailsView); + + connect(m_detailsView->locationNavigator(), SIGNAL(historyChanged()), this, SLOT(slotHistoryChanged())); + + // Create the tree view + m_tree = new TreeView(m_splitter); + m_splitter->moveToFirst(m_tree); + + m_detailsView->setTreeView(m_tree); + m_detailsView->openUrl(KURL(KFTPCore::Config::defLocalDir())); + + // Create the filter widget + m_searchFilter = new FilterWidget(m_searchToolBar, m_detailsView); + m_searchToolBar->setItemAutoSized(2, true); + m_searchToolBar->setStretchableWidget(m_searchFilter); + + m_searchToolBar->updateRects(true); + m_searchToolBar->hide(); +} + +const KURL &View::url() const +{ + return m_detailsView->url(); +} + +const QValueList<LocationNavigator::Element> View::history(int &index) const +{ + return m_detailsView->history(index); +} + +const KFileItemList *View::selectedItems() const +{ + return m_detailsView->KFileView::selectedItems(); +} + +KURL::List View::selectedURLs() const +{ + KURL::List urls; + const KFileItemList *list = selectedItems(); + + if (list) { + KFileItemListIterator i(*list); + KFileItem *item; + + while ((item = i.current()) != 0) { + urls.append(item->url()); + ++i; + } + } + + return urls; +} + +const KFileItemList *View::items() const +{ + return m_detailsView->KFileView::items(); +} + +void View::openUrl(const KURL &url) +{ + m_detailsView->openUrl(url); +} + +void View::setShowHidden(bool value) +{ + m_detailsView->setShowHidden(value); +} + +void View::setHomeUrl(const KURL &url) +{ + m_detailsView->setHomeUrl(url); +} + +void View::goBack() +{ + m_detailsView->goBack(); +} + +void View::goForward() +{ + m_detailsView->goForward(); +} + +void View::goUp() +{ + m_detailsView->goUp(); +} + +void View::goHome() +{ + m_detailsView->goHome(); +} + +void View::reload() +{ + m_detailsView->reload(); +} + +void View::rename(const KURL &source, const QString &name) +{ + KURL dest(source.upURL()); + dest.addPath(name); + + if (source.isLocalFile()) + KIO::rename(source, dest, false); + else + m_session->getClient()->rename(source, dest); +} + +void View::slotConfigUpdate() +{ + setTreeVisible(KFTPCore::Config::showTree()); +} + +void View::setTreeVisible(bool visible) +{ + if (visible) + m_tree->show(); + else + m_tree->hide(); + + m_actions->m_toggleTreeViewAction->setChecked(visible); +} + +void View::populateToolbar() +{ + // Add the actions to the toolbar + m_actions->m_siteChangeAction->plug(m_toolBarFirst); + + m_toolBarFirst->insertSeparator(); + + m_actions->m_goUpAction->plug(m_toolBarFirst); + m_actions->m_goBackAction->plug(m_toolBarFirst); + m_actions->m_goForwardAction->plug(m_toolBarFirst); + m_actions->m_reloadAction->plug(m_toolBarFirst); + + m_toolBarFirst->insertSeparator(); + + m_actions->m_goHomeAction->plug(m_toolBarFirst); + m_actions->m_createDirAction->plug(m_toolBarFirst); + + m_toolBarFirst->insertSeparator(); + + m_actions->m_abortAction->plug(m_toolBarFirst); + m_actions->m_toggleTreeViewAction->plug(m_toolBarFirst); + m_actions->m_toggleFilterAction->plug(m_toolBarFirst); + + m_toolBarFirst->insertSeparator(); + + m_actions->m_moreActions->plug(m_toolBarFirst); +} + +void View::updateActions() +{ + // Force action update + m_actions->updateActions(); +} + +void View::updateBookmarks() +{ + // Repopulate bookmarks menu on updates + m_actions->m_connectAction->popupMenu()->clear(); + KFTPBookmarks::Manager::self()->guiPopulateBookmarksMenu(m_actions->m_connectAction, QDomNode(), false, m_session); +} + +void View::slotHistoryActivated(const QString &text) +{ + KURL dest = url(); + dest.setPath(text); + + openUrl(dest); +} + +void View::slotHistoryEraseClicked() +{ + m_historyCombo->setCurrentText(QString::null); + m_historyCombo->setFocus(); +} + +void View::slotHistoryChanged() +{ + /*m_historyCombo->insertItem(loadSmallPixmap("folder"), url().path(-1), 0); + m_historyCombo->setCurrentItem(0);*/ + m_historyCombo->addToHistory(url().path(-1)); +} + +void View::slotDisplayCertInfo() +{ + if (m_ftpClient->socket()->protocolName() == "ftp" && m_ftpClient->socket()->isEncrypted()) { + KSSLInfoDlg *sslInfo = new KSSLInfoDlg(true, this); + sslInfo->exec(); + } else if (m_ftpClient->socket()->protocolName() == "sftp") { + KMessageBox::information(this, i18n("This is a SSH encrypted connection. No certificate info is currently available.")); + } else { + KSSLInfoDlg *sslInfo = new KSSLInfoDlg(false, this); + sslInfo->exec(); + } +} + +void View::slotDurationUpdate() +{ + m_connDuration = m_connDuration.addSecs(1); + m_connDurationMsg->setText(m_connDuration.toString("hh:mm:ss")); +} + +void View::slotEngineEvent(KFTPEngine::Event *event) +{ + switch (event->type()) { + case Event::EventState: { + // Set new state + m_statusMsg->setText(event->getParameter(0).asString()); + break; + } + case Event::EventConnect: + case Event::EventDisconnect: { + // Change encryption icon + m_sslIcon->setIconSet(SmallIconSet(m_ftpClient->socket()->isEncrypted() ? "encrypted" : "decrypted")); + m_sslIcon->setEnabled(m_ftpClient->socket()->isConnected()); + + // Start or stop the duration timer + if (m_ftpClient->socket()->isConnected()) { + m_connTimer->start(1000); + m_connDuration.setHMS(0, 0, 0); + } else { + m_connTimer->stop(); + m_connDurationMsg->setText(""); + } + + // Reset selected charset to default + KPopupMenu *menu = m_actions->m_changeEncodingAction->popupMenu(); + menu->setItemChecked(m_actions->m_defaultCharsetOption, true); + menu->setItemChecked(m_actions->m_curCharsetOption, false); + m_actions->m_curCharsetOption = m_actions->m_defaultCharsetOption; + break; + } + default: break; + } + + if (m_ftpClient->socket()->isBusy()) { + m_tree->setEnabled(false); + m_detailsView->setEnabled(false); + m_toolBarSecond->setEnabled(false); + } else if (KFTPQueue::Manager::self()->getNumRunning(m_ftpClient->socket()->getCurrentUrl()) == 0) { + m_tree->setEnabled(true); + m_detailsView->setEnabled(true); + m_toolBarSecond->setEnabled(true); + } + + // Update actions + updateActions(); +} + +} + +} + +#include "view.moc" diff --git a/kftpgrabber/src/widgets/browser/view.h b/kftpgrabber/src/widgets/browser/view.h new file mode 100644 index 0000000..67dffa6 --- /dev/null +++ b/kftpgrabber/src/widgets/browser/view.h @@ -0,0 +1,258 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPFILEDIRVIEW_H +#define KFTPFILEDIRVIEW_H + +#include "browser/locationnavigator.h" + +#include <qwidget.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qtimer.h> +#include <qdatetime.h> +#include <qsplitter.h> + +#include <kurl.h> +#include <kfileitem.h> + +namespace KFTPSession { + class Session; + class Manager; +} + +class KToolBar; +class KHistoryCombo; +class KAction; +class KLineEdit; + +namespace KFTPEngine { + class Thread; + class Event; +} + +namespace KFTPWidgets { + +namespace Browser { + +class DetailsView; +class ListView; +class TreeView; +class Actions; +class FilterWidget; + +/** + * @author Jernej Kos + */ +class View : public QWidget +{ +Q_OBJECT +friend class Actions; +friend class DetailsView; +friend class ListView; +friend class TreeView; +friend class KFTPSession::Manager; +friend class KFTPSession::Session; +public: + /** + * Class constructor. + */ + View(QWidget *parent, const char *name, KFTPEngine::Thread *client, KFTPSession::Session *session); + + /** + * Class destructor. + */ + ~View(); + + /** + * Returns the current URL. + */ + const KURL &url() const; + + /** + * Returns the current history elements. + * + * @param index Variable to save the current history position to + * @return Current history element list + */ + const QValueList<LocationNavigator::Element> history(int &index) const; + + /** + * Returns all currenty selected items. + */ + const KFileItemList *selectedItems() const; + + /** + * Returns all currently selected URLs. + */ + KURL::List selectedURLs() const; + + /** + * Returns all items in the current sort order. + */ + const KFileItemList *items() const; + + /** + * Open an URL. Note that if a remote URL is specified the session needs to + * be connected to the specified host! + * + * @param url URL to open + */ + void openUrl(const KURL &url); + + /** + * Changes the visibility of tree widget. + * + * @param visible True to display the tree widget, false to hide it + */ + void setTreeVisible(bool visible); + + /** + * Changes the "show hidden files" setting. + * + * @param value True to enable showing hidden files, false otherwise + */ + void setShowHidden(bool value); + + /** + * Set the home URL. + * + * @param url URL to use as home URL + */ + void setHomeUrl(const KURL &url); + + /** + * Go one history hop back. + */ + void goBack(); + + /** + * Go one history hop forward. + */ + void goForward(); + + /** + * Go up in the directory structure. + */ + void goUp(); + + /** + * Go the the predefined home URL. + */ + void goHome(); + + /** + * Reload the current directory listing. + */ + void reload(); + + /** + * Renames the provided source file to a new name. + */ + void rename(const KURL &source, const QString &name); + + /** + * Returns the details view widget. + */ + DetailsView *getDetailsView() const { return m_detailsView; } + + /** + * Returns the tree view widget. + */ + TreeView *getTreeView() const { return m_tree; } + + /** + * Returns the status label widget. + */ + QLabel *getStatusLabel() const { return m_statusMsg; } + + /** + * Returns the associated session. + */ + KFTPSession::Session *getSession() const { return m_session; } +protected: + /** + * Initialize the widget. + */ + void init(); + + /** + * Populate the toolbar. + */ + void populateToolbar(); +private: + KFTPSession::Session *m_session; + KFTPEngine::Thread *m_ftpClient; + + DetailsView *m_detailsView; + TreeView *m_tree; + + Actions *m_actions; + + KToolBar *m_toolBarFirst; /* Upper toolbar */ + KToolBar *m_toolBarSecond; /* Lower toolbar */ + KToolBar *m_searchToolBar; + + QLabel *m_statusMsg; + QLabel *m_connDurationMsg; + QPushButton *m_sslIcon; + QSplitter *m_splitter; + + QTimer *m_connTimer; + QTime m_connDuration; + + KHistoryCombo *m_historyCombo; + FilterWidget *m_searchFilter; +public slots: + void updateActions(); + void updateBookmarks(); +private slots: + void slotHistoryEraseClicked(); + void slotHistoryActivated(const QString &text); + void slotHistoryChanged(); + + void slotDisplayCertInfo(); + void slotDurationUpdate(); + + void slotEngineEvent(KFTPEngine::Event *event); + + void slotConfigUpdate(); +}; + +} + +} + +#endif diff --git a/kftpgrabber/src/widgets/configdialog.cpp b/kftpgrabber/src/widgets/configdialog.cpp new file mode 100644 index 0000000..49d0d16 --- /dev/null +++ b/kftpgrabber/src/widgets/configdialog.cpp @@ -0,0 +1,187 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "configdialog.h" +#include "misc.h" +#include "misc/config.h" +#include "widgets/systemtray.h" + +#include <klocale.h> +#include <kfontdialog.h> +#include <kcolorbutton.h> +#include <kurlrequester.h> +#include <klineedit.h> +#include <knuminput.h> +#include <kglobal.h> +#include <kcharsets.h> +#include <kcombobox.h> + +#include <qframe.h> +#include <qlayout.h> +#include <qcheckbox.h> + +// Config layouts +#include "ui/config_general.h" +#include "ui/config_transfers.h" +#include "ui/config_log.h" +#include "ui/config_display.h" + +#include "configfilter.h" + +namespace KFTPWidgets { + +ConfigDialog::ConfigDialog(QWidget *parent, const char *name) + : KConfigDialog(parent, name, KFTPCore::Config::self(), KDialogBase::TreeList, Ok|Apply|Cancel, Ok, true) +{ + // Add all standard pages + addPage(new GeneralSettings(0, "General"), i18n("General"), "kfm"); + addPage(new TransferSettings(0, "Transfers"), i18n("Transfers"), "queue"); + addPage(new LogSettings(0, "Log"), i18n("Log"), "log"); + addPage(new DisplaySettings(0, "Display"), i18n("Display"), "display"); + + // Add the actions page + QFrame *aFrame = new QFrame(); + QVBoxLayout *aLayout = new QVBoxLayout(aFrame, 0, 0); + aLayout->addWidget(KFTPCore::Config::self()->dActions()->getConfigWidget(aFrame)); + aLayout->addSpacing(KDialog::spacingHint()); + aLayout->addWidget(KFTPCore::Config::self()->uActions()->getConfigWidget(aFrame)); + aLayout->addSpacing(KDialog::spacingHint()); + aLayout->addWidget(KFTPCore::Config::self()->fActions()->getConfigWidget(aFrame)); + aLayout->addStretch(1); + addPage(aFrame, i18n("Actions"), "kfm"); + + // Add the filter page + aFrame = new QFrame(); + aLayout = new QVBoxLayout(aFrame, 0, 0); + m_configFilter = new ConfigFilter(aFrame); + aLayout->addWidget(m_configFilter); + addPage(aFrame, i18n("Filters"), "kfm"); + + // Setup some stuff + static_cast<KURLRequester*>(child("kcfg_defLocalDir"))->setMode(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly); + + // Setup signals + connect(child("kcfg_globalMail"), SIGNAL(toggled(bool)), this, SLOT(slotGeneralEmailChanged(bool))); + connect(child("kcfg_portForceIp"), SIGNAL(toggled(bool)), this, SLOT(slotTransfersForceIpChanged(bool))); + connect(child("kcfg_activeForcePort"), SIGNAL(toggled(bool)), this, SLOT(slotTransfersForcePortChanged(bool))); + connect(child("kcfg_diskCheckSpace"), SIGNAL(toggled(bool)), this, SLOT(slotTransfersDiskChanged(bool))); + connect(child("kcfg_failedAutoRetry"), SIGNAL(toggled(bool)), this, SLOT(slotTransfersFailedRetryChanged(bool))); + connect(child("kcfg_saveToFile"), SIGNAL(toggled(bool)), this, SLOT(slotLogOutputFileChanged(bool))); + + // Refresh states + slotGeneralEmailChanged(static_cast<QCheckBox*>(child("kcfg_globalMail"))->isChecked()); + slotTransfersForceIpChanged(static_cast<QCheckBox*>(child("kcfg_portForceIp"))->isChecked()); + slotTransfersDiskChanged(static_cast<QCheckBox*>(child("kcfg_diskCheckSpace"))->isChecked()); + slotTransfersFailedRetryChanged(static_cast<QCheckBox*>(child("kcfg_failedAutoRetry"))->isChecked()); + slotLogOutputFileChanged(static_cast<QCheckBox*>(child("kcfg_saveToFile"))->isChecked()); + slotTransfersForcePortChanged(static_cast<QCheckBox*>(child("kcfg_activeForcePort"))->isChecked()); + + // Let the config be up-to-date + connect(this, SIGNAL(settingsChanged()), KFTPCore::Config::self(), SLOT(emitChange())); + connect(this, SIGNAL(okClicked()), this, SLOT(slotSettingsChanged())); +} + +void ConfigDialog::prepareDialog() +{ + // Update the actions + KFTPCore::Config::self()->dActions()->updateWidget(); + KFTPCore::Config::self()->uActions()->updateWidget(); + KFTPCore::Config::self()->fActions()->updateWidget(); + + // Populate charsets + QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames(); + static_cast<KComboBox*>(child("cfg_defEncoding"))->insertStringList(charsets); + + QString defEncoding = KFTPCore::Config::defEncoding(); + defEncoding = QString("%1 ( %2 )").arg(KGlobal::charsets()->languageForEncoding(defEncoding)).arg(defEncoding); + static_cast<KComboBox*>(child("cfg_defEncoding"))->setCurrentText(defEncoding); + + m_configFilter->loadSettings(); +} + +void ConfigDialog::slotSettingsChanged() +{ + // Update the actions + KFTPCore::Config::self()->dActions()->updateConfig(); + KFTPCore::Config::self()->uActions()->updateConfig(); + KFTPCore::Config::self()->fActions()->updateConfig(); + + m_configFilter->saveSettings(); + + // Save encoding + KFTPCore::Config::setDefEncoding(KGlobal::charsets()->encodingForName(static_cast<KComboBox*>(child("cfg_defEncoding"))->currentText())); + + // Show/hide the systray icon + if (KFTPCore::Config::showSystrayIcon()) + SystemTray::self()->show(); + else + SystemTray::self()->hide(); +} + +void ConfigDialog::slotGeneralEmailChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_anonMail"))->setEnabled(!on); +} + +void ConfigDialog::slotTransfersForceIpChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_portIp"))->setEnabled(on); +} + +void ConfigDialog::slotTransfersForcePortChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_activeMinPort"))->setEnabled(on); + static_cast<QWidget*>(child("kcfg_activeMaxPort"))->setEnabled(on); +} + +void ConfigDialog::slotTransfersDiskChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_diskCheckInterval"))->setEnabled(on); + static_cast<QWidget*>(child("kcfg_diskMinFreeSpace"))->setEnabled(on); +} + +void ConfigDialog::slotTransfersFailedRetryChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_failedAutoRetryCount"))->setEnabled(on); +} + +void ConfigDialog::slotLogOutputFileChanged(bool on) +{ + static_cast<QWidget*>(child("kcfg_outputFilename"))->setEnabled(on); +} + +} + +#include "configdialog.moc" diff --git a/kftpgrabber/src/widgets/configdialog.h b/kftpgrabber/src/widgets/configdialog.h new file mode 100644 index 0000000..6234c14 --- /dev/null +++ b/kftpgrabber/src/widgets/configdialog.h @@ -0,0 +1,71 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPCONFIGDIALOG_H +#define KFTPCONFIGDIALOG_H + +#include <kconfigdialog.h> + +namespace KFTPWidgets { + +class ConfigFilter; + +/** + * @author Jernej Kos + */ +class ConfigDialog : public KConfigDialog +{ +Q_OBJECT +public: + ConfigDialog(QWidget *parent, const char *name = 0); + + void prepareDialog(); +private: + ConfigFilter *m_configFilter; +private slots: + void slotGeneralEmailChanged(bool on); + + void slotTransfersForceIpChanged(bool on); + void slotTransfersDiskChanged(bool on); + void slotTransfersForcePortChanged(bool on); + void slotTransfersFailedRetryChanged(bool on); + + void slotLogOutputFileChanged(bool on); + + void slotSettingsChanged(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/configfilter.cpp b/kftpgrabber/src/widgets/configfilter.cpp new file mode 100644 index 0000000..c2dc3b9 --- /dev/null +++ b/kftpgrabber/src/widgets/configfilter.cpp @@ -0,0 +1,137 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "configfilter.h" +#include "filtereditor.h" + +#include "misc/config.h" +#include "misc.h" + +#include <klistview.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <kmessagebox.h> +#include <klineeditdlg.h> + +#include <klineedit.h> +#include <kcolorbutton.h> +#include <kdialogbase.h> + +#include <qcheckbox.h> +#include <qlayout.h> +#include <qtabwidget.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +ConfigFilter::ConfigFilter(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + // Create the main widget + QVBoxLayout *t = new QVBoxLayout(this, 0, 0); + + m_editorLayout = new ConfigFilterLayout(this); + t->addWidget(m_editorLayout); + + m_filterEditor = new FilterEditor(this); + m_editorLayout->tabWidget->insertTab(m_filterEditor, i18n("Filters"), 0); + m_editorLayout->tabWidget->setCurrentPage(0); + m_editorLayout->tabWidget->setMargin(KDialog::spacingHint()); + + loadSettings(); + + // Connect the slots + connect(m_editorLayout->addExtButton, SIGNAL(clicked()), this, SLOT(slotAddAscii())); + connect(m_editorLayout->removeExtButton, SIGNAL(clicked()), this, SLOT(slotRemoveAscii())); +} + +void ConfigFilter::loadSettings() +{ + m_filterEditor->reset(); + asciiLoadExtensions(); +} + +void ConfigFilter::saveSettings() +{ + // Save the settings + KFTPCore::Config::setAsciiList(asciiToStringList()); +} + +void ConfigFilter::slotAddAscii() +{ + if (!m_editorLayout->newExtension->text().stripWhiteSpace().isEmpty()) { + new QListViewItem(m_editorLayout->extensionList, m_editorLayout->newExtension->text().stripWhiteSpace()); + m_editorLayout->newExtension->clear(); + } +} + +void ConfigFilter::slotRemoveAscii() +{ + if (!m_editorLayout->extensionList->selectedItem()) + return; + + delete m_editorLayout->extensionList->selectedItem(); +} + +void ConfigFilter::asciiLoadExtensions() +{ + // Load the ascii extensions + m_editorLayout->extensionList->clear(); + QStringList p_extensions = KFTPCore::Config::asciiList(); + + QStringList::iterator end( p_extensions.end() ); + for (QStringList::iterator i( p_extensions.begin() ); i != end; ++i) { + new QListViewItem(m_editorLayout->extensionList, (*i)); + } + +} + +QStringList ConfigFilter::asciiToStringList() +{ + QStringList p_extensions; + QListViewItem *i = m_editorLayout->extensionList->firstChild(); + while (i) { + p_extensions.append(i->text(0)); + + i = i->itemBelow(); + } + + return p_extensions; +} + +} +#include "configfilter.moc" diff --git a/kftpgrabber/src/widgets/configfilter.h b/kftpgrabber/src/widgets/configfilter.h new file mode 100644 index 0000000..3d9ee22 --- /dev/null +++ b/kftpgrabber/src/widgets/configfilter.h @@ -0,0 +1,79 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSCONFIGFILTER_H +#define KFTPWIDGETSCONFIGFILTER_H + +#include <qwidget.h> +#include <kdialogbase.h> +#include <knuminput.h> +#include <qradiobutton.h> +#include <qvaluelist.h> + +// Layouts +#include "ui/config_filters.h" + +namespace KFTPWidgets { + +class FilterEditor; + +/** + * Filter related configuration dialog. + * + * @author Jernej Kos + */ +class ConfigFilter : public QWidget +{ +Q_OBJECT +public: + ConfigFilter(QWidget *parent = 0, const char *name = 0); + + void saveSettings(); + void loadSettings(); +private: + void asciiLoadExtensions(); + QStringList asciiToStringList(); + + FilterEditor *m_filterEditor; + ConfigFilterLayout *m_editorLayout; +private slots: + void slotAddAscii(); + void slotRemoveAscii(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/failedtransfers.cpp b/kftpgrabber/src/widgets/failedtransfers.cpp new file mode 100644 index 0000000..30fc0a6 --- /dev/null +++ b/kftpgrabber/src/widgets/failedtransfers.cpp @@ -0,0 +1,213 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "failedtransfers.h" +#include "kftpqueue.h" +#include "listview.h" +#include "misc.h" +#include "kftpapi.h" + +#include <klocale.h> +#include <kpopupmenu.h> +#include <kio/job.h> +#include <kmessagebox.h> + +#include <qlayout.h> +#include <qheader.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +FailedTransferItem::FailedTransferItem(KFTPQueue::FailedTransfer *transfer, QListView *parent) + : KFTPWidgets::ListViewItem(parent), + m_failedTransfer(transfer) +{ + QString desc = "<nobr><b>"; + desc += i18n("Transfer"); + desc += ":</b> "; + desc += transfer->getTransfer()->getSourceUrl().prettyURL(); + desc += " <b>>>></b> "; + desc += transfer->getTransfer()->getDestUrl().prettyURL(); + desc += "<br><b>"; + desc += i18n("Error"); + desc += ":</b> <i>"; + desc += transfer->getError(); + desc += "</i></nobr>"; + + // Setup columns + setRichText(0, desc); + setText(1, KIO::convertSize(transfer->getTransfer()->getActualSize())); + setText(2, QString::number(transfer->getTransfer()->getId())); + + setPixmap(0, loadSmallPixmap("info")); +} + +KActionCollection *FailedTransfers::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +FailedTransfers::FailedTransfers(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + // Create the list view + m_list = new KFTPWidgets::ListView(this); + + // Create the columns + m_list->addColumn(i18n("Description"), 500); + m_list->addColumn(i18n("Size"), 75); + m_list->header()->setStretchEnabled(true, 0); + + // Text when there are no failed transfers + m_list->setEmptyListText(i18n("There are no failed transfers.")); + m_list->setAllColumnsShowFocus(true); + + layout->addWidget(m_list); + + connect(KFTPQueue::Manager::self(), SIGNAL(failedTransferNew(KFTPQueue::FailedTransfer*)), this, SLOT(slotFailedTransferNew(KFTPQueue::FailedTransfer*))); + connect(KFTPQueue::Manager::self(), SIGNAL(failedTransferRemoved(long)), this, SLOT(slotFailedTransferRemoved(long))); + + connect(m_list, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, SLOT(contextMenuRequested(KListView*, QListViewItem*, const QPoint&))); + + // Initialize the actions + initActions(); +} + +FailedTransfers::~FailedTransfers() +{ +} + +void FailedTransfers::initActions() +{ + m_restartAction = new KAction(i18n("&Restart Transfer"), "launch", KShortcut(), this, SLOT(slotRestart()), actionCollection(), "launch"); + m_addToQueueAction = new KAction(i18n("&Add To Queue"), "queue", KShortcut(), this, SLOT(slotAddToQueue()), actionCollection(), "addtoqueue"); + m_addAllToQueueAction = new KAction(i18n("Add All To Queue"), KShortcut(), this, SLOT(slotAddAllToQueue()), actionCollection(), "addalltoqueue"); + m_removeAction = new KAction(i18n("R&emove"), "editdelete", KShortcut(), this, SLOT(slotRemove()), actionCollection(), "remove"); + m_removeAllAction = new KAction(i18n("Remove All"), KShortcut(), this, SLOT(slotRemoveAll()), actionCollection(), "removeall"); +} + +void FailedTransfers::updateActions() +{ + m_restartAction->setEnabled(m_list->selectedItem()); + m_addToQueueAction->setEnabled(m_list->selectedItem()); + m_removeAction->setEnabled(m_list->selectedItem()); + + m_addAllToQueueAction->setEnabled(m_list->childCount()); + m_removeAllAction->setEnabled(m_list->childCount()); +} + +void FailedTransfers::slotFailedTransferNew(KFTPQueue::FailedTransfer *transfer) +{ + // Create a new failed transfer list item + new FailedTransferItem(transfer, m_list); +} + +void FailedTransfers::slotFailedTransferRemoved(long id) +{ + // Delete the failed transfer item + QListViewItem *item = m_list->findItem(QString::number(id), 2); + + if (item) + delete item; +} + +void FailedTransfers::slotRestart() +{ + // First restore the transfer + KFTPQueue::TransferFile *transfer = static_cast<FailedTransferItem*>(m_list->selectedItem())->getFailedTransfer()->restore(); + + // Then execute it + transfer->delayedExecute(); +} + +void FailedTransfers::slotAddToQueue() +{ + // Restore the transfer + static_cast<FailedTransferItem*>(m_list->selectedItem())->getFailedTransfer()->restore(); +} + +void FailedTransfers::slotAddAllToQueue() +{ + KFTPQueue::FailedTransfer *transfer; + QPtrList<KFTPQueue::FailedTransfer> *list = KFTPQueue::Manager::self()->getFailedTransferList(); + QPtrListIterator<KFTPQueue::FailedTransfer> i(*list); + + while ((transfer = i.current()) != 0) { + ++i; + + // Restore the transfer + transfer->restore(); + } +} + +void FailedTransfers::slotRemove() +{ + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove this failed transfer?")) == KMessageBox::Yes) { + // Remove the failed transfer + KFTPQueue::Manager::self()->removeFailedTransfer(static_cast<FailedTransferItem*>(m_list->selectedItem())->getFailedTransfer()); + } +} + +void FailedTransfers::slotRemoveAll() +{ + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove ALL failed transfers?")) == KMessageBox::Yes) { + KFTPQueue::Manager::self()->clearFailedTransferList(); + } +} + +void FailedTransfers::contextMenuRequested(KListView*, QListViewItem*, const QPoint &p) +{ + KPopupMenu *contextMenu = new KPopupMenu(m_list); + + m_restartAction->plug(contextMenu); + m_addToQueueAction->plug(contextMenu); + m_addAllToQueueAction->plug(contextMenu); + contextMenu->insertSeparator(); + m_removeAction->plug(contextMenu); + m_removeAllAction->plug(contextMenu); + + // Update the actions + updateActions(); + + contextMenu->exec(p); +} + +} + +#include "failedtransfers.moc" + diff --git a/kftpgrabber/src/widgets/failedtransfers.h b/kftpgrabber/src/widgets/failedtransfers.h new file mode 100644 index 0000000..2b17a5a --- /dev/null +++ b/kftpgrabber/src/widgets/failedtransfers.h @@ -0,0 +1,111 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSFAILEDTRANSFERS_H +#define KFTPWIDGETSFAILEDTRANSFERS_H + +#include <klistview.h> +#include <kaction.h> + +#include <qwidget.h> +#include <qguardedptr.h> + +#include "listviewitem.h" + +namespace KFTPQueue { + class FailedTransfer; +} + +namespace KFTPWidgets { + +class ListView; + +/** + * This class represents a QListViewItem item that contains information + * about a specific failed transfer. + * + * @author Jernej Kos + */ +class FailedTransferItem : public KFTPWidgets::ListViewItem +{ +public: + FailedTransferItem(KFTPQueue::FailedTransfer *transfer, QListView *parent); + + KFTPQueue::FailedTransfer *getFailedTransfer() { return m_failedTransfer; } +private: + QGuardedPtr<KFTPQueue::FailedTransfer> m_failedTransfer; +}; + +/** + * This class provides a list of failed transfers. The transfers + * can be restarted. + * + * @author Jernej Kos + */ +class FailedTransfers : public QWidget +{ +Q_OBJECT +public: + FailedTransfers(QWidget *parent = 0, const char *name = 0); + ~FailedTransfers(); + + void updateActions(); + void initActions(); +private: + KActionCollection *actionCollection(); + + KFTPWidgets::ListView *m_list; + + KAction *m_restartAction; + KAction *m_addToQueueAction; + KAction *m_addAllToQueueAction; + KAction *m_removeAction; + KAction *m_removeAllAction; +private slots: + void slotRestart(); + void slotAddToQueue(); + void slotAddAllToQueue(); + void slotRemove(); + void slotRemoveAll(); + + void contextMenuRequested(KListView*, QListViewItem*, const QPoint&); + + void slotFailedTransferNew(KFTPQueue::FailedTransfer*); + void slotFailedTransferRemoved(long); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/filtereditor.cpp b/kftpgrabber/src/widgets/filtereditor.cpp new file mode 100644 index 0000000..9be3b6e --- /dev/null +++ b/kftpgrabber/src/widgets/filtereditor.cpp @@ -0,0 +1,625 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "filtereditor.h" +#include "listview.h" +#include "misc/filterwidgethandler.h" + +#include <qlayout.h> +#include <qhbox.h> +#include <qtooltip.h> +#include <qheader.h> +#include <qbuttongroup.h> + +#include <kiconloader.h> +#include <klocale.h> +#include <kdialog.h> +#include <kinputdialog.h> + +using namespace KFTPCore::Filter; + +namespace KFTPWidgets { + +FilterEditor::FilterEditor(QWidget *parent) + : QWidget(parent), + m_rule(0) +{ + QHBoxLayout *mainLayout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_listView = new FilterListView(this); + mainLayout->addWidget(m_listView, 1); + + QVBoxLayout *rightLayout = new QVBoxLayout(mainLayout); + mainLayout->setStretchFactor(rightLayout, KDialog::spacingHint()); + + m_enabledCheck = new QCheckBox(i18n("Filter &enabled"), this); + rightLayout->addWidget(m_enabledCheck); + + m_conditionsList = new FilterConditionsList(this); + rightLayout->addWidget(m_conditionsList, 0, Qt::AlignTop); + + m_actionsList = new FilterActionsList(this); + rightLayout->addWidget(m_actionsList, 0, Qt::AlignTop); + + rightLayout->addStretch(1); + + // Connect some signals + connect(m_enabledCheck, SIGNAL(clicked()), this, SLOT(slotEnabledChanged())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), this, SLOT(slotRuleChanged(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), this, SLOT(slotRuleRemoved())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), m_conditionsList, SLOT(loadRule(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), m_conditionsList, SLOT(reset())); + + connect(m_listView, SIGNAL(ruleChanged(KFTPCore::Filter::Rule*)), m_actionsList, SLOT(loadRule(KFTPCore::Filter::Rule*))); + connect(m_listView, SIGNAL(ruleRemoved()), m_actionsList, SLOT(reset())); +} + +void FilterEditor::slotRuleChanged(KFTPCore::Filter::Rule *rule) +{ + m_enabledCheck->setEnabled(true); + m_enabledCheck->setChecked(rule->isEnabled()); + + m_rule = rule; +} + +void FilterEditor::slotRuleRemoved() +{ + m_enabledCheck->setChecked(false); + m_enabledCheck->setEnabled(false); +} + +void FilterEditor::slotEnabledChanged() +{ + if (m_rule) + m_rule->setEnabled(m_enabledCheck->isChecked()); +} + +void FilterEditor::reset() +{ + m_enabledCheck->setChecked(false); + m_enabledCheck->setEnabled(false); + + m_conditionsList->reset(); + m_actionsList->reset(); + m_listView->reset(); +} + +FilterListItem::FilterListItem(ListView *parent, KFTPCore::Filter::Rule *rule) + : QListViewItem(parent), + m_rule(rule) +{ + setText(0, rule->name()); +} + +FilterListView::FilterListView(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Filters"), parent) +{ + m_listView = new ListView(this); + m_listView->setSelectionMode(QListView::Single); + m_listView->setSorting(-1); + m_listView->header()->hide(); + m_listView->setMinimumWidth(150); + m_listView->setEmptyListText(i18n("No filters.")); + m_listView->addColumn(""); + m_listView->setFullWidth(true); + + QHBox *hb = new QHBox(this); + hb->setSpacing(4); + + // Up/down buttons + m_buttonUp = new KPushButton(QString::null, hb); + m_buttonUp->setAutoRepeat(true); + m_buttonUp->setIconSet(BarIconSet("up", KIcon::SizeSmall)); + m_buttonUp->setMinimumSize(m_buttonUp->sizeHint() * 1.2); + + m_buttonDown = new KPushButton(QString::null, hb); + m_buttonDown->setAutoRepeat(true); + m_buttonDown->setIconSet(BarIconSet("down", KIcon::SizeSmall)); + m_buttonDown->setMinimumSize(m_buttonDown->sizeHint() * 1.2); + + QToolTip::add(m_buttonUp, i18n("Up")); + QToolTip::add(m_buttonDown, i18n("Down")); + + // New, copy, delete buttons + hb = new QHBox(this); + hb->setSpacing(4); + + m_buttonNew = new QPushButton(QString::null, hb); + m_buttonNew->setPixmap(BarIcon("filenew", KIcon::SizeSmall)); + m_buttonNew->setMinimumSize(m_buttonNew->sizeHint() * 1.2); + + m_buttonCopy = new QPushButton(QString::null, hb); + m_buttonCopy->setPixmap(BarIcon("editcopy", KIcon::SizeSmall)); + m_buttonCopy->setMinimumSize(m_buttonCopy->sizeHint() * 1.2); + + m_buttonDelete = new QPushButton(QString::null, hb); + m_buttonDelete->setPixmap(BarIcon("editdelete", KIcon::SizeSmall)); + m_buttonDelete->setMinimumSize(m_buttonDelete->sizeHint() * 1.2); + + m_buttonRename = new QPushButton(i18n("Rename..."), hb); + + QToolTip::add(m_buttonNew, i18n("New")); + QToolTip::add(m_buttonCopy, i18n("Copy")); + QToolTip::add(m_buttonDelete, i18n("Delete")); + + // Connect the signals + connect(m_buttonNew, SIGNAL(clicked()), this, SLOT(slotNewRule())); + connect(m_buttonDelete, SIGNAL(clicked()), this, SLOT(slotDeleteRule())); + connect(m_buttonRename, SIGNAL(clicked()), this, SLOT(slotRenameRule())); + connect(m_buttonCopy, SIGNAL(clicked()), this, SLOT(slotCopyRule())); + + connect(m_buttonUp, SIGNAL(clicked()), this, SLOT(slotUp())); + connect(m_buttonDown, SIGNAL(clicked()), this, SLOT(slotDown())); + + connect(m_listView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotSelectionChanged(QListViewItem*))); + + m_buttonUp->setEnabled(false); + m_buttonDown->setEnabled(false); + m_buttonRename->setEnabled(false); + + // Reset the view, loading all the existing rules + reset(); +} + +void FilterListView::reset() +{ + m_listView->clear(); + + // Load all existing rules + Filters *filters = Filters::self(); + Filters::ConstIterator le = filters->end(); + + for (Filters::ConstIterator i = filters->begin(); i != le; ++i) { + FilterListItem *item = new FilterListItem(m_listView, (*i)); + item->moveItem(m_listView->lastItem()); + } + + // Select the first rule + m_listView->setSelected(m_listView->firstChild(), true); +} + +void FilterListView::slotSelectionChanged(QListViewItem *item) +{ + FilterListItem *selected = static_cast<FilterListItem*>(item); + + m_buttonUp->setEnabled(item->itemAbove()); + m_buttonDown->setEnabled(item->nextSibling()); + m_buttonRename->setEnabled(true); + + // Signal the rule change + emit ruleChanged(selected->rule()); +} + +void FilterListView::slotNewRule() +{ + Rule *rule = new Rule(i18n("Unnamed Rule")); + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + FilterListItem *item = new FilterListItem(m_listView, rule); + + if (selected) { + Filters::self()->insert(Filters::self()->findRef(selected->rule()) + 1, rule); + item->moveItem(selected); + } else { + Filters::self()->append(rule); + } + + m_listView->setSelected(item, true); +} + +void FilterListView::slotDeleteRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + Rule *rule = selected->rule(); + delete selected; + + emit ruleRemoved(); + + Filters::self()->removeRef(rule); + m_listView->setSelected(m_listView->lastItem(), true); + } + + if (!m_listView->selectedItem()) + m_buttonRename->setEnabled(false); +} + +void FilterListView::slotRenameRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + QString name = KInputDialog::getText(i18n("Rename Rule"), i18n("Rename rule '%1' to:").arg(selected->rule()->name()), selected->rule()->name()); + + if (name.stripWhiteSpace().isEmpty()) + name = i18n("Unnamed Rule"); + + selected->rule()->setName(name); + selected->setText(0, name); + } +} + +void FilterListView::slotCopyRule() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + + if (selected) { + Rule *rule = new Rule(selected->rule()); + FilterListItem *item = new FilterListItem(m_listView, rule); + + Filters::self()->insert(Filters::self()->findRef(selected->rule()) + 1, rule); + item->moveItem(selected); + m_listView->setSelected(item, true); + } +} + +void FilterListView::slotUp() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + QListViewItem *tmp = selected->itemAbove(); + if (!tmp) + return; + + FilterListItem *previous = static_cast<FilterListItem*>(tmp->itemAbove()); + + if (selected) { + Rule *rule = Filters::self()->take(Filters::self()->findRef(selected->rule())); + + if (previous) { + Filters::self()->insert(Filters::self()->findRef(previous->rule()) + 1, rule); + selected->moveItem(previous); + } else { + Filters::self()->insert(0, rule); + m_listView->takeItem(selected); + m_listView->insertItem(selected); + m_listView->setSelected(selected, true); + } + + m_buttonUp->setEnabled(selected->itemAbove()); + m_buttonDown->setEnabled(selected->nextSibling()); + } +} + +void FilterListView::slotDown() +{ + FilterListItem *selected = static_cast<FilterListItem*>(m_listView->selectedItem()); + FilterListItem *next = static_cast<FilterListItem*>(selected->nextSibling()); + + if (selected && next) { + Rule *rule = Filters::self()->take(Filters::self()->findRef(selected->rule())); + Filters::self()->insert(Filters::self()->findRef(next->rule()) + 1, rule); + selected->moveItem(next); + + m_buttonUp->setEnabled(selected->itemAbove()); + m_buttonDown->setEnabled(selected->nextSibling()); + } +} + +FilterConditionsList::FilterConditionsList(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Conditions"), parent) +{ + setEnabled(false); + + m_buttonAll = new QRadioButton(i18n("Match a&ll of the following"), this); + m_buttonAny = new QRadioButton(i18n("Match an&y of the following"), this); + + m_buttonAll->setChecked(true); + m_buttonAny->setChecked(false); + + QButtonGroup *bg = new QButtonGroup(this); + bg->hide(); + bg->insert(m_buttonAll, (int) ConditionChain::All); + bg->insert(m_buttonAny, (int) ConditionChain::Any); + + // Connect some signals + connect(bg, SIGNAL(clicked(int)), this, SLOT(slotMatchTypeChanged(int))); + + m_lister = new FilterConditionWidgetLister(this); +} + +void FilterConditionsList::reset() +{ + m_lister->clear(); + setEnabled(false); +} + +void FilterConditionsList::loadRule(Rule *rule) +{ + m_rule = rule; + + switch (rule->conditions()->type()) { + case ConditionChain::All: m_buttonAll->setChecked(true); break; + case ConditionChain::Any: m_buttonAny->setChecked(true); break; + } + + m_lister->loadConditions(rule); + setEnabled(true); +} + +void FilterConditionsList::slotMatchTypeChanged(int type) +{ + if (m_rule) + const_cast<ConditionChain*>(m_rule->conditions())->setType((ConditionChain::Type) type); +} + +FilterConditionWidgetLister::FilterConditionWidgetLister(QWidget *parent) + : WidgetLister(parent, 0, 7), + m_rule(0) +{ + setMinimumWidth(400); +} + +void FilterConditionWidgetLister::loadConditions(KFTPCore::Filter::Rule *rule) +{ + const ConditionChain *conditions = rule->conditions(); + + // Clear the current list + setNumberShown(QMAX(conditions->count(), 0)); + + ConditionChain::ConstIterator le = conditions->end(); + QPtrList<QWidget>::Iterator wi = m_widgetList.begin(); + for (ConditionChain::ConstIterator i = conditions->begin(); i != le; ++i, ++wi) + static_cast<FilterConditionWidget*>((*wi))->setCondition((*i)); + + m_rule = rule; +} + +void FilterConditionWidgetLister::slotMore() +{ + WidgetLister::slotMore(); + + // Actually add the condition and update the latest widget + Condition *condition = new Condition(Filename, Condition::Contains, QVariant("")); + + const_cast<ConditionChain*>(m_rule->conditions())->append(condition); + static_cast<FilterConditionWidget*>(m_widgetList.last())->setCondition(condition); +} + +void FilterConditionWidgetLister::slotFewer() +{ + // Actually remove the condition + Condition *condition = static_cast<FilterConditionWidget*>(m_widgetList.last())->condition(); + const_cast<ConditionChain*>(m_rule->conditions())->remove(condition); + + WidgetLister::slotFewer(); +} + +void FilterConditionWidgetLister::slotClear() +{ + if (m_rule) + const_cast<ConditionChain*>(m_rule->conditions())->clear(); + + WidgetLister::slotClear(); +} + +QWidget *FilterConditionWidgetLister::createWidget(QWidget *parent) +{ + return new FilterConditionWidget(parent); +} + +FilterConditionWidget::FilterConditionWidget(QWidget *parent) + : QWidget(parent), + m_condition(0) +{ + QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_fieldCombo = new QComboBox(this); + m_fieldCombo->insertStringList(Filters::self()->getFieldNames()); + layout->addWidget(m_fieldCombo); + + m_typeStack = new QWidgetStack(this); + m_typeStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_typeStack); + + m_valueStack = new QWidgetStack(this); + m_valueStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_valueStack); + layout->setStretchFactor(m_valueStack, 10); + + // Initialize widgets + WidgetHandlerManager::self()->createConditionWidgets(m_typeStack, m_valueStack, this); + + // Connect signals + connect(m_fieldCombo, SIGNAL(activated(int)), this, SLOT(slotFieldChanged(int))); + + setFocusProxy(m_fieldCombo); +} + +void FilterConditionWidget::setCondition(const Condition *condition) +{ + m_condition = const_cast<Condition*>(condition); + + m_fieldCombo->setCurrentItem((int) condition->field()); + WidgetHandlerManager::self()->setCondition(m_typeStack, m_valueStack, condition); +} + +void FilterConditionWidget::slotFieldChanged(int field) +{ + WidgetHandlerManager::self()->update((Field) field, m_typeStack, m_valueStack); + + if (m_condition) { + // Update the current condition + m_condition->setField((Field) field); + slotTypeChanged(); + } +} + +void FilterConditionWidget::slotTypeChanged() +{ + if (m_condition) { + // Update the current condition + m_condition->setType(WidgetHandlerManager::self()->getConditionType(m_condition->field(), m_typeStack)); + slotValueChanged(); + } +} + +void FilterConditionWidget::slotValueChanged() +{ + if (m_condition) { + // Update the current condition + m_condition->setValue(WidgetHandlerManager::self()->getConditionValue(m_condition->field(), m_valueStack)); + } +} + +FilterActionsList::FilterActionsList(QWidget *parent) + : QGroupBox(1, Horizontal, i18n("Actions"), parent) +{ + setEnabled(false); + + m_lister = new FilterActionWidgetLister(this); +} + +void FilterActionsList::reset() +{ + m_lister->clear(); + setEnabled(false); +} + +void FilterActionsList::loadRule(Rule *rule) +{ + m_rule = rule; + + m_lister->loadActions(rule); + setEnabled(true); +} + +FilterActionWidgetLister::FilterActionWidgetLister(QWidget *parent) + : WidgetLister(parent, 0, 7), + m_rule(0) +{ + setMinimumWidth(400); +} + +void FilterActionWidgetLister::loadActions(KFTPCore::Filter::Rule *rule) +{ + const ActionChain *actions = rule->actions(); + + // Clear the current list + setNumberShown(QMAX(actions->count(), 0)); + + ActionChain::ConstIterator le = actions->end(); + QPtrList<QWidget>::Iterator wi = m_widgetList.begin(); + for (ActionChain::ConstIterator i = actions->begin(); i != le; ++i, ++wi) + static_cast<FilterActionWidget*>((*wi))->setAction((*i)); + + m_rule = rule; +} + +void FilterActionWidgetLister::slotMore() +{ + WidgetLister::slotMore(); + + // Actually add the action and update the latest widget + Action *action = new Action(Action::None, QVariant()); + + const_cast<ActionChain*>(m_rule->actions())->append(action); + static_cast<FilterActionWidget*>(m_widgetList.last())->setAction(action); +} + +void FilterActionWidgetLister::slotFewer() +{ + // Actually remove the action + Action *action = static_cast<FilterActionWidget*>(m_widgetList.last())->action(); + const_cast<ActionChain*>(m_rule->actions())->remove(action); + + WidgetLister::slotFewer(); +} + +void FilterActionWidgetLister::slotClear() +{ + if (m_rule) + const_cast<ActionChain*>(m_rule->actions())->clear(); + + WidgetLister::slotClear(); +} + +QWidget *FilterActionWidgetLister::createWidget(QWidget *parent) +{ + return new FilterActionWidget(parent); +} + +FilterActionWidget::FilterActionWidget(QWidget *parent) + : QWidget(parent), + m_action(0) +{ + QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_actionCombo = new QComboBox(this); + m_actionCombo->insertStringList(Filters::self()->getActionNames()); + layout->addWidget(m_actionCombo); + + m_valueStack = new QWidgetStack(this); + m_valueStack->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + layout->addWidget(m_valueStack); + layout->setStretchFactor(m_valueStack, 10); + + // Initialize widgets + WidgetHandlerManager::self()->createActionWidgets(m_valueStack, this); + + // Connect signals + connect(m_actionCombo, SIGNAL(activated(int)), this, SLOT(slotActionChanged(int))); + connect(m_actionCombo, SIGNAL(activated(int)), m_valueStack, SLOT(raiseWidget(int))); + + setFocusProxy(m_actionCombo); +} + +void FilterActionWidget::setAction(const Action *action) +{ + m_action = const_cast<Action*>(action); + + m_actionCombo->setCurrentItem((int) action->type()); + WidgetHandlerManager::self()->setAction(m_valueStack, action); +} + +void FilterActionWidget::slotActionChanged(int field) +{ + if (m_action) { + m_action->setType((Action::Type) field); + slotValueChanged(); + } +} + +void FilterActionWidget::slotValueChanged() +{ + if (m_action) + m_action->setValue(WidgetHandlerManager::self()->getActionValue(m_valueStack)); +} + +} + +#include "filtereditor.moc" + diff --git a/kftpgrabber/src/widgets/filtereditor.h b/kftpgrabber/src/widgets/filtereditor.h new file mode 100644 index 0000000..95fd664 --- /dev/null +++ b/kftpgrabber/src/widgets/filtereditor.h @@ -0,0 +1,375 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETSFILTEREDITOR_H +#define KFTPWIDGETSFILTEREDITOR_H + +#include "widgetlister.h" +#include "misc/filter.h" + +#include <qwidget.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlistview.h> +#include <qradiobutton.h> +#include <qcombobox.h> +#include <qwidgetstack.h> +#include <qcheckbox.h> + +#include <kpushbutton.h> + +namespace KFTPWidgets { + +class ListView; + +/** + * A visual representation of a condition. + * + * @author Jernej Kos + */ +class FilterConditionWidget : public QWidget { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterConditionWidget(QWidget *parent); + + /** + * Associate a condition with this widget. + * + * @param condition The internal condition representation + */ + void setCondition(const KFTPCore::Filter::Condition *condition); + + /** + * Return the condition associated with this widget. + * + * @return A valid condition or 0 if no condition has been associated + */ + KFTPCore::Filter::Condition *condition() const { return m_condition; } +private slots: + void slotFieldChanged(int field); + void slotTypeChanged(); + void slotValueChanged(); +private: + QComboBox *m_fieldCombo; + QWidgetStack *m_typeStack; + QWidgetStack *m_valueStack; + + KFTPCore::Filter::Condition *m_condition; +}; + +/** + * A container for condition representation widgets. + * + * @author Jernej Kos + */ +class FilterConditionWidgetLister : public WidgetLister { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterConditionWidgetLister(QWidget *parent); + + /** + * Load the conditions from the specified rule. + * + * @param rule The rule instance + */ + void loadConditions(KFTPCore::Filter::Rule *rule); +protected: + QWidget *createWidget(QWidget *parent); +protected slots: + void slotMore(); + void slotFewer(); + void slotClear(); +private: + KFTPCore::Filter::Rule *m_rule; +}; + +/** + * A list of conditions together with all/any configuration. + * + * @author Jernej Kos + */ +class FilterConditionsList : public QGroupBox { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterConditionsList(QWidget *parent); +public slots: + /** + * Reset the condition list and disable it. + */ + void reset(); + + /** + * Load the conditions from the specified rule. + * + * @param rule The rule instance + */ + void loadRule(KFTPCore::Filter::Rule *rule); +private slots: + void slotMatchTypeChanged(int type); +private: + QRadioButton *m_buttonAll; + QRadioButton *m_buttonAny; + + FilterConditionWidgetLister *m_lister; + KFTPCore::Filter::Rule *m_rule; +}; + +/** + * A visual representation of an action. + * + * @author Jernej Kos + */ +class FilterActionWidget : public QWidget { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterActionWidget(QWidget *parent); + + /** + * Associate an action with this widget. + * + * @param action The internal action representation + */ + void setAction(const KFTPCore::Filter::Action *action); + + /** + * Return the action associated with this widget. + * + * @return A valid action or 0 if no action has been associated + */ + KFTPCore::Filter::Action *action() const { return m_action; } +private slots: + void slotActionChanged(int field); + void slotValueChanged(); +private: + QComboBox *m_actionCombo; + QWidgetStack *m_valueStack; + + KFTPCore::Filter::Action *m_action; +}; + +/** + * A container for action representation widgets. + * + * @author Jernej Kos + */ +class FilterActionWidgetLister : public WidgetLister { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterActionWidgetLister(QWidget *parent); + + /** + * Load the actions from the specified rule. + * + * @param rule The rule instance + */ + void loadActions(KFTPCore::Filter::Rule *rule); +protected: + QWidget *createWidget(QWidget *parent); +protected slots: + void slotMore(); + void slotFewer(); + void slotClear(); +private: + KFTPCore::Filter::Rule *m_rule; +}; + +/** + * A list of actions. + * + * @author Jernej Kos + */ +class FilterActionsList : public QGroupBox { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterActionsList(QWidget *parent); +public slots: + /** + * Reset the action list and disable it. + */ + void reset(); + + /** + * Load the actions from the specified rule. + * + * @param rule The rule instance + */ + void loadRule(KFTPCore::Filter::Rule *rule); +private: + FilterActionWidgetLister *m_lister; + KFTPCore::Filter::Rule *m_rule; +}; + +/** + * A widget that displays the list of currently loaded filter rules. + * + * @author Jernej Kos + */ +class FilterListView : public QGroupBox { +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + FilterListView(QWidget *parent); + + /** + * Reset the filter editor and reload all the rules. + */ + void reset(); +private slots: + void slotSelectionChanged(QListViewItem *item); + + void slotNewRule(); + void slotDeleteRule(); + void slotRenameRule(); + void slotCopyRule(); + + void slotUp(); + void slotDown(); +private: + ListView *m_listView; + + KPushButton *m_buttonUp; + KPushButton *m_buttonDown; + + QPushButton *m_buttonNew; + QPushButton *m_buttonCopy; + QPushButton *m_buttonDelete; + QPushButton *m_buttonRename; +signals: + /** + * This signal gets emitted when a new rule should be displayed by + * other widgets. + * + * @param rule The rule to display + */ + void ruleChanged(KFTPCore::Filter::Rule *rule); + + /** + * This signal gets emitted when a rule is removed. + */ + void ruleRemoved(); +}; + +/** + * An item visually representing a filter rule. + * + * @author Jernej Kos + */ +class FilterListItem : public QListViewItem { +public: + /** + * Class constructor. + * + * @param parent The parent list view + * @param rule Rule this item represents + */ + FilterListItem(ListView *parent, KFTPCore::Filter::Rule *rule); + + /** + * Get the rule this item represents. + */ + KFTPCore::Filter::Rule *rule() { return m_rule; } +private: + KFTPCore::Filter::Rule *m_rule; +}; + +/** + * This widget is a global filter editor and enables the user to add, + * remove or modify existing filters. + * + * @author Jernej Kos + */ +class FilterEditor : public QWidget { +Q_OBJECT +public: + /** + * Class constructor. + */ + FilterEditor(QWidget *parent); + + /** + * Reset the filter editor and reload all the rules. + */ + void reset(); +private slots: + void slotRuleChanged(KFTPCore::Filter::Rule *rule); + void slotRuleRemoved(); + + void slotEnabledChanged(); +private: + KFTPCore::Filter::Rule *m_rule; + + QCheckBox *m_enabledCheck; + FilterListView *m_listView; + FilterConditionsList *m_conditionsList; + FilterActionsList *m_actionsList; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/kftpfilteraddpatternlayout.cpp b/kftpgrabber/src/widgets/kftpfilteraddpatternlayout.cpp new file mode 100644 index 0000000..50c403b --- /dev/null +++ b/kftpgrabber/src/widgets/kftpfilteraddpatternlayout.cpp @@ -0,0 +1,92 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/home/kostko/development/kftpgrabber/src/widgets/kftpfilteraddpatternlayout.ui' +** +** Created: Mon Oct 20 18:26:31 2003 +** by: The User Interface Compiler ($Id: kftpfilteraddpatternlayout.cpp,v 1.1.1.1 2004/02/13 13:33:43 kostko Exp $) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "kftpfilteraddpatternlayout.h" + +#include <qvariant.h> +#include <qpushbutton.h> +#include <qgroupbox.h> +#include <qlabel.h> +#include <klineedit.h> +#include <kcolorbutton.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a KFTPFilterAddPatternLayout as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + */ +KFTPFilterAddPatternLayout::KFTPFilterAddPatternLayout( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "KFTPFilterAddPatternLayout" ); + KFTPFilterAddPatternLayoutLayout = new QGridLayout( this, 1, 1, 11, 6, "KFTPFilterAddPatternLayoutLayout"); + + groupBox1 = new QGroupBox( this, "groupBox1" ); + groupBox1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)5, (QSizePolicy::SizeType)2, 0, 0, groupBox1->sizePolicy().hasHeightForWidth() ) ); + groupBox1->setColumnLayout(0, Qt::Vertical ); + groupBox1->layout()->setSpacing( 6 ); + groupBox1->layout()->setMargin( 11 ); + groupBox1Layout = new QGridLayout( groupBox1->layout() ); + groupBox1Layout->setAlignment( Qt::AlignTop ); + + layout9 = new QHBoxLayout( 0, 0, 6, "layout9"); + + layout8 = new QVBoxLayout( 0, 0, 6, "layout8"); + + textLabel1 = new QLabel( groupBox1, "textLabel1" ); + layout8->addWidget( textLabel1 ); + + textLabel2 = new QLabel( groupBox1, "textLabel2" ); + layout8->addWidget( textLabel2 ); + layout9->addLayout( layout8 ); + + layout7 = new QVBoxLayout( 0, 0, 6, "layout7"); + + kLineEdit1 = new KLineEdit( groupBox1, "kLineEdit1" ); + layout7->addWidget( kLineEdit1 ); + + kColorButton1 = new KColorButton( groupBox1, "kColorButton1" ); + kColorButton1->setSizePolicy( QSizePolicy( (QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, kColorButton1->sizePolicy().hasHeightForWidth() ) ); + layout7->addWidget( kColorButton1 ); + layout9->addLayout( layout7 ); + + groupBox1Layout->addLayout( layout9, 0, 0 ); + + KFTPFilterAddPatternLayoutLayout->addWidget( groupBox1, 0, 0 ); + languageChange(); + resize( QSize(380, 110).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); +} + +/* + * Destroys the object and frees any allocated resources + */ +KFTPFilterAddPatternLayout::~KFTPFilterAddPatternLayout() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void KFTPFilterAddPatternLayout::languageChange() +{ + setCaption( tr2i18n( "Form1" ) ); + groupBox1->setTitle( tr2i18n( "New Pattern" ) ); + textLabel1->setText( tr2i18n( "Filename pattern:" ) ); + textLabel2->setText( tr2i18n( "Color:" ) ); + kColorButton1->setText( QString::null ); +} + +#include "kftpfilteraddpatternlayout.moc" diff --git a/kftpgrabber/src/widgets/kftpfiltereditorlayout.cpp b/kftpgrabber/src/widgets/kftpfiltereditorlayout.cpp new file mode 100644 index 0000000..b52913c --- /dev/null +++ b/kftpgrabber/src/widgets/kftpfiltereditorlayout.cpp @@ -0,0 +1,115 @@ +#include <klocale.h> +/**************************************************************************** +** Form implementation generated from reading ui file '/home/kostko/development/kftpgrabber/src/widgets/kftpfiltereditorlayout.ui' +** +** Created: Mon Oct 20 16:14:00 2003 +** by: The User Interface Compiler ($Id: kftpfiltereditorlayout.cpp,v 1.1.1.1 2004/02/13 13:33:43 kostko Exp $) +** +** WARNING! All changes made in this file will be lost! +****************************************************************************/ + +#include "kftpfiltereditorlayout.h" + +#include <qvariant.h> +#include <qpushbutton.h> +#include <qtabwidget.h> +#include <kpushbutton.h> +#include <qheader.h> +#include <klistview.h> +#include <qcheckbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qtooltip.h> +#include <qwhatsthis.h> + +/* + * Constructs a KFTPFilterEditorLayout as a child of 'parent', with the + * name 'name' and widget flags set to 'f'. + */ +KFTPFilterEditorLayout::KFTPFilterEditorLayout( QWidget* parent, const char* name, WFlags fl ) + : QWidget( parent, name, fl ) +{ + if ( !name ) + setName( "KFTPFilterEditorLayout" ); + KFTPFilterEditorLayoutLayout = new QGridLayout( this, 1, 1, 11, 6, "KFTPFilterEditorLayoutLayout"); + + tabWidget2 = new QTabWidget( this, "tabWidget2" ); + + tab = new QWidget( tabWidget2, "tab" ); + tabLayout = new QGridLayout( tab, 1, 1, 11, 6, "tabLayout"); + + layout1 = new QVBoxLayout( 0, 0, 6, "layout1"); + + addPatternButton = new KPushButton( tab, "addPatternButton" ); + layout1->addWidget( addPatternButton ); + + editPatternButton = new KPushButton( tab, "editPatternButton" ); + layout1->addWidget( editPatternButton ); + + removePatternButton = new KPushButton( tab, "removePatternButton" ); + layout1->addWidget( removePatternButton ); + + tabLayout->addLayout( layout1, 0, 1 ); + QSpacerItem* spacer = new QSpacerItem( 31, 111, QSizePolicy::Minimum, QSizePolicy::Expanding ); + tabLayout->addItem( spacer, 1, 1 ); + + layout2 = new QVBoxLayout( 0, 0, 6, "layout2"); + + patternList = new KListView( tab, "patternList" ); + patternList->addColumn( tr2i18n( "Pattern" ) ); + patternList->addColumn( tr2i18n( "Color" ) ); + layout2->addWidget( patternList ); + + enabledCheck = new QCheckBox( tab, "enabledCheck" ); + layout2->addWidget( enabledCheck ); + + tabLayout->addMultiCellLayout( layout2, 0, 1, 0, 0 ); + tabWidget2->insertTab( tab, QString("") ); + + tab_2 = new QWidget( tabWidget2, "tab_2" ); + + textLabel1 = new QLabel( tab_2, "textLabel1" ); + textLabel1->setGeometry( QRect( 10, 10, 130, 20 ) ); + tabWidget2->insertTab( tab_2, QString("") ); + + tab_3 = new QWidget( tabWidget2, "tab_3" ); + + textLabel1_2 = new QLabel( tab_3, "textLabel1_2" ); + textLabel1_2->setGeometry( QRect( 10, 10, 130, 20 ) ); + tabWidget2->insertTab( tab_3, QString("") ); + + KFTPFilterEditorLayoutLayout->addWidget( tabWidget2, 0, 0 ); + languageChange(); + resize( QSize(456, 299).expandedTo(minimumSizeHint()) ); + clearWState( WState_Polished ); +} + +/* + * Destroys the object and frees any allocated resources + */ +KFTPFilterEditorLayout::~KFTPFilterEditorLayout() +{ + // no need to delete child widgets, Qt does it all for us +} + +/* + * Sets the strings of the subwidgets using the current + * language. + */ +void KFTPFilterEditorLayout::languageChange() +{ + setCaption( tr2i18n( "Form1" ) ); + addPatternButton->setText( tr2i18n( "Add pattern" ) ); + editPatternButton->setText( tr2i18n( "Edit" ) ); + removePatternButton->setText( tr2i18n( "Remove" ) ); + patternList->header()->setLabel( 0, tr2i18n( "Pattern" ) ); + patternList->header()->setLabel( 1, tr2i18n( "Color" ) ); + enabledCheck->setText( tr2i18n( "Enabled" ) ); + tabWidget2->changeTab( tab, tr2i18n( "Highlighting" ) ); + textLabel1->setText( tr2i18n( "<b>Not yet implemented.</b>" ) ); + tabWidget2->changeTab( tab_2, tr2i18n( "Skip List" ) ); + textLabel1_2->setText( tr2i18n( "<b>Not yet implemented.</b>" ) ); + tabWidget2->changeTab( tab_3, tr2i18n( "ASCII xtensions" ) ); +} + +#include "kftpfiltereditorlayout.moc" diff --git a/kftpgrabber/src/widgets/kftpselectserverdialog.cpp b/kftpgrabber/src/widgets/kftpselectserverdialog.cpp new file mode 100644 index 0000000..f3b6b3a --- /dev/null +++ b/kftpgrabber/src/widgets/kftpselectserverdialog.cpp @@ -0,0 +1,79 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "kftpbookmarks.h" +#include "kftpselectserverdialog.h" +#include "kftpbookmarks.h" +#include "bookmarks/listview.h" +#include "misc.h" + +#include <klistview.h> +#include <kiconloader.h> +#include <klocale.h> + +using namespace KFTPGrabberBase; + +KFTPSelectServerDialog::KFTPSelectServerDialog(QWidget *parent, const char *name) + : KDialogBase(parent, name, true, "Select a server", KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok), m_selectedSite(0) +{ + m_tree = new KFTPWidgets::Bookmarks::ListView(KFTPBookmarks::Manager::self(), this); + m_tree->setMinimumWidth(270); + m_tree->fillBookmarkData(); + + connect(m_tree, SIGNAL(clicked(QListViewItem*)), this, SLOT(slotTreeClicked())); + + // Set some stuff + setMainWidget(m_tree); + enableButtonOK(false); +} + +void KFTPSelectServerDialog::slotTreeClicked() +{ + enableButtonOK(false); + + if (m_tree->selectedItem()) { + if (static_cast<KFTPWidgets::Bookmarks::ListViewItem*>(m_tree->selectedItem())->m_type == 1) { + // Set the active server + m_selectedSite = static_cast<KFTPWidgets::Bookmarks::ListViewItem*>(m_tree->selectedItem())->m_site; + + enableButtonOK(true); + return; + } + } +} + + +#include "kftpselectserverdialog.moc" diff --git a/kftpgrabber/src/widgets/kftpselectserverdialog.h b/kftpgrabber/src/widgets/kftpselectserverdialog.h new file mode 100644 index 0000000..8c4afd3 --- /dev/null +++ b/kftpgrabber/src/widgets/kftpselectserverdialog.h @@ -0,0 +1,70 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPSELECTSERVERDIALOG_H +#define KFTPSELECTSERVERDIALOG_H + +#include <kdialogbase.h> +#include <qdom.h> +#include <qlistview.h> + +namespace KFTPBookmarks { + class Site; +} + +namespace KFTPWidgets { +namespace Bookmarks { + class ListView; +} +} + +/** +@author Jernej Kos +*/ +class KFTPSelectServerDialog : public KDialogBase +{ +Q_OBJECT +public: + KFTPSelectServerDialog(QWidget *parent = 0, const char *name = 0); + + KFTPBookmarks::Site *getSelectedSite() { return m_selectedSite; } +private: + KFTPWidgets::Bookmarks::ListView *m_tree; + KFTPBookmarks::Site *m_selectedSite; +private slots: + void slotTreeClicked(); +}; + +#endif diff --git a/kftpgrabber/src/widgets/kftpserverlineedit.cpp b/kftpgrabber/src/widgets/kftpserverlineedit.cpp new file mode 100644 index 0000000..87e94e3 --- /dev/null +++ b/kftpgrabber/src/widgets/kftpserverlineedit.cpp @@ -0,0 +1,105 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "kftpbookmarks.h" +#include "kftpserverlineedit.h" +#include "kftpselectserverdialog.h" + +#include <kdialog.h> +#include <kpushbutton.h> +#include <klocale.h> + +#include <qlayout.h> + +KFTPServerLineEdit::KFTPServerLineEdit(QWidget *parent, const char *name, WFlags f) + : QWidget(parent, name, f), m_currentSite(0) +{ + QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint()); + + m_lineEdit = new KLineEdit(this); + m_lineEdit->setReadOnly(true); + + KPushButton *selectButton = new KPushButton(i18n("Select..."), this); + selectButton->setFlat(true); + connect(selectButton, SIGNAL(clicked()), this, SLOT(slotSelectButtonClicked())); + + layout->addWidget(m_lineEdit); + layout->addWidget(selectButton); +} + +KFTPServerLineEdit::~KFTPServerLineEdit() +{ +} + +void KFTPServerLineEdit::setCurrentSite(KFTPBookmarks::Site *site) +{ + if (site) { + m_currentSite = site; + m_lineEdit->setText(m_currentSite->getAttribute("name")); + + emit siteChanged(m_currentSite); + } else { + m_currentSite = 0L; + + clear(); + } +} + +void KFTPServerLineEdit::clear() +{ + m_lineEdit->clear(); +} + +void KFTPServerLineEdit::slotSelectButtonClicked() +{ + KFTPSelectServerDialog *dialog = new KFTPSelectServerDialog(this); + + if (dialog->exec() == QDialog::Accepted) { + m_currentSite = dialog->getSelectedSite(); + + if (m_currentSite) + m_lineEdit->setText(m_currentSite->getAttribute("name")); + else + m_lineEdit->setText(i18n("No name")); + + emit siteChanged(m_currentSite); + } + + delete dialog; +} + + + +#include "kftpserverlineedit.moc" diff --git a/kftpgrabber/src/widgets/kftpserverlineedit.h b/kftpgrabber/src/widgets/kftpserverlineedit.h new file mode 100644 index 0000000..dd471ae --- /dev/null +++ b/kftpgrabber/src/widgets/kftpserverlineedit.h @@ -0,0 +1,71 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPSERVERLINEEDIT_H +#define KFTPSERVERLINEEDIT_H + +#include <qwidget.h> +#include <qdom.h> + +#include <klineedit.h> + +namespace KFTPBookmarks { + class Site; +} + +/** +@author Jernej Kos +*/ +class KFTPServerLineEdit : public QWidget +{ +Q_OBJECT +public: + KFTPServerLineEdit(QWidget *parent = 0, const char *name = 0, WFlags f = 0); + ~KFTPServerLineEdit(); + + KFTPBookmarks::Site *getCurrentSite() { return m_currentSite; } + void setCurrentSite(KFTPBookmarks::Site *site); + + void clear(); +private: + KFTPBookmarks::Site *m_currentSite; + KLineEdit *m_lineEdit; +private slots: + void slotSelectButtonClicked(); +signals: + void siteChanged(KFTPBookmarks::Site *site); +}; + +#endif diff --git a/kftpgrabber/src/widgets/kftptabwidget.cpp b/kftpgrabber/src/widgets/kftptabwidget.cpp new file mode 100644 index 0000000..317f887 --- /dev/null +++ b/kftpgrabber/src/widgets/kftptabwidget.cpp @@ -0,0 +1,53 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "kftptabwidget.h" +#include "kftptabwidget.moc" + +KFTPTabWidget::KFTPTabWidget( QWidget* parent, const char* name ) + : KTabWidget ( parent, name ) +{ +} + + +KFTPTabWidget::~KFTPTabWidget() +{ +} + +void KFTPTabWidget::mousePressEvent( QMouseEvent* ) +{ + emit mouseEvent( this->name() ); +} diff --git a/kftpgrabber/src/widgets/kftptabwidget.h b/kftpgrabber/src/widgets/kftptabwidget.h new file mode 100644 index 0000000..d17efe3 --- /dev/null +++ b/kftpgrabber/src/widgets/kftptabwidget.h @@ -0,0 +1,60 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPTABWIDGET_H +#define KFTPTABWIDGET_H + +#include <ktabwidget.h> + +/** +@author Blacknator +*/ +class KFTPTabWidget : public KTabWidget +{ + private: + Q_OBJECT + + public: + KFTPTabWidget( QWidget* parent = 0, const char* name = 0 ); + ~KFTPTabWidget(); + + virtual void mousePressEvent( QMouseEvent* mouseEvent ); + + signals: + void mouseEvent( QString widgetName ); + +}; + +#endif diff --git a/kftpgrabber/src/widgets/kftpzeroconflistview.cpp b/kftpgrabber/src/widgets/kftpzeroconflistview.cpp new file mode 100644 index 0000000..eb60204 --- /dev/null +++ b/kftpgrabber/src/widgets/kftpzeroconflistview.cpp @@ -0,0 +1,98 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "kftpzeroconflistview.h" +#include "kftpapi.h" +#include "kftpsession.h" + +#include <kdeversion.h> + +#if KDE_IS_VERSION(3,4,0) +#include "kftpzeroconf.h" +#endif + +#include <klocale.h> +#include <kiconloader.h> + +KFTPZeroConfListView::KFTPZeroConfListView(QWidget *parent, const char *name) + : KFTPWidgets::ListView(parent, name) +{ + // Set some stuff + setMinimumWidth(150); + setFullWidth(true); + addColumn(i18n("Sites Near You")); + setRootIsDecorated(true); + setEmptyListText(i18n("No sites published.")); + setItemsRenameable(false); + +#if KDE_IS_VERSION(3,4,0) + connect(KFTPAPI::getInstance()->zeroConfInterface(), SIGNAL(servicesUpdated()), this, SLOT(slotSitesChanged())); + connect(this, SIGNAL(executed(QListViewItem*)), this, SLOT(slotSiteExecuted(QListViewItem*))); + + slotSitesChanged(); +#endif +} + +void KFTPZeroConfListView::slotSitesChanged() +{ +#if KDE_IS_VERSION(3,4,0) + // Update the site list + QValueList<DNSSD::RemoteService::Ptr> list = KFTPAPI::getInstance()->zeroConfInterface()->getServiceList(); + + clear(); + if (!list.isEmpty()) { + QValueList<DNSSD::RemoteService::Ptr>::iterator end(list.end()); + + for (QValueList<DNSSD::RemoteService::Ptr>::iterator i(list.begin()); i != end; ++i) { + QString name = (*i)->serviceName(); + QString ip = (*i)->hostName(); + QString port = QString::number((*i)->port()); + + KListViewItem *site = new KListViewItem(this, name, ip, port); + site->setPixmap(0, SmallIcon("lan")); + } + } +#endif +} + +void KFTPZeroConfListView::slotSiteExecuted(QListViewItem *item) +{ +#if KDE_IS_VERSION(3,4,0) + // Connect to the site + KFTPAPI::getInstance()->mainWindow()->slotQuickConnect(item->text(0), item->text(1), item->text(2).toInt()); +#endif +} + +#include "kftpzeroconflistview.moc" diff --git a/kftpgrabber/src/widgets/kftpzeroconflistview.h b/kftpgrabber/src/widgets/kftpzeroconflistview.h new file mode 100644 index 0000000..9aea9aa --- /dev/null +++ b/kftpgrabber/src/widgets/kftpzeroconflistview.h @@ -0,0 +1,56 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPZEROCONFLISTVIEW_H +#define KFTPZEROCONFLISTVIEW_H + +#include "listview.h" + +/** + * This class provides a list view that displays all current FTP servers published via Zeroconf protocol. + * + * @author Jernej Kos + */ +class KFTPZeroConfListView : public KFTPWidgets::ListView +{ +Q_OBJECT +public: + KFTPZeroConfListView(QWidget *parent = 0, const char *name = 0); +private slots: + void slotSitesChanged(); + void slotSiteExecuted(QListViewItem*); +}; + +#endif diff --git a/kftpgrabber/src/widgets/listview.cpp b/kftpgrabber/src/widgets/listview.cpp new file mode 100644 index 0000000..635130b --- /dev/null +++ b/kftpgrabber/src/widgets/listview.cpp @@ -0,0 +1,85 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "listview.h" + +#include <qpainter.h> +#include <qstringlist.h> + +namespace KFTPWidgets { + +ListView::ListView(QWidget *parent, const char *name) + : KListView(parent, name) +{ +} + + +ListView::~ListView() +{ +} + +void ListView::resizeEvent(QResizeEvent *e) +{ + KListView::resizeEvent(e); + triggerUpdate(); +} + +void ListView::setEmptyListText(const QString &text) +{ + m_emptyListText = text; + triggerUpdate(); +} + +void ListView::drawContentsOffset(QPainter * p, int ox, int oy, int cx, int cy, int cw, int ch) +{ + KListView::drawContentsOffset(p, ox, oy, cx, cy, cw, ch); + + if (childCount() == 0 && !m_emptyListText.isEmpty()) { + p->setPen(Qt::darkGray); + + QStringList lines = QStringList::split("\n", m_emptyListText); + int ypos = 10 + p->fontMetrics().height(); + + QStringList::Iterator end(lines.end()); + for (QStringList::Iterator str( lines.begin() ); str != end; ++str) { + p->drawText((viewport()->width()/2)-(p->fontMetrics().width(*str)/2), ypos, *str); + ypos += p->fontMetrics().lineSpacing(); + } + } +} + +} + +#include "listview.moc" diff --git a/kftpgrabber/src/widgets/listview.h b/kftpgrabber/src/widgets/listview.h new file mode 100644 index 0000000..8718f97 --- /dev/null +++ b/kftpgrabber/src/widgets/listview.h @@ -0,0 +1,63 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPLISTVIEW_H +#define KFTPLISTVIEW_H + +#include <klistview.h> + +namespace KFTPWidgets { + +/** + * @author Jernej Kos + */ +class ListView : public KListView +{ +Q_OBJECT +public: + ListView(QWidget *parent = 0, const char *name = 0); + ~ListView(); + + void setEmptyListText(const QString &text); + virtual void resizeEvent(QResizeEvent *e); +protected: + virtual void drawContentsOffset(QPainter * p, int ox, int oy, int cx, int cy, int cw, int ch ); +private: + QString m_emptyListText; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/listviewitem.cpp b/kftpgrabber/src/widgets/listviewitem.cpp new file mode 100644 index 0000000..6b91feb --- /dev/null +++ b/kftpgrabber/src/widgets/listviewitem.cpp @@ -0,0 +1,96 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "listviewitem.h" + +#include <qheader.h> +#include <qpixmap.h> +#include <qpainter.h> +#include <qsimplerichtext.h> + +namespace KFTPWidgets { + +ListViewItem::ListViewItem(QListView *parent) + : KListViewItem(parent) +{ +} + +void ListViewItem::setRichText(int col, const QString &text) +{ + setText(col, QString::null); + m_richText[col] = text; +} + +void ListViewItem::setup() +{ + QListViewItem::setup(); + + int maxHeight = height(); + + for (int i = 0; i < listView()->header()->count() - 1; i++) { + if (text(i).isNull()) { + QSimpleRichText rt(m_richText[i], QFont()); + maxHeight = rt.height() > maxHeight ? rt.height() : maxHeight; + } + } + + setHeight(maxHeight); +} + +void ListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + if (text(column).isNull()) { + KListViewItem::paintCell(p, cg, column, width, alignment); + int pad = 0; + + if (pixmap(column)) { + pad = pixmap(column)->width() + 5; + } + + QSimpleRichText rt(m_richText[column], p->font()); + rt.draw(p, pad, 0, QRect(pad, 0, width, height()), cg); + } else if (m_colors.contains(column)) { + QColorGroup _cg(cg); + QColor c = _cg.text(); + + _cg.setColor(QColorGroup::Text, m_colors[column]); + KListViewItem::paintCell(p, _cg, column, width, alignment); + _cg.setColor(QColorGroup::Text, c); + } else { + KListViewItem::paintCell(p, cg, column, width, alignment); + } +} + +} diff --git a/kftpgrabber/src/widgets/listviewitem.h b/kftpgrabber/src/widgets/listviewitem.h new file mode 100644 index 0000000..b9edc23 --- /dev/null +++ b/kftpgrabber/src/widgets/listviewitem.h @@ -0,0 +1,71 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSLISTVIEWITEM_H +#define KFTPWIDGETSLISTVIEWITEM_H + +#include <klistview.h> + +#include <qmap.h> +#include <qcolor.h> + +namespace KFTPWidgets { + +/** + * This class is a simple QListViewItem replacement that supports displaying + * richtext. + * + * @author Jernej Kos + */ +class ListViewItem : public KListViewItem +{ +public: + ListViewItem(QListView *parent); + + void setRichText(int col, const QString &text); + QString richText(int col) { return m_richText[col]; } + + void setTextColor(int col, QColor color) { m_colors[col] = color; } + + void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + void setup(); +private: + QMap<int, QString> m_richText; + QMap<int, QColor> m_colors; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/logview.cpp b/kftpgrabber/src/widgets/logview.cpp new file mode 100644 index 0000000..bac9df8 --- /dev/null +++ b/kftpgrabber/src/widgets/logview.cpp @@ -0,0 +1,143 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "logview.h" +#include "misc/config.h" +#include "kftpapi.h" + +#include <klocale.h> +#include <kstdaction.h> +#include <kfiledialog.h> +#include <kmessagebox.h> + +#include <qfile.h> +#include <qtextstream.h> + +namespace KFTPWidgets { + +LogView::LogView(QWidget *parent, const char *name) + : KTextEdit(parent, name) +{ + setTextFormat(Qt::LogText); + setMaxLogLines(200); + setFont(KFTPCore::Config::logFont()); + + // Override disabled background of KTextEdit + unsetPalette(); + + // Init actions + m_saveToFileAction = KStdAction::saveAs(this, SLOT(slotSaveToFile()), KFTPAPI::getInstance()->mainWindow()->actionCollection(), "log_safeAs"); + m_clearLogAction = KStdAction::clear(this, SLOT(slotClearLog()), KFTPAPI::getInstance()->mainWindow()->actionCollection(), "log_clear"); + + append(i18n("<b>KFTPGrabber</b> logger initialized.<br>")); +} + + +LogView::~LogView() +{ +} + +QPopupMenu *LogView::createPopupMenu(const QPoint &pos) +{ + QPopupMenu *menu = KTextEdit::createPopupMenu(pos); + + m_saveToFileAction->plug(menu); + menu->insertSeparator(); + m_clearLogAction->plug(menu); + + return menu; +} + +void LogView::slotSaveToFile() +{ + QString savePath = KFileDialog::getSaveFileName(); + + if (!savePath.isEmpty()) { + QFile file(savePath); + if (file.open(IO_WriteOnly)) { + QTextStream stream(&file); + stream << text(); + file.close(); + } else { + KMessageBox::error(0L, i18n("Unable to open file for writing.")); + } + } +} + +void LogView::slotClearLog() +{ + clear(); +} + +void LogView::append(const QString &text) +{ + QDateTime dt = QDateTime::currentDateTime(); + QTextEdit::append("[" + dt.toString("hh:mm:ss") + "] " + text); + scrollToBottom(); +} + +void LogView::ftpLog(int type, const QString &text) +{ + // Set the font if changed + if (KFTPCore::Config::logFont() != font()) + setFont(KFTPCore::Config::logFont()); + + QString line; + line = text.stripWhiteSpace(); + line.replace("<", "<"); + line.replace(">", ">"); + switch (type) { + case 0: { + QString code = line.section(" ", 0, 0); + QString text = line.mid(line.find(' ')+1); + append("<font color=" + KFTPCore::Config::logResponsesColor().name() + "><b>" + code + "</b> " + text + "</font><br>"); + break; + } + case 1: { + if (line.left(4) == "PASS") + line = "PASS (hidden)"; + + append("<font color=" + KFTPCore::Config::logCommandsColor().name() + "><b>" + line + "</b></font><br>"); + break; + } + case 2: append("<font color=" + KFTPCore::Config::logMultilineColor().name() + ">" + line + "</font><br>"); break; + case 3: append("<font color=" + KFTPCore::Config::logStatusColor().name() + "><b>*** " + line + "</b></font><br>"); break; + case 4: append("<font color=" + KFTPCore::Config::logErrorColor().name() + "><b>*** " + line + "</b></font><br>"); break; + } +} + +} + +#include "logview.moc" diff --git a/kftpgrabber/src/widgets/logview.h b/kftpgrabber/src/widgets/logview.h new file mode 100644 index 0000000..ac2f9e3 --- /dev/null +++ b/kftpgrabber/src/widgets/logview.h @@ -0,0 +1,73 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPLOGVIEW_H +#define KFTPLOGVIEW_H + +#include <ktextedit.h> +#include <kaction.h> + +#include <qpopupmenu.h> + +namespace KFTPWidgets { + +/** + * This class provides a simple log widget. + * + * @author Jernej Kos + */ +class LogView : public KTextEdit +{ +Q_OBJECT +public: + LogView(QWidget *parent = 0, const char *name = 0); + ~LogView(); + + void append(const QString &text); +protected: + KAction *m_saveToFileAction; + KAction *m_clearLogAction; + + QPopupMenu *createPopupMenu(const QPoint &pos); +public slots: + void ftpLog(int type, const QString &text); +private slots: + void slotSaveToFile(); + void slotClearLog(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/multitabbar.cpp b/kftpgrabber/src/widgets/multitabbar.cpp new file mode 100644 index 0000000..2b7c583 --- /dev/null +++ b/kftpgrabber/src/widgets/multitabbar.cpp @@ -0,0 +1,1160 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2001-2003 by Joseph Wenninger <jowenn@kde.org> + * Copyright (C) 2005 by Mark Kretschmann <markey@web.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "multitabbar.h" +#include "multitabbar.moc" +#include "multitabbar_p.h" +#include "multitabbar_p.moc" + +#include <math.h> + +#include <qapplication.h> +#include <qbutton.h> +#include <qpopupmenu.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qtooltip.h> +#include <qfontmetrics.h> +#include <qstyle.h> +#include <qtimer.h> + +#include <kiconloader.h> +#include <kdebug.h> +#include <kstringhandler.h> + +#define NEARBYINT(i) ((int(float(i) + 0.5))) + +namespace KFTPWidgets { + +class MultiTabBarTabPrivate +{ +public: + QPixmap pix; +}; + + +MultiTabBarInternal::MultiTabBarInternal( QWidget *parent, MultiTabBar::MultiTabBarMode bm ) : QScrollView( parent ) +{ + m_expandedTabSize = -1; + m_showActiveTabTexts = false; + m_tabs.setAutoDelete( true ); + m_barMode = bm; + setHScrollBarMode( AlwaysOff ); + setVScrollBarMode( AlwaysOff ); + if ( bm == MultiTabBar::Vertical ) { + box = new QWidget( viewport() ); + mainLayout = new QVBoxLayout( box ); + mainLayout->setAutoAdd( true ); + box->setFixedWidth( 24 ); + setFixedWidth( 24 ); + } else { + box = new QWidget( viewport() ); + mainLayout = new QHBoxLayout( box ); + mainLayout->setAutoAdd( true ); + box->setFixedHeight( 24 ); + setFixedHeight( 24 ); + } + addChild( box ); + setFrameStyle( NoFrame ); + viewport() ->setBackgroundMode( Qt::PaletteBackground ); + /* box->setPaletteBackgroundColor(Qt::red); + setPaletteBackgroundColor(Qt::green);*/ +} + +void MultiTabBarInternal::setStyle( enum MultiTabBar::MultiTabBarStyle style ) +{ + m_style = style; + for ( uint i = 0;i < m_tabs.count();i++ ) + m_tabs.at( i ) ->setStyle( m_style ); + + if ( ( m_style == MultiTabBar::KDEV3 ) || + ( m_style == MultiTabBar::KDEV3ICON ) || + ( m_style == MultiTabBar::AMAROK ) ) { + delete mainLayout; + mainLayout = 0; + resizeEvent( 0 ); + } else if ( mainLayout == 0 ) { + if ( m_barMode == MultiTabBar::Vertical ) { + box = new QWidget( viewport() ); + mainLayout = new QVBoxLayout( box ); + box->setFixedWidth( 24 ); + setFixedWidth( 24 ); + } else { + box = new QWidget( viewport() ); + mainLayout = new QHBoxLayout( box ); + box->setFixedHeight( 24 ); + setFixedHeight( 24 ); + } + addChild( box ); + for ( uint i = 0;i < m_tabs.count();i++ ) + mainLayout->add( m_tabs.at( i ) ); + mainLayout->setAutoAdd( true ); + + } + viewport() ->repaint(); +} + +void MultiTabBarInternal::drawContents ( QPainter * paint, int clipx, int clipy, int clipw, int cliph ) +{ + QScrollView::drawContents ( paint , clipx, clipy, clipw, cliph ); + + if ( m_position == MultiTabBar::Right ) { + + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, 0, viewport() ->height() ); + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 1, 0, 1, viewport() ->height() ); + + + } else + if ( m_position == MultiTabBar::Left ) { + paint->setPen( colorGroup().light() ); + paint->drawLine( 23, 0, 23, viewport() ->height() ); + paint->drawLine( 22, 0, 22, viewport() ->height() ); + + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, 0, viewport() ->height() ); + } else + if ( m_position == MultiTabBar::Bottom ) { + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, viewport() ->width(), 0 ); + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 0, 1, viewport() ->width(), 1 ); + } else { + paint->setPen( colorGroup().light() ); + paint->drawLine( 0, 23, viewport() ->width(), 23 ); + paint->drawLine( 0, 22, viewport() ->width(), 22 ); + + /* paint->setPen(colorGroup().shadow()); + paint->drawLine(0,0,0,viewport()->height());*/ + + } + + +} + +void MultiTabBarInternal::contentsMousePressEvent( QMouseEvent *ev ) +{ + ev->ignore(); +} + +void MultiTabBarInternal::mousePressEvent( QMouseEvent *ev ) +{ + ev->ignore(); +} + + +#define CALCDIFF(m_tabs,diff,i) if (m_lines>(int)lines) {\ + /*kdDebug()<<"i="<<i<<" tabCount="<<tabCount<<" space="<<space<<endl;*/ \ + uint ulen=0;\ + diff=0; \ + for (uint i2=i;i2<tabCount;i2++) {\ + uint l1=m_tabs.at(i2)->neededSize();\ + if ((ulen+l1)>space){\ + if (ulen==0) diff=0;\ + else diff=((float)(space-ulen))/(i2-i);\ + break;\ + }\ + ulen+=l1;\ + }\ + } else {diff=0; } + + +void MultiTabBarInternal::resizeEvent( QResizeEvent *ev ) +{ + /* kdDebug()<<"MultiTabBarInternal::resizeEvent"<<endl; + kdDebug()<<"MultiTabBarInternal::resizeEvent - box geometry"<<box->geometry()<<endl; + kdDebug()<<"MultiTabBarInternal::resizeEvent - geometry"<<geometry()<<endl;*/ + if ( ev ) QScrollView::resizeEvent( ev ); + + if ( ( m_style == MultiTabBar::KDEV3 ) || + ( m_style == MultiTabBar::KDEV3ICON ) || + ( m_style == MultiTabBar::AMAROK ) ) { + box->setGeometry( 0, 0, width(), height() ); + int lines = 1; + uint space; + float tmp = 0; + if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) ) + space = width(); + else + space = height(); + + int cnt = 0; + //CALCULATE LINES + const uint tabCount = m_tabs.count(); + for ( uint i = 0;i < tabCount;i++ ) { + cnt++; + tmp += m_tabs.at( i ) ->neededSize(); + if ( tmp > space ) { + if ( cnt > 1 ) i--; + else if ( i == ( tabCount - 1 ) ) break; + cnt = 0; + tmp = 0; + lines++; + } + } + //SET SIZE & PLACE + float diff = 0; + cnt = 0; + + if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) ) { + + setFixedHeight( lines * 24 ); + box->setFixedHeight( lines * 24 ); + m_lines = height() / 24 - 1; + lines = 0; + CALCDIFF( m_tabs, diff, 0 ) + tmp = -diff; + + //kdDebug()<<"m_lines recalculated="<<m_lines<<endl; + for ( uint i = 0;i < tabCount;i++ ) { + MultiTabBarTab *tab = m_tabs.at( i ); + cnt++; + tmp += tab->neededSize() + diff; + if ( tmp > space ) { + //kdDebug()<<"about to start new line"<<endl; + if ( cnt > 1 ) { + CALCDIFF( m_tabs, diff, i ) + i--; + } else { + //kdDebug()<<"placing line on old line"<<endl; + kdDebug() << "diff=" << diff << endl; + tab->removeEventFilter( this ); + tab->move( NEARBYINT( tmp - tab->neededSize() ), lines * 24 ); + // tab->setFixedWidth(tab->neededSize()+diff); + tab->setFixedWidth( NEARBYINT( tmp + diff ) - tab->x() );; + tab->installEventFilter( this ); + CALCDIFF( m_tabs, diff, ( i + 1 ) ) + + } + tmp = -diff; + cnt = 0; + lines++; + //kdDebug()<<"starting new line:"<<lines<<endl; + + } else { + //kdDebug()<<"Placing line on line:"<<lines<<" pos: (x/y)=("<<tmp-m_tabs.at(i)->neededSize()<<"/"<<lines*24<<")"<<endl; + //kdDebug()<<"diff="<<diff<<endl; + tab->removeEventFilter( this ); + tab->move( NEARBYINT( tmp - tab->neededSize() ), lines * 24 ); + tab->setFixedWidth( NEARBYINT( tmp + diff ) - tab->x() );; + + //tab->setFixedWidth(tab->neededSize()+diff); + tab->installEventFilter( this ); + + } + } + } else { + setFixedWidth( lines * 24 ); + box->setFixedWidth( lines * 24 ); + m_lines = lines = width() / 24; + lines = 0; + CALCDIFF( m_tabs, diff, 0 ) + tmp = -diff; + + for ( uint i = 0;i < tabCount;i++ ) { + MultiTabBarTab *tab = m_tabs.at( i ); + cnt++; + tmp += tab->neededSize() + diff; + if ( tmp > space ) { + if ( cnt > 1 ) { + CALCDIFF( m_tabs, diff, i ); + tmp = -diff; + i--; + } else { + tab->removeEventFilter( this ); + tab->move( lines * 24, NEARBYINT( tmp - tab->neededSize() ) ); + tab->setFixedHeight( NEARBYINT( tmp + diff ) - tab->y() );; + tab->installEventFilter( this ); + } + cnt = 0; + tmp = -diff; + lines++; + } else { + tab->removeEventFilter( this ); + tab->move( lines * 24, NEARBYINT( tmp - tab->neededSize() ) ); + tab->setFixedHeight( NEARBYINT( tmp + diff ) - tab->y() );; + tab->installEventFilter( this ); + } + } + } + + + //kdDebug()<<"needed lines:"<<m_lines<<endl; + } else { + int size = 0; /*move the calculation into another function and call it only on add tab and tab click events*/ + for ( int i = 0;i < ( int ) m_tabs.count();i++ ) + size += ( m_barMode == MultiTabBar::Vertical ? m_tabs.at( i ) ->height() : m_tabs.at( i ) ->width() ); + if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) ) + box->setGeometry( 0, 0, size, height() ); + else box->setGeometry( 0, 0, width(), size ); + + } +} + + +void MultiTabBarInternal::showActiveTabTexts( bool show ) +{ + m_showActiveTabTexts = show; +} + + +MultiTabBarTab* MultiTabBarInternal::tab( int id ) const +{ + for ( QPtrListIterator<MultiTabBarTab> it( m_tabs );it.current();++it ) { + if ( it.current() ->id() == id ) return it.current(); + } + return 0; +} + +bool MultiTabBarInternal::eventFilter( QObject *, QEvent *e ) +{ + if ( e->type() == QEvent::Resize ) + resizeEvent( 0 ); + + //PATCH by markey: Allow switching of tabs with mouse wheel + if ( e->type() == QEvent::Wheel ) { + QWheelEvent* event = static_cast<QWheelEvent*>( e ); + const int delta = event->delta() / 120; + + // Determine which tab is currently active + uint i; + for( i = 0; i < m_tabs.count(); i++ ) + if ( m_tabs.at( i )->isOn() ) break; + + // Calculate index of the new tab to activate + int newTab = i - delta; + if ( newTab < 0 ) newTab = 0; + if ( newTab > (int)m_tabs.count() - 1 ) newTab = m_tabs.count() - 1; + + if ( i < m_tabs.count() && newTab != (int)i ) + m_tabs.at( newTab )->animateClick(); + + // Must return true here for the wheel to work properly + return true; + } + + return false; +} + +int MultiTabBarInternal::appendTab(const QPixmap &pic , int id, const QString &text) +{ + MultiTabBarTab *tab; + + m_tabs.append(tab = new MultiTabBarTab(this, pic, text, id, box, m_position, m_style)); + tab->installEventFilter(this); + tab->showActiveTabText(m_showActiveTabTexts); + + if (m_style == MultiTabBar::KONQSBC) { + if (m_expandedTabSize < tab->neededSize()) { + m_expandedTabSize = tab->neededSize(); + + for (uint i = 0; i < m_tabs.count(); i++) + m_tabs.at(i)->setSize(m_expandedTabSize); + } else { + tab->setSize(m_expandedTabSize); + } + } else { + tab->updateState(); + } + + tab->show(); + resizeEvent(0); + + return 0; +} + +void MultiTabBarInternal::removeTab( int id ) +{ + for ( uint pos = 0;pos < m_tabs.count();pos++ ) { + if ( m_tabs.at( pos ) ->id() == id ) { + m_tabs.remove( pos ); + resizeEvent( 0 ); + break; + } + } +} + +void MultiTabBarInternal::setPosition( enum MultiTabBar::MultiTabBarPosition pos ) +{ + m_position = pos; + for ( uint i = 0;i < m_tabs.count();i++ ) + m_tabs.at( i ) ->setTabsPosition( m_position ); + viewport() ->repaint(); +} + + +MultiTabBarButton::MultiTabBarButton(MultiTabBarInternal *tb, const QPixmap& pic, const QString& text, QPopupMenu *popup, + int id, QWidget *parent, MultiTabBar::MultiTabBarPosition pos, MultiTabBar::MultiTabBarStyle style ) + : QPushButton(QIconSet(), text, parent), + m_tb(tb), + m_style(style), + m_animCount(0), + m_animTimer(new QTimer(this)) +{ + setIconSet(pic); + setText(text); + + m_position = pos; + + if (popup) + setPopup( popup ); + + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id = id; + + connect(this, SIGNAL(clicked()), this, SLOT(slotClicked())); + connect(m_animTimer, SIGNAL(timeout()), this, SLOT(slotAnimTimer())); +} + +MultiTabBarButton::MultiTabBarButton(MultiTabBarInternal *tb, const QString& text, QPopupMenu *popup, + int id, QWidget *parent, MultiTabBar::MultiTabBarPosition pos, MultiTabBar::MultiTabBarStyle style ) + : QPushButton(QIconSet(), text, parent), + m_tb(tb), + m_style(style), + m_animCount(0), + m_animTimer(new QTimer(this)) +{ + setText(text); + m_position = pos; + + if (popup) + setPopup(popup); + + setFlat(true); + setFixedHeight(24); + setFixedWidth(24); + m_id = id; + + connect(this, SIGNAL(clicked()), this, SLOT(slotClicked())); + connect(m_animTimer, SIGNAL(timeout()), this, SLOT(slotAnimTimer())); +} + +MultiTabBarButton::~MultiTabBarButton() +{} + +int MultiTabBarButton::id() const +{ + return m_id; +} + +void MultiTabBarButton::setText(const QString& text) +{ + QPushButton::setText(text); + m_text = text; +} + +void MultiTabBarButton::slotClicked() +{ + emit clicked(m_id); +} + +void MultiTabBarButton::setPosition(MultiTabBar::MultiTabBarPosition pos) +{ + m_position = pos; + repaint(); +} + +void MultiTabBarButton::setStyle(MultiTabBar::MultiTabBarStyle style) +{ + m_style = style; + repaint(); +} + +void MultiTabBarButton::hideEvent(QHideEvent* he) +{ + QPushButton::hideEvent(he); + + MultiTabBar *tb = dynamic_cast<MultiTabBar*>(parentWidget()); + if (tb) + tb->updateSeparator(); +} + +void MultiTabBarButton::showEvent(QShowEvent* he) +{ + QPushButton::showEvent(he); + + MultiTabBar *tb = dynamic_cast<MultiTabBar*>(parentWidget()); + if (tb) + tb->updateSeparator(); +} + +void MultiTabBarButton::enterEvent(QEvent*) +{ + m_animEnter = true; + m_animCount = 0; + + m_animTimer->start(ANIM_INTERVAL); +} + +void MultiTabBarButton::leaveEvent(QEvent*) +{ + if (m_animCount == 0) + m_animCount = 1; + + m_animEnter = false; + m_animTimer->start(ANIM_INTERVAL); +} + +void MultiTabBarButton::slotAnimTimer() +{ + if (m_animEnter) { + m_animCount += 1; + repaint(false); + + if (m_animCount >= ANIM_MAX) + m_animTimer->stop(); + } else { + m_animCount -= 1; + repaint(false); + + if (m_animCount <= 0) + m_animTimer->stop(); + } +} + +QSize MultiTabBarButton::sizeHint() const +{ + constPolish(); + + int w = 0, h = 0; + + // calculate contents size... +#ifndef QT_NO_ICONSET + if ( iconSet() && !iconSet() ->isNull() ) { + int iw = iconSet() ->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4; + int ih = iconSet() ->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + w += iw; + h = QMAX( h, ih ); + } +#endif + if ( isMenuButton() ) + w += style().pixelMetric( QStyle::PM_MenuButtonIndicator, this ); + + if ( pixmap() ) { + QPixmap * pm = ( QPixmap * ) pixmap(); + w += pm->width(); + h += pm->height(); + } else { + QString s( text() ); + bool empty = s.isEmpty(); + if ( empty ) + s = QString::fromLatin1( "XXXX" ); + QFontMetrics fm = fontMetrics(); + QSize sz = fm.size( ShowPrefix, s ); + if ( !empty || !w ) + w += sz.width(); + if ( !empty || !h ) + h = QMAX( h, sz.height() ); + } + + //PATCH by markey + if ((m_style == MultiTabBar::AMAROK)) { + if (m_position == MultiTabBar::Bottom) + w = (parentWidget()->width() - 3) / m_tb->tabs()->count(); + else + h = (parentWidget()->height() - 3) / m_tb->tabs()->count(); + } + + return ( style().sizeFromContents( QStyle::CT_ToolButton, this, QSize( w, h ) ). + expandedTo( QApplication::globalStrut() ) ); +} + + +MultiTabBarTab::MultiTabBarTab( MultiTabBarInternal *tb, const QPixmap& pic, const QString& text, + int id, QWidget *parent, MultiTabBar::MultiTabBarPosition pos, + MultiTabBar::MultiTabBarStyle style ) + : MultiTabBarButton(tb, text, 0, id, parent, pos, style), + m_showActiveTabText(false) +{ + d = new MultiTabBarTabPrivate(); + setIcon( pic ); + m_expandedSize = 24; + setToggleButton( true ); + + // Prevent flicker on redraw + setWFlags( getWFlags() | Qt::WNoAutoErase ); +} + +MultiTabBarTab::~MultiTabBarTab() +{ + delete d; +} + + +void MultiTabBarTab::setTabsPosition( MultiTabBar::MultiTabBarPosition pos ) +{ + if ( ( pos != m_position ) && ( ( pos == MultiTabBar::Left ) || ( pos == MultiTabBar::Right ) ) ) { + if ( !d->pix.isNull() ) { + QWMatrix temp; // (1.0F, 0.0F, 0.0F, -1.0F, 0.0F, 0.0F); + temp.rotate( 180 ); + d->pix = d->pix.xForm( temp ); + setIconSet( d->pix ); + } + } + + setPosition( pos ); + // repaint(); +} + +void MultiTabBarTab::setIcon( const QString& icon ) +{ + QPixmap pic = SmallIcon( icon ); + setIcon( pic ); +} + +void MultiTabBarTab::setIcon( const QPixmap& icon ) +{ + + if ( m_style != MultiTabBar::KDEV3 ) { + if ( ( m_position == MultiTabBar::Left ) || ( m_position == MultiTabBar::Right ) ) { + QWMatrix rotateMatrix; + if ( m_position == MultiTabBar::Left ) + rotateMatrix.rotate( 90 ); + else + rotateMatrix.rotate( -90 ); + QPixmap pic = icon.xForm( rotateMatrix ); //TODO FIX THIS, THIS SHOWS WINDOW + d->pix = pic; + setIconSet( pic ); + } else setIconSet( icon ); + } +} + +void MultiTabBarTab::slotClicked() +{ + if (m_animTimer->isActive()) { + m_animCount = ANIM_MAX; + m_animTimer->stop(); + repaint(); + } + + updateState(); + MultiTabBarButton::slotClicked(); +} + +void MultiTabBarTab::setState(bool b) +{ + setOn(b); + updateState(); +} + +void MultiTabBarTab::updateState() +{ + + if ( m_style != MultiTabBar::KONQSBC ) { + if ( ( m_style == MultiTabBar::KDEV3 ) || ( m_style == MultiTabBar::KDEV3ICON ) || ( m_style == MultiTabBar::AMAROK ) || ( isOn() ) ) { + QPushButton::setText( m_text ); + } else { + kdDebug() << "MultiTabBarTab::updateState(): setting text to an empty QString***************" << endl; + QPushButton::setText( QString::null ); + } + + if ( ( m_position == MultiTabBar::Right || m_position == MultiTabBar::Left ) ) { + setFixedWidth( 24 ); + if ( ( m_style == MultiTabBar::KDEV3 ) || ( m_style == MultiTabBar::KDEV3ICON ) || ( m_style == MultiTabBar::AMAROK ) || ( isOn() ) ) { + setFixedHeight( MultiTabBarButton::sizeHint().width() ); + } else setFixedHeight( 36 ); + } else { + setFixedHeight( 24 ); + if ( ( m_style == MultiTabBar::KDEV3 ) || ( m_style == MultiTabBar::KDEV3ICON ) || ( m_style == MultiTabBar::AMAROK ) || ( isOn() ) ) { + setFixedWidth( MultiTabBarButton::sizeHint().width() ); + } else setFixedWidth( 36 ); + } + } else { + if ( ( !isOn() ) || ( !m_showActiveTabText ) ) { + setFixedWidth( 24 ); + setFixedHeight( 24 ); + return ; + } + if ( ( m_position == MultiTabBar::Right || m_position == MultiTabBar::Left ) ) + setFixedHeight( m_expandedSize ); + else + setFixedWidth( m_expandedSize ); + } + QApplication::sendPostedEvents( 0, QEvent::Paint | QEvent::Move | QEvent::Resize | QEvent::LayoutHint ); + QApplication::flush(); +} + +int MultiTabBarTab::neededSize() +{ + if (m_style == MultiTabBar::AMAROK) { + if (m_position == MultiTabBar::Left) + return (parentWidget()->height() - 3) / m_tb->tabs()->count(); + else + return (parentWidget()->width() - 3) / m_tb->tabs()->count(); + } else { + return (((m_style != MultiTabBar::KDEV3 ) ? 24 : 0) + QFontMetrics(QFont()).width(m_text) + 6); + } +} + +void MultiTabBarTab::setSize( int size ) +{ + m_expandedSize = size; + updateState(); +} + +void MultiTabBarTab::showActiveTabText(bool show) +{ + m_showActiveTabText = show; +} + +void MultiTabBarTab::drawButtonLabel(QPainter *p) +{ + drawButton(p); +} +void MultiTabBarTab::drawButton(QPainter *paint) +{ + if (m_style == MultiTabBar::AMAROK) { + drawButtonAmarok(paint); + } else if (m_style != MultiTabBar::KONQSBC) { + drawButtonStyled(paint); + } else { + drawButtonClassic(paint); + } +} + +void MultiTabBarTab::drawButtonStyled( QPainter *paint ) +{ + + QSize sh; + const int width = 36; // rotated + const int height = 24; + if ( ( m_style == MultiTabBar::KDEV3 ) || ( m_style == MultiTabBar::KDEV3ICON ) || ( m_style == MultiTabBar::AMAROK ) || ( isOn() ) ) { + if ( ( m_position == MultiTabBar::Left ) || ( m_position == MultiTabBar::Right ) ) + sh = QSize( this->height(), this->width() ); //MultiTabBarButton::sizeHint(); + else sh = QSize( this->width(), this->height() ); + } else + sh = QSize( width, height ); + + QPixmap pixmap( sh.width(), height ); ///,sh.height()); + pixmap.fill( eraseColor() ); + QPainter painter( &pixmap ); + + + QStyle::SFlags st = QStyle::Style_Default; + + st |= QStyle::Style_Enabled; + + if ( isOn() ) st |= QStyle::Style_On; + + style().drawControl( QStyle::CE_PushButton, &painter, this, QRect( 0, 0, pixmap.width(), pixmap.height() ), colorGroup(), st ); + style().drawControl( QStyle::CE_PushButtonLabel, &painter, this, QRect( 0, 0, pixmap.width(), pixmap.height() ), colorGroup(), st ); + + switch ( m_position ) { + case MultiTabBar::Left: + paint->rotate( -90 ); + paint->drawPixmap( 1 - pixmap.width(), 0, pixmap ); + break; + case MultiTabBar::Right: + paint->rotate( 90 ); + paint->drawPixmap( 0, 1 - pixmap.height(), pixmap ); + break; + + default: + paint->drawPixmap( 0, 0, pixmap ); + break; + } + // style().drawControl(QStyle::CE_PushButtonLabel,painter,this, QRect(0,0,pixmap.width(),pixmap.height()), + // colorGroup(),QStyle::Style_Enabled); + + +} + +void MultiTabBarTab::drawButtonClassic( QPainter *paint ) +{ + QPixmap pixmap; + if ( iconSet() ) + pixmap = iconSet() ->pixmap( QIconSet::Small, QIconSet::Normal ); + paint->fillRect( 0, 0, 24, 24, colorGroup().background() ); + + if ( !isOn() ) { + + if ( m_position == MultiTabBar::Right ) { + paint->fillRect( 0, 0, 21, 21, QBrush( colorGroup().background() ) ); + + paint->setPen( colorGroup().background().dark( 150 ) ); + paint->drawLine( 0, 22, 23, 22 ); + + paint->drawPixmap( 12 - pixmap.width() / 2, 12 - pixmap.height() / 2, pixmap ); + + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, 0, 23 ); + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 1, 0, 1, 23 ); + + } else + if ( ( m_position == MultiTabBar::Bottom ) || ( m_position == MultiTabBar::Top ) ) { + paint->fillRect( 0, 1, 23, 22, QBrush( colorGroup().background() ) ); + + paint->drawPixmap( 12 - pixmap.width() / 2, 12 - pixmap.height() / 2, pixmap ); + + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 23, 0, 23, 23 ); + + + paint->setPen( colorGroup().light() ); + paint->drawLine( 0, 22, 23, 22 ); + paint->drawLine( 0, 23, 23, 23 ); + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, 23, 0 ); + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 0, 1, 23, 1 ); + + } else { + paint->setPen( colorGroup().background().dark( 120 ) ); + paint->drawLine( 0, 23, 23, 23 ); + paint->fillRect( 0, 0, 23, 21, QBrush( colorGroup().background() ) ); + paint->drawPixmap( 12 - pixmap.width() / 2, 12 - pixmap.height() / 2, pixmap ); + + paint->setPen( colorGroup().light() ); + paint->drawLine( 23, 0, 23, 23 ); + paint->drawLine( 22, 0, 22, 23 ); + + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 0, 0, 23 ); + + } + + + } else { + if ( m_position == MultiTabBar::Right ) { + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, height() - 1, 23, height() - 1 ); + paint->drawLine( 0, height() - 2, 23, height() - 2 ); + paint->drawLine( 23, 0, 23, height() - 1 ); + paint->drawLine( 22, 0, 22, height() - 1 ); + paint->fillRect( 0, 0, 21, height() - 3, QBrush( colorGroup().light() ) ); + paint->drawPixmap( 10 - pixmap.width() / 2, 10 - pixmap.height() / 2, pixmap ); + + if ( m_showActiveTabText ) { + if ( height() < 25 + 4 ) return ; + + QPixmap tpixmap( height() - 25 - 3, width() - 2 ); + QPainter painter( &tpixmap ); + + painter.fillRect( 0, 0, tpixmap.width(), tpixmap.height(), QBrush( colorGroup().light() ) ); + + painter.setPen( colorGroup().text() ); + painter.drawText( 0, + width() / 2 + QFontMetrics( QFont() ).height() / 2, m_text ); + + paint->rotate( 90 ); + kdDebug() << "tpixmap.width:" << tpixmap.width() << endl; + paint->drawPixmap( 25, -tpixmap.height() + 1, tpixmap ); + } + + } else + if ( m_position == MultiTabBar::Top ) { + paint->fillRect( 0, 0, width() - 1, 23, QBrush( colorGroup().light() ) ); + paint->drawPixmap( 10 - pixmap.width() / 2, 10 - pixmap.height() / 2, pixmap ); + if ( m_showActiveTabText ) { + paint->setPen( colorGroup().text() ); + paint->drawText( 25, height() / 2 + QFontMetrics( QFont() ).height() / 2, m_text ); + } + } else + if ( m_position == MultiTabBar::Bottom ) { + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, 23, width() - 1, 23 ); + paint->drawLine( 0, 22, width() - 1, 22 ); + paint->fillRect( 0, 0, width() - 1, 21, QBrush( colorGroup().light() ) ); + paint->drawPixmap( 10 - pixmap.width() / 2, 10 - pixmap.height() / 2, pixmap ); + if ( m_showActiveTabText ) { + paint->setPen( colorGroup().text() ); + paint->drawText( 25, height() / 2 + QFontMetrics( QFont() ).height() / 2, m_text ); + } + + } else { + + + paint->setPen( colorGroup().shadow() ); + paint->drawLine( 0, height() - 1, 23, height() - 1 ); + paint->drawLine( 0, height() - 2, 23, height() - 2 ); + paint->fillRect( 0, 0, 23, height() - 3, QBrush( colorGroup().light() ) ); + paint->drawPixmap( 10 - pixmap.width() / 2, 10 - pixmap.height() / 2, pixmap ); + if ( m_showActiveTabText ) { + + if ( height() < 25 + 4 ) return ; + + QPixmap tpixmap( height() - 25 - 3, width() - 2 ); + QPainter painter( &tpixmap ); + + painter.fillRect( 0, 0, tpixmap.width(), tpixmap.height(), QBrush( colorGroup().light() ) ); + + painter.setPen( colorGroup().text() ); + painter.drawText( tpixmap.width() - QFontMetrics( QFont() ).width( m_text ), + width() / 2 + QFontMetrics( QFont() ).height() / 2, m_text ); + + paint->rotate( -90 ); + kdDebug() << "tpixmap.width:" << tpixmap.width() << endl; + + paint->drawPixmap( -24 - tpixmap.width(), 2, tpixmap ); + + } + + } + + } +} + +void MultiTabBarTab::drawButtonAmarok(QPainter *paint) +{ + QColor fillColor, textColor; + + if (isOn()) { + fillColor = blendColors(colorGroup().highlight(), colorGroup().background(), static_cast<int>(m_animCount * 3.5)); + textColor = blendColors(colorGroup().highlightedText(), colorGroup().text(), static_cast<int>(m_animCount * 4.5)); + } else { + fillColor = blendColors(colorGroup().background(), colorGroup().highlight(), static_cast<int>(m_animCount * 3.5)); + textColor = blendColors(colorGroup().text(), colorGroup().highlightedText(), static_cast<int>(m_animCount * 4.5)); + } + + const QPixmap icon = iconSet()->pixmap(QIconSet::Small, QIconSet::Normal); + + // Our pixmap + QPixmap pixmap; + + if (m_position == MultiTabBar::Left) + pixmap.resize(height(), width()); + else + pixmap.resize(width(), height()); + + pixmap.fill(fillColor); + QPainter painter(&pixmap); + + // Draw the frame + painter.setPen(colorGroup().mid()); + if (m_id != m_tb->tabs()->count() - 1) + painter.drawLine(0, 0, 0, pixmap.height() - 1); + painter.drawLine(0, pixmap.height() - 1, pixmap.width() - 1, pixmap.height() - 1); + + // Draw the text + QFont font; + font.setBold(isOn()); + painter.setFont(font); + QString text = KStringHandler::rPixelSqueeze(m_text, QFontMetrics(font), pixmap.width() - icon.width() - 3); + text.replace( "...", ".." ); + const int textX = pixmap.width() / 2 - QFontMetrics( font ).width( text ) / 2; + painter.setPen(textColor); + const QRect rect(textX + icon.width() / 2 + 2, 0, pixmap.width(), pixmap.height()); + painter.drawText(rect, Qt::AlignLeft | Qt::AlignVCenter, text); + + // Draw the icon + painter.drawPixmap(textX - icon.width() / 2 - 2, pixmap.height() / 2 - icon.height() / 2, icon); + + // Paint to widget + if (m_position == MultiTabBar::Left) { + paint->rotate(-90); + paint->drawPixmap(1 - pixmap.width(), 0, pixmap); + } else { + paint->drawPixmap(0, 0, pixmap); + } +} + +QColor MultiTabBarTab::blendColors( const QColor& color1, const QColor& color2, int percent ) +{ + const float factor1 = ( 100 - ( float ) percent ) / 100; + const float factor2 = ( float ) percent / 100; + + const int r = static_cast<int>( color1.red() * factor1 + color2.red() * factor2 ); + const int g = static_cast<int>( color1.green() * factor1 + color2.green() * factor2 ); + const int b = static_cast<int>( color1.blue() * factor1 + color2.blue() * factor2 ); + + QColor result; + result.setRgb( r, g, b ); + + return result; +} + + + + +MultiTabBar::MultiTabBar( MultiTabBarMode bm, QWidget *parent, const char *name ) : QWidget( parent, name ) +{ + m_buttons.setAutoDelete( false ); + if ( bm == Vertical ) { + m_l = new QVBoxLayout( this ); + setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Expanding, true ); + // setFixedWidth(24); + } else { + m_l = new QHBoxLayout( this ); + setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Fixed, true ); + // setFixedHeight(24); + } + m_l->setMargin( 0 ); + m_l->setAutoAdd( false ); + + m_internal = new MultiTabBarInternal( this, bm ); + setPosition( ( bm == MultiTabBar::Vertical ) ? MultiTabBar::Right : MultiTabBar::Bottom ); + setStyle( VSNET ); + // setStyle(KDEV3); + //setStyle(KONQSBC); + m_l->insertWidget( 0, m_internal ); + m_l->insertWidget( 0, m_btnTabSep = new QFrame( this ) ); + m_btnTabSep->setFixedHeight( 4 ); + m_btnTabSep->setFrameStyle( QFrame::Panel | QFrame::Sunken ); + m_btnTabSep->setLineWidth( 2 ); + m_btnTabSep->hide(); + + updateGeometry(); +} + +MultiTabBar::~MultiTabBar() +{} + +/*int MultiTabBar::insertButton(QPixmap pic,int id ,const QString&) +{ +(new KToolbarButton(pic,id,m_internal))->show(); +return 0; +}*/ + +int MultiTabBar::appendButton( const QPixmap &pic , int id, QPopupMenu *popup, const QString& ) +{ + MultiTabBarButton * btn; + m_buttons.append(btn = new MultiTabBarButton(m_internal, pic, QString::null, popup, id, this, m_position, m_internal->m_style)); + + m_l->insertWidget( 0, btn ); + btn->show(); + m_btnTabSep->show(); + + return 0; +} + +void MultiTabBar::updateSeparator() +{ + bool hideSep = true; + for ( QPtrListIterator<MultiTabBarButton> it( m_buttons );it.current();++it ) { + if ( it.current() ->isVisibleTo( this ) ) { + hideSep = false; + break; + } + } + if ( hideSep ) m_btnTabSep->hide(); + else m_btnTabSep->show(); + +} + +int MultiTabBar::appendTab( const QPixmap &pic , int id , const QString& text ) +{ + m_internal->appendTab( pic, id, text ); + return 0; +} + +MultiTabBarButton* MultiTabBar::button( int id ) const +{ + for ( QPtrListIterator<MultiTabBarButton> it( m_buttons );it.current();++it ) { + if ( it.current() ->id() == id ) return it.current(); + } + return 0; +} + +MultiTabBarTab* MultiTabBar::tab( int id ) const +{ + return m_internal->tab( id ); +} + + + +void MultiTabBar::removeButton( int id ) +{ + for ( uint pos = 0;pos < m_buttons.count();pos++ ) { + if ( m_buttons.at( pos ) ->id() == id ) { + m_buttons.take( pos ) ->deleteLater(); + break; + } + } + if ( m_buttons.count() == 0 ) m_btnTabSep->hide(); +} + +void MultiTabBar::removeTab( int id ) +{ + m_internal->removeTab( id ); +} + +void MultiTabBar::setTab( int id, bool state ) +{ + MultiTabBarTab * ttab = tab( id ); + if ( ttab ) { + ttab->setState( state ); + } +} + +bool MultiTabBar::isTabRaised( int id ) const +{ + MultiTabBarTab * ttab = tab( id ); + if ( ttab ) { + return ttab->isOn(); + } + + return false; +} + + +void MultiTabBar::showActiveTabTexts( bool show ) +{ + m_internal->showActiveTabTexts( show ); +} + +void MultiTabBar::setStyle( MultiTabBarStyle style ) +{ + m_internal->setStyle( style ); +} + +void MultiTabBar::setPosition( MultiTabBarPosition pos ) +{ + m_position = pos; + m_internal->setPosition( pos ); + for ( uint i = 0;i < m_buttons.count();i++ ) + m_buttons.at( i ) ->setPosition( pos ); +} +void MultiTabBar::fontChange( const QFont& /* oldFont */ ) +{ + for ( uint i = 0;i < tabs() ->count();i++ ) + tabs() ->at( i ) ->resize(); + repaint(); +} + +QPtrList<MultiTabBarTab> *MultiTabBar::tabs() +{ + return m_internal->tabs(); +} + +QPtrList<MultiTabBarButton>* MultiTabBar::buttons() +{ + return & m_buttons; +} + +} diff --git a/kftpgrabber/src/widgets/multitabbar.h b/kftpgrabber/src/widgets/multitabbar.h new file mode 100644 index 0000000..ece61bf --- /dev/null +++ b/kftpgrabber/src/widgets/multitabbar.h @@ -0,0 +1,281 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2001-2003 by Joseph Wenninger <jowenn@kde.org> + * Copyright (C) 2005 by Mark Kretschmann <markey@web.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSMULTITABBAR_H +#define KFTPWIDGETSMULTITABBAR_H + +#include <qscrollview.h> +#include <qvbox.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qstring.h> +#include <qptrlist.h> +#include <qpushbutton.h> + +class QPixmap; +class QPainter; +class QFrame; + +namespace KFTPWidgets { + +class MultiTabBarPrivate; +class MultiTabBarTabPrivate; +class MultiTabBarButtonPrivate; +class MultiTabBarInternal; + +/** + * A Widget for horizontal and vertical tabs. + * It is possible to add normal buttons to the top/left + * The handling if only one tab at a time or multiple tabs + * should be raisable is left to the "user". + * + * @author Joseph Wenninger + */ +class MultiTabBar: public QWidget +{ +Q_OBJECT +friend class MultiTabBarButton; +public: + enum MultiTabBarMode { Horizontal, Vertical }; + enum MultiTabBarPosition { Left, Right, Top, Bottom }; + + /** + * VSNET == Visual Studio .Net like (only show the text of active tabs + * KDEV3 == Kdevelop 3 like (always show the text) + * KONQSBC == konqy's classic sidebar style (unthemed), this one is disabled + * at the moment, but will be renabled soon too + * AMAROK == A nice clean style by the amaroK team + */ + enum MultiTabBarStyle { VSNET = 0, KDEV3 = 1, KONQSBC = 2, KDEV3ICON = 3, AMAROK = 4, STYLELAST = 0xffff }; + + MultiTabBar(MultiTabBarMode bm, QWidget *parent = 0, const char *name = 0); + virtual ~MultiTabBar(); + + /** + * append a new button to the button area. The button can later on be accessed with button(ID) + * eg for connecting signals to it + * + * @param pic a pixmap for the button + * @param id an arbitraty ID value. It will be emitted in the clicked signal for identifying the button + * if more than one button is connected to a signals. + * @param popup A popup menu which should be displayed if the button is clicked + * @param not_used_yet will be used for a popup text in the future + */ + int appendButton(const QPixmap &pic, int id = -1, QPopupMenu* popup = 0, const QString& not_used_yet = QString::null); + + /** + * remove a button with the given ID + */ + void removeButton(int id); + + /** + * append a new tab to the tab area. It can be accessed lateron with tabb(id); + * @param pic a bitmap for the tab + * @param id an arbitrary ID which can be used later on to identify the tab + * @param text if a mode with text is used it will be the tab text, otherwise a mouse over hint + */ + int appendTab( const QPixmap &pic, int id = -1, const QString& text = QString::null ); + + /** + * remove a tab with a given ID + */ + void removeTab( int id ); + /** + * set a tab to "raised" + * @param id The ID of the tab to manipulate + * @param state true == activated/raised, false == not active + */ + void setTab( int id , bool state ); + /** + * return the state of a tab, identified by it's ID + */ + bool isTabRaised( int id ) const; + /** + * get a pointer to a button within the button area identified by its ID + */ + class MultiTabBarButton *button( int id ) const; + + /** + * get a pointer to a tab within the tab area, identiifed by its ID + */ + class MultiTabBarTab *tab( int id ) const; + /** + * set the real position of the widget. + * @param pos if the mode is horizontal, only use top, bottom, if it is vertical use left or right + */ + void setPosition( MultiTabBarPosition pos ); + /** + * set the display style of the tabs + */ + void setStyle( MultiTabBarStyle style ); + /** + * be carefull, don't delete tabs yourself and don't delete the list itself + */ + QPtrList<MultiTabBarTab>* tabs(); + /** + * be carefull, don't delete buttons yourself and don't delete the list itself + */ + QPtrList<MultiTabBarButton>* buttons(); + + /** + * might vanish, not sure yet + */ + void showActiveTabTexts( bool show = true ); +protected: + virtual void fontChange( const QFont& ); + void updateSeparator(); +private: + class MultiTabBarInternal *m_internal; + QBoxLayout *m_l; + QFrame *m_btnTabSep; + QPtrList<MultiTabBarButton> m_buttons; + MultiTabBarPosition m_position; + MultiTabBarPrivate *d; +}; + +/** + * This class should never be created except with the appendButton call of MultiTabBar + */ +class MultiTabBarButton: public QPushButton +{ +Q_OBJECT +public: + MultiTabBarButton(MultiTabBarInternal *tb, const QPixmap& pic, const QString&, QPopupMenu *popup, + int id, QWidget *parent, MultiTabBar::MultiTabBarPosition pos, MultiTabBar::MultiTabBarStyle style); + MultiTabBarButton(MultiTabBarInternal *tb, const QString&, QPopupMenu *popup, + int id, QWidget *parent, MultiTabBar::MultiTabBarPosition pos, MultiTabBar::MultiTabBarStyle style); + virtual ~MultiTabBarButton(); + + int id() const; +public slots: + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of MultiTabBar is invoked though this modifications will be overwritten + */ + void setPosition( MultiTabBar::MultiTabBarPosition ); + /** + * this is used internaly, but can be used by the user, if (s)he wants to + * It the according call of MultiTabBar is invoked though this modifications will be overwritten + */ + void setStyle( MultiTabBar::MultiTabBarStyle ); + + /** + * modify the text of the button + */ + void setText( const QString & ); + + QSize sizeHint() const; +protected: + static const int ANIM_INTERVAL = 18; + static const int ANIM_MAX = 20; + + MultiTabBarInternal *m_tb; + + MultiTabBar::MultiTabBarPosition m_position; + MultiTabBar::MultiTabBarStyle m_style; + + QString m_text; + int m_id; + bool m_animEnter; + int m_animCount; + class QTimer *m_animTimer; + + virtual void hideEvent(class QHideEvent*); + virtual void showEvent(class QShowEvent*); + virtual void enterEvent(class QEvent*); + virtual void leaveEvent(class QEvent*); +private: + MultiTabBarButtonPrivate *d; +signals: + /** + * this is emitted if the button is clicked + * @param id the ID identifying the button + */ + void clicked(int id); +protected slots: + virtual void slotClicked(); + virtual void slotAnimTimer(); +}; + +/** + * This class should never be created except with the appendTab call of MultiTabBar + */ +class MultiTabBarTab: public MultiTabBarButton +{ +Q_OBJECT +friend class MultiTabBarInternal; +public: + MultiTabBarTab(MultiTabBarInternal *tb, const QPixmap &pic, const QString&, int id, QWidget *parent, + MultiTabBar::MultiTabBarPosition pos, MultiTabBar::MultiTabBarStyle style); + virtual ~MultiTabBarTab(); + /** + * set the active state of the tab + * @param state true==active false==not active + */ + void setState( bool state ); + /** + * choose if the text should always be displayed + * this is only used in classic mode if at all + */ + void showActiveTabText( bool show ); + void resize() { setSize( neededSize() ); } +private: + bool m_showActiveTabText; + int m_expandedSize; + + MultiTabBarTabPrivate *d; +protected: + void setSize( int ); + int neededSize(); + void updateState(); + virtual void drawButton( QPainter * ); + virtual void drawButtonLabel( QPainter * ); + void drawButtonStyled( QPainter * ); + void drawButtonClassic( QPainter * ); + void drawButtonAmarok( QPainter * ); + QColor blendColors( const QColor& color1, const QColor& color2, int percent ); +protected slots: + virtual void slotClicked(); + void setTabsPosition( MultiTabBar::MultiTabBarPosition ); +public slots: + virtual void setIcon( const QString& ); + virtual void setIcon( const QPixmap& ); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/multitabbar_p.h b/kftpgrabber/src/widgets/multitabbar_p.h new file mode 100644 index 0000000..c630f61 --- /dev/null +++ b/kftpgrabber/src/widgets/multitabbar_p.h @@ -0,0 +1,85 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2001-2003 by Joseph Wenninger <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. + * + * This program is distributed in the hope that it will be useful, but + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSMULTITABBAR_P_H +#define KFTPWIDGETSMULTITABBAR_P_H + +#include <qscrollview.h> + +#include "multitabbar.h" + +namespace KFTPWidgets { + +class MultiTabBarInternal : public QScrollView +{ +Q_OBJECT +friend class MultiTabBar; +public: + MultiTabBarInternal(QWidget *parent,MultiTabBar::MultiTabBarMode bm); + int appendTab(const QPixmap &,int=-1,const QString& =QString::null); + MultiTabBarTab *tab(int) const; + void removeTab(int); + void setPosition(enum MultiTabBar::MultiTabBarPosition pos); + void setStyle(enum MultiTabBar::MultiTabBarStyle style); + void showActiveTabTexts(bool show); + QPtrList<MultiTabBarTab>* tabs() { return &m_tabs; } +private: + QWidget *box; + QBoxLayout *mainLayout; + QPtrList<MultiTabBarTab> m_tabs; + enum MultiTabBar::MultiTabBarPosition m_position; + bool m_showActiveTabTexts; + enum MultiTabBar::MultiTabBarStyle m_style; + int m_expandedTabSize; + int m_lines; + MultiTabBar::MultiTabBarMode m_barMode; +protected: + virtual bool eventFilter(QObject *,QEvent*); + virtual void drawContents ( QPainter *, int, int, int, int); + + /** + * [contentsM|m]ousePressEvent are reimplemented from QScrollView + * in order to ignore all mouseEvents on the viewport, so that the + * parent can handle them. + */ + virtual void contentsMousePressEvent(QMouseEvent *); + virtual void mousePressEvent(QMouseEvent *); + virtual void resizeEvent(QResizeEvent *); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/overlaywidget.cpp b/kftpgrabber/src/widgets/overlaywidget.cpp new file mode 100644 index 0000000..58ae387 --- /dev/null +++ b/kftpgrabber/src/widgets/overlaywidget.cpp @@ -0,0 +1,83 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Max Howell <max.howell@methyblue.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "overlaywidget.h" + +#include <qpoint.h> + +namespace KFTPWidgets { + +OverlayWidget::OverlayWidget(QWidget *parent, QWidget *anchor) + : QFrame(parent->parentWidget()), + m_parent(parent), + m_anchor(anchor) +{ + parent->installEventFilter(this); + hide(); +} + +void OverlayWidget::reposition() +{ + setMaximumSize(parentWidget()->size()); + adjustSize(); + + // P is in the alignWidget's coordinates + QPoint p; + + p.setX(m_anchor->width() - width()); + p.setY(-height()); + + // Position in the toplevelWidget's coordinates + QPoint pTopLevel = m_anchor->mapTo(topLevelWidget(), p); + + // Position in the widget's parentWidget coordinates + QPoint pParent = parentWidget()->mapFrom(topLevelWidget(), pTopLevel); + + if (pParent.x() < 0) + pParent.rx() = 0; + + move(pParent); +} + +bool OverlayWidget::event(QEvent *event) +{ + if (event->type() == QEvent::ChildInserted) + adjustSize(); + + return QFrame::event(event); +} + +} diff --git a/kftpgrabber/src/widgets/overlaywidget.h b/kftpgrabber/src/widgets/overlaywidget.h new file mode 100644 index 0000000..1140909 --- /dev/null +++ b/kftpgrabber/src/widgets/overlaywidget.h @@ -0,0 +1,60 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Max Howell <max.howell@methyblue.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETSOVERLAYWIDGET_H +#define KFTPWIDGETSOVERLAYWIDGET_H + +#include <qhbox.h> + +namespace KFTPWidgets { + +/** + * @author Max Howell + */ +class OverlayWidget : public QFrame { +public: + OverlayWidget(QWidget *parent, QWidget *anchor); + virtual void reposition(); +protected: + virtual bool event(QEvent *event); +private: + QWidget *m_parent; + QWidget *m_anchor; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/popupmessage.cpp b/kftpgrabber/src/widgets/popupmessage.cpp new file mode 100644 index 0000000..62ee3c8 --- /dev/null +++ b/kftpgrabber/src/widgets/popupmessage.cpp @@ -0,0 +1,314 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Max Howell <max.howell@methyblue.com> + * Copyright (C) 2005 Seb Ruiz <me@sebruiz.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "popupmessage.h" + +#include <kactivelabel.h> +#include <kpushbutton.h> +#include <kstdguiitem.h> + +#include <qfont.h> +#include <qframe.h> +#include <qlabel.h> +#include <qmessagebox.h> +#include <qpainter.h> +#include <qtimer.h> +#include <qtooltip.h> + +namespace KFTPWidgets { + +PopupMessage::PopupMessage(QWidget *parent, QWidget *anchor, int timeout) + : OverlayWidget(parent, anchor), + m_anchor(anchor), + m_parent(parent), + m_maskEffect(Slide), + m_dissolveSize(0), + m_dissolveDelta(-1), + m_offset(0), + m_counter(0), + m_stage(1), + m_timeout(timeout), + m_showCounter(true) +{ + setFrameStyle(QFrame::Panel | QFrame::Raised); + setFrameShape(QFrame::StyledPanel); + setWFlags(Qt::WX11BypassWM); + + QPalette p = QToolTip::palette(); + setPalette(p); + + QHBoxLayout *hbox; + QLabel *label; + KActiveLabel *alabel; + + m_layout = new QVBoxLayout(this, 9, 6); + hbox = new QHBoxLayout(m_layout, 12); + + hbox->addWidget(m_countdownFrame = new QFrame(this, "counterVisual")); + m_countdownFrame->setFixedWidth(fontMetrics().width("X")); + m_countdownFrame->setFrameStyle(QFrame::Plain | QFrame::Box); + m_countdownFrame->setPaletteForegroundColor(paletteBackgroundColor().dark()); + + label = new QLabel(this, "image"); + hbox->add(label); + + alabel = new KActiveLabel(this, "label"); + alabel->setTextFormat(Qt::RichText); + alabel->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); + alabel->setPalette(p); + + hbox->add(alabel); + + hbox = new QHBoxLayout(m_layout); + + hbox->addItem(new QSpacerItem(4, 4, QSizePolicy::Expanding, QSizePolicy::Preferred)); + hbox->add(new KPushButton(KStdGuiItem::close(), this, "closeButton")); + + connect(child("closeButton"), SIGNAL(clicked()), SLOT(close())); +} + +void PopupMessage::addWidget(QWidget *widget) +{ + m_layout->add(widget); + adjustSize(); +} + +void PopupMessage::setShowCloseButton(bool show) +{ + static_cast<KPushButton*>(child("closeButton"))->setShown(show); + adjustSize(); +} + +void PopupMessage::setShowCounter(bool show) +{ + m_showCounter = show; + static_cast<QFrame*>(child("counterVisual"))->setShown(show); + adjustSize(); +} + +void PopupMessage::setText(const QString &text) +{ + static_cast<KActiveLabel*>(child("label"))->setText(text); + adjustSize(); +} + +void PopupMessage::setImage(const QString &location) +{ + static_cast<QLabel*>(child("image"))->setPixmap(QPixmap(location)); + adjustSize(); +} + +void PopupMessage::setImage(const QPixmap &pix) +{ + static_cast<QLabel*>(child("image"))->setPixmap(pix); + adjustSize(); +} + +void PopupMessage::close() +{ + m_stage = 3; + killTimer(m_timerId); + m_timerId = startTimer(6); +} + +void PopupMessage::display() +{ + m_dissolveSize = 24; + m_dissolveDelta = -1; + + if (m_maskEffect == Dissolve) { + m_mask.resize(width(), height()); + dissolveMask(); + m_timerId = startTimer(1000 / 30); + } else { + m_timerId = startTimer( 6 ); + } + + show(); +} + +void PopupMessage::timerEvent(QTimerEvent*) +{ + switch(m_maskEffect) { + case Plain: plainMask(); break; + case Slide: slideMask(); break; + case Dissolve: dissolveMask(); break; + } +} + +void PopupMessage::countDown() +{ + if (!m_timeout) { + killTimer(m_timerId); + return; + } + + QFrame *&h = m_countdownFrame; + + if (m_counter < h->height() - 3) + QPainter(h).fillRect(2, 2, h->width() - 4, m_counter, palette().active().highlight()); + + if (!hasMouse()) + m_counter++; + + if (m_counter > h->height()) { + m_stage = 3; + killTimer(m_timerId); + m_timerId = startTimer(6); + } else { + killTimer(m_timerId); + m_timerId = startTimer(m_timeout / h->height()); + } +} + +void PopupMessage::dissolveMask() +{ + if (m_stage == 1) { + repaint(false); + QPainter maskPainter(&m_mask); + + m_mask.fill(Qt::black); + + maskPainter.setBrush(Qt::white); + maskPainter.setPen(Qt::white); + maskPainter.drawRect(m_mask.rect()); + + m_dissolveSize += m_dissolveDelta; + + if (m_dissolveSize > 0) { + maskPainter.setRasterOp(Qt::EraseROP); + + int x, y, s; + const int size = 16; + + for (y = 0; y < height() + size; y += size) { + x = width(); + s = m_dissolveSize * x / 128; + + for (; x > size; x -= size, s -= 2) { + if (s < 0) + break; + + maskPainter.drawEllipse(x - s / 2, y - s / 2, s, s); + } + } + } else if (m_dissolveSize < 0) { + m_dissolveDelta = 1; + killTimer(m_timerId); + + if (m_timeout) { + m_timerId = startTimer(40); + m_stage = 2; + } + } + + setMask(m_mask); + } else if (m_stage == 2) { + countDown(); + } else { + deleteLater(); + } +} + +void PopupMessage::plainMask() +{ + switch (m_stage) { + case 1: { + // Raise + killTimer(m_timerId); + + if (m_timeout) { + m_timerId = startTimer(40); + m_stage = 2; + } + + break; + } + + case 2: { + // Counter + countDown(); + break; + } + + case 3: { + // Lower/Remove + deleteLater(); + break; + } + } +} + +void PopupMessage::slideMask() +{ + switch (m_stage) { + case 1: { + // Raise + move(0, m_parent->y() - m_offset); + m_offset++; + + if (m_offset > height()) { + killTimer(m_timerId); + + if (m_timeout) { + m_timerId = startTimer(40); + m_stage = 2; + } + } + break; + } + + case 2: { + // Fill in pause timer bar + countDown(); + break; + } + + case 3: { + // Lower + m_offset--; + move(0, m_parent->y() - m_offset); + + if (m_offset < 0) + deleteLater(); + } + } +} + +} + +#include "popupmessage.moc" diff --git a/kftpgrabber/src/widgets/popupmessage.h b/kftpgrabber/src/widgets/popupmessage.h new file mode 100644 index 0000000..0550d41 --- /dev/null +++ b/kftpgrabber/src/widgets/popupmessage.h @@ -0,0 +1,113 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Max Howell <max.howell@methyblue.com> + * Copyright (C) 2005 Seb Ruiz <me@sebruiz.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETSPOPUPMESSAGE_H +#define KFTPWIDGETSPOPUPMESSAGE_H + +#include "overlaywidget.h" + +#include <qbitmap.h> +#include <qlayout.h> +#include <qpixmap.h> + +namespace KFTPWidgets { + +/** + * Widget that animates itself into a position relative to an anchor widget. + */ +class PopupMessage : public OverlayWidget { +Q_OBJECT +public: + /** + * Possible animation effects. + */ + enum MaskEffect { + Plain, + Slide, + Dissolve + }; + + /** + * Class constructor. + * + * @param parent Parent widget + * @param anchor Which widget to tie the popup widget to + * @param timeout How long to wait before auto closing + */ + PopupMessage(QWidget *parent, QWidget *anchor, int timeout = 5000); + + void addWidget(QWidget *widget); + void setShowCloseButton(bool show); + void setShowCounter(bool show); + void setImage(const QString &location); + void setImage(const QPixmap &pixmap); + void setMaskEffect(MaskEffect type) { m_maskEffect = type; } + void setText(const QString &text); + void setTimeout(int timeout) { m_timeout = timeout; } +public slots: + void close(); + void display(); +protected: + void timerEvent(QTimerEvent *event); + void countDown(); + + void dissolveMask(); + void plainMask(); + void slideMask(); +private: + QVBoxLayout *m_layout; + QFrame *m_countdownFrame; + QWidget *m_anchor; + QWidget *m_parent; + QBitmap m_mask; + MaskEffect m_maskEffect; + + int m_dissolveSize; + int m_dissolveDelta; + + int m_offset; + int m_counter; + int m_stage; + int m_timeout; + int m_timerId; + + bool m_showCounter; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/queueview/Makefile.am b/kftpgrabber/src/widgets/queueview/Makefile.am new file mode 100644 index 0000000..5ba11d9 --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/Makefile.am @@ -0,0 +1,13 @@ +INCLUDES = -I$(srcdir)/../.. \ + -I$(srcdir)/../../engine \ + -I$(srcdir)/../../misc \ + -I$(srcdir)/../../ui -I../../ui\ + -I$(srcdir)/.. \ + -I$(srcdir)/../browser \ + $(all_includes) + +METASOURCES = AUTO +noinst_LIBRARIES = libqueueviewwidget.a +libqueueviewwidget_a_SOURCES = queueeditor.cpp queueview.cpp threadview.cpp + +noinst_HEADERS = queueeditor.h queueview.h threadview.h diff --git a/kftpgrabber/src/widgets/queueview/queueeditor.cpp b/kftpgrabber/src/widgets/queueview/queueeditor.cpp new file mode 100644 index 0000000..c565165 --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/queueeditor.cpp @@ -0,0 +1,323 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "queueeditor.h" +#include "kftpserverlineedit.h" +#include "kftpbookmarks.h" +#include "kftpqueueeditorlayout.h" + +#include <klineedit.h> +#include <kpassdlg.h> +#include <kcombobox.h> +#include <klocale.h> + +#include <qspinbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qtabwidget.h> + +#define REMOTE_PROTOCOL m_transfer->getSourceUrl().isLocalFile() ? m_transfer->getDestUrl().protocol() : m_transfer->getSourceUrl().protocol() + +namespace KFTPWidgets { + +QueueEditor::QueueEditor(QWidget *parent, const char *name) +: KDialogBase(parent, name, true, "Edit queue", KDialogBase::Ok | KDialogBase::Cancel, + KDialogBase::Ok, true) +{ + m_layout = new KFTPQueueEditorLayout(this); + setMainWidget(m_layout); + + connect(m_layout->srcPath, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + connect(m_layout->dstPath, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + + connect(m_layout->srcHost, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + connect(m_layout->srcUser, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + connect(m_layout->srcPass, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + + connect(m_layout->dstHost, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + connect(m_layout->dstUser, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + connect(m_layout->dstPass, SIGNAL(textChanged(const QString&)), this, SLOT(slotTextChanged())); + + connect(m_layout->srcName, SIGNAL(siteChanged(KFTPBookmarks::Site*)), this, SLOT(slotSourceSiteChanged(KFTPBookmarks::Site*))); + connect(m_layout->dstName, SIGNAL(siteChanged(KFTPBookmarks::Site*)), this, SLOT(slotDestSiteChanged(KFTPBookmarks::Site*))); + + connect(m_layout->transferType, SIGNAL(activated(int)), this, SLOT(slotTransferModeChanged(int))); + + setMaximumHeight(250); + setInitialSize(QSize(500, 250)); + + enableButtonOK(false); +} + +void QueueEditor::resetTabs() +{ + m_layout->serverTab->setTabEnabled(m_layout->tab, false); + m_layout->serverTab->setTabEnabled(m_layout->tab_2, false); +} + +void QueueEditor::resetServerData() +{ + // Source + m_layout->srcName->clear(); + m_layout->srcHost->setText(""); + m_layout->srcPort->setValue(21); + m_layout->srcUser->setText(""); + m_layout->srcPass->erase(); + + // Destination + m_layout->dstName->clear(); + m_layout->dstHost->setText(""); + m_layout->dstPort->setValue(21); + m_layout->dstUser->setText(""); + m_layout->dstPass->erase(); +} + +void QueueEditor::slotTransferModeChanged(int index) +{ + if (m_lastTransferType == index) + return; + else + m_lastTransferType = (KFTPQueue::TransferType) index; + + resetTabs(); + resetServerData(); + + switch (index) { + case 0: { + // Download - source: remote dest: local + m_layout->serverTab->setTabEnabled(m_layout->tab, true); + m_layout->serverTab->showPage(m_layout->tab); + break; + } + case 1: { + // Upload - source: local dest: remote + m_layout->serverTab->setTabEnabled(m_layout->tab_2, true); + m_layout->serverTab->showPage(m_layout->tab_2); + break; + } + case 2: { + // FXP - source: remote dest: remote + m_layout->serverTab->setTabEnabled(m_layout->tab, true); + m_layout->serverTab->setTabEnabled(m_layout->tab_2, true); + m_layout->serverTab->showPage(m_layout->tab); + break; + } + } + + slotTextChanged(); +} + +bool QueueEditor::sourceIsValid() +{ + if (m_lastTransferType == 1) return true; + + if (m_layout->srcHost->text().stripWhiteSpace().isEmpty() || m_layout->srcUser->text().stripWhiteSpace().isEmpty()) + return false; + else + return true; +} + +bool QueueEditor::destIsValid() +{ + if (m_lastTransferType == 0) return true; + + if (m_layout->dstHost->text().stripWhiteSpace().isEmpty() || m_layout->dstUser->text().stripWhiteSpace().isEmpty()) + return false; + else + return true; +} + +void QueueEditor::slotTextChanged() +{ + if (m_layout->srcPath->text().stripWhiteSpace().isEmpty() || m_layout->dstPath->text().stripWhiteSpace().isEmpty() || + m_layout->srcPath->text().left(1) != "/" || m_layout->dstPath->text().left(1) != "/" || + !sourceIsValid() || !destIsValid() ) + enableButtonOK(false); + else + enableButtonOK(true); +} + +void QueueEditor::setData(KFTPQueue::Transfer *transfer) +{ + KURL sUrl, dUrl; + + m_layout->srcPath->setText(transfer->getSourceUrl().path()); + m_layout->dstPath->setText(transfer->getDestUrl().path()); + + // Source + sUrl = transfer->getSourceUrl(); + + if (!sUrl.isLocalFile()) { + m_layout->srcName->setCurrentSite(KFTPBookmarks::Manager::self()->findSite(sUrl)); + m_layout->srcHost->setText(sUrl.host()); + m_layout->srcPort->setValue(sUrl.port()); + m_layout->srcUser->setText(sUrl.user()); + + m_layout->srcPass->erase(); + m_layout->srcPass->insert(sUrl.pass()); + } else { + m_layout->serverTab->setTabEnabled(m_layout->tab, false); + } + + // Destination + dUrl = transfer->getDestUrl(); + + if (!dUrl.isLocalFile()) { + m_layout->dstName->setCurrentSite(KFTPBookmarks::Manager::self()->findSite(dUrl)); + m_layout->dstHost->setText(dUrl.host()); + m_layout->dstPort->setValue(dUrl.port()); + m_layout->dstUser->setText(dUrl.user()); + + m_layout->dstPass->erase(); + m_layout->dstPass->insert(dUrl.pass()); + } else { + m_layout->serverTab->setTabEnabled(m_layout->tab_2, false); + } + + // Transfer type + m_lastTransferType = transfer->getTransferType(); + m_layout->transferType->setCurrentItem(m_lastTransferType); + + m_transfer = transfer; +} + +void QueueEditor::saveData() +{ + KURL sUrl, dUrl; + + if (m_lastTransferType != 1) { + sUrl.setProtocol(REMOTE_PROTOCOL); + sUrl.setHost(m_layout->srcHost->text()); + sUrl.setPort(m_layout->srcPort->value()); + sUrl.setUser(m_layout->srcUser->text()); + sUrl.setPass(m_layout->srcPass->password()); + + if (m_transfer->getSourceUrl().pass().isEmpty() && sUrl.pass().isEmpty()) + sUrl.setPass(QString::null); + } else { + sUrl.setProtocol("file"); + } + + sUrl.setPath(m_layout->srcPath->text()); + + if (m_lastTransferType != 0) { + dUrl.setProtocol(REMOTE_PROTOCOL); + dUrl.setHost(m_layout->dstHost->text()); + dUrl.setPort(m_layout->dstPort->value()); + dUrl.setUser(m_layout->dstUser->text()); + dUrl.setPass(m_layout->dstPass->password()); + + if (m_transfer->getDestUrl().pass().isEmpty() && dUrl.pass().isEmpty()) + dUrl.setPass(QString::null); + } else { + dUrl.setProtocol("file"); + } + + dUrl.setPath(m_layout->dstPath->text()); + + m_transfer->setSourceUrl(sUrl); + m_transfer->setDestUrl(dUrl); + m_transfer->setTransferType(m_lastTransferType); + + // If the transfer is a directory, we have to update all child transfers + // as well. + if (m_transfer->isDir()) + recursiveSaveData(static_cast<KFTPQueue::TransferDir*>(m_transfer), sUrl, dUrl); +} + +void QueueEditor::recursiveSaveData(KFTPQueue::TransferDir *parent, const KURL &srcUrl, const KURL &dstUrl) +{ + KFTPQueue::QueueObject *o; + QPtrList<KFTPQueue::QueueObject> children = parent->getChildrenList(); + + KURL sUrl, dUrl; + + for (o = children.first(); o; o = children.next()) { + KFTPQueue::Transfer *i = static_cast<KFTPQueue::Transfer*>(o); + + // Modify the urls + sUrl = srcUrl; + dUrl = dstUrl; + + sUrl.addPath(i->getSourceUrl().fileName()); + dUrl.addPath(i->getDestUrl().fileName()); + + // Set the urls + i->setSourceUrl(sUrl); + i->setDestUrl(dUrl); + i->setTransferType(m_lastTransferType); + i->emitUpdate(); + + if (i->isDir()) + recursiveSaveData(static_cast<KFTPQueue::TransferDir*>(i), sUrl, dUrl); + } +} + +void QueueEditor::slotSourceSiteChanged(KFTPBookmarks::Site *site) +{ + if (site) { + m_layout->srcHost->setText(site->getProperty("host")); + m_layout->srcPort->setValue(site->getIntProperty("port")); + m_layout->srcUser->setText(site->getProperty("username")); + m_layout->srcPass->erase(); + m_layout->srcPass->insert(site->getProperty("password")); + } else { + m_layout->srcHost->clear(); + m_layout->srcPort->setValue(21); + m_layout->srcUser->clear(); + m_layout->srcPass->erase(); + } +} + +void QueueEditor::slotDestSiteChanged(KFTPBookmarks::Site *site) +{ + if (site) { + m_layout->dstHost->setText(site->getProperty("host")); + m_layout->dstPort->setValue(site->getIntProperty("port")); + m_layout->dstUser->setText(site->getProperty("username")); + m_layout->dstPass->erase(); + m_layout->dstPass->insert(site->getProperty("password")); + } else { + m_layout->dstHost->clear(); + m_layout->dstPort->setValue(21); + m_layout->dstUser->clear(); + m_layout->dstPass->erase(); + } +} + +} + +#include "queueeditor.moc" + diff --git a/kftpgrabber/src/widgets/queueview/queueeditor.h b/kftpgrabber/src/widgets/queueview/queueeditor.h new file mode 100644 index 0000000..09027d6 --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/queueeditor.h @@ -0,0 +1,82 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPQUEUEEDITOR_H +#define KFTPQUEUEEDITOR_H + +#include "kftpqueue.h" +#include "kftpbookmarks.h" + +#include <kdialogbase.h> +#include <qdom.h> + +class KFTPQueueEditorLayout; + +namespace KFTPWidgets { + +/** +@author Jernej Kos +*/ +class QueueEditor : public KDialogBase +{ +Q_OBJECT +public: + QueueEditor(QWidget *parent = 0, const char *name = 0); + + void setData(KFTPQueue::Transfer *transfer); + void saveData(); +private: + KFTPQueueEditorLayout *m_layout; + KFTPQueue::Transfer *m_transfer; + KFTPQueue::TransferType m_lastTransferType; + + void resetTabs(); + void resetServerData(); + + bool sourceIsValid(); + bool destIsValid(); + + void recursiveSaveData(KFTPQueue::TransferDir *parent, const KURL &srcUrl, const KURL &dstUrl); +private slots: + void slotTextChanged(); + void slotTransferModeChanged(int index); + + void slotSourceSiteChanged(KFTPBookmarks::Site *site); + void slotDestSiteChanged(KFTPBookmarks::Site *site); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/queueview/queueview.cpp b/kftpgrabber/src/widgets/queueview/queueview.cpp new file mode 100644 index 0000000..4fc8e5f --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/queueview.cpp @@ -0,0 +1,888 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "misc.h" + +#include "listview.h" +#include "queueview.h" +#include "kftpqueue.h" +#include "kftpapi.h" +#include "queueeditor.h" +#include "widgets/searchdialog.h" +#include "misc/config.h" + +#include <kapplication.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <kio/job.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <kpopupmenu.h> +#include <klistviewsearchline.h> +#include <kdebug.h> + +#include <qspinbox.h> +#include <qtooltip.h> + +using namespace KFTPGrabberBase; +using namespace KFTPCore; + +namespace KFTPWidgets { + +QueueViewItem::QueueViewItem(QueueView *view, KFTPQueue::QueueObject *object, QListView *parent) + : QListViewItem(parent), + m_lastChild(0), + m_queueObject(object), + m_queueView(view), + m_queueId(object->getId()) +{ + init(); +} + +QueueViewItem::QueueViewItem(QueueView *view, KFTPQueue::QueueObject *object, QListViewItem *parent) + : QListViewItem(parent, static_cast<QueueViewItem*>(parent)->lastChild()), + m_lastChild(0), + m_queueObject(object), + m_queueView(view), + m_queueId(object->getId()) +{ + init(); +} + +QueueViewItem::~QueueViewItem() +{ + m_queueView->m_queuedItems.remove(m_queueId); +} + +void QueueViewItem::insertItem(QListViewItem *newChild) +{ + QListViewItem::insertItem(newChild); + m_lastChild = newChild; +} + +void QueueViewItem::takeItem(QListViewItem *item) +{ + if (item == m_lastChild) { + QListViewItem *above = item->itemAbove(); + + if (above->parent() == m_lastChild->parent()) + m_lastChild = above; + else + m_lastChild = 0; + } + + QListViewItem::takeItem(item); +} + +void QueueViewItem::moveUp() +{ + QListViewItem *above = itemAbove(); + + if (above && above->parent() == QListViewItem::parent()) { + QListViewItem *previous = above->itemAbove(); + + if (previous && previous->parent() == QListViewItem::parent()) { + QueueViewItem *parent = static_cast<QueueViewItem*>(QListViewItem::parent()); + moveItem(previous); + + if (parent && this == parent->lastChild()) + parent->m_lastChild = above; + } else { + moveToTop(); + } + } +} + +void QueueViewItem::moveDown() +{ + QueueViewItem *parent = static_cast<QueueViewItem*>(QListViewItem::parent()); + QueueViewItem *next = static_cast<QueueViewItem*>(nextSibling()); + + if (next) { + moveItem(next); + + if (parent && parent->lastChild() == next) + parent->m_lastChild = this; + } +} + +void QueueViewItem::moveToTop() +{ + QueueViewItem *parent = static_cast<QueueViewItem*>(QListViewItem::parent()); + + // Just reinsert the item + if (parent) { + if (this == parent->lastChild()) + parent->m_lastChild = itemAbove(); + + parent->QListViewItem::takeItem(this); + parent->QListViewItem::insertItem(this); + } else { + ListView *view = m_queueView->m_queue; + view->QListView::takeItem(this); + view->QListView::insertItem(this); + } +} + +void QueueViewItem::moveToBottom() +{ + QueueViewItem *parent = static_cast<QueueViewItem*>(QListViewItem::parent()); + + // Just reinsert the item + if (parent) { + QListViewItem *last = parent->lastChild(); + + parent->takeItem(this); + parent->insertItem(this); + moveItem(last); + } else { + ListView *view = m_queueView->m_queue; + view->takeItem(this); + view->insertItem(this); + } +} + +void QueueViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QColorGroup _cg(cg); + QColor c = _cg.text(); + + QColor n_color; + + if (m_queueObject && m_queueObject->isTransfer()) { + switch (m_queueObject->getStatus()) { + case KFTPQueue::Transfer::Running: n_color.setRgb(255, 0, 0); break; + case KFTPQueue::Transfer::Connecting: n_color.setRgb(0, 0, 255); break; + case KFTPQueue::Transfer::Waiting: n_color.setRgb(0, 0, 255); break; + case KFTPQueue::Transfer::Locked: n_color.setRgb(0, 150, 0); break; + default: break; + } + } + + if (n_color.isValid()) + _cg.setColor(QColorGroup::Text, n_color); + + QListViewItem::paintCell(p, _cg, column, width, alignment); + _cg.setColor(QColorGroup::Text, c); +} + +void QueueViewItem::init() +{ + if (m_queueObject->isTransfer()) { + KFTPQueue::Transfer *transfer = static_cast<KFTPQueue::Transfer*>(getObject()); + + setText(0, transfer->getSourceUrl().fileName()); + setText(1, KIO::convertSize(transfer->getActualSize())); + setText(2, transfer->getSourceUrl().pathOrURL()); + setText(3, transfer->getDestUrl().pathOrURL()); + + // Icon + QString iconText; + if (transfer->isDir()) { + iconText = "folder"; + } else { + KMimeType::Ptr theType = KMimeType::findByURL("/" + transfer->getSourceUrl().path(), 0, false, true); + iconText = theType->icon(QString::null, false); + } + + setPixmap(0, loadSmallPixmap(iconText)); + } else if (m_queueObject->getType() == KFTPQueue::QueueObject::Site) { + KFTPQueue::Site *site = static_cast<KFTPQueue::Site*>(getObject()); + + setText(0, QString("%1:%2").arg(site->getUrl().host()).arg(site->getUrl().port())); + setText(1, KIO::convertSize(site->getActualSize())); + + // Set the pixmap + setPixmap(0, loadSmallPixmap("server")); + } +} + +void QueueViewItem::refresh() +{ + if (!m_queueObject) + return; + + if (m_queueObject->isTransfer()) { + KFTPQueue::Transfer *transfer = static_cast<KFTPQueue::Transfer*>(getObject()); + + // Speed + bool noSpeed = transfer->getStatus() == KFTPQueue::Transfer::Waiting || transfer->getStatus() == KFTPQueue::Transfer::Connecting; + QString speed; + if ((!transfer->isDir() || !isOpen()) && transfer->isRunning() && !noSpeed) { + speed.sprintf( "%lld B/s", (transfer->getSpeed()) ); + + if (transfer->getSpeed() > 1024) + speed.sprintf( "%lld KB/s", (transfer->getSpeed() / 1024) ); + + if (transfer->getSpeed() > 1024*1024) + speed.sprintf("%lld MB/s", (transfer->getSpeed() / 1024) / 1024); + + if (transfer->getSpeed() == 0 && transfer->getTransferType() != KFTPQueue::FXP) + speed = i18n("stalled"); + + if (transfer->getSpeed() == 0 && transfer->getTransferType() == KFTPQueue::FXP) + speed = i18n("running"); + } + + // ETA + QString eta; + + if (transfer->isRunning() && transfer->getSpeed() > 0) { + eta = KIO::convertSeconds(KIO::calculateRemainingSeconds(transfer->getSize(), + transfer->getCompleted(), + transfer->getSpeed())); + } else { + eta = QString::null; + } + + // Set the columns + setText(0, transfer->getSourceUrl().fileName()); + setText(1, KIO::convertSize(transfer->getActualSize())); + setText(2, transfer->getSourceUrl().pathOrURL()); + setText(3, transfer->getDestUrl().pathOrURL()); + setText(5, speed); + setText(6, eta); + + // Don't show the file:// for local src/dest + if (transfer->getSourceUrl().isLocalFile()) { + setText(2, transfer->getSourceUrl().path()); + } else if (transfer->getDestUrl().isLocalFile()) { + setText(3, transfer->getDestUrl().path()); + } + + // Progress + int progress; + int r_progress; + + if (transfer->getSize() == 0) + progress = 0; + else + progress = transfer->getCompleted()*100/transfer->getSize(); + + if (transfer->getResumed() == 0) + r_progress = 0; + else + r_progress = transfer->getResumed()*100/transfer->getSize(); + + if (transfer->getStatus() == KFTPQueue::Transfer::Waiting) { + // Transfer is waiting for a free connection + setText(4, i18n("Waiting for connection...")); + setPixmap(4, NULL); + } else if (transfer->getStatus() == KFTPQueue::Transfer::Connecting) { + // Transfer is not yet connected, + setText(4, i18n("Connecting...")); + setPixmap(4, NULL); + } else if (progress > 0) { + setPixmap(4, createProgressPixmap(progress, r_progress)); + + QString progressText; + progressText.sprintf("%d %%", progress); + setText(4, progressText); + } else { + setPixmap(4, NULL); + setText(4, QString::null); + } + + // Icon + QString iconText; + if (transfer->isDir()) { + iconText = "folder"; + } else { + KMimeType::Ptr theType = KMimeType::findByURL("/" + transfer->getSourceUrl().path(), 0, false, true); + iconText = theType->icon(QString::null, false); + } + + setPixmap(0, loadSmallPixmap(iconText)); + } else if (m_queueObject->getType() == KFTPQueue::QueueObject::Site) { + KFTPQueue::Site *site = static_cast<KFTPQueue::Site*>(getObject()); + + // Speed + QString speed; + speed.sprintf( "%lld B/s", (site->getSpeed()) ); + + if (site->getSpeed() > 1024) + speed.sprintf( "%lld KB/s", (site->getSpeed() / 1024) ); + + if (site->getSpeed() > 1024*1024) + speed.sprintf("%lld MB/s", (site->getSpeed() / 1024) / 1024); + + if (site->getSpeed() == 0) + speed = QString::null; + + // ETA + QString eta; + + if (site->isRunning() && site->getSpeed() > 0) { + eta = KIO::convertSeconds(KIO::calculateRemainingSeconds(site->getSize(), + site->getCompleted(), + site->getSpeed())); + } else { + eta = ""; + } + + // Progress + if (site->isRunning()) { + int progress = 0; + + if (site->getSize() > 0) + progress = site->getCompleted()*100/site->getSize(); + + setPixmap(4, createProgressPixmap(progress, 0)); + + QString progressText; + progressText.sprintf("%d %%", progress); + setText(4, progressText); + } else { + setPixmap(4, NULL); + setText(4, QString::null); + } + + // Set the columns + setText(0, QString("%1:%2").arg(site->getUrl().host()).arg(site->getUrl().port())); + setText(1, KIO::convertSize(site->getActualSize())); + setText(5, speed); + setText(6, eta); + + // Set the pixmap + setPixmap(0, loadSmallPixmap("server")); + } +} + +QueueListView::QueueListView(QWidget *parent) + : ListView(parent) +{ +} + +void QueueListView::insertItem(QListViewItem *item) +{ + QListViewItem *last = lastChild(); + QListView::insertItem(item); + + if (last) + item->moveItem(last); +} + +QueueView::QueueView(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + m_toolBar = new KToolBar(this, "queueToolBar"); + m_toolBar->setIconSize(16); + layout->addWidget(m_toolBar); + + m_searchToolBar = new KToolBar(this, "searchToolBar"); + m_searchToolBar->setEnableContextMenu(false); + m_searchToolBar->setMovingEnabled(false); + m_searchToolBar->setFullSize(true); + + // Create the erase button + m_searchToolBar->insertButton(QApplication::reverseLayout() ? "clear_left" :"locationbar_erase", 0, SIGNAL(clicked()), this, SLOT(slotSearchEraseClicked()), true); + + // Create the labels + QLabel *searchLabel = new QLabel(i18n("Filter: "), m_searchToolBar); + m_searchToolBar->insertWidget(1, 35, searchLabel); + + // Create the list view + m_queue = new QueueListView(this); + + // Create the search field + m_searchField = new KListViewSearchLine(m_searchToolBar, m_queue); + + // Do some more stuff + m_searchToolBar->setItemAutoSized(1, true); + m_searchToolBar->setStretchableWidget(m_searchField); + m_searchToolBar->updateRects(true); + m_searchToolBar->hide(); + + layout->addWidget(m_searchToolBar); + + // Create the columns + m_queue->addColumn(i18n("Name"), 150); + m_queue->addColumn(i18n("Size"), 75); + m_queue->addColumn(i18n("Source"), 250); + m_queue->addColumn(i18n("Destination"), 250); + m_queue->addColumn(i18n("Progress"), 140); + m_queue->addColumn(i18n("Speed"), 70); + m_queue->addColumn(i18n("ETA"), 80); + + // Text when there is nothing queued + m_queue->setEmptyListText(i18n("You do not have any files in the queue.")); + + // Multi-select + m_queue->setSelectionModeExt(KListView::FileManager); + m_queue->setAllColumnsShowFocus(true); + m_queue->setRootIsDecorated(true); + m_queue->QListView::setSorting(-1); + m_queue->QListView::setSortColumn(-1); + + layout->addWidget(m_queue); + + // The signals + connect(m_queue, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), this, + SLOT(contextMenuRequested(KListView*, QListViewItem*, const QPoint&))); + connect(m_queue, SIGNAL(selectionChanged()), this, SLOT(updateActions())); + + // Let us be up-to-date + connect(KFTPQueue::Manager::self(), SIGNAL(transferRemoved(long)), this, SLOT(slotObjectRemoved(long))); + connect(KFTPQueue::Manager::self(), SIGNAL(siteRemoved(long)), this, SLOT(slotObjectRemoved(long))); + connect(KFTPQueue::Manager::self(), SIGNAL(newTransfer(KFTPQueue::Transfer*)), this, SLOT(slotTransferAdded(KFTPQueue::Transfer*))); + connect(KFTPQueue::Manager::self(), SIGNAL(newSite(KFTPQueue::Site*)), this, SLOT(slotSiteAdded(KFTPQueue::Site*))); + connect(KFTPQueue::Manager::self(), SIGNAL(queueUpdate()), this, SLOT(updateActions())); + + // Load the listview layout + loadLayout(); + + // Create the context menu actions + initActions(); + initToolBar(); + updateActions(); + + setMinimumHeight(150); +} + +void QueueView::saveLayout() +{ + m_queue->saveLayout(kapp->config(), "queueViewLayout"); +} + +void QueueView::loadLayout() +{ + m_queue->restoreLayout(kapp->config(), "queueViewLayout"); +} + +void QueueView::initToolBar() +{ + // Plug all actions + m_loadAction->plug(m_toolBar); + m_saveAction->plug(m_toolBar); + m_toolBar->insertSeparator(); + m_startAction->plug(m_toolBar); + m_pauseAction->plug(m_toolBar); + m_stopAction->plug(m_toolBar); + m_toolBar->insertSeparator(); + m_addAction->plug(m_toolBar); + m_removeAction->plug(m_toolBar); + m_searchAction->plug(m_toolBar); + m_toolBar->insertSeparator(); + m_filterAction->plug(m_toolBar); + + // Create speed control widgets + m_toolBar->insertSeparator(); + + QSpinBox *downloadSpeed = new QSpinBox(0, 10240, 1, m_toolBar); + QToolTip::add(downloadSpeed, i18n("Limit download transfer speed")); + m_toolBar->insertWidget(1, 35, new QLabel(i18n("Down: "), m_toolBar)); + m_toolBar->insertWidget(2, 35, downloadSpeed); + downloadSpeed->setValue(Config::downloadSpeedLimit()); + connect(downloadSpeed, SIGNAL(valueChanged(int)), this, SLOT(slotDownloadLimitChanged(int))); + + m_toolBar->insertSeparator(); + + QSpinBox *uploadSpeed = new QSpinBox(0, 10240, 1, m_toolBar); + QToolTip::add(uploadSpeed, i18n("Limit upload transfer speed")); + m_toolBar->insertWidget(3, 35, new QLabel(i18n("Up: "), m_toolBar)); + m_toolBar->insertWidget(4, 35, uploadSpeed); + uploadSpeed->setValue(Config::uploadSpeedLimit()); + connect(uploadSpeed, SIGNAL(valueChanged(int)), this, SLOT(slotUploadLimitChanged(int))); + + // Create thread count control widget + m_toolBar->insertSeparator(); + + QSpinBox *threadCount = new QSpinBox(1, 10, 1, m_toolBar); + QToolTip::add(threadCount, i18n("Per-session transfer thread count")); + m_toolBar->insertWidget(5, 35, new QLabel(i18n("Threads: "), m_toolBar)); + m_toolBar->insertWidget(6, 35, threadCount); + threadCount->setValue(Config::threadCount()); + connect(threadCount, SIGNAL(valueChanged(int)), this, SLOT(slotThreadCountChanged(int))); +} + +void QueueView::slotDownloadLimitChanged(int value) +{ + Config::setDownloadSpeedLimit(value); + Config::self()->emitChange(); +} + +void QueueView::slotUploadLimitChanged(int value) +{ + Config::setUploadSpeedLimit(value); + Config::self()->emitChange(); +} + +void QueueView::slotThreadCountChanged(int value) +{ + Config::setThreadCount(value); + Config::self()->emitChange(); +} + +void QueueView::initActions() +{ + m_actionCollection = new KActionCollection(this, this); + + // Create all the actions + m_launchAction = new KAction(i18n("&Start Transfer"), "launch", KShortcut(), this, SLOT(slotLaunch()), m_actionCollection, "launch"); + m_abortAction = new KAction(i18n("&Abort Transfer"), KShortcut(), this, SLOT(slotAbort()), m_actionCollection, "abort"); + m_removeAction = new KAction(i18n("&Remove"), "editdelete", KShortcut(Qt::Key_Delete), this, SLOT(slotRemove()), m_actionCollection, "remove"); + m_removeAllAction = new KAction(i18n("Remove &All"), KShortcut(), this, SLOT(slotRemoveAll()), m_actionCollection, "removeAll"); + m_moveUpAction = new KAction(i18n("Move &Up"), "up", KShortcut(), this, SLOT(slotMoveUp()), m_actionCollection, "moveUp"); + m_moveDownAction = new KAction(i18n("Move &Down"), "down", KShortcut("del"), this, SLOT(slotMoveDown()), m_actionCollection, "moveDown"); + m_moveTopAction = new KAction(i18n("Move To &Top"), "top", KShortcut(), this, SLOT(slotMoveTop()), m_actionCollection, "moveTop"); + m_moveBottomAction = new KAction(i18n("Move To &Bottom"), "bottom", KShortcut(), this, SLOT(slotMoveBottom()), m_actionCollection, "moveBottom"); + m_editAction = new KAction(i18n("&Change Transfer Info"), KShortcut(), this, SLOT(slotEdit()), m_actionCollection, "changeTransfer"); + + // Create the toolbar actions + m_loadAction = new KAction(i18n("&Load Queue From File"), "fileopen", KShortcut(), this, SLOT(slotLoad()), m_actionCollection, "load"); + m_saveAction = new KAction(i18n("&Save Queue to File"), "filesaveas", KShortcut(), this, SLOT(slotSave()), m_actionCollection, "save"); + m_startAction = new KAction(i18n("S&tart"), "player_play", KShortcut(), this, SLOT(slotStart()), m_actionCollection, "start"); + m_pauseAction = new KAction(i18n("&Pause"), "player_pause", KShortcut(), this, SLOT(slotPause()), m_actionCollection, "pause"); + m_stopAction = new KAction(i18n("St&op"), "player_stop", KShortcut(), this, SLOT(slotStop()), m_actionCollection, "stop"); + m_addAction = new KAction(i18n("&Add Transfer..."), "filenew", KShortcut(), this, SLOT(slotAdd()), m_actionCollection, "add"); + m_searchAction = new KAction(i18n("&Search && Replace..."), "find", KShortcut(), this, SLOT(slotSearch()), m_actionCollection, "search"); + m_filterAction = new KToggleAction(i18n("Show &Filter"), "filter", KShortcut(), this, SLOT(slotFilter()), m_actionCollection, "filter"); + + m_saveAction->setEnabled( false ); + m_startAction->setEnabled(false); + m_pauseAction->setEnabled(false); + m_stopAction->setEnabled(false); + m_addAction->setEnabled(false); + m_removeAction->setEnabled(false); + m_searchAction->setEnabled(false); + m_filterAction->setEnabled(true); +} + +void QueueView::updateActions() +{ + m_startAction->setEnabled(!KFTPQueue::Manager::self()->isProcessing() && KFTPQueue::Manager::self()->topLevelObject()->hasChildren() && !KFTPQueue::Manager::self()->getNumRunning()); + m_stopAction->setEnabled(KFTPQueue::Manager::self()->isProcessing()); + m_removeAllAction->setEnabled(!KFTPQueue::Manager::self()->isProcessing()); + + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + QueueViewItem *firstItem = static_cast<QueueViewItem*>(selection.first()); + + m_removeAction->setEnabled((bool) firstItem); + + if (!firstItem || !firstItem->getObject()) + return; + + bool locked = firstItem->getObject()->isLocked(); + bool parentRunning = false; + + if (firstItem->getObject()->hasParentObject()) + parentRunning = firstItem->getObject()->parentObject()->isRunning(); + + m_launchAction->setEnabled(!firstItem->getObject()->isRunning() && !KFTPQueue::Manager::self()->isProcessing() && !locked); + m_abortAction->setEnabled(firstItem->getObject()->isRunning() && !KFTPQueue::Manager::self()->isProcessing()); + m_removeAction->setEnabled(!firstItem->getObject()->isRunning() && !KFTPQueue::Manager::self()->isProcessing() && !locked); + m_editAction->setEnabled(!firstItem->getObject()->isRunning() && firstItem->getObject()->parentObject()->getType() == KFTPQueue::QueueObject::Site && !locked); + + // Only allow moving of multi selections if they have the same parent + bool allowMove = true; + for (QListViewItem *i = selection.first(); i; i = selection.next()) { + if (i->parent() != static_cast<QListViewItem*>(firstItem)->parent()) { + allowMove = false; + break; + } + } + + m_moveUpAction->setEnabled(allowMove && KFTPQueue::Manager::self()->canBeMovedUp(firstItem->getObject()) && !locked); + m_moveDownAction->setEnabled(allowMove && KFTPQueue::Manager::self()->canBeMovedDown(static_cast<QueueViewItem*>(selection.last())->getObject()) && !locked); + + m_moveTopAction->setEnabled(allowMove && KFTPQueue::Manager::self()->canBeMovedUp(firstItem->getObject()) && !locked); + m_moveBottomAction->setEnabled(allowMove && KFTPQueue::Manager::self()->canBeMovedDown(static_cast<QueueViewItem*>(selection.last())->getObject()) && !locked); +} + +void QueueView::slotSiteAdded(KFTPQueue::Site *site) +{ + // The site should be inserted top-level + m_queuedItems.insert(site->getId(), new QueueViewItem(this, site, m_queue)); + connect(site, SIGNAL(objectUpdated()), this, SLOT(slotObjectUpdated())); +} + +void QueueView::slotTransferAdded(KFTPQueue::Transfer *transfer) +{ + // This transfer should be inserted under some other transfer + QueueViewItem *parent = m_queuedItems.find(transfer->parentObject()->getId()); + + if (parent) { + m_queuedItems.insert(transfer->getId(), new QueueViewItem(this, transfer, parent)); + connect(transfer, SIGNAL(objectUpdated()), this, SLOT(slotObjectUpdated())); + } + + // Update actions + m_saveAction->setEnabled(true); + m_removeAllAction->setEnabled(true); + m_searchAction->setEnabled(true); +} + +void QueueView::slotObjectRemoved(long id) +{ + // Delete the transfer + QueueViewItem *item = m_queuedItems.find(id); + + if (item) + delete item; + + // Update actions + bool empty = (m_queue->childCount() == 0); + + m_saveAction->setEnabled(!empty); + if (empty) m_removeAction->setEnabled(false); + m_removeAllAction->setEnabled(!empty); + m_searchAction->setEnabled(!empty); +} + +void QueueView::slotObjectUpdated() +{ + KFTPQueue::QueueObject *object = (KFTPQueue::QueueObject*) QObject::sender(); + + if (object) { + QueueViewItem *item = m_queuedItems.find(object->getId()); + + if (item) + item->refresh(); + } +} + +void QueueView::contextMenuRequested(KListView*, QListViewItem* item, const QPoint& p) +{ + if (!item) + return; + + QueueViewItem *firstItem = static_cast<QueueViewItem*>(m_queue->selectedItems().first()); + KPopupMenu *contextMenu = new KPopupMenu(m_queue); + + // Populate context menu + if (firstItem->getObject()->isTransfer()) { + contextMenu->insertTitle(item->text(0) + ((m_queue->selectedItems().count() > 1) ? "..." : "" )); + m_launchAction->plug(contextMenu); + m_abortAction->plug(contextMenu); + contextMenu->insertSeparator(); + m_removeAction->plug(contextMenu); + m_removeAllAction->plug(contextMenu); + contextMenu->insertSeparator(); + m_moveTopAction->plug(contextMenu); + m_moveUpAction->plug(contextMenu); + m_moveDownAction->plug(contextMenu); + m_moveBottomAction->plug(contextMenu); + contextMenu->insertSeparator(); + m_editAction->plug(contextMenu); + } else if (firstItem->getObject()->getType() == KFTPQueue::QueueObject::Site) { + contextMenu->insertTitle(i18n("Site")); + m_launchAction->plug(contextMenu); + m_abortAction->plug(contextMenu); + contextMenu->insertSeparator(); + m_moveUpAction->plug(contextMenu); + m_moveDownAction->plug(contextMenu); + } + + // Update the actions + updateActions(); + + // Show the context menu + contextMenu->exec(p); +} + +void QueueView::slotLaunch() +{ + // Reset a possible preconfigured default action + KFTPQueue::Manager::self()->setDefaultFileExistsAction(); + + static_cast<QueueViewItem*>(m_queue->selectedItems().first())->getObject()->execute(); +} + +void QueueView::slotAbort() +{ + static_cast<QueueViewItem*>(m_queue->selectedItems().first())->getObject()->abort(); +} + +void QueueView::slotRemove() +{ + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove queued file(s)?")) == KMessageBox::Yes) { + KFTPQueue::Manager::self()->setEmitUpdate(false); + + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + for (QListViewItem *item = selection.first(); item; item = selection.next()) { + if (item && static_cast<QueueViewItem*>(item)->getObject()) + KFTPQueue::Manager::self()->removeTransfer(static_cast<KFTPQueue::Transfer*>(static_cast<QueueViewItem*>(item)->getObject())); + } + + KFTPQueue::Manager::self()->setEmitUpdate(true); + KFTPQueue::Manager::self()->doEmitUpdate(); + } +} + +void QueueView::slotRemoveAll() +{ + if (KMessageBox::questionYesNo(this, i18n("Are you sure you want to remove ALL queued files?")) == KMessageBox::Yes) { + KFTPQueue::Manager::self()->clearQueue(); + } +} + +void QueueView::slotMoveUp() +{ + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + + for (QListViewItem *item = selection.first(); item; item = selection.next()) { + QueueViewItem *queueItem = static_cast<QueueViewItem*>(item); + + // Move the transfer + KFTPQueue::Manager::self()->moveTransferUp(queueItem->getObject()); + queueItem->moveUp(); + } +} + +void QueueView::slotMoveDown() +{ + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + + for (QListViewItem *item = selection.last(); item; item = selection.prev()) { + QueueViewItem *queueItem = static_cast<QueueViewItem*>(item); + + // Move the transfer + KFTPQueue::Manager::self()->moveTransferDown(queueItem->getObject()); + queueItem->moveDown(); + } +} + +void QueueView::slotMoveTop() +{ + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + + for (QListViewItem *item = selection.last(); item; item = selection.prev()) { + QueueViewItem *queueItem = static_cast<QueueViewItem*>(item); + + // Move the transfer + KFTPQueue::Manager::self()->moveTransferTop(queueItem->getObject()); + queueItem->moveToTop(); + } +} + +void QueueView::slotMoveBottom() +{ + QPtrList<QListViewItem> selection = m_queue->selectedItems(); + + for (QListViewItem *item = selection.first(); item; item = selection.next()) { + QueueViewItem *queueItem = static_cast<QueueViewItem*>(item); + + // Move the transfer + KFTPQueue::Manager::self()->moveTransferBottom(queueItem->getObject()); + queueItem->moveToBottom(); + } +} + +void QueueView::slotEdit() +{ + QueueEditor *editor = new QueueEditor(this); + + QueueViewItem* item = static_cast<QueueViewItem*>(m_queue->selectedItems().first()); + editor->setData(static_cast<KFTPQueue::Transfer*>(item->getObject())); + + // Show the queue editor + if (editor->exec() == QDialog::Accepted) { + editor->saveData(); + + KFTPQueue::Manager::self()->revalidateTransfer(static_cast<KFTPQueue::Transfer*>(item->getObject())); + KFTPQueue::Manager::self()->doEmitUpdate(); + item->refresh(); + } +} + +void QueueView::slotSearch() +{ + SearchDialog *dialog = new SearchDialog(); + + dialog->exec(); + delete dialog; +} + +void QueueView::slotLoad() +{ + if (m_queue->childCount() && KMessageBox::warningContinueCancel(0L, i18n("Loading a new queue will overwrite the existing one; are you sure you want to continue?"), i18n("Load Queue")) == KMessageBox::Cancel) + return; + + QString loadPath = KFileDialog::getOpenFileName(); + + if (!loadPath.isEmpty()) { + KFTPQueue::Manager::self()->getConverter()->importQueue(loadPath); + } +} + +void QueueView::slotSave() +{ + QString savePath = KFileDialog::getSaveFileName(); + + if (!savePath.isEmpty()) { + KFTPQueue::Manager::self()->getConverter()->exportQueue(savePath); + } +} + +void QueueView::slotStart() +{ + // Begin queue processing + KFTPQueue::Manager::self()->start(); +} + +void QueueView::slotPause() +{ +} + +void QueueView::slotStop() +{ + // Abort queue processing + KFTPQueue::Manager::self()->abort(); +} + +void QueueView::slotAdd() +{ +} + +void QueueView::slotSearchEraseClicked() +{ + m_searchField->clear(); +} + +void QueueView::slotFilter() +{ + if (m_filterAction->isChecked()) + m_searchToolBar->show(); + else + m_searchToolBar->hide(); +} + +} + +#include "queueview.moc" diff --git a/kftpgrabber/src/widgets/queueview/queueview.h b/kftpgrabber/src/widgets/queueview/queueview.h new file mode 100644 index 0000000..d93e14f --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/queueview.h @@ -0,0 +1,296 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2005 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPQUEUEVIEW_H +#define KFTPQUEUEVIEW_H + +#include <qguardedptr.h> +#include <qintdict.h> +#include <qlayout.h> +#include <qlabel.h> + +#include <kaction.h> +#include <klistview.h> + +#include "kftpqueue.h" + +class KToolBar; +class KListViewSearchLine; + +namespace KFTPWidgets { + +class ListView; +class QueueView; + +/** + * A visual representation of a queued object. + */ +class QueueViewItem : public QListViewItem +{ +public: + /** + * Class constructor. + * + * @param view Queue view widget + * @param object Queue object + * @param parent Parent list view + */ + QueueViewItem(QueueView *view, KFTPQueue::QueueObject *object, QListView *parent); + + /** + * Class constructor. + * + * @param view Queue view widget + * @param object Queue object + * @param parent Parent item + */ + QueueViewItem(QueueView *view, KFTPQueue::QueueObject *object, QListViewItem *parent); + + /** + * Class destructor. + */ + ~QueueViewItem(); + + /** + * Refresh the visual representation with data from the actual queue object. + */ + void refresh(); + + /** + * Associate a queue object with this item. + * + * @param object A valid object pointer + */ + void setObject(KFTPQueue::QueueObject *object) { m_queueObject = object; } + + /** + * Returns the currently associated queue object. + */ + KFTPQueue::QueueObject *getObject() const { return m_queueObject; } + + /** + * Returns the last child item. + */ + QListViewItem *lastChild() const { return m_lastChild; } + + /** + * Moves this item one position up. + */ + void moveUp(); + + /** + * Moves this item one position down. + */ + void moveDown(); + + /** + * Moves this item to parent's top. + */ + void moveToTop(); + + /** + * Moves this item to parent's bottom. + */ + void moveToBottom(); + + /** + * @overload + * Reimplemented from QListViewItem. + */ + void insertItem(QListViewItem *newChild); + + /** + * @overload + * Reimplemented from QListViewItem. + */ + void takeItem(QListViewItem *item); + + /** + * @overload + * Reimplemented from QListViewItem for text colors. + */ + void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); + + /** + * @overload + * Reimplemented from QListViewItem. + */ + void sortChildItems(int, bool) {} +protected: + /** + * Init the item. + */ + void init(); +private: + QListViewItem *m_lastChild; + + KFTPQueue::QueueObject *m_queueObject; + QueueView *m_queueView; + long m_queueId; +}; + +/** + * The list view widget. + * + * @author Jernej Kos + */ +class QueueListView : public ListView { +public: + /** + * Class constructor. + * + * @param parent Parent widget + */ + QueueListView(QWidget *parent); + + /** + * @overload + * Reimplemented from QListView. + */ + void insertItem(QListViewItem *item); + + /** + * @overload + * Reimplemented from QListView. + */ + void setSorting(int, bool = true) { QListView::setSorting(-1); } +}; + +/** + * A widget for displaying and manipulating the current queue. + * + * @author Jernej Kos + */ +class QueueView : public QWidget +{ +friend class QueueViewItem; +Q_OBJECT +public: + /** + * Class constructor. + */ + QueueView(QWidget *parent, const char *name); + + /** + * Load queue list layout from the configuration file. + */ + void loadLayout(); + + /** + * Save queue list layout to the configuration file. + */ + void saveLayout(); +public slots: + void updateActions(); +protected: + /** + * Initialize actions. + */ + void initActions(); + + /** + * Initialize toolbar widgets. + */ + void initToolBar(); +private: + KActionCollection *m_actionCollection; + + // Actions + KAction *m_launchAction; + KAction *m_abortAction; + KAction *m_removeAction; + KAction *m_removeAllAction; + KAction *m_moveUpAction; + KAction *m_moveDownAction; + KAction *m_moveTopAction; + KAction *m_moveBottomAction; + KAction *m_editAction; + + // Toolbar Actions + KAction *m_loadAction; + KAction *m_saveAction; + KAction *m_startAction; + KAction *m_pauseAction; + KAction *m_stopAction; + KAction *m_addAction; + KAction *m_searchAction; + KToggleAction *m_filterAction; + + KListViewSearchLine *m_searchField; + + KToolBar *m_toolBar; + KToolBar *m_searchToolBar; + QueueListView *m_queue; + + QIntDict<QueueViewItem> m_queuedItems; +private slots: + void slotObjectRemoved(long); + void slotObjectUpdated(); + void slotTransferAdded(KFTPQueue::Transfer*); + void slotSiteAdded(KFTPQueue::Site*); + + void contextMenuRequested(KListView*, QListViewItem*, const QPoint&); + + void slotSearchEraseClicked(); + + // Slots for actions + void slotLaunch(); + void slotAbort(); + void slotRemove(); + void slotRemoveAll(); + void slotMoveUp(); + void slotMoveDown(); + void slotMoveTop(); + void slotMoveBottom(); + void slotEdit(); + + void slotLoad(); + void slotSave(); + void slotStart(); + void slotPause(); + void slotStop(); + void slotAdd(); + void slotSearch(); + void slotFilter(); + + void slotDownloadLimitChanged(int value); + void slotUploadLimitChanged(int value); + void slotThreadCountChanged(int value); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/queueview/threadview.cpp b/kftpgrabber/src/widgets/queueview/threadview.cpp new file mode 100644 index 0000000..fd1c663 --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/threadview.cpp @@ -0,0 +1,202 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "threadview.h" +#include "kftpapi.h" + +#include "listview.h" + +#include <qlayout.h> +#include <klocale.h> + +namespace KFTPWidgets { + +ThreadViewItem::ThreadViewItem(KFTPSession::Session *session, QListView *parent) + : QObject(parent), + QListViewItem(parent), + m_connection(0), + m_session(session) +{ + refresh(); +} + +ThreadViewItem::ThreadViewItem(KFTPSession::Connection *conn, QListViewItem *parent, int id) + : QObject(), + QListViewItem(parent), + m_id(id), + m_connection(conn), + m_session(0) +{ + connect(conn, SIGNAL(connectionRemoved()), this, SLOT(slotUpdateItemRequested())); + connect(conn, SIGNAL(connectionLost(KFTPSession::Connection*)), this, SLOT(slotUpdateItemRequested())); + connect(conn, SIGNAL(connectionEstablished()), this, SLOT(slotUpdateItemRequested())); + + // Connect the transfer signals if the transfer is already present + KFTPQueue::Transfer *transfer = m_connection->getTransfer(); + if (transfer) { + connect(transfer, SIGNAL(objectUpdated()), this, SLOT(slotUpdateItemRequested())); + } else { + connect(conn, SIGNAL(connectionAcquired()), this, SLOT(slotConnectionAcquired())); + } + + refresh(); +} + +void ThreadViewItem::slotConnectionAcquired() +{ + if (!m_connection->getTransfer()) + return; + + connect(m_connection->getTransfer(), SIGNAL(objectUpdated()), this, SLOT(slotUpdateItemRequested())); + refresh(); +} + +void ThreadViewItem::refresh() +{ + if (m_session) { + // Set the columns + setText(0, i18n("Site session [%1]").arg(m_session->getClient()->socket()->getCurrentUrl().host())); + setPixmap(0, loadSmallPixmap("ftp")); + } else if (m_connection) { + setText(0, i18n("Thread %1").arg(m_id)); + setPixmap(0, loadSmallPixmap("server")); + setText(1, m_connection->isConnected() ? i18n("idle") : i18n("disconnected")); + setText(2, ""); + + KFTPQueue::Transfer *transfer = m_connection->getTransfer(); + if (transfer && transfer->isRunning()) { + QString speed; + filesize_t rawSpeed = transfer->getSpeed(); + + speed.sprintf( "%lld KB/s", (rawSpeed / 1024) ); + + if (rawSpeed > 1024*1024) + speed.sprintf("%lld MB/s", (rawSpeed / 1024) / 1024); + else if (rawSpeed == 0) + speed = ""; + + if (transfer->getStatus() == KFTPQueue::Transfer::Connecting) { + setText(1, i18n("connecting")); + } else { + setText(1, i18n("transferring")); + } + + if (transfer->getTransferType() == KFTPQueue::FXP && rawSpeed == 0) { + KFTPSession::Connection *c = static_cast<KFTPQueue::TransferFile*>(transfer)->getOppositeConnection(m_connection); + + setText(2, i18n("FXP - [%1]").arg(c->getUrl().host())); + } else { + setText(2, speed); + } + } + } +} + +void ThreadViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment) +{ + QListViewItem::paintCell(p, cg, column, width, alignment); +} + +void ThreadViewItem::slotUpdateItemRequested() +{ + refresh(); +} + +KActionCollection *ThreadView::actionCollection() +{ + return KFTPAPI::getInstance()->mainWindow()->actionCollection(); +} + +ThreadView::ThreadView(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + + // Create the list view + m_threads = new KFTPWidgets::ListView(this); + + // Create the columns + m_threads->addColumn(i18n("Name"), 400); + m_threads->addColumn(i18n("Status"), 120); + m_threads->addColumn(i18n("Speed"), 70); + + // Text when there are no threads + m_threads->setEmptyListText(i18n("There are no threads currently running.")); + + // Multi-select + m_threads->setSelectionModeExt(KListView::FileManager); + m_threads->setAllColumnsShowFocus(true); + m_threads->setRootIsDecorated(true); + + layout->addWidget(m_threads); + + connect(KFTPSession::Manager::self(), SIGNAL(update()), this, SLOT(slotUpdateSessions())); +} + +ThreadView::~ThreadView() +{ +} + +void ThreadView::slotUpdateSessions() +{ + KFTPSession::SessionList *list = KFTPSession::Manager::self()->getSessionList(); + KFTPSession::Session *i; + + m_threads->clear(); + + for (i = list->first(); i; i = list->next()) { + if (i->isRemote()) { + ThreadViewItem *site = new ThreadViewItem(i, m_threads); + + QPtrList<KFTPSession::Connection> *c_list = i->getConnectionList(); + + if (c_list->count() > 0) { + KFTPSession::Connection *conn; + int id = 0; + + for (conn = c_list->first(); conn; conn = c_list->next()) { + new ThreadViewItem(conn, site, ++id); + } + + site->setOpen(true); + } + } + } +} + +} + +#include "threadview.moc" + diff --git a/kftpgrabber/src/widgets/queueview/threadview.h b/kftpgrabber/src/widgets/queueview/threadview.h new file mode 100644 index 0000000..5c37e6c --- /dev/null +++ b/kftpgrabber/src/widgets/queueview/threadview.h @@ -0,0 +1,93 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPTHREADVIEW_H +#define KFTPTHREADVIEW_H + +#include <qguardedptr.h> + +#include <kaction.h> +#include <klistview.h> + +#include "kftpsession.h" + +class KToolBar; + +namespace KFTPWidgets { + +class ListView; + +class ThreadViewItem : public QObject, public QListViewItem +{ +Q_OBJECT +public: + ThreadViewItem(KFTPSession::Session *session, QListView *parent); + ThreadViewItem(KFTPSession::Connection *conn, QListViewItem *parent, int id); + + void refresh(); + virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int alignment); +private: + int m_id; + + QGuardedPtr<KFTPSession::Connection> m_connection; + QGuardedPtr<KFTPSession::Session> m_session; +private slots: + void slotConnectionAcquired(); + void slotUpdateItemRequested(); +}; + +/** + * This widget shows all the currently used threads in KFTPGrabber transfers. + * + * @author Jernej Kos + */ +class ThreadView : public QWidget +{ +Q_OBJECT +public: + ThreadView(QWidget *parent = 0, const char *name = 0); + ~ThreadView(); + + KActionCollection *actionCollection(); + +private slots: + void slotUpdateSessions(); +private: + KFTPWidgets::ListView *m_threads; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/quickconnect.cpp b/kftpgrabber/src/widgets/quickconnect.cpp new file mode 100644 index 0000000..0eabdc8 --- /dev/null +++ b/kftpgrabber/src/widgets/quickconnect.cpp @@ -0,0 +1,476 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "widgets/quickconnect.h" +#include "bookmarks/editortls.h" +#include "misc/config.h" +#include "kftpbookmarks.h" +#include "misc.h" + +#include "engine/thread.h" +#include "engine/ftpsocket.h" + +#include <kglobal.h> +#include <kcharsets.h> +#include <kcombobox.h> +#include <klocale.h> +#include <klineedit.h> +#include <kpassdlg.h> +#include <kmessagebox.h> +#include <kpushbutton.h> + +/* KSSL includes */ +#include <ksslpkcs12.h> + +#include <qcheckbox.h> +#include <qspinbox.h> + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +QuickConnectDialog::QuickConnectDialog(QWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("Quick Connect"), Ok|Cancel, Ok), + m_noUrlChange(false), + m_protocolAdvancedDialog(0L), + m_portChanged(false) +{ + // Create the main widget + m_layout = new KFTPQuickConnectLayout(this); + + // Set the dialog options + setMainWidget(m_layout); + resize(QSize(200,300)); + + m_layout->clearRecent->setIconSet(loadSmallIcon("clear_left")); + m_layout->protoAdvanced->setIconSet(loadSmallIcon("configure")); + + // Connect the slots + connect(m_layout->urlBox, SIGNAL(textChanged(const QString&)), this, SLOT(slotUrlChanged(const QString &))); + connect(m_layout->hostBox, SIGNAL(textChanged(const QString&)), this, SLOT(slotHostChanged(const QString&))); + connect(m_layout->protocolBox, SIGNAL(activated(int)), this, SLOT(slotProtocolChanged(int))); + connect(m_layout->protoAdvanced, SIGNAL(clicked()), this, SLOT(slotProtoAdvancedClicked())); + connect(m_layout->usernameBox, SIGNAL(textChanged(const QString&)), this, SLOT(slotUserChanged())); + connect(m_layout->passwordBox, SIGNAL(textChanged(const QString&)), this, SLOT(slotPassChanged())); + connect(m_layout->portBox, SIGNAL(valueChanged(int)), this, SLOT(slotPortChanged(int))); + connect(m_layout->anonLogin, SIGNAL(clicked()), this, SLOT(slotAnonClicked())); + connect(m_layout->recentConnections, SIGNAL(activated(int)), this, SLOT(slotRecentConnectionActivated(int))); + connect(m_layout->clearRecent, SIGNAL(clicked()), this, SLOT(slotClearRecentClicked())); + + // Init url + m_url.setProtocol("ftp"); + m_url.setPort(21); + m_url.setPath("/"); + m_layout->urlBox->setURL(m_url); + + // Use anonymous account by default + m_layout->anonLogin->setChecked(true); + slotAnonClicked(); + + // Init the protocol advanced button + m_layout->protoAdvanced->setEnabled(false); + + // Populate charsets + QStringList charsets = KGlobal::charsets()->descriptiveEncodingNames(); + m_layout->serverEncoding->insertStringList(charsets); + + QString defEncoding = KFTPCore::Config::defEncoding(); + defEncoding = QString("%1 ( %2 )").arg(KGlobal::charsets()->languageForEncoding(defEncoding)).arg(defEncoding); + m_layout->serverEncoding->setCurrentText(defEncoding); + + // Populate recent sites + int index = 0; + QStringList recentSites = KFTPCore::Config::recentSites(); + for (QStringList::Iterator i = recentSites.begin(); i != recentSites.end(); ++i) { + KURL siteUrl = KURL(*i); + + m_recentSites[index] = siteUrl; + m_layout->recentConnections->insertItem(siteUrl.prettyURL(), index++); + } + + slotRecentConnectionActivated(0); +} + +QuickConnectDialog::~QuickConnectDialog() +{ + if (m_protocolAdvancedDialog) + delete m_protocolAdvancedDialog; +} + +void QuickConnectDialog::slotRecentConnectionActivated(int index) +{ + KURL url = m_recentSites[index]; + m_layout->urlBox->setText(url.url()); + + if (m_url.user() == "anonymous") { + m_layout->anonLogin->setChecked(true); + slotAnonClicked(); + } +} + +void QuickConnectDialog::slotClearRecentClicked() +{ + if (KMessageBox::questionYesNo(0, i18n("Clear list of recently accessed sites ?")) == KMessageBox::No) + return; + + m_layout->recentConnections->clear(); + m_recentSites.clear(); + KFTPCore::Config::setRecentSites(QStringList()); +} + +void QuickConnectDialog::slotUrlChanged(const QString &text) +{ + if (m_noUrlChange) + return; + + m_layout->anonLogin->setChecked(false); + m_layout->usernameBox->setEnabled(true); + m_layout->passwordBox->setEnabled(true); + + KURL tmpUrl = text; + if (!tmpUrl.isValid()) + return; + else + m_url = tmpUrl; + + m_noUrlChange = true; + + if (m_url.protocol() == "ftp") + m_layout->protocolBox->setCurrentItem(SP_FTP); + else if (m_url.protocol() == "sftp") + m_layout->protocolBox->setCurrentItem(SP_SFTP); + else { + // Force FTP protocol + m_url.setProtocol("ftp"); + m_layout->protocolBox->setCurrentItem(SP_FTP); + } + + m_layout->hostBox->setText(m_url.host()); + m_layout->usernameBox->setText(m_url.user()); + + if (m_url.hasPass()) { + m_layout->passwordBox->erase(); + m_layout->passwordBox->insert(m_url.pass()); + } + + if (m_url.port() == 0) { + switch (m_layout->protocolBox->currentItem()) { + case SP_SFTP: { + m_layout->portBox->setValue(22); + m_url.setPort(22); + break; + } + default: { + m_layout->portBox->setValue(21); + m_url.setPort(21); + break; + } + } + } else { + m_layout->portBox->setValue(m_url.port()); + } + + m_layout->urlBox->setText(m_url.prettyURL()); + m_noUrlChange = false; +} + +void QuickConnectDialog::slotHostChanged(const QString &text) +{ + if (m_noUrlChange) return; + + m_noUrlChange = true; + m_url.setHost(text); + m_layout->urlBox->setURL(m_url); + m_noUrlChange = false; +} + +void QuickConnectDialog::slotPortChanged(int port) +{ + if (m_noUrlChange) return; + + m_noUrlChange = true; + m_url.setPort(port); + m_layout->urlBox->setURL(m_url); + m_portChanged = true; + m_noUrlChange = false; +} + +void QuickConnectDialog::slotUserChanged() +{ + if (m_noUrlChange) return; + + m_noUrlChange = true; + m_url.setUser(m_layout->usernameBox->text()); + m_layout->urlBox->setURL(m_url); + m_noUrlChange = false; +} + +void QuickConnectDialog::slotPassChanged() +{ + if (m_noUrlChange) return; + + m_noUrlChange = true; + m_url.setPass(m_layout->passwordBox->password()); + m_layout->urlBox->setURL(m_url); + m_noUrlChange = false; +} + +void QuickConnectDialog::slotAnonClicked() +{ + static QString tmpUser, tmpPass; + + if (m_layout->anonLogin->isChecked()) { + m_layout->usernameBox->setEnabled(false); + m_layout->passwordBox->setEnabled(false); + tmpUser = m_layout->usernameBox->text(); + tmpPass = m_layout->passwordBox->text(); + m_layout->usernameBox->setText("anonymous"); + m_layout->passwordBox->erase(); + + // Use the appropriate e-mail address for anonymous accounts + if (!KFTPCore::Config::anonMail().isEmpty()) + m_layout->passwordBox->insert(KFTPCore::Config::anonMail()); + else + m_layout->passwordBox->insert("userlogin@anonymo.us"); + } else { + m_layout->usernameBox->setText(tmpUser); + m_layout->passwordBox->erase(); + m_layout->passwordBox->insert(tmpPass); + m_layout->usernameBox->setEnabled(true); + m_layout->passwordBox->setEnabled(true); + } + + slotUserChanged(); + slotPassChanged(); +} + +void QuickConnectDialog::slotOk() +{ + // Construct a nice error message + QString errorMessage; + + if (m_url.host().isEmpty()) + errorMessage = i18n("a hostname"); + + if (m_url.port() < 1) + errorMessage += (errorMessage.isEmpty() ? QString::null : QString::fromLatin1(", ")) + i18n("a valid port"); + + if (m_url.user().isEmpty()) + errorMessage += (errorMessage.isEmpty() ? QString::null : QString::fromLatin1(", ")) + i18n("your username"); + + if (m_url.pass().isEmpty()) + errorMessage += (errorMessage.isEmpty() ? QString::null : QString::fromLatin1(", ")) + i18n("your password"); + + if (errorMessage.findRev(",") != -1) + errorMessage = errorMessage.replace(errorMessage.findRev(","), 1 , i18n(" and")); + + if (!errorMessage.isEmpty()) { + KMessageBox::sorry(0, i18n("Please enter ") + errorMessage + "."); + return; + } + + if (m_layout->addBookmark->isChecked()) { + // Add the current connection to bookmarks. Use hostname as the bookmark name. + KFTPBookmarks::Site *root = KFTPBookmarks::Manager::self()->findCategory("root"); + KFTPBookmarks::Site *site = root->addSite(); + site->setAttribute("name", m_url.host()); + + site->setProperty("host", m_url.host()); + site->setProperty("port", m_url.port()); + site->setProperty("username", m_url.user()); + site->setProperty("password", encodePassword(m_url.pass())); + site->setProperty("defremotepath", "/"); + site->setProperty("protocol", m_layout->protocolBox->currentItem() == SP_SFTP ? "sftp" : "ftp"); + site->setProperty("use_tls", m_layout->protocolBox->currentItem() == SP_SSL_EXPLICIT); + site->setProperty("use_implicit", m_layout->protocolBox->currentItem() == SP_SSL_IMPLICIT); + site->setProperty("encoding", KGlobal::charsets()->encodingForName(m_layout->serverEncoding->currentText())); + + // Save TLS options + if (m_protocolAdvancedDialog) { + site->setProperty("tls_data_mode", m_protocolAdvancedDialog->getTLSMode()); + site->setProperty("use_cert", m_protocolAdvancedDialog->isCertChecked()); + + if (m_protocolAdvancedDialog->isCertChecked()) + site->setProperty("tls_cert_path", m_protocolAdvancedDialog->getCertPath()); + } + + KFTPBookmarks::Manager::self()->emitUpdate(); + } + + // Save to recent sites + QStringList recentSites = KFTPCore::Config::recentSites(); + if (m_url.user() == "anonymous") + m_url.setPass(""); + + if (recentSites.findIndex(m_url.url()) == -1) { + recentSites.prepend(m_url.url()); + + if (recentSites.count() > 10) + recentSites.pop_back(); + + KFTPCore::Config::setRecentSites(recentSites); + } + + // Close the dialog + accept(); +} + +void QuickConnectDialog::setupClient(KFTPEngine::Thread *client) +{ + // First activate the correct socket and reset the old flags + client->selectSocketForProtocol(KURL(QString("%1://test/").arg(m_layout->protocolBox->currentItem() == SP_SFTP ? "sftp" : "ftp"))); + client->socket()->initConfig(); + + client->socket()->setConfig("retry", 0); + + client->socket()->setConfig("ssl.use_tls", m_layout->protocolBox->currentItem() == SP_SSL_EXPLICIT); + client->socket()->setConfig("ssl.use_implicit", m_layout->protocolBox->currentItem() == SP_SSL_IMPLICIT); + client->socket()->setConfig("encoding", KGlobal::charsets()->encodingForName(m_layout->serverEncoding->currentText())); + + // Set TLS options + if (m_protocolAdvancedDialog) { + client->socket()->setConfig("ssl.prot_mode", m_protocolAdvancedDialog->getTLSMode()); + + // Should we use a X509 certificate ? + if (m_protocolAdvancedDialog->isCertChecked() && m_layout->protocolBox->currentItem() == SP_FTP) { + // Ask the user for the decryption password + QCString certPass; + KPasswordDialog::getPassword(certPass, i18n("Please provide your X509 certificate decryption password.")); + + static_cast<KFTPEngine::FtpSocket*>(client->socket())->setSslClientCertificate(KSSLPKCS12::loadCertFile(m_protocolAdvancedDialog->getCertPath(), certPass)); + } + } +} + +void QuickConnectDialog::slotProtocolChanged(int item) +{ + if (m_noUrlChange) return; + + // Enable/Disable the SSL/TLS settings if needed + m_layout->protoAdvanced->setEnabled( item == SP_SSL_EXPLICIT || item == SP_SSL_IMPLICIT ); + + // Set the default port + if (!m_portChanged) { + switch (item) { + case SP_SSL_IMPLICIT: + if (m_layout->portBox->value() == 21 || m_layout->portBox->value() == 22) + m_layout->portBox->setValue(993); + break; + case SP_SFTP: + if (m_layout->portBox->value() == 21 || m_layout->portBox->value() == 993) + m_layout->portBox->setValue(22); + break; + default: + if (m_layout->portBox->value() == 22 || m_layout->portBox->value() == 993) + m_layout->portBox->setValue(21); + break; + } + + m_portChanged = false; + } + + m_noUrlChange = true; + m_url.setProtocol( item == SP_SFTP ? "sftp" : "ftp"); + m_url.setPort( m_layout->portBox->value() ); + m_layout->urlBox->setURL(m_url); + m_noUrlChange = false; +} + +void QuickConnectDialog::slotProtoAdvancedClicked() +{ + if (!m_protocolAdvancedDialog) + m_protocolAdvancedDialog = new KFTPWidgets::Bookmarks::BookmarkEditorTLS(this); + + QChar tlsMode = m_protocolAdvancedDialog->getTLSMode(); + bool certChecked = m_protocolAdvancedDialog->isCertChecked(); + QString certPath = m_protocolAdvancedDialog->getCertPath(); + m_protocolAdvancedDialog->slotChangeActiveX509Group(); + + if (!m_protocolAdvancedDialog->exec()) { + m_protocolAdvancedDialog->setTLSMode(tlsMode); + m_protocolAdvancedDialog->setCertChecked(certChecked); + m_protocolAdvancedDialog->setCertPath(certPath); + m_protocolAdvancedDialog->slotChangeActiveX509Group(); + } +} + +QChar QuickConnectDialog::getTLSMode() +{ + if (!m_protocolAdvancedDialog) + return false; + + return m_protocolAdvancedDialog->getTLSMode(); +} + +bool QuickConnectDialog::isCertChecked() +{ + if (!m_protocolAdvancedDialog) + return false; + + return m_protocolAdvancedDialog->isCertChecked(); +} + +QString QuickConnectDialog::getCertPath() +{ + if (!m_protocolAdvancedDialog) + return QString::null; + + return m_protocolAdvancedDialog->getCertPath(); +} + +int QuickConnectDialog::getFTPMode() +{ + return m_layout->protocolBox->currentItem(); +} + +void QuickConnectDialog::setHost(const QString &host) +{ + m_layout->hostBox->setText(host); +} + +void QuickConnectDialog::setPort(int port) +{ + m_layout->portBox->setValue(port); +} + +void QuickConnectDialog::setFocusToUser() +{ + m_layout->usernameBox->setFocus(); +} + +} + +#include "quickconnect.moc" diff --git a/kftpgrabber/src/widgets/quickconnect.h b/kftpgrabber/src/widgets/quickconnect.h new file mode 100644 index 0000000..ad88212 --- /dev/null +++ b/kftpgrabber/src/widgets/quickconnect.h @@ -0,0 +1,162 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004 Markus Brueffer <markus@brueffer.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSQUICKCONNECT_H +#define KFTPWIDGETSQUICKCONNECT_H + +#include "kftpquickconnectlayout.h" + +#include <qmap.h> + +#include <kdialogbase.h> +#include <kurl.h> + +namespace KFTPEngine { + class Thread; +} + +namespace KFTPWidgets { + +namespace Bookmarks { + class BookmarkEditorTLS; +} + +/** + * @author Jernej Kos + */ +class QuickConnectDialog : public KDialogBase +{ +Q_OBJECT +public: + QuickConnectDialog(QWidget *parent = 0, const char *name = 0); + ~QuickConnectDialog(); + + /** + * Get URL the user is trying to connect to. + * + * @return a KURL representing the destination server + */ + KURL getUrl() { return m_url; } + + /** + * Get the currently selected file transfer protocol. + * + * @return index of currently selected protocol + */ + int getFTPMode(); + + /** + * Get the currently set TLS operation mode. + * + * @return currently set TLS operation mode + */ + QChar getTLSMode(); + + /** + * Is the "use custom X509 certificate" checked or not. + * + * @return true if the "use custom X509 certificate" is checked + */ + bool isCertChecked(); + + /** + * Get the currently set X509 certificate path. + * + * @return path to the user's X509 certificate for this connection + */ + QString getCertPath(); + + /** + * Set the destination server's hostname. + * + * @param host destination server's hostname + */ + void setHost(const QString &host); + + /** + * Set the destination server's port. + * + * @param port destination server's port + */ + void setPort(int port); + + /** + * Focus the dialog's username input field. + */ + void setFocusToUser(); + + /** + * Configures the client acoording to the settings chosen in the quick connect + * dialog. + * + * @param client a disconnected client socket + */ + void setupClient(KFTPEngine::Thread *client); +private: + enum ServerProtocol { + SP_FTP = 0, + SP_SSL_EXPLICIT, + SP_SSL_IMPLICIT, + SP_SFTP + }; + + KFTPQuickConnectLayout *m_layout; + + bool m_noUrlChange; + KURL m_url; + Bookmarks::BookmarkEditorTLS *m_protocolAdvancedDialog; + + bool m_portChanged; + + QMap<int, KURL> m_recentSites; +private slots: + virtual void slotOk(); + + void slotUrlChanged(const QString &); + void slotHostChanged(const QString&); + void slotPortChanged(int); + void slotUserChanged(); + void slotPassChanged(); + void slotAnonClicked(); + void slotProtocolChanged(int); + void slotProtoAdvancedClicked(); + void slotRecentConnectionActivated(int index); + void slotClearRecentClicked(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/searchdialog.cpp b/kftpgrabber/src/widgets/searchdialog.cpp new file mode 100644 index 0000000..ade32c3 --- /dev/null +++ b/kftpgrabber/src/widgets/searchdialog.cpp @@ -0,0 +1,165 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "widgets/searchdialog.h" +#include "kftpsearchlayout.h" +#include "kftpserverlineedit.h" +#include "kftpbookmarks.h" +#include "kftpqueue.h" + +#include <qcheckbox.h> +#include <qgroupbox.h> +#include <qspinbox.h> +#include <qregexp.h> + +#include <klocale.h> +#include <klineedit.h> +#include <kpassdlg.h> + +namespace KFTPWidgets { + +SearchDialog::SearchDialog(QWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("Search & Replace"), Ok|Cancel, Ok) +{ + // Create the main widget + m_layout = new KFTPSearchLayout(this); + + // Set the dialog options + setMainWidget(m_layout); + setInitialSize(QSize(500,400)); + + connect(m_layout->searchServer, SIGNAL(clicked()), this, SLOT(slotSearchServerClicked())); + connect(m_layout->searchServerName, SIGNAL(siteChanged(KFTPBookmarks::Site*)), this, SLOT(slotSiteChanged(KFTPBookmarks::Site*))); +} + +QString SearchDialog::replaceCap(QStringList cap, const QString &text) +{ + QString tmp = text; + + QStringList::Iterator end( cap.end() ); + for(QStringList::Iterator i( cap.begin() ); i != end; ++i) { + tmp.replace("$" + QString::number(cap.findIndex(*i)), *i); + } + + return tmp; +} + +void SearchDialog::replace(KFTPQueue::Transfer *i) +{ + QRegExp s, d; + + s.setPattern(m_layout->searchSrcPath->text()); + d.setPattern(m_layout->searchDstPath->text()); + + KURL tmp = i->getSourceUrl().isLocalFile() ? i->getDestUrl() : i->getSourceUrl(); + tmp.setPath("/"); + + KURL match; + match.setProtocol("ftp"); + match.setHost(m_layout->searchServerHost->text()); + match.setPort(m_layout->searchServerPort->value()); + match.setUser(m_layout->searchServerUser->text()); + match.setPass(m_layout->searchServerPass->password()); + match.setPath("/"); + + if (s.search(i->getSourceUrl().path()) != -1 && d.search(i->getDestUrl().path()) != -1 && + (!m_layout->searchServer->isChecked() || tmp.url() == match.url())) { + // Do the replacing + KURL newSource = i->getSourceUrl(); + KURL newDest = i->getDestUrl(); + + newSource.setPath(replaceCap(s.capturedTexts(), m_layout->replaceSrcPath->text())); + newDest.setPath(replaceCap(d.capturedTexts(), m_layout->replaceDstPath->text())); + + i->setSourceUrl(newSource); + i->setDestUrl(newDest); + + i->emitUpdate(); + } +} + +void SearchDialog::searchAndReplace(KFTPQueue::QueueObject *parent) +{ + if (parent->isLocked()) + return; + + QPtrList<KFTPQueue::QueueObject> list = parent->getChildrenList(); + + KFTPQueue::QueueObject *i; + for (i = list.first(); i; i = list.next()) { + if (i->hasChildren() && !i->isLocked()) { + searchAndReplace(i); + } + + if (i->isTransfer() && !i->isLocked()) + replace(static_cast<KFTPQueue::Transfer*>(i)); + } +} + +void SearchDialog::searchAndReplace() +{ + searchAndReplace(KFTPQueue::Manager::self()->topLevelObject()); +} + +void SearchDialog::slotOk() +{ + searchAndReplace(); + accept(); +} + +void SearchDialog::slotSearchServerClicked() +{ + m_layout->groupBox1->setEnabled(m_layout->searchServer->isChecked()); +} + +void SearchDialog::slotSiteChanged(KFTPBookmarks::Site *site) +{ + if (site) { + m_layout->searchServerHost->setText(site->getProperty("host")); + m_layout->searchServerPort->setValue(site->getIntProperty("port")); + m_layout->searchServerUser->setText(site->getProperty("username")); + m_layout->searchServerPass->erase(); + m_layout->searchServerPass->insert(site->getProperty("password")); + } else { + m_layout->searchServerHost->clear(); + m_layout->searchServerPort->setValue(21); + m_layout->searchServerUser->clear(); + m_layout->searchServerPass->erase(); + } +} + +} + +#include "searchdialog.moc" diff --git a/kftpgrabber/src/widgets/searchdialog.h b/kftpgrabber/src/widgets/searchdialog.h new file mode 100644 index 0000000..7ae598b --- /dev/null +++ b/kftpgrabber/src/widgets/searchdialog.h @@ -0,0 +1,85 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2004 by the KFTPGrabber developers + * Copyright (C) 2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSSEARCHDIALOG_H +#define KFTPWIDGETSSEARCHDIALOG_H + +#include <qdom.h> +#include <kdialogbase.h> + +namespace KFTPQueue { + class Transfer; + class QueueObject; +} + +namespace KFTPBookmarks { + class Site; +} + +class KFTPSearchLayout; + +namespace KFTPWidgets { + +/** + * This dialog provides search & replace functionality for queued transfers. + * + * @author Jernej Kos + */ +class SearchDialog : public KDialogBase +{ +Q_OBJECT +public: + /** + * Class constructor. + */ + SearchDialog(QWidget *parent = 0, const char *name = 0); +private: + KFTPSearchLayout *m_layout; + + void replace(KFTPQueue::Transfer *i); + + QString replaceCap(QStringList cap, const QString &text); + void searchAndReplace(KFTPQueue::QueueObject *parent); + void searchAndReplace(); +private slots: + virtual void slotOk(); + + void slotSearchServerClicked(); + void slotSiteChanged(KFTPBookmarks::Site *site); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/sidebar.cpp b/kftpgrabber/src/widgets/sidebar.cpp new file mode 100644 index 0000000..bd7545b --- /dev/null +++ b/kftpgrabber/src/widgets/sidebar.cpp @@ -0,0 +1,393 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004-2005 Max Howell <max.howell@methylblue.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "misc.h" +#include "sidebar.h" +#include "multitabbar.h" + +#include <kapplication.h> +#include <kconfig.h> +#include <kiconloader.h> +#include <klocale.h> + +#include <qcursor.h> +#include <qpainter.h> +#include <qsignalmapper.h> +#include <qstyle.h> + +namespace KFTPWidgets { + +class Splitter : public QWidget { +public: + Splitter(Sidebar *w) + : QWidget(w, "divider"), + m_position(w->m_position) + { + if (m_position == Sidebar::Left) + setCursor(QCursor(SplitHCursor)); + else + setCursor(QCursor(SplitVCursor)); + + styleChange(style()); + } + + virtual void paintEvent(QPaintEvent*) + { + QPainter p(this); + parentWidget()->style().drawPrimitive(QStyle::PE_Splitter, &p, rect(), colorGroup(), m_position == Sidebar::Left ? QStyle::Style_Horizontal : 0); + } + + virtual void styleChange(QStyle&) + { + if (m_position == Sidebar::Left) + setFixedWidth(style().pixelMetric(QStyle::PM_SplitterWidth, this)); + else + setFixedHeight(style().pixelMetric(QStyle::PM_SplitterWidth, this)); + } + + virtual void mouseMoveEvent(QMouseEvent *e) + { + static_cast<Sidebar*>(parent())->mouseMovedOverSplitter(e); + } +private: + Sidebar::Position m_position; +}; + +Sidebar::Sidebar(QWidget *parent, Position position) + : QWidget(parent, "Sidebar"), + m_position(position), + m_divider(new KFTPWidgets::Splitter(this)), + m_content(new QVBox(this)), + m_tabBar(new MultiTabBar(position == Left ? MultiTabBar::Vertical : MultiTabBar::Horizontal, this)), + m_sidebarBox(new QWidget(this)), + m_currentIndex(-1), + m_lastIndex(-1), + m_mapper(new QSignalMapper(this)) +{ + m_tabBar->setStyle(MultiTabBar::AMAROK); + m_tabBar->setPosition(m_position == Left ? MultiTabBar::Left : MultiTabBar::Bottom); + m_tabBar->showActiveTabTexts(true); + + if (m_position == Left) { + m_pos = m_tabBar->sizeHint().width() + 5; + + m_tabBar->setFixedWidth(m_pos); + m_tabBar->move(0, 3); + + QVBoxLayout *layout = new QVBoxLayout(m_sidebarBox); + layout->addSpacing(3); + layout->setAutoAdd(true); + + m_sidebarBox->move(m_pos, 0); + m_sidebarBox->hide(); + m_divider->hide(); + m_content->setSpacing(1); + } else { + m_pos = m_tabBar->sizeHint().height() + 5; + m_tabBar->setFixedHeight(m_pos); + + QVBoxLayout *layout = new QVBoxLayout(m_sidebarBox); + layout->setAutoAdd(true); + + m_sidebarBox->hide(); + m_divider->hide(); + m_content->setSpacing(1); + } + + connect(m_mapper, SIGNAL(mapped(int)), SLOT(showHideSidebar(int))); +} + +void Sidebar::setVisible(bool visible) +{ + if (m_position == Left) { + m_pos = m_tabBar->sizeHint().width() + 5; + m_tabBar->setFixedWidth(visible ? m_pos : 0); + } else { + m_pos = m_tabBar->sizeHint().height() + 5; + m_tabBar->setFixedHeight(visible ? m_pos : 0); + } + + if (m_currentIndex != -1) + showHideSidebar(m_currentIndex); + + if (visible) + m_tabBar->show(); + else + m_tabBar->hide(); + + adjustWidgetSizes(); +} + +Sidebar::~Sidebar() +{ + KConfig *config; + // Save the currently selected sidebar + if (m_position == Left) { + config = KFTPGrabberBase::config(QString("Sidebar_%1").arg("Left")); + } else { + config = KFTPGrabberBase::config(QString("Sidebar_%1").arg("Bottom")); + } + if (m_currentIndex != -1) { + config->writeEntry("CurrentSidebar", currentSidebar()->name()); + } else { + config->writeEntry("CurrentSidebar", QString::null); + } + if (m_position == Left) { + config->writeEntry("Size", m_sidebarBox->width()); + } else { + config->writeEntry("Size", m_sidebarBox->height()); + } +} + +void Sidebar::polish() +{ + QWidget::polish(); + + KConfig *config = KFTPGrabberBase::config(QString("Sidebar_%1").arg(m_position == Left ? "Left" : "Bottom")); + const int index = indexForName(config->readEntry("CurrentSidebar")); + + if (m_position == Left) { + uint M = 0; + for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) { + const uint m = (*it)->minimumWidth(); + if (m > M) M = m; + } + + const int width = config->readNumEntry("Size", sidebar(index)->sizeHint().width()); + + if (M > 250) { + M = 250; + } + + m_sidebarBox->setMinimumWidth(M); + m_sidebarBox->resize(width, height()); + } else { + uint M = 0; + for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) { + const uint m = (*it)->minimumHeight(); + if (m > M) M = m; + } + + const int height = config->readNumEntry("Size", sidebar(index)->height()); + + if (M > 250) { + M = 250; + } + + m_sidebarBox->setMinimumHeight(M); + m_sidebarBox->resize(width(), height); + } + + // If any sidebar should be open, open it + if (index != -1) + showHideSidebar(index); +} + +void Sidebar::adjustWidgetSizes() +{ + if (m_position == Left) { + const uint w = width(); + const uint h = height(); + const uint mxW = maxSidebarWidth(); + const uint p = (m_pos < mxW) ? m_pos : mxW; + const uint ppw = p + m_divider->width(); + const uint tbw = m_tabBar->width(); + + m_divider->move(p, 0); + + const uint offset = !m_divider->isHidden() ? ppw : tbw; + + m_sidebarBox->resize(p - tbw, h); + m_content->setGeometry(offset, 0, w - offset, h); + } else { + const uint w = width(); + const uint h = height(); + const uint mxH = maxSidebarHeight(); + const uint p = (m_pos < mxH) ? m_pos : mxH; + const uint pph = p + m_divider->height(); + const uint tbh = m_tabBar->height(); + + m_divider->move(0, h - pph); + + const uint offset = !m_divider->isHidden() ? pph : tbh; + + m_sidebarBox->setGeometry(0, h - p, w, p - tbh); + m_content->setGeometry(0, 0, w, h - offset); + m_tabBar->move(0, h - tbh); + } +} + +void Sidebar::mouseMovedOverSplitter(QMouseEvent *e) +{ + const uint oldPos = m_pos; + uint newPos; + uint minPos; + uint maxPos; + + if (m_position == Left) { + newPos = mapFromGlobal(e->globalPos()).x(); + minPos = m_tabBar->width() + m_sidebarBox->minimumWidth(); + maxPos = maxSidebarWidth(); + } else { + newPos = height() - mapFromGlobal(e->globalPos()).y(); + minPos = m_tabBar->height() + m_sidebarBox->minimumHeight(); + maxPos = maxSidebarHeight(); + } + + if (newPos < minPos) + m_pos = minPos; + else if (newPos > maxPos) + m_pos = maxPos; + else + m_pos = newPos; + + if (m_pos != oldPos) + adjustWidgetSizes(); +} + +bool Sidebar::event(QEvent *e) +{ + switch (e->type()) { + case QEvent::LayoutHint: { + if (m_position == Left) { + setMinimumWidth(m_tabBar->minimumWidth() + m_divider->minimumWidth() + m_sidebarBox->width() + m_content->minimumWidth()); + } else { + setMinimumHeight(m_tabBar->minimumHeight() + m_divider->minimumHeight() + m_sidebarBox->height() + m_content->minimumHeight()); + } + break; + } + case QEvent::Resize: { + if (m_position == Left) { + m_divider->resize(0, height()); + m_tabBar->resize(0, height()); + } else { + m_divider->resize(width(), 0); + m_tabBar->resize(width(), 0); + } + + adjustWidgetSizes(); + return true; + } + default: break; + } + + return QWidget::event(e); +} + +void Sidebar::addSidebar(QWidget *widget, const QString &title, const QString &icon) +{ + const int id = m_tabBar->tabs()->count(); // the next available id + const QString name(widget->name()); + QWidget *tab; + + widget->reparent(m_sidebarBox, QPoint()); + widget->hide(); + + m_tabBar->appendTab(SmallIcon(icon), id, title); + tab = m_tabBar->tab(id); + tab->setFocusPolicy(QWidget::NoFocus); + + // We use a SignalMapper to show/hide the corresponding browser when tabs are clicked + connect(tab, SIGNAL(clicked()), m_mapper, SLOT(map())); + m_mapper->setMapping(tab, id); + + m_sidebars.push_back(widget); +} + +void Sidebar::showHideSidebar(int index) +{ + const int prevIndex = m_currentIndex; + + if (m_currentIndex != -1) { + // First we need to hide the currentBrowser + m_currentIndex = -1; + + m_sidebars[prevIndex]->hide(); + m_tabBar->setTab(prevIndex, false); + } + + if (index == prevIndex) { + // Close the sidebar + m_sidebarBox->hide(); + m_divider->hide(); + + adjustWidgetSizes(); + } else if ((uint) index < m_sidebars.count()) { + // Open up target + QWidget* const target = m_sidebars[index]; + m_currentIndex = index; + + m_divider->show(); + target->show(); + target->setFocus(); + m_sidebarBox->show(); + m_tabBar->setTab(index, true); + + if (prevIndex == -1) { + if (m_position == Left) { + m_pos = m_sidebarBox->width() + m_tabBar->width(); + } else { + m_pos = currentSidebar()->height() + m_tabBar->height(); + } + + adjustWidgetSizes(); + } + } +} + +QWidget *Sidebar::sidebar(const QString &name) const +{ + for (SidebarList::ConstIterator it = m_sidebars.begin(), end = m_sidebars.end(); it != end; ++it) { + if (name == (*it)->name()) + return *it; + } + + return 0; +} + +int Sidebar::indexForName(const QString &name) const +{ + for (uint x = 0; x < m_sidebars.count(); ++x) { + if (name == m_sidebars[x]->name()) + return x; + } + + return -1; +} + +} + +#include "sidebar.moc" diff --git a/kftpgrabber/src/widgets/sidebar.h b/kftpgrabber/src/widgets/sidebar.h new file mode 100644 index 0000000..4d4f710 --- /dev/null +++ b/kftpgrabber/src/widgets/sidebar.h @@ -0,0 +1,157 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.net> + * Copyright (C) 2004-2005 Max Howell <max.howell@methylblue.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; 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSSIDEBAR_H +#define KFTPWIDGETSSIDEBAR_H + +#include <qwidget.h> +#include <qvaluevector.h> + +class KURL; +class QSignalMapper; +class QVBox; + +namespace KFTPWidgets { + +typedef QValueVector<QWidget*> SidebarList; + +class MultiTabBar; +class MultiTabBarTab; + +/** + * This class provides a sidebar. It uses a customised version of KMultiTabBar for + * displaying the actual tabs. It uses a QSignalMapper to map signals from the + * tabs to the actual sidebars. + * + * This class was copied from amaroK (BrowserBar) and modified to support bottom + * sidebars as well. + * + * @author amaroK developers + * @author Jernej Kos + */ +class Sidebar : public QWidget +{ +Q_OBJECT +friend class Splitter; +public: + enum Position { + Left, + Bottom + }; + + Sidebar(QWidget *parent, Position position); + ~Sidebar(); + + /** + * Toggle visibility of this sidebar. + * + * @param visible True if the sidbar should be visible, false otherwise + */ + void setVisible(bool visible); + + /** + * Returns the content box of the sidebar. This should be where the widget, that + * should be resized when the sidebar resizes, should be placed. + * + * @return A QVBox container widget + */ + QVBox *content() { return m_content; } + + /** + * Returns the sidebar by it's name. + * + * @param name The sidebar's name + * @return A QWidget representing the sidebar or NULL if it is not found + */ + QWidget *sidebar(const QString &name) const; + + /** + * Returns the sidebar by it's index. + * + * @param index The sidebar's index + * @return A QWidget representing the sidebar or NULL if the index is invalid + */ + QWidget *sidebar(int index) const { if (index < 0) index = 0; return m_sidebars[index]; } + + /** + * Returns the currently open sidebar. + * + * @return A QWidget representing the current sidebar + */ + QWidget *currentSidebar() const { return sidebar(m_currentIndex); } + + /** + * Adds a new sidebar widget. + * + * @param widget The widget to add + * @param title The title that will be displayed on the tab + * @param icon Name of the icon that will be displayed besides the title + */ + void addSidebar(QWidget *widget, const QString &title, const QString &icon); +protected: + virtual void polish(); + virtual bool event(QEvent *e); +public slots: + void showSidebar(const QString &name) { showSidebar(indexForName(name)); } + void showSidebar(int index) { if (index != m_currentIndex) showHideSidebar(index); } + void showHideSidebar(int); + void closeCurrentSidebar() { showHideSidebar(m_currentIndex); } +private: + int indexForName(const QString&) const; + void mouseMovedOverSplitter(QMouseEvent *e); + + void adjustWidgetSizes(); + uint maxSidebarWidth() const { return width() / 2; } + uint maxSidebarHeight() const { return height() / 2; } + + Position m_position; + uint m_pos; + + QWidget *m_divider; + QVBox *m_content; + MultiTabBar *m_tabBar; + QWidget *m_sidebarBox; + + SidebarList m_sidebars; + int m_currentIndex; + int m_lastIndex; + + QSignalMapper *m_mapper; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/systemtray.cpp b/kftpgrabber/src/widgets/systemtray.cpp new file mode 100644 index 0000000..98179b7 --- /dev/null +++ b/kftpgrabber/src/widgets/systemtray.cpp @@ -0,0 +1,123 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include <kpopupmenu.h> +#include <klocale.h> +#include <kwin.h> + +#include "widgets/systemtray.h" +#include "widgets/balloon.h" +#include "mainwindow.h" +#include "mainactions.h" +#include "kftpbookmarks.h" +#include "kftpqueue.h" +#include "misc.h" +#include "misc/config.h" + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +SystemTray *SystemTray::m_self = 0L; + +SystemTray::SystemTray(MainWindow *parent) + : KSystemTray(parent), + m_balloon(0), + m_actions(parent->getActions()) +{ + m_self = this; + + // Set icon and show it + setPixmap(loadToolbarPixmap("kftpgrabber")); + + if (KFTPCore::Config::showSystrayIcon()) + show(); + + // Add some actions + m_bookmarkMenu = new KActionMenu(i18n("Bookmarks")); + slotUpdateBookmarks(); + + // Let our bookmarks be up to date + connect(KFTPBookmarks::Manager::self(), SIGNAL(update()), this, SLOT(slotUpdateBookmarks())); + + m_actions->m_fileConnectAction->plug(contextMenu(), 1); + m_bookmarkMenu->plug(contextMenu(), 1); + + // Ensure that we actually quit + connect(this, SIGNAL(quitSelected()), this, SLOT(slotQuitSelected())); +} + +SystemTray::~SystemTray() +{ + delete m_bookmarkMenu; +} + +void SystemTray::slotQuitSelected() +{ + m_actions->m_closeApp = true; +} + +void SystemTray::slotUpdateBookmarks() +{ + // Re-create the bookmarks menu + m_bookmarkMenu->popupMenu()->clear(); + KFTPBookmarks::Manager::self()->guiPopulateBookmarksMenu(m_bookmarkMenu, QDomNode(), false); +} + +void SystemTray::showBalloon(const QString &text) +{ + // Create a little modified Kopete balloon + if (m_balloon) { + m_balloon->hide(); + delete m_balloon; + } + + m_balloon = new Balloon("<qt><nobr><b>KFTPGrabber</b><br>" + text + "</nobr></qt>", "info"); + m_balloon->setAnchor(mapToGlobal(pos())); + m_balloon->show(); + KWin::setOnAllDesktops(m_balloon->winId() , true); + + // Hide the balloon after 5 sec + QTimer::singleShot(5000, this, SLOT(slotHideBalloon())); +} + +void SystemTray::slotHideBalloon() +{ + m_balloon->hide(); +} + +} + +#include "systemtray.moc" diff --git a/kftpgrabber/src/widgets/systemtray.h b/kftpgrabber/src/widgets/systemtray.h new file mode 100644 index 0000000..ce77811 --- /dev/null +++ b/kftpgrabber/src/widgets/systemtray.h @@ -0,0 +1,93 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSSYSTEMTRAY_H +#define KFTPWIDGETSSYSTEMTRAY_H + +#include <ksystemtray.h> +#include <kaction.h> + +#include <qmenudata.h> + +class MainWindow; +class MainActions; + +namespace KFTPWidgets { + +class Balloon; + +/** + * A system tray icon that is used for some actions. + * + * @author Jernej Kos + */ +class SystemTray : public KSystemTray +{ +Q_OBJECT +public: + /** + * Get the global system tray instance. + */ + static SystemTray *self() { return SystemTray::m_self; } + + /** + * Class constructor. + */ + SystemTray(MainWindow *parent); + + /** + * Class destructor. + */ + ~SystemTray(); + + /** + * Show a balloon notification widget. + */ + void showBalloon(const QString &text); +protected: + static SystemTray *m_self; +private: + KActionMenu *m_bookmarkMenu; + Balloon *m_balloon; + MainActions *m_actions; +private slots: + void slotHideBalloon(); + void slotUpdateBookmarks(); + void slotQuitSelected(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/trafficgraph.cpp b/kftpgrabber/src/widgets/trafficgraph.cpp new file mode 100644 index 0000000..ddd339f --- /dev/null +++ b/kftpgrabber/src/widgets/trafficgraph.cpp @@ -0,0 +1,628 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2004 by the KFTPGrabber developers + * Copyright (C) 2003-2004 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include <math.h> +#include <string.h> + +#include <qpainter.h> +#include <qpixmap.h> + +#include <klocale.h> + +#include "trafficgraph.h" + +namespace KFTPWidgets { + +static inline int min(int a, int b) +{ + return (a < b ? a : b); +} + +TrafficGraph::TrafficGraph(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + // Auto deletion does not work for pointer to arrays. + m_beamData.setAutoDelete(false); + + setBackgroundMode(NoBackground); + + m_samples = 0; + m_minValue = m_maxValue = 0.0; + m_useAutoRange = true; + + m_graphStyle = GRAPH_POLYGON; + + // Anything smaller than this does not make sense. + setMinimumSize(16, 100); + setSizePolicy(QSizePolicy(QSizePolicy::Expanding, + QSizePolicy::Expanding, false)); + + m_showVerticalLines = true; + m_verticalLinesColor = QColor(0x04FB1D); + m_verticalLinesDistance = 30; + m_verticalLinesScroll = true; + m_verticalLinesOffset = 0; + m_horizontalScale = 1; + + m_showHorizontalLines = true; + m_horizontalLinesColor = QColor(0x04FB1D); + m_horizontalLinesCount = 5; + + m_showLabels = true; + m_showTopBar = false; + m_fontSize = 8; + + m_backgroundColor = QColor(0x313031); +} + + +TrafficGraph::~TrafficGraph() +{ + for (double* p = m_beamData.first(); p; p = m_beamData.next()) + delete [] p; +} + +bool TrafficGraph::addBeam(const QColor &color) +{ + double* d = new double[m_samples]; + memset(d, 0, sizeof(double) * m_samples); + m_beamData.append(d); + m_beamColor.append(color); + + return true; +} + +void TrafficGraph::addSample(const QValueList<double>& sampleBuf) +{ + if (m_beamData.count() != sampleBuf.count()) + return; + + double* d; + if (m_useAutoRange) { + double sum = 0; + for (d = m_beamData.first(); d; d = m_beamData.next()) { + sum += d[0]; + if (sum < m_minValue) + m_minValue = sum; + if (sum > m_maxValue) + m_maxValue = sum; + } + } + + /* If the vertical lines are scrolling, increment the offset + * so they move with the data. The vOffset / hScale confusion + * is because v refers to Vertical Lines, and h to the horizontal + * distance between the vertical lines. */ + if (m_verticalLinesScroll) { + m_verticalLinesOffset = (m_verticalLinesOffset + m_horizontalScale) + % m_verticalLinesDistance; + } + + // Shift data buffers one sample down and insert new samples. + QValueList<double>::ConstIterator s; + for (d = m_beamData.first(), s = sampleBuf.begin(); d; d = m_beamData.next(), ++s) { + memmove(d, d + 1, (m_samples - 1) * sizeof(double)); + d[m_samples - 1] = *s; + } + + update(); +} + +void TrafficGraph::changeRange(int beam, double min, double max) +{ + // Only the first beam affects range calculation. + if (beam > 1) + return; + + m_minValue = min; + m_maxValue = max; +} + +QValueList<QColor> &TrafficGraph::beamColors() +{ + return m_beamColor; +} + +void TrafficGraph::removeBeam(uint pos) +{ + m_beamColor.remove(m_beamColor.at(pos)); + m_beamData.remove(pos); +} + +void TrafficGraph::setUseAutoRange(bool value) +{ + m_useAutoRange = value; +} + +bool TrafficGraph::useAutoRange() const +{ + return m_useAutoRange; +} + +void TrafficGraph::setMinValue(double min) +{ + m_minValue = min; +} + +double TrafficGraph::minValue() const +{ + return (m_useAutoRange ? 0 : m_minValue); +} + +void TrafficGraph::setMaxValue(double max) +{ + m_maxValue = max; +} + +double TrafficGraph::maxValue() const +{ + return (m_useAutoRange ? 0 : m_maxValue); +} + +void TrafficGraph::setGraphStyle(uint style) +{ + m_graphStyle = style; +} + +uint TrafficGraph::graphStyle() const +{ + return m_graphStyle; +} + +void TrafficGraph::setHorizontalScale(uint scale) +{ + if (scale == m_horizontalScale) + return; + + m_horizontalScale = scale; + if (isVisible()) + updateDataBuffers(); +} + +uint TrafficGraph::horizontalScale() const +{ + return m_horizontalScale; +} + +void TrafficGraph::setShowVerticalLines(bool value) +{ + m_showVerticalLines = value; +} + +bool TrafficGraph::showVerticalLines() const +{ + return m_showVerticalLines; +} + +void TrafficGraph::setVerticalLinesColor(const QColor &color) +{ + m_verticalLinesColor = color; +} + +QColor TrafficGraph::verticalLinesColor() const +{ + return m_verticalLinesColor; +} + +void TrafficGraph::setVerticalLinesDistance(int distance) +{ + m_verticalLinesDistance = distance; +} + +int TrafficGraph::verticalLinesDistance() const +{ + return m_verticalLinesDistance; +} + +void TrafficGraph::setVerticalLinesScroll(bool value) +{ + m_verticalLinesScroll = value; +} + +bool TrafficGraph::verticalLinesScroll() const +{ + return m_verticalLinesScroll; +} + +void TrafficGraph::setShowHorizontalLines(bool value) +{ + m_showHorizontalLines = value; +} + +bool TrafficGraph::showHorizontalLines() const +{ + return m_showHorizontalLines; +} + +void TrafficGraph::setHorizontalLinesColor(const QColor &color) +{ + m_horizontalLinesColor = color; +} + +QColor TrafficGraph::horizontalLinesColor() const +{ + return m_horizontalLinesColor; +} + +void TrafficGraph::setHorizontalLinesCount(int count) +{ + m_horizontalLinesCount = count; +} + +int TrafficGraph::horizontalLinesCount() const +{ + return m_horizontalLinesCount; +} + +void TrafficGraph::setShowLabels(bool value) +{ + m_showLabels = value; +} + +bool TrafficGraph::showLabels() const +{ + return m_showLabels; +} + +void TrafficGraph::setShowTopBar(bool value) +{ + m_showTopBar = value; +} + +bool TrafficGraph::showTopBar() const +{ + return m_showTopBar; +} + +void TrafficGraph::setFontSize(int size) +{ + m_fontSize = size; +} + +int TrafficGraph::fontSize() const +{ + return m_fontSize; +} + +void TrafficGraph::setBackgroundColor(const QColor &color) +{ + m_backgroundColor = color; +} + +QColor TrafficGraph::backgroundColor() const +{ + return m_backgroundColor; +} + +void TrafficGraph::resizeEvent(QResizeEvent*) +{ + updateDataBuffers(); +} + +void TrafficGraph::updateDataBuffers() +{ + /* Since the data buffers for the beams are equal in size to the + * width of the widget minus 2 we have to enlarge or shrink the + * buffers accordingly when a resize occures. To have a nicer + * display we try to keep as much data as possible. Data that is + * lost due to shrinking the buffers cannot be recovered on + * enlarging though. */ + + /* Determine new number of samples first. + * +0.5 to ensure rounding up + * +2 for extra data points so there is + * 1) no wasted space and + * 2) no loss of precision when drawing the first data point. */ + uint newSampleNum = static_cast<uint>(((width() - 2 ) / m_horizontalScale) + 2.5); + + // overlap between the old and the new buffers. + int overlap = min(m_samples, newSampleNum); + + for (uint i = 0; i < m_beamData.count(); ++i) { + double* nd = new double[newSampleNum]; + + // initialize new part of the new buffer + if (newSampleNum > (uint) overlap) + memset(nd, 0, sizeof(double) * (newSampleNum - overlap)); + + // copy overlap from old buffer to new buffer + memcpy(nd + (newSampleNum - overlap), m_beamData.at(i) + (m_samples - overlap), overlap * sizeof(double)); + + m_beamData.remove(i); + m_beamData.insert(i, nd); + } + + m_samples = newSampleNum; +} + +void TrafficGraph::paintEvent(QPaintEvent*) +{ + uint w = width(); + uint h = height(); + + /* Do not do repaints when the widget is not yet setup properly. */ + if (w <= 2) + return; + + QPixmap pm(w, h); + QPainter p; + p.begin(&pm, this); + + pm.fill(m_backgroundColor); + /* Draw white line along the bottom and the right side of the + * widget to create a 3D like look. */ + p.setPen(QColor(colorGroup().light())); + p.drawLine(0, h - 1, w - 1, h - 1); + p.drawLine(w - 1, 0, w - 1, h - 1); + + p.setClipRect(1, 1, w - 2, h - 2); + double range = m_maxValue - m_minValue; + + /* If the range is too small we will force it to 1.0 since it + * looks a lot nicer. */ + if (range < 0.000001) + range = 1.0; + + double minValue = m_minValue; + if (m_useAutoRange) { + if (m_minValue != 0.0) { + double dim = pow(10, floor(log10(fabs(m_minValue )))) / 2; + if (m_minValue < 0.0) + minValue = dim * floor(m_minValue / dim); + else + minValue = dim * ceil(m_minValue / dim); + range = m_maxValue - minValue; + if (range < 0.000001) + range = 1.0; + } + + // Massage the range so that the grid shows some nice values. + double step = range / m_horizontalLinesCount; + double dim = pow(10, floor(log10(step))) / 2; + range = dim * ceil(step / dim) * m_horizontalLinesCount; + } + + double maxValue = minValue + range; + + int top = 0; + if (m_showTopBar && h > (m_fontSize + 2 + m_horizontalLinesCount * 10)) { + /* Draw horizontal bar with current sensor values at top of display. */ + p.setPen(m_horizontalLinesColor); + int x0 = w / 2; + p.setFont(QFont(p.font().family(), m_fontSize)); + top = p.fontMetrics().height(); + h -= top; + int h0 = top - 2; + p.drawText(0, 0, x0, top - 2, Qt::AlignCenter, i18n("Bandwidth usage")); + + p.drawLine(x0 - 1, 1, x0 - 1, h0); + p.drawLine(0, top - 1, w - 2, top - 1); + + double bias = -minValue; + double scaleFac = ( w - x0 - 2 ) / range; + QValueList<QColor>::Iterator col; + col = m_beamColor.begin(); + + for (double *d = m_beamData.first(); d; d = m_beamData.next(), ++col) { + int start = x0 + (int) (bias * scaleFac); + int end = x0 + (int) ((bias += d[ w - 3 ]) * scaleFac); + + /* If the rect is wider than 2 pixels we draw only the last + * pixels with the bright color. The rest is painted with + * a 50% darker color. */ + if (end - start > 1) { + p.setPen((*col).dark(150)); + p.setBrush((*col).dark(150)); + p.drawRect(start, 1, end - start, h0); + p.setPen(*col); + p.drawLine(end, 1, end, h0); + } else if (start - end > 1) { + p.setPen((*col).dark(150)); + p.setBrush((*col).dark(150)); + p.drawRect(end, 1, start - end, h0); + p.setPen(*col); + p.drawLine(end, 1, end, h0); + } else { + p.setPen(*col); + p.drawLine(start, 1, start, h0); + } + } + } + + /* Draw scope-like grid vertical lines */ + if (m_showVerticalLines && w > 60) { + p.setPen(m_verticalLinesColor); + for (uint x = m_verticalLinesOffset; x < (w - 2); x += m_verticalLinesDistance) + p.drawLine(w - x, top, w - x, h + top - 2); + } + + /* In autoRange mode we determine the range and plot the values in + * one go. This is more efficiently than running through the + * buffers twice but we do react on recently discarded samples as + * well as new samples one plot too late. So the range is not + * correct if the recently discarded samples are larger or smaller + * than the current extreme values. But we can probably live with + * this. */ + if (m_useAutoRange) + m_minValue = m_maxValue = 0.0; + + /* Plot stacked values */ + double scaleFac = (h - 2) / range; + if (m_graphStyle == GRAPH_ORIGINAL) { + int xPos = 0; + + for (int i = 0; i < m_samples; i++, xPos += m_horizontalScale) { + double bias = -minValue; + QValueList<QColor>::Iterator col; + col = m_beamColor.begin(); + double sum = 0.0; + + for (double *d = m_beamData.first(); d; d = m_beamData.next(), ++col) { + if (m_useAutoRange) { + sum += d[i]; + if (sum < m_minValue) + m_minValue = sum; + if (sum > m_maxValue) + m_maxValue = sum; + } + + int start = top + h - 2 - (int) (bias * scaleFac); + int end = top + h - 2 - (int) ((bias + d[ i ] ) * scaleFac); + bias += d[i]; + + /* If the line is longer than 2 pixels we draw only the last + * 2 pixels with the bright color. The rest is painted with + * a 50% darker color. */ + if (end - start > 2) { + p.fillRect(xPos, start, m_horizontalScale, end - start - 1, (*col).dark(150)); + p.fillRect(xPos, end - 1, m_horizontalScale, 2, *col); + } else if (start - end > 2) { + p.fillRect(xPos, start, m_horizontalScale, end - start + 1, (*col).dark(150)); + p.fillRect(xPos, end + 1, m_horizontalScale, 2, *col); + } else + p.fillRect(xPos, start, m_horizontalScale, end - start, *col); + + } + } + } else if (m_graphStyle == GRAPH_POLYGON) { + int *prevVals = new int[m_beamData.count()]; + int hack[4]; + int x1 = w - ((m_samples + 1) * m_horizontalScale); + + for (int i = 0; i < m_samples; i++) { + QValueList<QColor>::Iterator col; + col = m_beamColor.begin(); + double sum = 0.0; + int y = top + h - 2; + int oldY = top + h; + int oldPrevY = oldY; + int height = 0; + int j = 0; + int jMax = m_beamData.count() - 1; + x1 += m_horizontalScale; + int x2 = x1 + m_horizontalScale; + + for (double *d = m_beamData.first(); d; d = m_beamData.next(), ++col, j++) { + if (m_useAutoRange) { + sum += d[i]; + + if ( sum < m_minValue ) + m_minValue = sum; + if ( sum > m_maxValue ) + m_maxValue = sum; + } + + height = (int) ((d[i] - minValue) * scaleFac); + y -= height; + + /* If the line is longer than 2 pixels we draw only the last + * 2 pixels with the bright color. The rest is painted with + * a 50% darker color. */ + QPen lastPen = QPen(p.pen()); + p.setPen((*col).dark(150)); + p.setBrush((*col).dark(150)); + QPointArray pa(4); + int prevY = (i == 0) ? y : prevVals[j]; + pa.putPoints(0, 1, x1, prevY); + pa.putPoints(1, 1, x2, y); + pa.putPoints(2, 1, x2, oldY); + pa.putPoints(3, 1, x1, oldPrevY); + p.drawPolygon(pa); + p.setPen(lastPen); + if (jMax == 0) { + // draw as normal, no deferred drawing req'd. + p.setPen(*col); + p.drawLine(x1, prevY, x2, y); + } else if (j == jMax) { + // draw previous values and current values + p.drawLine(hack[0], hack[1], hack[2], hack[3]); + p.setPen(*col); + p.drawLine(x1, prevY, x2, y); + } else if (j == 0) { + // save values only + hack[0] = x1; + hack[1] = prevY; + hack[2] = x2; + hack[3] = y; + p.setPen(*col); + } else { + p.drawLine(hack[0], hack[1], hack[2], hack[3]); + hack[0] = x1; + hack[1] = prevY; + hack[2] = x2; + hack[3] = y; + p.setPen(*col); + } + + prevVals[j] = y; + oldY = y; + oldPrevY = prevY; + } + } + + delete[] prevVals; + } + + /* Draw horizontal lines and values. Lines are drawn when the + * height is greater than 10 times hCount + 1, values are shown + * when width is greater than 60 */ + if (m_showHorizontalLines && h > (10 * (m_horizontalLinesCount + 1))) { + p.setPen(m_horizontalLinesColor); + p.setFont(QFont(p.font().family(), m_fontSize)); + QString val; + + for (uint y = 1; y < m_horizontalLinesCount; y++) { + p.drawLine(0, top + y * (h / m_horizontalLinesCount), w - 2, top + y * (h / m_horizontalLinesCount)); + + if (m_showLabels && h > (m_fontSize + 1) * (m_horizontalLinesCount + 1) && w > 60 ) { + val = QString("%1").arg(maxValue - y * (range / m_horizontalLinesCount)); + p.drawText(6, top + y * (h / m_horizontalLinesCount) - 1, val); + } + } + + if (m_showLabels && h > (m_fontSize + 1) * (m_horizontalLinesCount + 1) && w > 60) { + val = QString("%1").arg(minValue); + p.drawText(6, top + h - 2, val); + } + } + + p.end(); + bitBlt(this, 0, 0, &pm); +} + +} + +#include "trafficgraph.moc" diff --git a/kftpgrabber/src/widgets/trafficgraph.h b/kftpgrabber/src/widgets/trafficgraph.h new file mode 100644 index 0000000..3822165 --- /dev/null +++ b/kftpgrabber/src/widgets/trafficgraph.h @@ -0,0 +1,155 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPTRAFFICGRAPH_H +#define KFTPTRAFFICGRAPH_H + +#include <qpoint.h> +#include <qdialog.h> +#include <qptrlist.h> +#include <qstring.h> +#include <qvaluelist.h> + +#define GRAPH_POLYGON 0 +#define GRAPH_ORIGINAL 1 + +class QColor; + +namespace KFTPWidgets { + +/** +@author Jernej Kos +*/ +class TrafficGraph : public QWidget +{ +Q_OBJECT +public: + TrafficGraph(QWidget *parent = 0, const char *name = 0); + ~TrafficGraph(); + + bool addBeam(const QColor &color); + void addSample(const QValueList<double> &samples); + + void removeBeam(uint pos); + + void changeRange(int beam, double min, double max); + + QValueList<QColor> &beamColors(); + + void setUseAutoRange(bool value); + bool useAutoRange() const; + + void setMinValue(double min); + double minValue() const; + + void setMaxValue(double max); + double maxValue() const; + + void setGraphStyle(uint style); + uint graphStyle() const; + + void setHorizontalScale(uint scale); + uint horizontalScale() const; + + void setShowVerticalLines(bool value); + bool showVerticalLines() const; + + void setVerticalLinesColor(const QColor &color); + QColor verticalLinesColor() const; + + void setVerticalLinesDistance(int distance); + int verticalLinesDistance() const; + + void setVerticalLinesScroll(bool value); + bool verticalLinesScroll() const; + + void setShowHorizontalLines(bool value); + bool showHorizontalLines() const; + + void setHorizontalLinesColor(const QColor &color); + QColor horizontalLinesColor() const; + + void setHorizontalLinesCount(int count); + int horizontalLinesCount() const; + + void setShowLabels(bool value); + bool showLabels() const; + + void setShowTopBar(bool value); + bool showTopBar() const; + + void setFontSize(int size); + int fontSize() const; + + void setBackgroundColor(const QColor &color); + QColor backgroundColor() const; +protected: + void updateDataBuffers(); + + virtual void resizeEvent(QResizeEvent*); + virtual void paintEvent(QPaintEvent*); +private: + double m_minValue; + double m_maxValue; + bool m_useAutoRange; + + uint m_graphStyle; + + bool m_showVerticalLines; + QColor m_verticalLinesColor; + uint m_verticalLinesDistance; + bool m_verticalLinesScroll; + uint m_verticalLinesOffset; + uint m_horizontalScale; + + bool m_showHorizontalLines; + QColor m_horizontalLinesColor; + uint m_horizontalLinesCount; + + bool m_showLabels; + bool m_showTopBar; + uint m_fontSize; + + QColor m_backgroundColor; + + QPtrList<double> m_beamData; + QValueList<QColor> m_beamColor; + + int m_samples; +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/verifier.cpp b/kftpgrabber/src/widgets/verifier.cpp new file mode 100644 index 0000000..1f6c9d9 --- /dev/null +++ b/kftpgrabber/src/widgets/verifier.cpp @@ -0,0 +1,148 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#include "verifier.h" +#include "misc.h" +#include "listviewitem.h" + +#include <klocale.h> +#include <klistview.h> +#include <kmessagebox.h> +#include <kprogress.h> +#include <kurl.h> + +#include <qheader.h> +#include <qlabel.h> + +// UI layouts +#include "ui/checksum_verifier.h" + +using namespace KFTPGrabberBase; + +namespace KFTPWidgets { + +Verifier::Verifier(QWidget *parent, const char *name) + : KDialogBase(parent, name, true, i18n("Checksum verifier"), Cancel, Cancel, true), + m_verifier(0) +{ + m_layout = new VerifierLayout(this); + setMainWidget(m_layout); + + // Create columns + m_layout->fileList->addColumn(i18n("Filename")); + m_layout->fileList->addColumn(i18n("Checksum"), 100); + + m_layout->fileList->setAllColumnsShowFocus(true); + m_layout->fileList->header()->setStretchEnabled(true, 0); +} + +Verifier::~Verifier() +{ + if (m_verifier) + delete m_verifier; +} + +void Verifier::setFile(const QString &filename) +{ + // Create the verifier + m_verifier = new KFTPCore::ChecksumVerifier(filename); + m_layout->currentFile->setText(KURL(filename).fileName()); + + connect(m_verifier, SIGNAL(fileList(QValueList<QPair<QString, QString> >)), this, SLOT(slotHaveFileList(QValueList<QPair<QString, QString> >))); + connect(m_verifier, SIGNAL(fileDone(const QString&, KFTPCore::ChecksumVerifier::Result)), this, SLOT(slotFileDone(const QString&, KFTPCore::ChecksumVerifier::Result))); + connect(m_verifier, SIGNAL(progress(int)), this, SLOT(slotProgress(int))); + connect(m_verifier, SIGNAL(error()), this, SLOT(slotError())); + + // Start the verification + m_verifier->verify(); +} + +void Verifier::slotHaveFileList(QValueList<QPair<QString, QString> > list) +{ + for (QValueList<QPair<QString, QString> >::iterator i = list.begin(); i != list.end(); ++i) { + KFTPWidgets::ListViewItem *item = new KFTPWidgets::ListViewItem(m_layout->fileList); + item->setText(0, (*i).first); + item->setText(1, (*i).second); + } +} + +void Verifier::slotFileDone(const QString &filename, KFTPCore::ChecksumVerifier::Result result) +{ + KFTPWidgets::ListViewItem *item = static_cast<KFTPWidgets::ListViewItem*>(m_layout->fileList->findItem(filename, 0)); + + if (item) { + switch (result) { + case KFTPCore::ChecksumVerifier::Ok: { + item->setPixmap(0, loadSmallPixmap("ok")); + item->setTextColor(0, QColor(0, 200, 0)); + item->setTextColor(1, QColor(0, 200, 0)); + break; + } + case KFTPCore::ChecksumVerifier::NotFound: { + item->setPixmap(0, loadSmallPixmap("error")); + item->setTextColor(0, QColor(128, 128, 128)); + item->setTextColor(1, QColor(128, 128, 128)); + break; + } + case KFTPCore::ChecksumVerifier::Error: { + item->setPixmap(0, loadSmallPixmap("error")); + item->setTextColor(0, QColor(255, 0, 0)); + item->setTextColor(1, QColor(255, 0, 0)); + break; + } + } + + m_layout->fileList->ensureItemVisible(item); + } +} + +void Verifier::slotProgress(int percent) +{ + m_layout->checkProgress->setProgress(percent); + + if (percent == 100) { + KMessageBox::information(0, i18n("Verification complete!")); + } +} + +void Verifier::slotError() +{ + KMessageBox::error(0, i18n("Unable to open checksum file or file has an incorrect format!")); + close(); +} + +} +#include "verifier.moc" diff --git a/kftpgrabber/src/widgets/verifier.h b/kftpgrabber/src/widgets/verifier.h new file mode 100644 index 0000000..6f1ee1e --- /dev/null +++ b/kftpgrabber/src/widgets/verifier.h @@ -0,0 +1,74 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2005 by the KFTPGrabber developers + * Copyright (C) 2003-2005 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ + +#ifndef KFTPWIDGETSVERIFIER_H +#define KFTPWIDGETSVERIFIER_H + +#include "checksumverifier.h" + +#include <kdialogbase.h> + +#include <qvaluelist.h> +#include <qpair.h> + +class VerifierLayout; + +namespace KFTPWidgets { + +/** + * @author Jernej Kos + */ +class Verifier : public KDialogBase +{ +Q_OBJECT +public: + Verifier(QWidget *parent = 0, const char *name = 0); + ~Verifier(); + + void setFile(const QString &filename); +private: + VerifierLayout *m_layout; + KFTPCore::ChecksumVerifier *m_verifier; +private slots: + void slotHaveFileList(QValueList<QPair<QString, QString> > list); + void slotFileDone(const QString &filename, KFTPCore::ChecksumVerifier::Result result); + void slotProgress(int percent); + void slotError(); +}; + +} + +#endif diff --git a/kftpgrabber/src/widgets/widgetlister.cpp b/kftpgrabber/src/widgets/widgetlister.cpp new file mode 100644 index 0000000..55022d2 --- /dev/null +++ b/kftpgrabber/src/widgets/widgetlister.cpp @@ -0,0 +1,172 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "widgetlister.h" + +#include <klocale.h> +#include <kguiitem.h> +#include <kpushbutton.h> +#include <kdialog.h> + +#include <qpushbutton.h> +#include <qlayout.h> +#include <qhbox.h> + +namespace KFTPWidgets { + +WidgetLister::WidgetLister(QWidget *parent, int minWidgets, int maxWidgets) + : QWidget(parent) +{ + m_widgetList.setAutoDelete(true); + + m_minWidgets = QMAX(minWidgets, 0); + m_maxWidgets = QMAX(maxWidgets, m_minWidgets + 1); + + // The button box + m_layout = new QVBoxLayout(this, 0, 4); + m_buttonBox = new QHBox(this); + m_buttonBox->setSpacing(KDialog::spacingHint()); + m_layout->addWidget(m_buttonBox); + + m_buttonMore = new KPushButton(KGuiItem(i18n("more widgets", "More"), "button_more"), m_buttonBox); + m_buttonBox->setStretchFactor(m_buttonMore, 0); + + m_buttonFewer = new KPushButton(KGuiItem(i18n("fewer widgets", "Fewer"), "button_fewer"), m_buttonBox); + m_buttonBox->setStretchFactor(m_buttonFewer, 0); + + QWidget *spacer = new QWidget(m_buttonBox); + m_buttonBox->setStretchFactor(spacer, 1); + + m_buttonClear = new KPushButton(KGuiItem(i18n("clear widgets", "Clear"), "locationbar_erase"), m_buttonBox); + m_buttonBox->setStretchFactor(m_buttonClear, 0); + + // Connect signals + connect(m_buttonMore, SIGNAL(clicked()), this, SLOT(slotMore())); + connect(m_buttonFewer, SIGNAL(clicked()), this, SLOT(slotFewer())); + connect(m_buttonClear, SIGNAL(clicked()), this, SLOT(slotClear())); + + enableControls(); +} + +WidgetLister::~WidgetLister() +{ +} + +void WidgetLister::slotMore() +{ + addWidget(); + enableControls(); +} + +void WidgetLister::slotFewer() +{ + removeWidget(); + enableControls(); +} + +void WidgetLister::clear() +{ + setNumberShown(m_minWidgets); + + // Clear remaining widgets + QPtrListIterator<QWidget> i(m_widgetList); + for (i.toFirst(); i.current(); ++i) + clearWidget((*i)); + + enableControls(); + emit clearWidgets(); +} + +void WidgetLister::slotClear() +{ + clear(); +} + +void WidgetLister::addWidget(QWidget *widget) +{ + if (!widget) + widget = createWidget(this); + + m_layout->insertWidget(m_layout->findWidget(m_buttonBox), widget); + m_widgetList.append(widget); + widget->show(); + + enableControls(); + emit widgetAdded(widget); +} + +void WidgetLister::removeWidget() +{ + m_widgetList.removeLast(); + + enableControls(); + emit widgetRemoved(); +} + +void WidgetLister::clearWidget(QWidget *widget) +{ + Q_UNUSED(widget) +} + +QWidget *WidgetLister::createWidget(QWidget* parent) +{ + return new QWidget(parent); +} + +void WidgetLister::setNumberShown(int number) +{ + int superfluousWidgets = QMAX((int) m_widgetList.count() - number, 0); + int missingWidgets = QMAX(number - (int) m_widgetList.count(), 0); + + // Remove superfluous widgets + for (; superfluousWidgets; superfluousWidgets--) + removeWidget(); + + // Add missing widgets + for (; missingWidgets; missingWidgets--) + addWidget(); +} + +void WidgetLister::enableControls() +{ + int count = m_widgetList.count(); + bool isMaxWidgets = (count >= m_maxWidgets); + bool isMinWidgets = (count <= m_minWidgets); + + m_buttonMore->setEnabled(!isMaxWidgets); + m_buttonFewer->setEnabled(!isMinWidgets); +} + +} diff --git a/kftpgrabber/src/widgets/widgetlister.h b/kftpgrabber/src/widgets/widgetlister.h new file mode 100644 index 0000000..8aac58f --- /dev/null +++ b/kftpgrabber/src/widgets/widgetlister.h @@ -0,0 +1,177 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * You must obey the GNU General Public License in all respects + * for all of the code used other than OpenSSL. If you modify + * file(s) with this exception, you may extend this exception to your + * version of the file(s), but you are not obligated to do so. If you + * do not wish to do so, delete this exception statement from your + * version. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#ifndef KFTPWIDGETSWIDGETLISTER_H +#define KFTPWIDGETSWIDGETLISTER_H + +#include <qwidget.h> +#include <qptrlist.h> + +class QPushButton; +class QVBoxLayout; +class QHBox; + +namespace KFTPWidgets { + +/** + * This class has been adopted from KDEPIM with slight functional and style + * changes. + * + * @author Jernej Kos + * @author Marc Mutz <marc@mutz.com> + */ +class WidgetLister : public QWidget +{ +Q_OBJECT +public: + /** + * Class constructor. + * + * @param parent Parent widget + * @param minWidgets Minimum number of widgets in the list + * @param maxWidgets Maximum number of widgets in the list + */ + WidgetLister(QWidget* parent, int minWidgets, int maxWidgets); + + /** + * Class destructor. + */ + virtual ~WidgetLister(); + + /** + * Clears all widgets. + */ + void clear(); + + /** + * Sets the number of currently shown widgets on screen. + * + * @param number The number of widgets that should be visible + */ + virtual void setNumberShown(int number); +protected slots: + /** + * Called whenever the user clicks on the 'more' button. Reimplementations + * should call this method, because this implementation does all the dirty + * work with adding the widgets to the layout (through @ref addWidget) + * and enabling/disabling the control buttons. + */ + virtual void slotMore(); + + /** + * Called whenever the user clicks on the 'fewer' button. Reimplementations + * should call this method, because this implementation does all the dirty + * work with removing the widgets from the layout (through @ref removeWidget) + * and enabling/disabling the control buttons. + */ + virtual void slotFewer(); + + /** + * Called whenever the user clicks on the 'clear' button. Reimplementations + * should call this method, because this implementation does all the dirty + * work with removing all but @ref m_minWidgets widgets from the layout and + * enabling/disabling the control buttons. + */ + virtual void slotClear(); +protected: + /** + * Adds a single widget. Doesn't care if there are already @ref m_maxWidgets + * on screen and whether it should enable/disable any controls. It simply does + * what it is asked to do. You want to reimplement this method if you want to + * initialize the the widget when showing it on screen. Make sure you call this + * implementaion, though, since you cannot put the widget on screen from derived + * classes (@p m_layout is private). Make sure the parent of the QWidget to add is + * this WidgetLister. + * + * @param widget The widget that should be added + */ + virtual void addWidget(QWidget *widget = 0); + + /** + * Removes a single (always the last) widget. Doesn't care if there are still only + * @ref m_minWidgets left on screen and whether it should enable/disable any controls. + * It simply does what it is asked to do. You want to reimplement this method if you + * want to save the the widget's state before removing it from screen. Make sure you + * call this implementaion, though, since you should not remove the widget from + * screen from derived classes. + */ + virtual void removeWidget(); + + /** + * Called to clear a given widget. The default implementation does nothing. + * + * @param widget The widget that should be cleared + */ + virtual void clearWidget(QWidget *widget); + + /** + * This method should return a new widget to add to the widget list. + * + * @param parent The parent widget + * @return A valid QWidget + */ + virtual QWidget *createWidget(QWidget *parent); +protected: + QPtrList<QWidget> m_widgetList; + int m_minWidgets; + int m_maxWidgets; +signals: + /** + * This signal is emitted whenever a widget gets added. + */ + void widgetAdded(QWidget *widget); + + /** + * This signal is emitted whenever a widget gets removed. + */ + void widgetRemoved(); + + /** + * This signal is emitted whenever the clear button is clicked. + */ + void clearWidgets(); +private: + void enableControls(); + + QPushButton *m_buttonMore; + QPushButton *m_buttonFewer; + QPushButton *m_buttonClear; + QVBoxLayout *m_layout; + QHBox *m_buttonBox; +}; + +} + +#endif |