diff options
author | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-10 01:02:50 +0000 |
---|---|---|
committer | tpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da> | 2010-02-10 01:02:50 +0000 |
commit | c66249b79aa9bfa0924494adcd5345b5b1244b0c (patch) | |
tree | 19a77c57cc41d8b522554fbde0c36d6f20d7dc7b /src/app | |
download | gwenview-c66249b79aa9bfa0924494adcd5345b5b1244b0c.tar.gz gwenview-c66249b79aa9bfa0924494adcd5345b5b1244b0c.zip |
Added old abandoned KDE3 version of gwenview
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/gwenview@1088034 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/app')
35 files changed, 6072 insertions, 0 deletions
diff --git a/src/app/.vimrc b/src/app/.vimrc new file mode 100644 index 0000000..a37475c --- /dev/null +++ b/src/app/.vimrc @@ -0,0 +1,4 @@ +set tabstop=4 +set shiftwidth=4 +set noexpandtab +set makeprg=unsermake diff --git a/src/app/Makefile.am b/src/app/Makefile.am new file mode 100644 index 0000000..037933a --- /dev/null +++ b/src/app/Makefile.am @@ -0,0 +1,56 @@ +bin_PROGRAMS= +lib_LTLIBRARIES= + +kdeinit_LTLIBRARIES = gwenview.la + +# -D_LARGEFILE64_SOURCE is necessary on Debian Woody +AM_CPPFLAGS = -D_LARGEFILE64_SOURCE + +noinst_LTLIBRARIES = libgwenshared.la + +libgwenshared_la_SOURCES = vtabwidget.cpp + +gwenview_COMPILE_FIRST = ../gvcore/miscconfig.h ../gvcore/slideshowconfig.h ../gvcore/fileoperationconfig.h ../gvcore/fullscreenconfig.h ../gvcore/imageviewconfig.h ../gvcore/fileviewconfig.h + +gwenview_la_SOURCES = \ + bookmarkowner.cpp \ + bookmarkviewcontroller.cpp \ + bookmarkdialogbase.ui \ + bookmarkdialog.cpp \ + configfileoperationspage.ui \ + configfullscreenpage.ui \ + configimagelistpage.ui \ + configimageviewpage.ui \ + configmiscpage.ui \ + configslideshowpage.ui \ + kipiinterface.cpp \ + mainwindow.cpp \ + metaedit.cpp \ + treeview.cpp \ + dirviewcontroller.cpp \ + configdialog.cpp \ + history.cpp \ + main.cpp + +gwenview_la_LIBADD = libgwenshared.la ../gvcore/libgwenviewcore.la $(GV_LIB_KIPI) $(LIB_KUTILS) + +# the library search path. +gwenview_la_LDFLAGS = $(all_libraries) -module $(KDE_PLUGIN) + + +# set the include path for X, qt and KDE +INCLUDES = -I$(srcdir)/.. $(all_includes) + +METASOURCES = AUTO + +rcdir = $(kde_datadir)/gwenview +rc_DATA = gwenviewui.rc + + +check_PROGRAMS = testvtabwidget +testvtabwidget_SOURCES = testvtabwidget.cpp +testvtabwidget_LDADD = \ + libgwenshared.la \ + $(LIB_KUTILS) $(LIB_KFILE) $(LIB_KDEUI) $(LIB_KDECORE) $(LIB_KDEPRINT) $(LIB_QT) \ + $(LIBJPEG) +testvtabwidget_LDFLAGS = $(all_libraries) diff --git a/src/app/bookmarkdialog.cpp b/src/app/bookmarkdialog.cpp new file mode 100644 index 0000000..0572fc2 --- /dev/null +++ b/src/app/bookmarkdialog.cpp @@ -0,0 +1,115 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "bookmarkdialog.moc" +// Qt +#include <qlabel.h> + +// KDE +#include <kfile.h> +#include <kicondialog.h> +#include <klineedit.h> +#include <klocale.h> +#include <kurlrequester.h> + +// Local +#include "bookmarkdialogbase.h" +namespace Gwenview { + +class BookmarkDialogPrivate { +public: + BookmarkDialogBase* mContent; + BookmarkDialog::Mode mMode; +}; + +BookmarkDialog::BookmarkDialog(QWidget* parent, BookmarkDialog::Mode mode) +: KDialogBase(parent,"folderconfig",true,QString::null,Ok|Cancel) +{ + d=new BookmarkDialogPrivate; + d->mContent=new BookmarkDialogBase(this); + d->mMode=mode; + + setMainWidget(d->mContent); + setCaption(d->mContent->caption()); + d->mContent->mUrl->setMode(KFile::Directory); + d->mContent->mIcon->setIcon("folder"); + + connect(d->mContent->mTitle,SIGNAL(textChanged(const QString&)), + this, SLOT(updateOk())); + connect(d->mContent->mIcon,SIGNAL(iconChanged(QString)), + this, SLOT(updateOk())); + + if (mode==BOOKMARK_GROUP) { + d->mContent->mUrlLabel->hide(); + d->mContent->mUrl->hide(); + } else { + connect(d->mContent->mUrl,SIGNAL(textChanged(const QString&)), + this, SLOT(updateOk())); + } + + switch (mode) { + case BOOKMARK_GROUP: + setCaption( i18n("Add/Edit Bookmark Folder") ); + break; + case BOOKMARK: + setCaption( i18n("Add/Edit Bookmark") ); + break; + } + + updateOk(); +} + +BookmarkDialog::~BookmarkDialog() { + delete d; +} + +void BookmarkDialog::updateOk() { + bool enabled= + !d->mContent->mTitle->text().isEmpty() + && (d->mMode==BOOKMARK_GROUP || !d->mContent->mUrl->url().isEmpty()); + + enableButton(Ok, enabled); +} + +void BookmarkDialog::setIcon(const QString& icon) { + d->mContent->mIcon->setIcon(icon); +} + +QString BookmarkDialog::icon() const { + return d->mContent->mIcon->icon(); +} + +void BookmarkDialog::setTitle(const QString& title) { + d->mContent->mTitle->setText(title); +} + +QString BookmarkDialog::title() const { + return d->mContent->mTitle->text(); +} + +void BookmarkDialog::setURL(const QString& url) { + d->mContent->mUrl->setURL(url); +} + +QString BookmarkDialog::url() const { + return d->mContent->mUrl->url(); +} + +} // namespace diff --git a/src/app/bookmarkdialog.h b/src/app/bookmarkdialog.h new file mode 100644 index 0000000..46f4aaf --- /dev/null +++ b/src/app/bookmarkdialog.h @@ -0,0 +1,54 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef BOOKMARKDIALOG_H +#define BOOKMARKDIALOG_H + +// KDE includes +#include <kdialogbase.h> +namespace Gwenview { + +class BookmarkDialogPrivate; + +class BookmarkDialog : public KDialogBase { +Q_OBJECT +public: + enum Mode { BOOKMARK_GROUP, BOOKMARK }; + BookmarkDialog(QWidget* parent, Mode mode); + ~BookmarkDialog(); + + + void setIcon(const QString&); + QString icon() const; + void setTitle(const QString&); + QString title() const; + void setURL(const QString&); + QString url() const; + +protected slots: + void updateOk(); + +private: + BookmarkDialogPrivate* d; +}; + +} // namespace +#endif + diff --git a/src/app/bookmarkdialogbase.ui b/src/app/bookmarkdialogbase.ui new file mode 100644 index 0000000..4768e4f --- /dev/null +++ b/src/app/bookmarkdialogbase.ui @@ -0,0 +1,109 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>BookmarkDialogBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>BookmarkDialogBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>500</width> + <height>90</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>400</width> + <height>0</height> + </size> + </property> + <property name="caption"> + <string>Add New Branch</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>mUrlLabel</cstring> + </property> + <property name="text"> + <string>URL:</string> + </property> + </widget> + <widget class="KLineEdit" row="1" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mTitle</cstring> + </property> + </widget> + <widget class="KURLRequester" row="2" column="1" rowspan="1" colspan="2"> + <property name="name"> + <cstring>mUrl</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Title:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string>Icon:</string> + </property> + </widget> + <widget class="KIconButton" row="0" column="1"> + <property name="name"> + <cstring>mIcon</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>383</width> + <height>16</height> + </size> + </property> + </spacer> + </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/app/bookmarkowner.cpp b/src/app/bookmarkowner.cpp new file mode 100644 index 0000000..ac484e7 --- /dev/null +++ b/src/app/bookmarkowner.cpp @@ -0,0 +1,53 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// KDE +#include <kbookmarkmenu.h> + +// Local +#include "bookmarkowner.moc" +namespace Gwenview { + + +BookmarkOwner::BookmarkOwner(QWidget* parent) +: QObject(parent) +{} + + +void BookmarkOwner::openBookmarkURL(const QString& strURL) +{ + KURL url(strURL); + emit openURL(url); +} + + +QString BookmarkOwner::currentURL() const +{ + return mURL.prettyURL(); +} + + +void BookmarkOwner::setURL(const KURL& url) +{ + mURL=url; +} + +} // namespace diff --git a/src/app/bookmarkowner.h b/src/app/bookmarkowner.h new file mode 100644 index 0000000..85dab1b --- /dev/null +++ b/src/app/bookmarkowner.h @@ -0,0 +1,53 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef BOOKMARKOWNER_H +#define BOOKMARKOWNER_H + + +// KDE includes +#include <kbookmarkmanager.h> +#include <kurl.h> +namespace Gwenview { + + +class BookmarkOwner : public QObject, public KBookmarkOwner { +Q_OBJECT +public: + BookmarkOwner(QWidget* parent); + + // KBookmarkOwner interface + void openBookmarkURL(const QString&); + QString currentURL() const; + +public slots: + void setURL(const KURL&); + +signals: + void openURL(const KURL&); + +private: + KURL mURL; +}; + + +} // namespace +#endif + diff --git a/src/app/bookmarkviewcontroller.cpp b/src/app/bookmarkviewcontroller.cpp new file mode 100644 index 0000000..7fb4daa --- /dev/null +++ b/src/app/bookmarkviewcontroller.cpp @@ -0,0 +1,415 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "bookmarkviewcontroller.moc" + +#include <memory> + +// Qt +#include <qcursor.h> +#include <qheader.h> +#include <qpopupmenu.h> +#include <qtooltip.h> +#include <qvbox.h> + +// KDE +#include <kaction.h> +#include <kactioncollection.h> +#include <kbookmarkmanager.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kiconloader.h> +#include <klistview.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kmimetype.h> +#include <ktoolbar.h> +#include <kurl.h> +#include <kurldrag.h> + +// Local +#include "bookmarkdialog.h" +#include "../gvcore/fileoperation.h" + +namespace Gwenview { + +// URLDropListView +URLDropListView::URLDropListView(QWidget* parent) +: KListView(parent) { + setAcceptDrops(true); +} + + +void URLDropListView::contentsDragMoveEvent(QDragMoveEvent* event) { + if (KURLDrag::canDecode(event)) { + event->accept(); + } else { + event->ignore(); + } +} + + + + +struct BookmarkItem : public KListViewItem { + template <class ItemParent> + BookmarkItem(ItemParent* parent, const KBookmark& bookmark) + : KListViewItem(parent) + , mBookmark(bookmark) + { + refresh(); + } + + void refresh() { + setText(0, mBookmark.text() ); + setPixmap(0, SmallIcon(mBookmark.icon()) ); + } + + KBookmark mBookmark; +}; + + +class BookmarkToolTip : public QToolTip { +public: + BookmarkToolTip(KListView* lv) + : QToolTip(lv->viewport()) + , mListView(lv) {} + + void maybeTip(const QPoint& pos) { + BookmarkItem *item = static_cast<BookmarkItem*>( mListView->itemAt(pos) ); + if ( !item) return; + if (item->mBookmark.isGroup()) return; + + QRect rect=mListView->itemRect(item); + tip(rect, item->mBookmark.url().prettyURL()); + }; + + KListView* mListView; +}; + + +struct BookmarkViewController::Private { + QVBox* mBox; + KListView* mListView; + KBookmarkManager* mManager; + KURL mCurrentURL; + std::auto_ptr<BookmarkToolTip> mToolTip; + KActionCollection* mActionCollection; + KURL mDroppedURL; + + template <class ItemParent> + void addGroup(ItemParent* itemParent, const KBookmarkGroup& group) { + KBookmark bookmark=group.first(); + BookmarkItem* previousItem=0; + BookmarkItem* item=0; + for (;!bookmark.isNull(); bookmark=group.next(bookmark) ) { + if (bookmark.isSeparator()) continue; + + // Create the item and make sure it's placed at the end + previousItem=item; + item=new BookmarkItem(itemParent, bookmark); + if (previousItem) { + item->moveItem(previousItem); + } + + if (bookmark.isGroup()) { + addGroup(item, static_cast<const KBookmarkGroup&>(bookmark) ); + } + } + } + + KBookmarkGroup findBestParentGroup() { + KBookmarkGroup parentGroup; + BookmarkItem* item=static_cast<BookmarkItem*>( mListView->currentItem() ); + if (item) { + if (item->mBookmark.isGroup()) { + parentGroup=item->mBookmark.toGroup(); + } else { + parentGroup=item->mBookmark.parentGroup(); + } + } else { + parentGroup=mManager->root(); + } + + return parentGroup; + } + + void bookmarkURL(const KURL& url) { + BookmarkDialog dialog(mListView, BookmarkDialog::BOOKMARK); + dialog.setTitle(url.fileName()); + dialog.setURL(url.prettyURL()); + dialog.setIcon(KMimeType::iconForURL(url)); + if (dialog.exec()==QDialog::Rejected) return; + + KBookmarkGroup parentGroup=findBestParentGroup(); + parentGroup.addBookmark(mManager, dialog.title(), dialog.url(), dialog.icon()); + mManager->emitChanged(parentGroup); + } +}; + + +void URLDropListView::contentsDropEvent(QDropEvent* event) { + KURL::List urls; + if (!KURLDrag::decode(event, urls)) return; + emit urlDropped(event, urls); +} + + +BookmarkViewController::BookmarkViewController(QWidget* parent) +: QObject(parent) +{ + d=new Private; + d->mManager=0; + + d->mBox=new QVBox(parent); + + // Init listview + d->mListView=new URLDropListView(d->mBox); + d->mToolTip.reset(new BookmarkToolTip(d->mListView) ); + d->mActionCollection=new KActionCollection(d->mListView); + + d->mListView->header()->hide(); + d->mListView->setRootIsDecorated(true); + d->mListView->addColumn(QString::null); + d->mListView->setSorting(-1); + d->mListView->setShowToolTips(false); + d->mListView->setFullWidth(true); + + connect(d->mListView, SIGNAL(clicked(QListViewItem*)), + this, SLOT(slotOpenBookmark(QListViewItem*)) ); + connect(d->mListView, SIGNAL(returnPressed(QListViewItem*)), + this, SLOT(slotOpenBookmark(QListViewItem*)) ); + connect(d->mListView, SIGNAL(contextMenuRequested(QListViewItem*, const QPoint&, int)), + this, SLOT(slotContextMenu(QListViewItem*)) ); + connect(d->mListView, SIGNAL(urlDropped(QDropEvent*, const KURL::List&)), + this, SLOT(slotURLDropped(QDropEvent*, const KURL::List&)) ); + + // Init toolbar + KToolBar* toolbar=new KToolBar(d->mBox, "", true); + KAction* action; + toolbar->setIconText(KToolBar::IconTextRight); + action=new KAction(i18n("Add a bookmark (keep it short)", "Add"), "bookmark_add", 0, + this, SLOT(bookmarkCurrentURL()), d->mActionCollection); + action->plug(toolbar); + action=new KAction(i18n("Remove a bookmark (keep it short)", "Remove"), "editdelete", 0, + this, SLOT(deleteCurrentBookmark()), d->mActionCollection); + action->plug(toolbar); +} + + +BookmarkViewController::~BookmarkViewController() { + delete d; +} + + +void BookmarkViewController::init(KBookmarkManager* manager) { + // This method should not be called twice + Q_ASSERT(!d->mManager); + + d->mManager=manager; + // For now, we ignore the caller parameter and just refresh the full list on update + connect(d->mManager, SIGNAL(changed(const QString&, const QString&)), + this, SLOT(fill()) ); + fill(); +} + + +void BookmarkViewController::setURL(const KURL& url) { + d->mCurrentURL=url; +} + + +QWidget* BookmarkViewController::widget() const { + return d->mBox; +} + + +void BookmarkViewController::fill() { + d->mListView->clear(); + KBookmarkGroup root=d->mManager->root(); + d->addGroup(d->mListView, root); +} + + +void BookmarkViewController::slotURLDropped(QDropEvent* event, const KURL::List& urls) { + // Get a pointer to the drop item + QPoint point(0,event->pos().y()); + KListView* lst=d->mListView; + BookmarkItem* item=static_cast<BookmarkItem*>( lst->itemAt(lst->contentsToViewport(point)) ); + + QPopupMenu menu(lst); + int addBookmarkID=menu.insertItem( SmallIcon("bookmark_add"), i18n("&Add Bookmark"), + this, SLOT(slotBookmarkDroppedURL()) ); + if (urls.count()==1) { + d->mDroppedURL=*urls.begin(); + } else { + menu.setItemEnabled(addBookmarkID, false); + } + + if (item) { + menu.insertSeparator(); + KURL dest=item->mBookmark.url(); + FileOperation::fillDropURLMenu(&menu, urls, dest); + } + + menu.insertSeparator(); + menu.insertItem( SmallIcon("cancel"), i18n("Cancel") ); + menu.exec(QCursor::pos()); +} + + +void BookmarkViewController::slotBookmarkDroppedURL() { + d->bookmarkURL(d->mDroppedURL); +} + + +void BookmarkViewController::slotOpenBookmark(QListViewItem* item_) { + if (!item_) return; + BookmarkItem* item=static_cast<BookmarkItem*>(item_); + const KURL& url=item->mBookmark.url(); + if (!url.isValid()) return; + emit openURL(url); +} + + +void BookmarkViewController::slotContextMenu(QListViewItem* item_) { + BookmarkItem* item=static_cast<BookmarkItem*>(item_); + QPopupMenu menu(d->mListView); + menu.insertItem(SmallIcon("bookmark_add"), i18n("Add Bookmark..."), + this, SLOT(bookmarkCurrentURL())); + menu.insertItem(SmallIcon("bookmark_folder"), i18n("Add Bookmark Folder..."), + this, SLOT(addBookmarkGroup())); + + if (item) { + menu.insertSeparator(); + menu.insertItem(SmallIcon("edit"), i18n("Edit..."), + this, SLOT(editCurrentBookmark())); + menu.insertItem(SmallIcon("editdelete"), i18n("Delete"), + this, SLOT(deleteCurrentBookmark())); + } + menu.exec(QCursor::pos()); +} + + +void BookmarkViewController::bookmarkCurrentURL() { + d->bookmarkURL(d->mCurrentURL); +} + + +void BookmarkViewController::addBookmarkGroup() { + BookmarkDialog dialog(d->mListView, BookmarkDialog::BOOKMARK_GROUP); + if (dialog.exec()==QDialog::Rejected) return; + + KBookmarkGroup parentGroup=d->findBestParentGroup(); + KBookmarkGroup newGroup=parentGroup.createNewFolder(d->mManager, dialog.title()); + newGroup.internalElement().setAttribute("icon", dialog.icon()); + d->mManager->emitChanged(parentGroup); + QListViewItem* item=d->mListView->currentItem(); + if (item) { + item->setOpen(true); + } +} + + +void BookmarkViewController::editCurrentBookmark() { + BookmarkItem* item=static_cast<BookmarkItem*>( d->mListView->currentItem() ); + Q_ASSERT(item); + if (!item) return; + KBookmark bookmark=item->mBookmark; + bool isGroup=bookmark.isGroup(); + + BookmarkDialog dialog(d->mListView, + isGroup ? BookmarkDialog::BOOKMARK_GROUP : BookmarkDialog::BOOKMARK); + + dialog.setIcon(bookmark.icon()); + dialog.setTitle(bookmark.text()); + if (!isGroup) { + dialog.setURL(bookmark.url().prettyURL()); + } + if (dialog.exec()==QDialog::Rejected) return; + + QDomElement element=bookmark.internalElement(); + element.setAttribute("icon", dialog.icon()); + if (!isGroup) { + element.setAttribute("href", dialog.url()); + } + + // Find title element (or create it if it does not exist) + QDomElement titleElement; + QDomNode tmp=element.namedItem("title"); + if (tmp.isNull()) { + titleElement=element.ownerDocument().createElement("title"); + element.appendChild(titleElement); + } else { + titleElement=tmp.toElement(); + } + Q_ASSERT(!titleElement.isNull()); + + // Get title element content (or create) + QDomText titleText; + tmp=titleElement.firstChild(); + if (tmp.isNull()) { + titleText=element.ownerDocument().createTextNode(""); + titleElement.appendChild(titleText); + } else { + titleText=tmp.toText(); + } + Q_ASSERT(!titleText.isNull()); + + // Set title (at last!) + titleText.setData(dialog.title()); + + KBookmarkGroup group=bookmark.parentGroup(); + d->mManager->emitChanged(group); +} + + +void BookmarkViewController::deleteCurrentBookmark() { + BookmarkItem* item=static_cast<BookmarkItem*>( d->mListView->currentItem() ); + Q_ASSERT(item); + if (!item) return; + KBookmark bookmark=item->mBookmark; + + QString msg; + QString title; + if (bookmark.isGroup()) { + msg=i18n("Are you sure you want to delete the bookmark folder <b>%1</b>?<br>This will delete the folder and all the bookmarks in it.") + .arg(bookmark.text()); + title=i18n("Delete Bookmark &Folder"); + } else { + msg=i18n("Are you sure you want to delete the bookmark <b>%1</b>?") + .arg(bookmark.text()); + title=i18n("Delete &Bookmark"); + } + + int response=KMessageBox::warningContinueCancel(d->mListView, + "<qt>" + msg + "</qt>", title, + KGuiItem(title, "editdelete") + ); + if (response==KMessageBox::Cancel) return; + + KBookmarkGroup group=bookmark.parentGroup(); + group.deleteBookmark(bookmark); + d->mManager->emitChanged(group); +} + + +} // namespace diff --git a/src/app/bookmarkviewcontroller.h b/src/app/bookmarkviewcontroller.h new file mode 100644 index 0000000..bdc8050 --- /dev/null +++ b/src/app/bookmarkviewcontroller.h @@ -0,0 +1,93 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef BOOKMARKVIEWCONTROLLER_H +#define BOOKMARKVIEWCONTROLLER_H + +// Qt +#include <qobject.h> + +// KDE +#include <klistview.h> +#include <kurl.h> + +class QDragMoveEvent; +class QDropEvent; +class QListViewItem; +class QPoint; +class KBookmarkManager; +class KURL; + +namespace Gwenview { + + +/** + * A listview on which the user can drop urls + */ +class URLDropListView : public KListView { +Q_OBJECT +public: + URLDropListView(QWidget* parent); + +signals: + void urlDropped(QDropEvent*, const KURL::List&); + +protected: + virtual void contentsDragMoveEvent(QDragMoveEvent* event); + virtual void contentsDropEvent(QDropEvent* event); +}; + + +class BookmarkViewController : public QObject { +Q_OBJECT +public: + BookmarkViewController(QWidget*); + ~BookmarkViewController(); + + void init(KBookmarkManager*); + + QWidget* widget() const; + +signals: + void openURL(const KURL&); + +public slots: + void setURL(const KURL&); + +private slots: + void slotOpenBookmark(QListViewItem*); + void fill(); + void slotContextMenu(QListViewItem*); + void slotURLDropped(QDropEvent*, const KURL::List&); + void slotBookmarkDroppedURL(); + void bookmarkCurrentURL(); + void addBookmarkGroup(); + void editCurrentBookmark(); + void deleteCurrentBookmark(); + +private: + struct Private; + Private* d; +}; + + +} // namespace +#endif + diff --git a/src/app/configdialog.cpp b/src/app/configdialog.cpp new file mode 100644 index 0000000..571b6d6 --- /dev/null +++ b/src/app/configdialog.cpp @@ -0,0 +1,306 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Qt +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qmap.h> +#include <qradiobutton.h> +#include <qspinbox.h> +#include <qstylesheet.h> +#include <qtextedit.h> + +// KDE +#include <kcolorbutton.h> +#include <kconfigdialogmanager.h> +#include <kdeversion.h> +#include <kdirsize.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kio/netaccess.h> +#include <kmessagebox.h> +#include <kurllabel.h> +#include <kurlrequester.h> + +#include <config.h> +// KIPI +#ifdef GV_HAVE_KIPI +#include <libkipi/pluginloader.h> +#endif + +// Local +#include "configfileoperationspage.h" +#include "configfullscreenpage.h" +#include "configimagelistpage.h" +#include "configimageviewpage.h" +#include "configmiscpage.h" +#include "configslideshowpage.h" +#include "gvcore/captionformatter.h" +#include "gvcore/filethumbnailview.h" +// This path is different because it's a generated file, so it's stored in builddir +#include <../gvcore/miscconfig.h> +#include <../gvcore/slideshowconfig.h> +#include <../gvcore/fileoperationconfig.h> +#include <../gvcore/fullscreenconfig.h> +#include <../gvcore/imageviewconfig.h> +#include <../gvcore/fileviewconfig.h> +#include "gvcore/thumbnailloadjob.h" + +#include "configdialog.moc" +namespace Gwenview { + +typedef QValueList<KConfigDialogManager*> ConfigManagerList; + +class ConfigDialogPrivate { +public: + ConfigImageViewPage* mImageViewPage; + ConfigImageListPage* mImageListPage; + ConfigFullScreenPage* mFullScreenPage; + ConfigFileOperationsPage* mFileOperationsPage; + ConfigMiscPage* mMiscPage; + ConfigSlideshowPage* mSlideShowPage; +#ifdef GV_HAVE_KIPI + KIPI::ConfigWidget* mKIPIConfigWidget; +#endif + + ConfigManagerList mManagers; +}; + + +// Two helper functions to create the config pages +template<class T> +void addConfigPage(KDialogBase* dialog, T* content, const QString& header, const QString& name, const char* iconName) { + QFrame* page=dialog->addPage(name, header, BarIcon(iconName, 32)); + content->reparent(page, QPoint(0,0)); + QVBoxLayout* layout=new QVBoxLayout(page, 0, KDialog::spacingHint()); + layout->addWidget(content); + layout->addStretch(); +} + +template<class T> +T* addConfigPage(KDialogBase* dialog, const QString& header, const QString& name, const char* iconName) { + T* content=new T; + addConfigPage(dialog, content, header, name, iconName); + return content; +} + + +ConfigDialog::ConfigDialog(QWidget* parent, KIPI::PluginLoader* pluginLoader) +: KDialogBase( + KDialogBase::IconList, + i18n("Configure"), + KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Apply, + KDialogBase::Ok, + parent, + "ConfigDialog", + true, + true) +{ + d=new ConfigDialogPrivate; + + // Create dialog pages + d->mImageListPage = addConfigPage<ConfigImageListPage>( + this, i18n("Configure Image List"), i18n("Image List"), "view_icon"); + d->mManagers << new KConfigDialogManager(d->mImageListPage, FileViewConfig::self()); + + d->mImageViewPage = addConfigPage<ConfigImageViewPage>( + this, i18n("Configure Image View"), i18n("Image View"), "looknfeel"); + d->mManagers << new KConfigDialogManager(d->mImageViewPage, ImageViewConfig::self()); + + d->mFullScreenPage = addConfigPage<ConfigFullScreenPage>( + this, i18n("Configure Full Screen Mode"), i18n("Full Screen"), "window_fullscreen"); + d->mManagers << new KConfigDialogManager(d->mFullScreenPage, FullScreenConfig::self()); + + d->mFileOperationsPage = addConfigPage<ConfigFileOperationsPage>( + this, i18n("Configure File Operations"), i18n("File Operations"), "folder"); + d->mManagers << new KConfigDialogManager(d->mFileOperationsPage, FileOperationConfig::self()); + + d->mSlideShowPage = addConfigPage<ConfigSlideshowPage>( + this, i18n("SlideShow"), i18n("SlideShow"), "slideshow_play"); + d->mManagers << new KConfigDialogManager(d->mSlideShowPage, SlideShowConfig::self()); + +#ifdef GV_HAVE_KIPI + Q_ASSERT(pluginLoader); + d->mKIPIConfigWidget = pluginLoader->configWidget(this); + addConfigPage( + this, d->mKIPIConfigWidget, i18n("Configure KIPI Plugins"), i18n("KIPI Plugins"), "kipi"); +#else + // Avoid "unused parameter" warning + pluginLoader=pluginLoader; +#endif + + d->mMiscPage = addConfigPage<ConfigMiscPage>( + this, i18n("Miscellaneous Settings"), i18n("Misc"), "gear"); + d->mManagers << new KConfigDialogManager(d->mMiscPage, MiscConfig::self()); + // Read config, because the modified behavior might have changed + MiscConfig::self()->readConfig(); + + // Image List tab + int details=FileViewConfig::thumbnailDetails(); + d->mImageListPage->mShowFileName->setChecked(details & FileThumbnailView::FILENAME); + d->mImageListPage->mShowFileDate->setChecked(details & FileThumbnailView::FILEDATE); + d->mImageListPage->mShowFileSize->setChecked(details & FileThumbnailView::FILESIZE); + d->mImageListPage->mShowImageSize->setChecked(details & FileThumbnailView::IMAGESIZE); + + connect(d->mImageListPage->mCalculateCacheSize,SIGNAL(clicked()), + this,SLOT(calculateCacheSize())); + connect(d->mImageListPage->mEmptyCache,SIGNAL(clicked()), + this,SLOT(emptyCache())); + + // Image View tab + d->mImageViewPage->mMouseWheelGroup->setButton(ImageViewConfig::mouseWheelScroll()?1:0); + + // Full Screen tab + QTextEdit* edit=d->mFullScreenPage->kcfg_osdFormat; + edit->setMaximumHeight(edit->fontMetrics().height()*3); + connect(edit, SIGNAL(textChanged()), SLOT(updateOSDPreview()) ); + + // File Operations tab + d->mFileOperationsPage->kcfg_destDir->fileDialog()->setMode( + static_cast<KFile::Mode>(KFile::Directory | KFile::ExistingOnly | KFile::LocalOnly)); + + d->mFileOperationsPage->mDeleteGroup->setButton(FileOperationConfig::deleteToTrash()?1:0); + + ConfigManagerList::Iterator it(d->mManagers.begin()); + for (;it!=d->mManagers.end(); ++it) { + (*it)->updateWidgets(); + } + updateOSDPreview(); +} + + + +ConfigDialog::~ConfigDialog() { + delete d; +} + + +void ConfigDialog::slotOk() { + slotApply(); + accept(); +} + + +void ConfigDialog::slotApply() { + bool needSignal=false; + + // Image List tab + int details= + (d->mImageListPage->mShowFileName->isChecked() ? FileThumbnailView::FILENAME : 0) + | (d->mImageListPage->mShowFileDate->isChecked() ? FileThumbnailView::FILEDATE : 0) + | (d->mImageListPage->mShowFileSize->isChecked() ? FileThumbnailView::FILESIZE : 0) + | (d->mImageListPage->mShowImageSize->isChecked() ? FileThumbnailView::IMAGESIZE : 0) + ; + if (details!=FileViewConfig::thumbnailDetails()) { + FileViewConfig::setThumbnailDetails(details); + needSignal=true; + } + + // Image View tab + ImageViewConfig::setMouseWheelScroll( + d->mImageViewPage->mMouseWheelGroup->selected()==d->mImageViewPage->mMouseWheelScroll); + + // File Operations tab + FileOperationConfig::setDeleteToTrash( + d->mFileOperationsPage->mDeleteGroup->selected()==d->mFileOperationsPage->mDeleteToTrash); + + // KIPI tab +#ifdef GV_HAVE_KIPI + d->mKIPIConfigWidget->apply(); +#endif + + ConfigManagerList::Iterator it(d->mManagers.begin()); + for (;it!=d->mManagers.end(); ++it) { + if ((*it)->hasChanged()) { + needSignal=true; + } + (*it)->updateSettings(); + } + if (needSignal) { + emit settingsChanged(); + } +} + + +void ConfigDialog::calculateCacheSize() { + KURL url; + url.setPath(ThumbnailLoadJob::thumbnailBaseDir()); + unsigned long size=KDirSize::dirSize(url); + KMessageBox::information( this,i18n("Cache size is %1").arg(KIO::convertSize(size)) ); +} + + +void ConfigDialog::updateOSDPreview() { + CaptionFormatter formatter; + KURL url; + url.setPath(i18n("/path/to/some/image.jpg")); + formatter.mPath=url.path(); + formatter.mFileName=url.fileName(); + formatter.mComment=i18n("A comment"); + formatter.mImageSize=QSize(1600, 1200); + formatter.mPosition=4; + formatter.mCount=12; + formatter.mAperture="F2.8"; + formatter.mExposureTime="1/60 s"; + formatter.mIso="100"; + formatter.mFocalLength="8.88 mm"; + + QString txt=formatter.format( d->mFullScreenPage->kcfg_osdFormat->text() ); + d->mFullScreenPage->mOSDPreviewLabel->setText(txt); +} + + +void ConfigDialog::emptyCache() { + QString dir=ThumbnailLoadJob::thumbnailBaseDir(); + + if (!QFile::exists(dir)) { + KMessageBox::information( this,i18n("Cache is already empty.") ); + return; + } + + int response=KMessageBox::warningContinueCancel(this, + "<qt>" + i18n("Are you sure you want to empty the thumbnail cache?" + " This will delete the folder <b>%1</b>.").arg(QStyleSheet::escape(dir)) + "</qt>", + QString::null, + KStdGuiItem::del()); + + if (response==KMessageBox::Cancel) return; + + KURL url; + url.setPath(dir); + if (KIO::NetAccess::del(url, topLevelWidget()) ) { + KMessageBox::information( this,i18n("Cache emptied.") ); + } +} + + +void ConfigDialog::onCacheEmptied(KIO::Job* job) { + if ( job->error() ) { + job->showErrorDialog(this); + return; + } + KMessageBox::information( this,i18n("Cache emptied.") ); +} + +} // namespace diff --git a/src/app/configdialog.h b/src/app/configdialog.h new file mode 100644 index 0000000..58a479a --- /dev/null +++ b/src/app/configdialog.h @@ -0,0 +1,65 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef CONFIGDIALOG_H +#define CONFIGDIALOG_H + +// KDE +#include <kdialogbase.h> + +// KIPI +namespace KIPI { +class PluginLoader; +} + + +namespace Gwenview { + +class ConfigDialogPrivate; + +class ConfigDialog : public KDialogBase { +Q_OBJECT +public: + ConfigDialog(QWidget*, KIPI::PluginLoader*); + ~ConfigDialog(); + +signals: + void settingsChanged(); + +protected slots: + void slotOk(); + void slotApply(); + +private slots: + void updateOSDPreview(); + void calculateCacheSize(); + void emptyCache(); + void onCacheEmptied(KIO::Job*); + +private: + ConfigDialogPrivate* d; +}; + + + +} // namespace +#endif + diff --git a/src/app/configfileoperationspage.ui b/src/app/configfileoperationspage.ui new file mode 100644 index 0000000..b3d2f39 --- /dev/null +++ b/src/app/configfileoperationspage.ui @@ -0,0 +1,173 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigFileOperationsPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigFileOperationsPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>308</width> + <height>252</height> + </rect> + </property> + <property name="caption"> + <string>Configure File Operations</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2_2_2</cstring> + </property> + <property name="text"> + <string><b>Moving & Copying Files</b></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_confirmCopy</cstring> + </property> + <property name="text"> + <string>Show copy dialog</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_confirmMove</cstring> + </property> + <property name="text"> + <string>Show move dialog</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel2</cstring> + </property> + <property name="text"> + <string>Default destination folder:</string> + </property> + </widget> + <widget class="KURLRequester"> + <property name="name"> + <cstring>kcfg_destDir</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10_2_2_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string><b>Deleting Files</b></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_confirmDelete</cstring> + </property> + <property name="text"> + <string>Ask for confirmation</string> + </property> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>mDeleteGroup</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mDeleteToTrash</cstring> + </property> + <property name="text"> + <string>Move deleted files to the trash</string> + </property> + <property name="buttonGroupId"> + <number>1</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mReallyDelete</cstring> + </property> + <property name="text"> + <string>Really delete files (dangerous)</string> + </property> + <property name="buttonGroupId"> + <number>0</number> + </property> + </widget> + </vbox> + </widget> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kurlrequester.h</includehint> + <includehint>klineedit.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/src/app/configfullscreenpage.ui b/src/app/configfullscreenpage.ui new file mode 100644 index 0000000..c0eaeba --- /dev/null +++ b/src/app/configfullscreenpage.ui @@ -0,0 +1,144 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigFullScreenPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigFullScreenPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>516</width> + <height>411</height> + </rect> + </property> + <property name="caption"> + <string>Configure Full Screen Mode</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_showBusyPtr</cstring> + </property> + <property name="text"> + <string>Show busy mouse pointer when loading an image</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10_2_3_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel3_2</cstring> + </property> + <property name="text"> + <string><b>On Screen Display</b></string> + </property> + </widget> + <widget class="QTextEdit"> + <property name="name"> + <cstring>kcfg_osdFormat</cstring> + </property> + <property name="textFormat"> + <enum>PlainText</enum> + </property> + <property name="text"> + <string>%f - %n/%N +%c</string> + </property> + <property name="wordWrap"> + <enum>WidgetWidth</enum> + </property> + <property name="autoFormatting"> + <set>AutoNone</set> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Preview:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>mOSDPreviewLabel</cstring> + </property> + <property name="frameShape"> + <enum>LineEditPanel</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="text"> + <string>file.jpg - 1024x768 +The file comment</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string><qt> +You can use the following keywords to format the On Screen Display: +<ul> +<li>%f: filename</li> +<li>%p: filepath</li> +<li>%c: comment</li> +<li>%r: resolution</li> +<li>%n: current image position</li> +<li>%N: image count</li> +<li>%a: aperture</li> +<li>%t: exposure time</li> +<li>%i: iso</li> +<li>%l: focal length</li> +</ul> +</qt></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10_2_3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>18</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/app/configimagelistpage.ui b/src/app/configimagelistpage.ui new file mode 100644 index 0000000..7b378c7 --- /dev/null +++ b/src/app/configimagelistpage.ui @@ -0,0 +1,294 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigImageListPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigImageListPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>352</width> + <height>437</height> + </rect> + </property> + <property name="caption"> + <string>Configure Image List</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_showDirs</cstring> + </property> + <property name="text"> + <string>Show folders and archives</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><b>Thumbnail View</b></string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>Layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>TextLabel1</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Margin between thumbnails:</string> + </property> + <property name="buddy" stdset="0"> + <cstring></cstring> + </property> + </widget> + <widget class="QSpinBox"> + <property name="name"> + <cstring>kcfg_thumbnailMarginSize</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="buttonSymbols"> + <enum>UpDownArrows</enum> + </property> + <property name="maxValue"> + <number>50</number> + </property> + <property name="minValue"> + <number>2</number> + </property> + <property name="lineStep"> + <number>1</number> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>Spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Information to display in the thumbnail text:</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer7</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="0" column="1"> + <property name="name"> + <cstring>mShowFileName</cstring> + </property> + <property name="text"> + <string>File name</string> + </property> + </widget> + <widget class="QCheckBox" row="3" column="1"> + <property name="name"> + <cstring>mShowImageSize</cstring> + </property> + <property name="text"> + <string>Image size</string> + </property> + </widget> + <widget class="QCheckBox" row="2" column="1"> + <property name="name"> + <cstring>mShowFileSize</cstring> + </property> + <property name="text"> + <string>File size</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="1"> + <property name="name"> + <cstring>mShowFileDate</cstring> + </property> + <property name="text"> + <string>File date</string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer10</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string><b>Thumbnail Cache</b></string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_storeThumbnailsInCache</cstring> + </property> + <property name="text"> + <string>Store thumbnails in cache</string> + </property> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_deleteCacheOnExit</cstring> + </property> + <property name="text"> + <string>Automatically empty thumbnail cache on exit</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>mCalculateCacheSize</cstring> + </property> + <property name="text"> + <string>Calculate Cache Size</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>mEmptyCache</cstring> + </property> + <property name="text"> + <string>Empty Cache</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/app/configimageviewpage.ui b/src/app/configimageviewpage.ui new file mode 100644 index 0000000..6abbf7b --- /dev/null +++ b/src/app/configimageviewpage.ui @@ -0,0 +1,330 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigImageViewPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigImageViewPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>387</width> + <height>404</height> + </rect> + </property> + <property name="caption"> + <string>Configure Image View</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>kcfg_enlargeSmallImages</cstring> + </property> + <property name="text"> + <string>Enlarge small images when auto &zoom is activated</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Background color:</string> + </property> + </widget> + <widget class="KColorButton" row="2" column="2"> + <property name="name"> + <cstring>kcfg_backgroundColor</cstring> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer row="2" column="3" rowspan="1" colspan="3"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>181</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="3" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>textLabel1_3_2</cstring> + </property> + <property name="text"> + <string><b>Smoothing</b></string> + </property> + </widget> + <widget class="QLayoutWidget" row="4" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>kcfg_smoothAlgorithm</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mSmoothNone</cstring> + </property> + <property name="text"> + <string>None</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="buttonGroupId"> + <number>0</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mSmoothFast</cstring> + </property> + <property name="text"> + <string>Fast</string> + </property> + <property name="buttonGroupId"> + <number>1</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mSmoothNormal</cstring> + </property> + <property name="text"> + <string>Normal</string> + </property> + <property name="buttonGroupId"> + <number>2</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mSmoothBest</cstring> + </property> + <property name="text"> + <string>Best</string> + </property> + <property name="buttonGroupId"> + <number>3</number> + </property> + </widget> + </vbox> + </widget> + <widget class="Line"> + <property name="name"> + <cstring>line1</cstring> + </property> + <property name="frameShape"> + <enum>VLine</enum> + </property> + <property name="frameShadow"> + <enum>Sunken</enum> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frame3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_delayedSmoothing</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Delayed smoothing</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="margin"> + <number>3</number> + </property> + <property name="text"> + <string>Using this option, Gwenview will display the image as fast as possible, and smooth it after a short delay. +Use this option if your computer is not very fast.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignTop</set> + </property> + <property name="buddy" stdset="0"> + <cstring>mDelayedSmoothing</cstring> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <spacer row="5" column="4"> + <property name="name"> + <cstring>spacer10_2_3_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QButtonGroup" row="7" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>mMouseWheelGroup</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mMouseWheelScroll</cstring> + </property> + <property name="text"> + <string>Scroll current image</string> + </property> + <property name="buttonGroupId"> + <number>1</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mMouseWheelBrowse</cstring> + </property> + <property name="text"> + <string>Browse image list</string> + </property> + <property name="buttonGroupId"> + <number>0</number> + </property> + </widget> + </vbox> + </widget> + <widget class="QLabel" row="6" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>textLabel1_3</cstring> + </property> + <property name="text"> + <string><b>Mouse Wheel Behavior over Image</b></string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="6"> + <property name="name"> + <cstring>kcfg_showScrollBars</cstring> + </property> + <property name="text"> + <string>Show scroll bars</string> + </property> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>mSmoothNone</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_delayedSmoothing</receiver> + <slot>setDisabled(bool)</slot> + </connection> + <connection> + <sender>mSmoothNone</sender> + <signal>toggled(bool)</signal> + <receiver>textLabel1_4</receiver> + <slot>setDisabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/src/app/configmiscpage.ui b/src/app/configmiscpage.ui new file mode 100644 index 0000000..e4768f2 --- /dev/null +++ b/src/app/configmiscpage.ui @@ -0,0 +1,204 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigMiscPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigMiscPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>457</width> + <height>303</height> + </rect> + </property> + <property name="caption"> + <string>Miscellaneous Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2_2</cstring> + </property> + <property name="text"> + <string>What to do when leaving a modified image</string> + </property> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>kcfg_modifiedBehavior</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="title"> + <string></string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mModifyAsk</cstring> + </property> + <property name="text"> + <string>Ask</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="buttonGroupId"> + <number>0</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mModifySave</cstring> + </property> + <property name="text"> + <string>Save silently</string> + </property> + <property name="buttonGroupId"> + <number>1</number> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>mModifyDiscard</cstring> + </property> + <property name="text"> + <string>Discard changes</string> + </property> + <property name="buttonGroupId"> + <number>2</number> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>24</height> + </size> + </property> + </spacer> + <widget class="QCheckBox"> + <property name="name"> + <cstring>kcfg_autoRotateImages</cstring> + </property> + <property name="text"> + <string>Automatically rotate images on load</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1_2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>24</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Which settings should be remembered next time you start Gwenview</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Fixed</enum> + </property> + <property name="sizeHint"> + <size> + <width>11</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QCheckBox" row="1" column="1"> + <property name="name"> + <cstring>kcfg_rememberURL</cstring> + </property> + <property name="text"> + <string>Last opened URL</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="1"> + <property name="name"> + <cstring>kcfg_rememberFilter</cstring> + </property> + <property name="text"> + <string>State of filter</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </grid> + </widget> + <spacer> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>41</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/src/app/configslideshowpage.ui b/src/app/configslideshowpage.ui new file mode 100644 index 0000000..cb06835 --- /dev/null +++ b/src/app/configslideshowpage.ui @@ -0,0 +1,134 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>ConfigSlideshowPage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>ConfigSlideshowPage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>494</width> + <height>148</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_loop</cstring> + </property> + <property name="text"> + <string>Loop</string> + </property> + </widget> + <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_random</cstring> + </property> + <property name="text"> + <string>Show images in random order</string> + </property> + </widget> + <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_fullscreen</cstring> + </property> + <property name="text"> + <string>Start in fullscreen mode</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + <widget class="QCheckBox" row="3" column="0" rowspan="1" colspan="3"> + <property name="name"> + <cstring>kcfg_stopAtEnd</cstring> + </property> + <property name="text"> + <string>Stop on the last image of the folder</string> + </property> + <property name="whatsThis" stdset="0"> + <string>By default, if you start the slideshow from the middle of a folder, the slideshow will show all images after the start image, then all images before the start image. + +When this option is enabled, the slideshow will stop on the last image of the folder.</string> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>mDelayLabel</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Delay between images (in seconds):</string> + </property> + <property name="buddy" stdset="0"> + <cstring></cstring> + </property> + </widget> + <spacer row="4" column="2"> + <property name="name"> + <cstring>Spacer7_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>180</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KDoubleSpinBox" row="4" column="1"> + <property name="name"> + <cstring>kcfg_delay</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="lineStep"> + <number>0.1</number> + </property> + <property name="acceptLocalizedNumbers"> + <bool>false</bool> + </property> + <property name="precision"> + <number>2</number> + </property> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<connections> + <connection> + <sender>kcfg_loop</sender> + <signal>toggled(bool)</signal> + <receiver>kcfg_stopAtEnd</receiver> + <slot>setDisabled(bool)</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/src/app/dirviewcontroller.cpp b/src/app/dirviewcontroller.cpp new file mode 100644 index 0000000..c5fc538 --- /dev/null +++ b/src/app/dirviewcontroller.cpp @@ -0,0 +1,143 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Self +#include "dirviewcontroller.moc" + +// Qt +#include <qpopupmenu.h> + +// KDE +#include <kdebug.h> +#include <kiconloader.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kpropsdlg.h> + +// Local +#include <treeview.h> +#include <gvcore/fileoperation.h> + + +namespace Gwenview { + +#undef ENABLE_LOG +#undef LOG +//#define ENABLE_LOG +#ifdef ENABLE_LOG +#define LOG(x) kdDebug() << k_funcinfo << x << endl +#else +#define LOG(x) ; +#endif + +struct DirViewController::Private { + TreeView* mTreeView; +}; + + +DirViewController::DirViewController(QWidget* parent) +: QObject(parent) +{ + d=new Private; + + d->mTreeView=new TreeView(parent); + + connect(d->mTreeView, SIGNAL(selectionChanged(QListViewItem*)), + this, SLOT(slotTreeViewSelectionChanged(QListViewItem*)) ); + + connect(d->mTreeView, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)), + this, SLOT(slotTreeViewContextMenu(KListView*, QListViewItem*, const QPoint&)) ); +} + + +DirViewController::~DirViewController() { + delete d; +} + + +QWidget* DirViewController::widget() const { + return d->mTreeView; +} + + +void DirViewController::setURL(const KURL& url) { + d->mTreeView->setURL(url); +} + + +void DirViewController::slotTreeViewSelectionChanged(QListViewItem* item) { + if (!item) return; + LOG(d->mTreeView->currentURL()); + emit urlChanged(d->mTreeView->currentURL()); +} + + +void DirViewController::slotTreeViewContextMenu(KListView*, QListViewItem*, const QPoint& pos) { + QPopupMenu menu(d->mTreeView); + menu.insertItem(SmallIcon("folder_new"),i18n("New Folder..."),this,SLOT(makeDir())); + menu.insertSeparator(); + menu.insertItem(i18n("Rename..."),this,SLOT(renameDir())); + menu.insertItem(SmallIcon("editdelete"),i18n("Delete"),this,SLOT(removeDir())); + menu.insertSeparator(); + menu.insertItem(i18n("Properties"),this,SLOT(showPropertiesDialog())); + + menu.exec(pos); +} + + +void DirViewController::makeDir() { + if (!d->mTreeView->currentItem()) return; + FileOperation::makeDir(d->mTreeView->currentURL(), d->mTreeView, this, SLOT(slotDirMade()) ); +} + + +void DirViewController::slotDirMade() { + if (!d->mTreeView->currentItem()) return; + d->mTreeView->currentItem()->setOpen(true); +} + + +void DirViewController::renameDir() { + if (!d->mTreeView->currentItem()) return; + FileOperation::rename(d->mTreeView->currentURL(), d->mTreeView); +} + + +void DirViewController::removeDir() { + if (!d->mTreeView->currentItem()) return; + + KURL::List list; + list << d->mTreeView->currentURL(); + FileOperation::del(list, d->mTreeView); + + QListViewItem* item=d->mTreeView->currentItem(); + if (!item) return; + item=item->parent(); + if (!item) return; + d->mTreeView->setCurrentItem(item); +} + + +void DirViewController::showPropertiesDialog() { + (void)new KPropertiesDialog(d->mTreeView->currentURL(), d->mTreeView); +} + +} // namespace diff --git a/src/app/dirviewcontroller.h b/src/app/dirviewcontroller.h new file mode 100644 index 0000000..129cc8f --- /dev/null +++ b/src/app/dirviewcontroller.h @@ -0,0 +1,71 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef DIRVIEWCONTROLLER_H +#define DIRVIEWCONTROLLER_H + +// Qt +#include "qobject.h" + +class QListViewItem; +class QPoint; +class QWidget; +class KListView; +class KURL; + +namespace KIO { +class Job; +} + +namespace Gwenview { + +class DirViewController : public QObject { + Q_OBJECT +public: + DirViewController(QWidget* parent); + virtual ~DirViewController(); + QWidget* widget() const; + +public slots: + void setURL(const KURL&); + +signals: + void urlChanged(const KURL&); + void urlRenamed(const KURL& from, const KURL& to); + +private: + struct Private; + Private* d; + +private slots: + void slotTreeViewSelectionChanged(QListViewItem*); + void slotTreeViewContextMenu(KListView*, QListViewItem*, const QPoint&); + + void makeDir(); + void slotDirMade(); + void renameDir(); + void removeDir(); + void showPropertiesDialog(); +}; + +} // namespace + +#endif /* DIRVIEWCONTROLLER_H */ diff --git a/src/app/gwenviewui.rc b/src/app/gwenviewui.rc new file mode 100644 index 0000000..6e165ad --- /dev/null +++ b/src/app/gwenviewui.rc @@ -0,0 +1,133 @@ +<?xml version="1.0"?> +<!DOCTYPE gui SYSTEM "kpartgui.dtd"> +<kpartgui name="Gwenview" version="27"> +<MenuBar> + <Menu name="file"> + <Action name="file_rename"/> + <Action name="file_copy"/> + <Action name="file_move"/> + <Action name="file_link"/> + <Action name="file_delete"/> + <Separator/> + <Action name="file_properties"/> + </Menu> + <Menu name="edit"> + <Action name="rotate_left"/> + <Action name="rotate_right"/> + <Action name="mirror"/> + <Action name="flip"/> + </Menu> + <Menu name="view" noMerge="1"> + <text>&View</text> + <Action name="reload"/> + <Separator/> + <Action name="switch_to_view_mode" /> + <Action name="switch_to_browse_mode" /> + <Action name="fullscreen"/> + <Action name="slideshow"/> + <Separator/> + <Action name="list_mode" /> + <Action name="side_thumbnail_mode" /> + <Action name="bottom_thumbnail_mode" /> + <Action name="show_dot_files"/> + <Separator/> + <Menu name="colors"> + <text>&Colors</text> + <Action name="increase_gamma"/> + <Action name="decrease_gamma"/> + <Action name="increase_brightness"/> + <Action name="decrease_brightness"/> + <Action name="increase_contrast"/> + <Action name="decrease_contrast"/> + <Action name="adjust_bcg"/> + </Menu> + <Action name="view_zoom_to_fit"/> + <Action name="view_zoom_to_width"/> + <Action name="view_zoom_to_height"/> + <Action name="view_zoom_in"/> + <Action name="view_zoom_out"/> + <Action name="view_actual_size"/> + <Action name="view_zoom_lock"/> + </Menu> + <Menu name="go_web" noMerge="1"> + <text>&Go</text> + <Action name="first"/> + <Action name="previous"/> + <Action name="next"/> + <Action name="last"/> + <Separator/> + <Action name="go_back"/> + <Action name="go_forward"/> + <Action name="go_home"/> + <Separator/> + <Action name="go_up"/> + <Action name="first_sub_folder"/> + <Action name="previous_folder"/> + <Action name="next_folder"/> + </Menu> + <Action name="bookmarks"/> + <Menu name="settings"> + <Action name="configure_tools" append="configure_merge"/> + </Menu> + <Menu name="plugins"> + <text>&Plugins</text> + <Menu name="kipi_images"> + <text>Images</text> + <ActionList name="image_actions"/> + </Menu> + <Menu name="kipi_effects"> + <text>Effects</text> + <ActionList name="effect_actions"/> + </Menu> + <Menu name="kipi_tools"> + <text>Tools</text> + <ActionList name="tool_actions"/> + </Menu> + <Menu name="kipi_batch"> + <text>Batch Processing</text> + <ActionList name="batch_actions"/> + </Menu> + <Menu name="kipi_import"> + <text>Import</text> + <ActionList name="import_actions"/> + </Menu> + <Menu name="kipi_export"> + <text>Export</text> + <ActionList name="export_actions"/> + </Menu> + <Menu name="kipi_collections"> + <text>Collections</text> + <ActionList name="collection_actions"/> + </Menu> + </Menu> + <Menu name="window"> + <text>&Window</text> + <ActionList name="winlist"/> + <Separator/> + <Action name="reset_dock_widgets"/> + </Menu> +</MenuBar> + +<ToolBar name="mainToolBar" noMerge="1" iconText="icontextright"> + <text>Main Toolbar</text> + <Action name="switch_to_browse_mode"/> + <Action name="switch_to_view_mode"/> + <Action name="fullscreen"/> + <Action name="slideshow"/> +</ToolBar> + +<ToolBar name="locationToolBar"> + <text>Location Toolbar</text> + <Action name="go_back" /> + <Action name="go_forward" /> + <Action name="go_up" /> + <Action name="go_home" /> + <Action name="clear_location" /> + <Action name="location_label" /> + <Action name="location_url" /> + <Action name="location_go" /> +</ToolBar> + +<StatusBar/> + +</kpartgui> diff --git a/src/app/history.cpp b/src/app/history.cpp new file mode 100644 index 0000000..d9cb30e --- /dev/null +++ b/src/app/history.cpp @@ -0,0 +1,137 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau +Copyright 2003 Tudor Calin + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +// KDE +#include <kaction.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kdeversion.h> +#include <kstdaccel.h> +#include <kstdguiitem.h> + +// Local +#include "history.moc" +namespace Gwenview { + + +const unsigned int MAX_HISTORY_SIZE=12; + +History::History(KActionCollection* actionCollection) { + mPosition=mHistoryList.end(); + mMovingInHistory=false; + + // Actions + QPair<KGuiItem, KGuiItem> backForward = KStdGuiItem::backAndForward(); + mGoBack=new KToolBarPopupAction(backForward.first, + KStdAccel::shortcut(KStdAccel::Back), + this, SLOT(goBack()), actionCollection, "go_back"); + mGoForward=new KToolBarPopupAction(backForward.second, + KStdAccel::shortcut(KStdAccel::Forward), + this, SLOT(goForward()), actionCollection, "go_forward"); + + // Connections + connect(mGoBack->popupMenu(),SIGNAL(activated(int)), + this,SLOT(goBackTo(int)) ); + connect(mGoForward->popupMenu(),SIGNAL(activated(int)), + this,SLOT(goForwardTo(int)) ); + + connect(mGoBack->popupMenu(), SIGNAL(aboutToShow()), + this, SLOT(fillGoBackMenu()) ); + connect(mGoForward->popupMenu(), SIGNAL(aboutToShow()), + this, SLOT(fillGoForwardMenu()) ); +} + + +History::~History() { +} + + +void History::addURLToHistory(const KURL& url2) { + KURL url( url2 ); + url.setFileName( QString::null ); + if (!mMovingInHistory) { + if (mPosition!=mHistoryList.end() && url.equals(*mPosition, true)) return; + + // Drop everything after current + HistoryList::iterator it=mPosition; + ++it; + mHistoryList.erase(it, mHistoryList.end()); + + mHistoryList.append(url); + if(mHistoryList.count()==MAX_HISTORY_SIZE) mHistoryList.pop_front(); + mPosition=mHistoryList.fromLast(); + } + + mGoBack->setEnabled(mPosition!=mHistoryList.begin()); + mGoForward->setEnabled(mPosition!=mHistoryList.fromLast()); +} + + +void History::fillGoBackMenu() { + QPopupMenu* menu=mGoBack->popupMenu(); + menu->clear(); + HistoryList::ConstIterator it; + + int pos=1; + for(it=mHistoryList.begin(); it!=mPosition; ++it, ++pos) { + menu->insertItem( (*it).prettyURL(-1), pos, 0); + } +} + +void History::fillGoForwardMenu() { + QPopupMenu* menu=mGoForward->popupMenu(); + menu->clear(); + HistoryList::ConstIterator it=mPosition; + ++it; + + int pos=1; + for(; it!=mHistoryList.end(); ++it, ++pos) { + menu->insertItem( (*it).prettyURL(-1), pos, -1); + } +} + +void History::goBack() { + goBackTo(1); +} + + +void History::goForward() { + goForwardTo(1); +} + + +void History::goBackTo(int id) { + for (;id>0; --id) --mPosition; + mMovingInHistory=true; + emit urlChanged(*mPosition); + mMovingInHistory=false; +} + + +void History::goForwardTo(int id) { + for (;id>0; --id) ++mPosition; + mMovingInHistory=true; + emit urlChanged(*mPosition); + mMovingInHistory=false; +} + +} // namespace diff --git a/src/app/history.h b/src/app/history.h new file mode 100644 index 0000000..38e912d --- /dev/null +++ b/src/app/history.h @@ -0,0 +1,71 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau +Copyright 2003 Tudor Calin + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef HISTORY_H +#define HISTORY_H + +// Qt +#include <qobject.h> +#include <qvaluelist.h> + +// KDE +#include <kurl.h> + +class KToolBarPopupAction; +class KActionCollection; + +typedef QValueList<KURL> HistoryList; + +namespace Gwenview { +class History : public QObject { +Q_OBJECT + +public: + History(KActionCollection*); + ~History(); + +signals: + void urlChanged(const KURL&); + +public slots: + void addURLToHistory(const KURL&); + +private: + KToolBarPopupAction* mGoBack; + KToolBarPopupAction* mGoForward; + HistoryList mHistoryList; + HistoryList::Iterator mPosition; + bool mMovingInHistory; + +private slots: + void fillGoBackMenu(); + void fillGoForwardMenu(); + void goBack(); + void goForward(); + void goBackTo(int); + void goForwardTo(int); +}; + +} // namespace +#endif + + + diff --git a/src/app/kipiinterface.cpp b/src/app/kipiinterface.cpp new file mode 100644 index 0000000..94b2455 --- /dev/null +++ b/src/app/kipiinterface.cpp @@ -0,0 +1,224 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include <config.h> +#ifdef GV_HAVE_KIPI + +// Qt +#include <qdir.h> +#include <qregexp.h> +#include <qtimer.h> + +// KDE +#include <kdebug.h> +#include <kfileitem.h> +#include <klocale.h> +#include <kurl.h> + +// KIPI +#include <libkipi/imagecollectionshared.h> +#include <libkipi/imageinfoshared.h> + +// Local +#include "gvcore/archive.h" +#include "gvcore/cache.h" +#include "gvcore/fileviewbase.h" +#include "gvcore/fileviewcontroller.h" +#include "imageutils/jpegcontent.h" +#include "kipiinterface.moc" +namespace Gwenview { + +#undef ENABLE_LOG +#undef LOG +//#define ENABLE_LOG +#ifdef ENABLE_LOG +#define LOG(x) kdDebug() << k_funcinfo << x << endl +#else +#define LOG(x) ; +#endif + +class ImageCollection : public KIPI::ImageCollectionShared { +public: + ImageCollection(KURL dirURL, const QString& name, const KURL::List& images) + : KIPI::ImageCollectionShared() + , mDirURL(dirURL) + , mName(name) + , mImages(images) {} + + QString name() { return mName; } + QString comment() { return QString::null; } + KURL::List images() { return mImages; } + KURL uploadRoot() { return KURL("/"); } + KURL uploadPath() { return mDirURL; } + QString uploadRootName() { return "/"; } + bool isDirectory() { return true; } + +private: + KURL mDirURL; + QString mName; + KURL::List mImages; +}; + + + +class ImageInfo : public KIPI::ImageInfoShared { + static const QRegExp sExtensionRE; +public: + ImageInfo(KIPI::Interface* interface, const KURL& url) : KIPI::ImageInfoShared(interface, url) {} + + QString title() { + QString txt=_url.fileName(); + txt.replace("_", " "); + txt.replace(sExtensionRE, ""); + return txt; + } + + QString description() { + if (!_url.isLocalFile()) return QString::null; + + ImageUtils::JPEGContent content; + bool ok=content.load(_url.path()); + if (!ok) return QString::null; + + return content.comment(); + } + + void setDescription(const QString&) {} + + QMap<QString,QVariant> attributes() { + return QMap<QString,QVariant>(); + } + + void clearAttributes() {} + + void addAttributes(const QMap<QString, QVariant>&) {} +}; + +const QRegExp ImageInfo::sExtensionRE("\\.[a-z0-9]+$", false /*caseSensitive*/); + + +struct KIPIInterfacePrivate { + FileViewController* mFileView; +}; + + +KIPIInterface::KIPIInterface( QWidget* parent, FileViewController* fileView) +:KIPI::Interface(parent, "Gwenview kipi interface") { + d=new KIPIInterfacePrivate; + d->mFileView=fileView; + + connect(d->mFileView, SIGNAL(selectionChanged()), + this, SLOT(slotSelectionChanged()) ); + + connect(d->mFileView, SIGNAL(completed()), + this, SLOT(slotDirectoryChanged()) ); +// delay a bit, so that it's called after loadPlugins() + QTimer::singleShot( 0, this, SLOT( init())); +} + + +KIPIInterface::~KIPIInterface() { + delete d; +} + + +void KIPIInterface::init() { + slotDirectoryChanged(); + slotSelectionChanged(); +} + +KIPI::ImageCollection KIPIInterface::currentAlbum() { + LOG(""); + KURL::List list; + KFileItemListIterator it( *d->mFileView->currentFileView()->items() ); + for ( ; it.current(); ++it ) { + KFileItem* item=it.current(); + if (!Archive::fileItemIsDirOrArchive(item)) { + list.append(it.current()->url()); + } + } + KURL url=d->mFileView->dirURL(); + return KIPI::ImageCollection(new ImageCollection(url, url.fileName(), list)); +} + + +KIPI::ImageCollection KIPIInterface::currentSelection() { + LOG(""); + KURL::List list=d->mFileView->selectedImageURLs(); + KURL url=d->mFileView->dirURL(); + return KIPI::ImageCollection(new ImageCollection(url, i18n("%1 (Selected Images)").arg(url.fileName()), list)); +} + + +QValueList<KIPI::ImageCollection> KIPIInterface::allAlbums() { + LOG(""); + QValueList<KIPI::ImageCollection> list; + list << currentAlbum() << currentSelection(); + return list; +} + + +KIPI::ImageInfo KIPIInterface::info(const KURL& url) { + LOG(""); + return KIPI::ImageInfo( new ImageInfo(this, url) ); +} + +int KIPIInterface::features() const { + return KIPI::AcceptNewImages; +} + +/** + * KDirLister will pick up the image if necessary, so no updating is needed + * here, it is however necessary to discard caches if the plugin preserves timestamp + */ +bool KIPIInterface::addImage(const KURL& url, QString&) { + Cache::instance()->invalidate( url ); + return true; +} + +void KIPIInterface::delImage(const KURL& url) { + Cache::instance()->invalidate( url ); +} + +// TODO currently KDirWatch doesn't have watching of files in a directory +// implemented, so KDirLister will not inform when a file changes +void KIPIInterface::refreshImages( const KURL::List& urls ) { + for( KURL::List::ConstIterator it = urls.begin(); + it != urls.end(); + ++it ) { + Cache::instance()->invalidate( *it ); + } + d->mFileView->refreshItems( urls ); +} + + +void KIPIInterface::slotSelectionChanged() { + emit selectionChanged(d->mFileView->selectionSize() > 0); +} + + +void KIPIInterface::slotDirectoryChanged() { + emit currentAlbumChanged(d->mFileView->fileCount() > 0); +} + + +} // namespace + +#endif /* GV_HAVE_KIPI */ diff --git a/src/app/kipiinterface.h b/src/app/kipiinterface.h new file mode 100644 index 0000000..c664409 --- /dev/null +++ b/src/app/kipiinterface.h @@ -0,0 +1,62 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aurélien Gâteau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef KIPIINTERFACE_H +#define KIPIINTERFACE_H + +#include <config.h> +#ifdef GV_HAVE_KIPI + +#include <libkipi/interface.h> +namespace Gwenview { + +class KIPIInterfacePrivate; + +class FileViewController; + +class KIPIInterface :public KIPI::Interface { + Q_OBJECT + +public: + KIPIInterface( QWidget* parent, FileViewController*); + virtual ~KIPIInterface(); + + KIPI::ImageCollection currentAlbum(); + KIPI::ImageCollection currentSelection(); + QValueList<KIPI::ImageCollection> allAlbums(); + KIPI::ImageInfo info( const KURL& ); + int features() const; + virtual bool addImage(const KURL&, QString& err); + virtual void delImage( const KURL& ); + virtual void refreshImages( const KURL::List& urls ); + +private: + KIPIInterfacePrivate* d; + +private slots: + void slotSelectionChanged(); + void slotDirectoryChanged(); + void init(); +}; + +#endif /* GV_HAVE_KIPI */ +} // namespace +#endif /* KIPIINTERFACE_H */ + diff --git a/src/app/main.cpp b/src/app/main.cpp new file mode 100644 index 0000000..9fe8cb2 --- /dev/null +++ b/src/app/main.cpp @@ -0,0 +1,163 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2006 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include <qdir.h> + +#include <kaboutdata.h> +#include <kapplication.h> +#include <kcmdlineargs.h> +#include <kdebug.h> +#include <klocale.h> + +#include "gvcore/cache.h" +#include "gvcore/fileviewcontroller.h" +#include <../gvcore/fileviewconfig.h> +#include <../gvcore/miscconfig.h> +#include "mainwindow.h" +namespace Gwenview { + +static KCmdLineOptions options[] = { + { "f", I18N_NOOP("Start in fullscreen mode"), 0 }, + { "filter-type <all,images,videos>", I18N_NOOP("Filter by file type"), 0 }, + { "filter-name <pattern>", I18N_NOOP("Filter by file pattern (*.jpg, 01*...)"), 0 }, + { "filter-from <date>", I18N_NOOP("Only show files newer or equal to <date>"), 0 }, + { "filter-to <date>", I18N_NOOP("Only show files older or equal to <date>"), 0 }, + { "+[file or folder]", I18N_NOOP("A starting file or folder"), 0 }, + KCmdLineLastOption +}; + +static const char version[] = "1.4.2"; + + +void applyFilterArgs(KCmdLineArgs* args, FileViewController* controller) { + QString filterType = args->getOption("filter-type"); + QString filterName = args->getOption("filter-name"); + QString filterFrom = args->getOption("filter-from"); + QString filterTo = args->getOption("filter-to"); + // Do nothing if there is no filter + if (filterType.isEmpty() && filterName.isEmpty() + && filterFrom.isEmpty() && filterTo.isEmpty()) + { + return; + } + + QStringList typeList; + typeList << "all" << "images" << "videos"; + int mode = typeList.findIndex(filterType); + if (mode == -1) { + // Default to "all" + controller->setFilterMode(0); + } else { + controller->setFilterMode(mode); + } + + controller->setShowFilterBar( + !filterName.isEmpty() + || !filterFrom.isEmpty() + || !filterTo.isEmpty() ); + + controller->setFilterName(filterName); + + bool ok = false; + QDate date; + if (!filterFrom.isEmpty()) { + date = KGlobal::locale()->readDate(filterFrom, &ok); + if (!ok) { + kdWarning() << "Invalid value for filter-from option\n"; + } + } + controller->setFilterFromDate(date); + + date=QDate(); + if (!filterTo.isEmpty()) { + date = KGlobal::locale()->readDate(filterTo, &ok); + if (!ok) { + kdWarning() << "Invalid value for filter-to option\n"; + } + } + controller->setFilterToDate(date); + + controller->applyFilter(); +} + + +#ifndef __KDE_HAVE_GCC_VISIBILITY +#undef KDE_EXPORT +#define KDE_EXPORT +#endif + +extern "C" +KDE_EXPORT int kdemain (int argc, char *argv[]) { + KAboutData aboutData("gwenview", I18N_NOOP("Gwenview"), + version, I18N_NOOP("An image viewer for KDE"), KAboutData::License_GPL, + "Copyright 2000-2006, The Gwenview developers",0,"http://gwenview.sourceforge.net"); + aboutData.addAuthor("Aurélien Gâteau", I18N_NOOP("Main developer"), "aurelien.gateau@free.fr"); + aboutData.addAuthor("LuboÅ¡ Luňák", I18N_NOOP("Developer"), "l.lunak@suse.cz"); + + aboutData.addCredit("Frank Becker", I18N_NOOP("Fast JPEG thumbnail generation (v0.13.0)"), "ff@telus.net"); + aboutData.addCredit("Tudor Calin", I18N_NOOP("Address bar (v0.16.0)\nHistory support (v1.0.0)"), "tudor_calin@mymail.ro"); + aboutData.addCredit("Avinash Chopde", I18N_NOOP("File operation patch (v0.9.2)"), "avinash@acm.org"); + aboutData.addCredit("Marco Gazzetta", I18N_NOOP("Fixed crash when trying to generate a thumbnail for a broken JPEG file (v0.16.0)"), "mililani@pobox.com"); + aboutData.addCredit("GeniusR13", I18N_NOOP("Fixed compilation on KDE 3.0 (v0.16.1)"), "geniusr13@gmx.net"); + aboutData.addCredit("Ian Koenig", I18N_NOOP("First RPM spec file"), "iguy@ionsphere.org"); + aboutData.addCredit("Meni Livne", I18N_NOOP("Toolbar layout patch for RTL languages (v0.16.0)"), "livne@kde.org"); + aboutData.addCredit("Angelo Naselli", I18N_NOOP("Printing support (v1.0.0)"), "anaselli@linux.it"); + aboutData.addCredit("Jos van den Oever", I18N_NOOP("File info view (v1.0.0)\nPatch to toggle auto-zoom on click (v1.0.0)"), "jos@vandenoever.info"); + aboutData.addCredit("Jeroen Peters", I18N_NOOP("Configurable mouse wheel behavior (v1.1.1)"), "jpeters@coldmail.nl"); + aboutData.addCredit("Andreas Pfaller", I18N_NOOP("Option to prevent Gwenview from automatically loading the first image of a folder (v0.15.0)"), "apfaller@yahoo.com.au"); + aboutData.addCredit("Renchi Raju", I18N_NOOP("Fixed thumbnail generation to share the thumbnail folder of Konqueror v3 (v0.15.0)"), "renchi@green.tam.uiuc.edu"); + aboutData.addCredit("Michael Spanier", I18N_NOOP("Patch for mouse navigation (v0.7.0)"), "mail@michael-spanier.de"); + aboutData.addCredit("Christian A Strømmen", I18N_NOOP("Integration in Konqueror folder context menu"), "number1@realityx.net"); + + KCmdLineArgs::init( argc, argv, &aboutData ); + KCmdLineArgs::addCmdLineOptions( options ); + + KApplication kapplication; + + if (kapplication.isRestored()) { + RESTORE(MainWindow) + } else { + KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); + + MainWindow *mainWindow = new MainWindow; + applyFilterArgs(args, mainWindow->fileViewController()); + + bool fullscreen=args->isSet("f"); + if (fullscreen) mainWindow->setFullScreen(true); + + KURL url; + if (args->count()>0) { + url=args->url(0); + } else { + if (MiscConfig::rememberURL() && MiscConfig::history().count() > 0) { + url = KURL(MiscConfig::history()[0]); + } else { + url.setPath( QDir::currentDirPath() ); + } + } + mainWindow->openURL(url); + + mainWindow->show(); + } + + return kapplication.exec(); +} + +} // namespace diff --git a/src/app/mainwindow.cpp b/src/app/mainwindow.cpp new file mode 100644 index 0000000..2cd873a --- /dev/null +++ b/src/app/mainwindow.cpp @@ -0,0 +1,1371 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "mainwindow.moc" + +// Qt +#include <qdir.h> +#include <qdockarea.h> +#include <qwidgetstack.h> + +// KDE +#include <kaboutdata.h> +#include <kaccel.h> +#include <kaction.h> +#include <kapplication.h> +#include <kbookmarkmanager.h> +#include <kbookmarkmenu.h> +#include <kcombobox.h> +#include <kconfig.h> +#include <kcursor.h> +#include <kdebug.h> +#include <kdeversion.h> +#include <kdockwidget.h> +#include <kedittoolbar.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <khelpmenu.h> +#include <kiconloader.h> +#include <kio/netaccess.h> +#include <kkeydialog.h> +#include <klargefile.h> +#include <klistview.h> +#include <klocale.h> +#include <kmenubar.h> +#include <kmessagebox.h> +#include <kpopupmenu.h> +#include <kpropsdlg.h> +#include <kprotocolinfo.h> +#include <kstandarddirs.h> +#include <kstatusbar.h> +#include <kstdaccel.h> +#include <kstdaction.h> +#include <ktoolbarlabelaction.h> +#include <kurlcompletion.h> +#include <kurlpixmapprovider.h> +#include <kprinter.h> + +#include <config.h> +// KIPI +#ifdef GV_HAVE_KIPI +#include <libkipi/plugin.h> +#include <libkipi/pluginloader.h> +#endif + +// Local +#include "bookmarkowner.h" +#include "bookmarkviewcontroller.h" +#include "configdialog.h" +#include "dirviewcontroller.h" +#include "history.h" +#include "metaedit.h" +#include "truncatedtextlabel.h" +#include "vtabwidget.h" + +#include "gvcore/externaltoolcontext.h" +#include "gvcore/externaltoolmanager.h" +#include "gvcore/fileoperation.h" +#include "gvcore/archive.h" +#include "gvcore/captionformatter.h" +#include "gvcore/document.h" +#include "gvcore/externaltooldialog.h" +#include "gvcore/fileviewbase.h" +#include "gvcore/fileviewcontroller.h" +#include "gvcore/imageview.h" +#include "gvcore/imageviewcontroller.h" +#include "gvcore/slideshow.h" +#include "gvcore/printdialog.h" +#include "gvcore/cache.h" +#include "gvcore/thumbnailloadjob.h" +#include <../gvcore/slideshowconfig.h> +#include <../gvcore/fullscreenconfig.h> +#include <../gvcore/fileviewconfig.h> +#include <../gvcore/miscconfig.h> + +#include "config.h" + +#ifdef GV_HAVE_KIPI +#include "kipiinterface.h" +#endif + +namespace Gwenview { + +const char CONFIG_DOCK_GROUP[]="dock"; +const char CONFIG_DIRWIDGET_GROUP[]="dir widget"; +const char CONFIG_PIXMAPWIDGET_GROUP[]="pixmap widget"; +const char CONFIG_CACHE_GROUP[]="cache"; + +const char CONFIG_GWENVIEW_DOCK_VERSION[]="Gwenview version"; + +const char CONFIG_SESSION_URL[] = "url"; + +// This version is here to avoid configuration migration troubles when changes +// are made to the dock behavior +const int GWENVIEW_DOCK_VERSION=2; + +// The timeout before an hint in the statusbar disappear (in msec) +const int HINT_TIMEOUT=10000; + +// How many items should be stored in history +const int HISTORY_MAX_COUNT=20; + +#undef ENABLE_LOG +#undef LOG +//#define ENABLE_LOG +#ifdef ENABLE_LOG +#define LOG(x) kdDebug() << k_funcinfo << x << endl +#else +#define LOG(x) ; +#endif + +enum { StackIDBrowse, StackIDView }; + + +static bool urlIsDirectory(QWidget* parent, const KURL& url) { + if( url.filename( false ).isEmpty()) return true; // file:/somewhere/<nothing here> + // Do direct stat instead of using KIO if the file is local (faster) + if( url.isLocalFile() + && !KIO::probably_slow_mounted( url.path())) { + KDE_struct_stat buff; + if ( KDE_stat( QFile::encodeName(url.path()), &buff ) == 0 ) { + return S_ISDIR( buff.st_mode ); + } + } + KIO::UDSEntry entry; + if( KIO::NetAccess::stat( url, entry, parent)) { + KIO::UDSEntry::ConstIterator it; + for(it=entry.begin();it!=entry.end();++it) { + if ((*it).m_uds==KIO::UDS_FILE_TYPE) { + return S_ISDIR( (*it).m_long ); + } + } + } + return false; +} + + +MainWindow::MainWindow() +: KMainWindow() +#ifdef GV_HAVE_KIPI +, mPluginLoader(0) +#endif +{ + // Backend + mDocument=new Document(this); + mHistory=new History(actionCollection()); + // GUI + createActions(); + createWidgets(); + createLocationToolBar(); + createObjectInteractions(); + + setStandardToolBarMenuEnabled(true); + createGUI("gwenviewui.rc", false); + + createConnections(); + mWindowListActions.setAutoDelete(true); + updateWindowActions(); + KMainWindow::applyMainWindowSettings(KGlobal::config(), "MainWindow"); +} + + +void MainWindow::setFullScreen(bool value) { + if (value != mToggleFullScreen->isChecked()) { + mToggleFullScreen->activate(); + } +} + + +bool MainWindow::queryClose() { + mDocument->saveBeforeClosing(); + + KConfig* config=KGlobal::config(); + + // Don't store dock layout if only the image dock is visible. This avoid + // saving layout when in "fullscreen" or "image only" mode. + if (mFileViewController->isVisible() || mDirViewController->widget()->isVisible()) { + mDockArea->writeDockConfig(config,CONFIG_DOCK_GROUP); + } + + if (FileViewConfig::deleteCacheOnExit()) { + QString dir=ThumbnailLoadJob::thumbnailBaseDir(); + + if (QFile::exists(dir)) { + KURL url; + url.setPath(dir); + KIO::NetAccess::del(url, this); + } + } + + if (!mToggleFullScreen->isChecked()) { + saveMainWindowSettings(KGlobal::config(), "MainWindow"); + } + MiscConfig::setHistory( mURLEdit->historyItems() ); + MiscConfig::writeConfig(); + return true; +} + +void MainWindow::saveProperties( KConfig* cfg ) { + cfg->writeEntry( CONFIG_SESSION_URL, mFileViewController->url().url()); +} + +void MainWindow::readProperties( KConfig* cfg ) { + KURL url(cfg->readEntry(CONFIG_SESSION_URL)); + openURL(url); +} + +//----------------------------------------------------------------------- +// +// Public slots +// +//----------------------------------------------------------------------- +void MainWindow::openURL(const KURL& url) { + bool isDir = urlIsDirectory(this, url); + LOG("url=" << url.prettyURL() << ", isDir=" << isDir); + + if (isDir) { + mFileViewController->setDirURL(url); + mFileViewController->setFocus(); + } else { + mDocument->setURL(url); + mFileViewController->setDirURL(url.upURL()); + mFileViewController->setFileNameToSelect(url.filename()); + mImageViewController->setFocus(); + } + + if (!mToggleFullScreen->isChecked() && !isDir && !mSwitchToViewMode->isChecked()) { + mSwitchToViewMode->activate(); + } +} + +void MainWindow::slotRenamed(const QString& fileName) { + KURL url = mDocument->url(); + url.setFileName(fileName); + mDocument->setURL(url); +} + +void MainWindow::slotDirURLChanged(const KURL& dirURL) { + LOG(dirURL.prettyURL(0,KURL::StripFileProtocol)); + + mGoUp->setEnabled(dirURL.path()!="/"); + + updateStatusInfo(); + updateImageActions(); + updateLocationURL(); +} + +void MainWindow::updateLocationURL() { + LOG(""); + KURL url; + if (mSwitchToBrowseMode->isChecked()) { + url=mFileViewController->dirURL(); + if (!url.isValid()) { + url=mDocument->url(); + } + } else { + url=mDocument->url(); + } + LOG(url.prettyURL()); + mURLEdit->setEditText(url.pathOrURL()); + mURLEdit->addToHistory(url.pathOrURL()); +} + +void MainWindow::goUp() { + KURL url = mFileViewController->dirURL(); + mFileViewController->setDirURL(url.upURL()); + mFileViewController->setFileNameToSelect(url.fileName()); +} + +void MainWindow::updateFullScreenLabel() { + CaptionFormatter formatter; + formatter.mPath=mDocument->url().path(); + formatter.mFileName=mDocument->url().fileName(); + formatter.mComment=mDocument->comment(); + formatter.mImageSize=mDocument->image().size(); + formatter.mPosition=mFileViewController->shownFilePosition()+1; + formatter.mCount=mFileViewController->fileCount(); + formatter.mAperture=mDocument->aperture(); + formatter.mExposureTime=mDocument->exposureTime(); + formatter.mIso=mDocument->iso(); + formatter.mFocalLength=mDocument->focalLength(); + + QString txt=formatter.format( FullScreenConfig::osdFormat() ); + mFullScreenLabelAction->label()->setText(txt); +} + +void MainWindow::goUpTo(int id) { + KPopupMenu* menu=mGoUp->popupMenu(); + KURL url(menu->text(id)); + KURL childURL; + int index=menu->indexOf(id); + if (index>0) { + childURL=KURL(menu->text(menu->idAt(index-1))); + } else { + childURL=mDocument->dirURL(); + } + mFileViewController->setDirURL(url); + mFileViewController->setFileNameToSelect(childURL.fileName()); +} + +void MainWindow::fillGoUpMenu() { + QPopupMenu* menu = mGoUp->popupMenu(); + menu->clear(); + int pos = 0; + KURL url = mFileViewController->dirURL().upURL(); + for (; url.hasPath() && pos<10; url=url.upURL(), ++pos) { + menu->insertItem(url.pathOrURL()); + if (url.path()=="/") break; + } +} + + +//----------------------------------------------------------------------- +// +// File operations +// +//----------------------------------------------------------------------- +void MainWindow::goHome() { + KURL url; + url.setPath( QDir::homeDirPath() ); + mFileViewController->setDirURL(url); +} + + +void MainWindow::renameFile() { + KURL url; + if (mFileViewController->isVisible()) { + KURL::List list = mFileViewController->selectedURLs(); + Q_ASSERT(list.count()==1); + if (list.count()!=1) return; + url = list.first(); + } else { + url = mDocument->url(); + } + FileOperation::rename(url, this, this, SLOT(slotRenamed(const QString &))); +} + + +void MainWindow::copyFiles() { + KURL::List list; + if (mFileViewController->isVisible()) { + list = mFileViewController->selectedURLs(); + } else { + list << mDocument->url(); + } + FileOperation::copyTo(list, this); +} + +void MainWindow::linkFiles() { + KURL::List list; + if (mFileViewController->isVisible()) { + list = mFileViewController->selectedURLs(); + } else { + list << mDocument->url(); + } + FileOperation::linkTo(list, this); +} + + +void MainWindow::moveFiles() { + KURL::List list; + if (mFileViewController->isVisible()) { + list = mFileViewController->selectedURLs(); + } else { + list << mDocument->url(); + } + FileOperation::moveTo(list, this); +} + + +void MainWindow::deleteFiles() { + KURL::List list; + if (mFileViewController->isVisible()) { + list = mFileViewController->selectedURLs(); + } else { + list << mDocument->url(); + } + FileOperation::del(list, this); +} + + +void MainWindow::makeDir() { + FileOperation::makeDir(mFileViewController->dirURL(), this); +} + + +void MainWindow::showFileProperties() { + if (mFileViewController->isVisible()) { + const KFileItemList* list = mFileViewController->currentFileView()->selectedItems(); + if (list->count() > 0) { + (void)new KPropertiesDialog(*list, this); + } else { + (void)new KPropertiesDialog(mFileViewController->dirURL(), this); + } + } else { + (void)new KPropertiesDialog(mDocument->url(), this); + } +} + + +void MainWindow::rotateLeft() { + mDocument->transform(ImageUtils::ROT_270); +} + +void MainWindow::rotateRight() { + mDocument->transform(ImageUtils::ROT_90); +} + +void MainWindow::mirror() { + mDocument->transform(ImageUtils::HFLIP); +} + +void MainWindow::flip() { + mDocument->transform(ImageUtils::VFLIP); +} + +void MainWindow::showFileDialog() { + KURL url=KFileDialog::getOpenURL(); + if (!url.isValid()) return; + + openURL(url); +} + + +void MainWindow::printFile() { + KPrinter printer; + + printer.setDocName(mDocument->filename()); + const KAboutData* pAbout = KApplication::kApplication()->aboutData(); + QString nm = pAbout->appName(); + nm += "-"; + nm += pAbout->version(); + printer.setCreator( nm ); + + KPrinter::addDialogPage( new PrintDialogPage( mDocument, this, " page")); + + if (printer.setup(this, QString::null, true)) { + mDocument->print(&printer); + } +} + + +//----------------------------------------------------------------------- +// +// Private slots +// +//----------------------------------------------------------------------- +void MainWindow::openFileViewControllerContextMenu(const QPoint& pos, bool onItem) { + int selectionSize; + ExternalToolContext* externalToolContext; + + if (onItem) { + const KFileItemList* items = mFileViewController->currentFileView()->selectedItems(); + selectionSize = items->count(); + externalToolContext = + ExternalToolManager::instance()->createContext(this, items); + } else { + selectionSize = 0; + externalToolContext = + ExternalToolManager::instance()->createContext(this, mFileViewController->dirURL()); + } + + QPopupMenu menu(this); + + menu.insertItem( + i18n("External Tools"), externalToolContext->popupMenu()); + + actionCollection()->action("view_sort")->plug(&menu); + mGoUp->plug(&menu); + + menu.insertItem(SmallIcon("folder_new"), i18n("New Folder..."), this, SLOT(makeDir())); + + menu.insertSeparator(); + + if (selectionSize==1) { + mRenameFile->plug(&menu); + } + + if (selectionSize>=1) { + mCopyFiles->plug(&menu); + mMoveFiles->plug(&menu); + mLinkFiles->plug(&menu); + mDeleteFiles->plug(&menu); + menu.insertSeparator(); + } + + mShowFileProperties->plug(&menu); + menu.exec(pos); +} + + +void MainWindow::slotImageLoading() { + if (FullScreenConfig::showBusyPtr() || !mToggleFullScreen->isChecked()) { + kapp->setOverrideCursor(KCursor::workingCursor(), true /* replace */); + } +} + + +void MainWindow::slotImageLoaded() { + // Reciproc of slotImageLoading + if (FullScreenConfig::showBusyPtr() || !mToggleFullScreen->isChecked()) { + kapp->restoreOverrideCursor(); + } + updateStatusInfo(); + updateImageActions(); + updateLocationURL(); + if (mToggleFullScreen->isChecked()) { + updateFullScreenLabel(); + } +} + + +void MainWindow::hideToolBars() { + QPtrListIterator<KToolBar> it=toolBarIterator(); + KToolBar* bar; + + for(;it.current()!=0L; ++it) { + bar=it.current(); + if (bar->area()) { + bar->area()->hide(); + } else { + bar->hide(); + } + } +} + + +void MainWindow::showToolBars() { + QPtrListIterator<KToolBar> it=toolBarIterator(); + + KToolBar* bar; + + for(;it.current()!=0L; ++it) { + bar=it.current(); + if (bar->area()) { + bar->area()->show(); + } else { + bar->show(); + } + } +} + + +void MainWindow::toggleFullScreen() { + if (mToggleFullScreen->isChecked()) { + saveMainWindowSettings(KGlobal::config(), "MainWindow"); + + showFullScreen(); + menuBar()->hide(); + statusBar()->hide(); + + /* Hide toolbar + * If the toolbar is docked we hide the DockArea to avoid + * having a one pixel band remaining + * For the same reason, we hide all the empty DockAreas + * + * NOTE: This does not work really well if the toolbar is in + * the left or right dock area. + */ + hideToolBars(); + if (leftDock()->isEmpty()) leftDock()->hide(); + if (rightDock()->isEmpty()) rightDock()->hide(); + if (topDock()->isEmpty()) topDock()->hide(); + if (bottomDock()->isEmpty()) bottomDock()->hide(); + + if (mSwitchToBrowseMode->isChecked()) { + mImageViewController->widget()->reparent(mViewModeWidget, QPoint(0,0)); + mCentralStack->raiseWidget(StackIDView); + } + updateFullScreenLabel(); + mImageViewController->setFullScreen(true); + mImageViewController->setFocus(); + } else { + // Stop the slideshow if it's running + if (mSlideShow->isRunning()) { + mToggleSlideShow->activate(); + } + + // Make sure the file view points to the right URL, it might not be the + // case if we are getting out of a slideshow + mFileViewController->setDirURL(mDocument->url().upURL()); + mFileViewController->setFileNameToSelect(mDocument->url().fileName()); + + showNormal(); + menuBar()->show(); + + showToolBars(); + leftDock()->show(); + rightDock()->show(); + topDock()->show(); + bottomDock()->show(); + + statusBar()->show(); + mImageViewController->setFullScreen(false); + + if (mSwitchToBrowseMode->isChecked()) { + mImageDock->setWidget(mImageViewController->widget()); + mCentralStack->raiseWidget(StackIDBrowse); + mFileViewController->setFocus(); + } + } +} + + +void MainWindow::toggleSlideShow() { + if (mSlideShow->isRunning()) { + mSlideShow->stop(); + return; + } + + KURL::List list; + KFileItemListIterator it( *mFileViewController->currentFileView()->items() ); + for ( ; it.current(); ++it ) { + KFileItem* item=it.current(); + if (!item->isDir() && !Archive::fileItemIsArchive(item)) { + list.append(item->url()); + } + } + if (list.count()==0) { + return; + } + + if (SlideShowConfig::fullscreen() && !mToggleFullScreen->isChecked()) { + mToggleFullScreen->activate(); + } + mSlideShow->start(list); + } + + +void MainWindow::slotSlideShowChanged(bool running) { + mToggleSlideShow->setIcon(running ? "slideshow_pause" : "slideshow_play"); +} + + +void MainWindow::showConfigDialog() { +#ifdef GV_HAVE_KIPI + if (!mPluginLoader) loadPlugins(); + ConfigDialog dialog(this, mPluginLoader); +#else + ConfigDialog dialog(this, 0); +#endif + connect(&dialog, SIGNAL(settingsChanged()), + mSlideShow, SLOT(slotSettingsChanged()) ); + connect(&dialog, SIGNAL(settingsChanged()), + mImageViewController, SLOT(updateFromSettings()) ); + connect(&dialog, SIGNAL(settingsChanged()), + mFileViewController, SLOT(updateFromSettings()) ); + dialog.exec(); +} + + +void MainWindow::showExternalToolDialog() { + ExternalToolDialog* dialog=new ExternalToolDialog(this); + dialog->show(); +} + + +void MainWindow::showKeyDialog() { + KKeyDialog dialog(true, this); + dialog.insert(actionCollection()); + dialog.configure(true); +} + + +void MainWindow::showToolBarDialog() { + saveMainWindowSettings(KGlobal::config(), "MainWindow"); + KEditToolbar dlg(actionCollection()); + connect(&dlg,SIGNAL(newToolbarConfig()),this,SLOT(applyMainWindowSettings())); + dlg.exec(); +} + +void MainWindow::applyMainWindowSettings() { + createGUI(); + KMainWindow::applyMainWindowSettings(KGlobal::config(), "MainWindow"); +} + + + +void MainWindow::escapePressed() { + if (mToggleFullScreen->isChecked()) { + mToggleFullScreen->activate(); + } +} + + +void MainWindow::slotDirRenamed(const KURL& oldURL, const KURL& newURL) { + LOG(oldURL.prettyURL(0,KURL::StripFileProtocol) << " to " << newURL.prettyURL(0,KURL::StripFileProtocol)); + + KURL url(mFileViewController->dirURL()); + if (!oldURL.isParentOf(url) ) { + LOG(oldURL.prettyURL() << " is not a parent of " << url.prettyURL()); + return; + } + + QString oldPath=oldURL.path(); + LOG("current path: " << url.path() ); + QString path=newURL.path() + url.path().mid(oldPath.length()); + LOG("new path: " << path); + url.setPath(path); + mFileViewController->setDirURL(url); +} + + +void MainWindow::slotGo() { + KURL url(mURLEditCompletion->replacedPath(mURLEdit->currentText())); + LOG(url.prettyURL()); + openURL(url); + mFileViewController->setFocus(); +} + +void MainWindow::slotShownFileItemRefreshed(const KFileItem*) { + LOG(""); + mDocument->reload(); +} + + +void MainWindow::slotToggleCentralStack() { + LOG(""); + if (mSwitchToBrowseMode->isChecked()) { + mImageDock->setWidget(mImageViewController->widget()); + mCentralStack->raiseWidget(StackIDBrowse); + mFileViewController->setSilentMode( false ); + // force re-reading the directory to show the error + if( mFileViewController->lastURLError()) mFileViewController->retryURL(); + } else { + mImageViewController->widget()->reparent(mViewModeWidget, QPoint(0,0)); + mCentralStack->raiseWidget(StackIDView); + mFileViewController->setSilentMode( true ); + } + + // Make sure the window list actions are disabled if we are in view mode, + // otherwise weird things happens when we go back to browse mode + QPtrListIterator<KAction> it(mWindowListActions); + for (;it.current(); ++it) { + it.current()->setEnabled(mSwitchToBrowseMode->isChecked()); + } + updateImageActions(); + updateLocationURL(); +} + + +void MainWindow::resetDockWidgets() { + int answer=KMessageBox::warningContinueCancel(this, + i18n("You are about to revert the window setup to factory defaults, are you sure?"), + QString::null /* caption */, + i18n("Reset")); + if (answer==KMessageBox::Cancel) return; + + mFolderDock->undock(); + mImageDock->undock(); + mMetaDock->undock(); + + mFolderDock->manualDock(mFileDock, KDockWidget::DockLeft, 4000); + mImageDock->manualDock(mFolderDock, KDockWidget::DockBottom, 3734); + mMetaDock->manualDock(mImageDock, KDockWidget::DockBottom, 8560); +} + + +/** + * Display a hint as a temporary message in the status bar + */ +void MainWindow::showHint(const QString& hint) { + mSBHintLabel->setText(hint); + + mSBHintLabel->show(); + mHintTimer->start(HINT_TIMEOUT, true); +} + + +//----------------------------------------------------------------------- +// +// GUI +// +//----------------------------------------------------------------------- +void MainWindow::updateStatusInfo() { + QStringList tokens; + + if ( KProtocolInfo::supportsListing(mFileViewController->url()) ) { + int pos = mFileViewController->shownFilePosition(); + uint count = mFileViewController->fileCount(); + if (count > 0) { + tokens << i18n("%1/%2").arg(pos+1).arg(count); + } else { + tokens << i18n("No images"); + } + } + + QString filename = mDocument->filename(); + + QSize size = mDocument->image().size(); + if (!size.isEmpty()) { + tokens << i18n("%1 x %2 pixels").arg(size.width()).arg(size.height()); + } + + mSBDetailLabel->setText(tokens.join(" - ")); + setCaption(filename); +} + + +void MainWindow::updateImageActions() { + mToggleSlideShow->setEnabled(mDocument->urlKind()!=MimeTypeUtils::KIND_UNKNOWN); + + bool imageActionsEnabled = !mDocument->isNull(); + + mRotateLeft->setEnabled(imageActionsEnabled); + mRotateRight->setEnabled(imageActionsEnabled); + mMirror->setEnabled(imageActionsEnabled); + mFlip->setEnabled(imageActionsEnabled); + mSaveFile->setEnabled(imageActionsEnabled); + mSaveFileAs->setEnabled(imageActionsEnabled); + mFilePrint->setEnabled(imageActionsEnabled); + mReload->setEnabled(imageActionsEnabled); + + bool fileActionsEnabled = + imageActionsEnabled + || (mFileViewController->isVisible() && mFileViewController->selectionSize()>0); + + mRenameFile->setEnabled(fileActionsEnabled); + mCopyFiles->setEnabled(fileActionsEnabled); + mMoveFiles->setEnabled(fileActionsEnabled); + mLinkFiles->setEnabled(fileActionsEnabled); + mDeleteFiles->setEnabled(fileActionsEnabled); + mShowFileProperties->setEnabled(fileActionsEnabled); +} + + +/** + * This method creates all the widgets. Interactions between them and with + * actions are created in createObjectInteractions + */ +void MainWindow::createWidgets() { + KConfig* config=KGlobal::config(); + + mCentralStack=new QWidgetStack(this); + setCentralWidget(mCentralStack); + + mDockArea=new KDockArea(mCentralStack); + mCentralStack->addWidget(mDockArea, StackIDBrowse); + mDockArea->manager()->setSplitterHighResolution(true); + mDockArea->manager()->setSplitterOpaqueResize(true); + + mViewModeWidget=new QWidget(mCentralStack); + QVBoxLayout* layout=new QVBoxLayout(mViewModeWidget); + layout->setAutoAdd(true); + mCentralStack->addWidget(mViewModeWidget); + + // Status bar + mSBDetailLabel=new QLabel("", statusBar()); + + mSBHintLabel=new TruncatedTextLabel(statusBar()); + QFont font=mSBHintLabel->font(); + font.setItalic(true); + mSBHintLabel->setFont(font); + + statusBar()->addWidget(mSBDetailLabel, 0); + statusBar()->addWidget(mSBHintLabel, 1); + mHintTimer=new QTimer(this); + connect(mHintTimer, SIGNAL(timeout()), + mSBHintLabel, SLOT(clear()) ); + + // Pixmap widget + mImageDock = mDockArea->createDockWidget("Image",SmallIcon("gwenview"),NULL,i18n("Image")); + mImageViewController=new ImageViewController(mImageDock, mDocument, actionCollection()); + mImageDock->setWidget(mImageViewController->widget()); + connect(mImageViewController, SIGNAL(requestHintDisplay(const QString&)), + this, SLOT(showHint(const QString&)) ); + + // Folder widget + mFolderDock = mDockArea->createDockWidget("Folders",SmallIcon("folder_open"),NULL,i18n("Folders")); + VTabWidget* vtabWidget=new VTabWidget(mFolderDock); + mFolderDock->setWidget(vtabWidget); + + mDirViewController=new DirViewController(vtabWidget); + vtabWidget->addTab(mDirViewController->widget(), SmallIcon("folder"), i18n("Folders")); + + mBookmarkViewController=new BookmarkViewController(vtabWidget); + vtabWidget->addTab(mBookmarkViewController->widget(), SmallIcon("bookmark"), i18n("Bookmarks")); + + // File widget + mFileDock = mDockArea->createDockWidget("Files",SmallIcon("image"),NULL,i18n("Files")); + mFileViewController=new FileViewController(this, actionCollection()); + mFileDock->setWidget(mFileViewController); + mFileDock->setEnableDocking(KDockWidget::DockNone); + mDockArea->setMainDockWidget(mFileDock); + + // Meta info edit widget + mMetaDock = mDockArea->createDockWidget("File Attributes", SmallIcon("info"),NULL, + i18n("Image Comment")); + mMetaEdit = new MetaEdit(mMetaDock, mDocument); + mMetaDock->setWidget(mMetaEdit); + + // Slide show controller (not really a widget) + mSlideShow=new SlideShow(mDocument); + + // Default position on desktop + setGeometry(20,20,720,520); + + // Default dock config + // (The "magic numbers" were found by adjusting the layout from within the + // app and looking at the result in the configuration file) + mFolderDock->manualDock(mFileDock, KDockWidget::DockLeft, 4000); + mImageDock->manualDock(mFolderDock, KDockWidget::DockBottom, 3734); + mMetaDock->manualDock(mImageDock, KDockWidget::DockBottom, 8560); + + // Load dock config if up to date + if (config->hasGroup(CONFIG_DOCK_GROUP)) { + config->setGroup(CONFIG_DOCK_GROUP); + if (config->readNumEntry(CONFIG_GWENVIEW_DOCK_VERSION, 1)==GWENVIEW_DOCK_VERSION) { + mDockArea->readDockConfig(config,CONFIG_DOCK_GROUP); + } else { + KMessageBox::sorry(this, i18n( + "<qt><b>Configuration update</b><br>" + "Due to some changes in the dock behavior, your old dock configuration has been discarded. " + "Please adjust your docks again.</qt>") + ); + // Store the default dock config and create the + // GWENVIEW_DOCK_VERSION entry + mDockArea->writeDockConfig(config,CONFIG_DOCK_GROUP); + config->writeEntry(CONFIG_GWENVIEW_DOCK_VERSION, GWENVIEW_DOCK_VERSION); + config->sync(); + } + } else { + // There was no dock config, lets create the GWENVIEW_DOCK_VERSION entry + config->setGroup(CONFIG_DOCK_GROUP); + config->writeEntry(CONFIG_GWENVIEW_DOCK_VERSION, GWENVIEW_DOCK_VERSION); + config->sync(); + } + + // Load config + Cache::instance()->readConfig(config,CONFIG_CACHE_GROUP); +} + + +/** + * This method creates all the actions Interactions between them and with + * widgets are created in createObjectInteractions + */ +void MainWindow::createActions() { + // Stack + mSwitchToBrowseMode=new KRadioAction(i18n("Browse"), "folder_image", CTRL + Key_Return, this, SLOT(slotToggleCentralStack()), actionCollection(), "switch_to_browse_mode"); + mSwitchToBrowseMode->setExclusiveGroup("centralStackMode"); + mSwitchToBrowseMode->setChecked(true); + mSwitchToViewMode=new KRadioAction(i18n("View Image"), "image", 0, this, SLOT(slotToggleCentralStack()), actionCollection(), "switch_to_view_mode"); + mSwitchToViewMode->setExclusiveGroup("centralStackMode"); + + // File + KStdAction::open(this,SLOT(showFileDialog()),actionCollection() ); + mSaveFile=KStdAction::save(mDocument,SLOT(save()),actionCollection() ); + mSaveFileAs=KStdAction::saveAs(mDocument,SLOT(saveAs()),actionCollection() ); + mFilePrint = KStdAction::print(this, SLOT(printFile()), actionCollection()); + mRenameFile=new KAction(i18n("&Rename..."),Key_F2,this,SLOT(renameFile()),actionCollection(),"file_rename"); + mCopyFiles=new KAction(i18n("&Copy To..."),Key_F7,this,SLOT(copyFiles()),actionCollection(),"file_copy"); + mMoveFiles=new KAction(i18n("&Move To..."),Key_F8,this,SLOT(moveFiles()),actionCollection(),"file_move"); + mLinkFiles=new KAction(i18n("&Link To..."),Key_F9,this,SLOT(linkFiles()),actionCollection(),"file_link"); + mDeleteFiles=new KAction(i18n("&Delete"),"editdelete",Key_Delete,this,SLOT(deleteFiles()),actionCollection(),"file_delete"); + mShowFileProperties=new KAction(i18n("Properties"),0,this,SLOT(showFileProperties()),actionCollection(),"file_properties"); + KStdAction::quit( kapp, SLOT (closeAllWindows()), actionCollection() ); + + // Edit + mRotateLeft=new KAction(i18n("Rotate &Left"),"rotate_left",CTRL + Key_L, this, SLOT(rotateLeft()),actionCollection(),"rotate_left"); + mRotateRight=new KAction(i18n("Rotate &Right"),"rotate_right",CTRL + Key_R, this, SLOT(rotateRight()),actionCollection(),"rotate_right"); + mMirror=new KAction(i18n("&Mirror"),"mirror",0, this, SLOT(mirror()),actionCollection(),"mirror"); + mFlip=new KAction(i18n("&Flip"),"flip",0, this, SLOT(flip()),actionCollection(),"flip"); + + // View + mReload=new KAction(i18n("Reload"), "reload", Key_F5, mDocument, SLOT(reload()), actionCollection(), "reload"); + mReload->setEnabled(false); + + mToggleFullScreen= KStdAction::fullScreen(this,SLOT(toggleFullScreen()),actionCollection(),0); + mToggleSlideShow=new KAction(i18n("Slide Show"),"slideshow_play",0,this,SLOT(toggleSlideShow()),actionCollection(),"slideshow"); + mFullScreenLabelAction=new KToolBarLabelAction("", 0, 0, 0, actionCollection(), "fullscreen_label"); + + // Go + mGoUp=new KToolBarPopupAction(i18n("Up"), "up", ALT + Key_Up, this, SLOT(goUp()), actionCollection(), "go_up"); + new KAction( i18n( "Home" ), "gohome", KStdAccel::shortcut(KStdAccel::Home), this, SLOT(goHome()), actionCollection(), "go_home"); + + // Window + mResetDockWidgets = new KAction(i18n("Reset"), 0, this, SLOT(resetDockWidgets()), actionCollection(), "reset_dock_widgets"); + + // Settings + mShowConfigDialog= + KStdAction::preferences(this, SLOT(showConfigDialog()), actionCollection() ); + mShowKeyDialog= + KStdAction::keyBindings(this, SLOT(showKeyDialog()), actionCollection() ); + (void)new KAction(i18n("Configure External Tools..."), "configure", 0, + this, SLOT(showExternalToolDialog()), actionCollection(), "configure_tools"); + (void)KStdAction::configureToolbars( + this, SLOT(showToolBarDialog()), actionCollection() ); + + actionCollection()->readShortcutSettings(); +} + + +/** + * This method creates the interactions between objects, when it's called, all + * widgets and actions have already been created + */ +void MainWindow::createObjectInteractions() { + // Actions in image view + { + KActionPtrList actions; + actions + << mToggleFullScreen + << mToggleSlideShow + << mFileViewController->selectPrevious() + << mFileViewController->selectNext() + << mRotateLeft + << mRotateRight + << mFullScreenLabelAction + ; + mImageViewController->setFullScreenCommonActions(actions); + } + + { + KActionPtrList actions; + actions + << mFileViewController->selectPrevious() + << mFileViewController->selectNext() + << mReload + ; + mImageViewController->setNormalCommonActions(actions); + } + + { + KActionPtrList actions; + actions + << actionCollection()->action("view_zoom_in") + << actionCollection()->action("view_zoom_to") + << actionCollection()->action("view_zoom_out") + << mRotateLeft + << mRotateRight + ; + mImageViewController->setImageViewActions(actions); + } + + // Make sure file actions are correctly updated + connect(mFileViewController, SIGNAL(selectionChanged()), + this, SLOT(updateImageActions()) ); + + connect(mFileViewController, SIGNAL(requestContextMenu(const QPoint&, bool)), + this, SLOT(openFileViewControllerContextMenu(const QPoint&, bool)) ); + + // Bookmarks + QString file = locate( "data", "kfile/bookmarks.xml" ); + if (file.isEmpty()) { + file = locateLocal( "data", "kfile/bookmarks.xml" ); + } + + KBookmarkManager* manager=KBookmarkManager::managerForFile(file,false); + manager->setUpdate(true); + manager->setShowNSBookmarks(false); + mBookmarkViewController->init(manager); + + BookmarkOwner* bookmarkOwner=new BookmarkOwner(this); + + KActionMenu* bookmark=new KActionMenu(i18n( "&Bookmarks" ), "bookmark", actionCollection(), "bookmarks" ); + new KBookmarkMenu(manager, bookmarkOwner, bookmark->popupMenu(), 0, true); + + connect(bookmarkOwner,SIGNAL(openURL(const KURL&)), + mFileViewController,SLOT(setDirURL(const KURL&)) ); + + connect(mFileViewController,SIGNAL(directoryChanged(const KURL&)), + bookmarkOwner,SLOT(setURL(const KURL&)) ); +} + + +void MainWindow::createHideShowAction(KDockWidget* dock) { + QString caption; + if (dock->mayBeHide()) { + caption=i18n("Hide %1").arg(dock->caption()); + } else { + caption=i18n("Show %1").arg(dock->caption()); + } + + KAction* action=new KAction(caption, 0, dock, SLOT(changeHideShowState()), (QObject*)0 ); + if (dock->icon()) { + action->setIconSet( QIconSet(*dock->icon()) ); + } + mWindowListActions.append(action); +} + + +void MainWindow::updateWindowActions() { + unplugActionList("winlist"); + mWindowListActions.clear(); + createHideShowAction(mFolderDock); + createHideShowAction(mImageDock); + createHideShowAction(mMetaDock); + plugActionList("winlist", mWindowListActions); +} + + +void MainWindow::createConnections() { + connect(mGoUp->popupMenu(), SIGNAL(aboutToShow()), + this,SLOT(fillGoUpMenu())); + + connect(mGoUp->popupMenu(), SIGNAL(activated(int)), + this,SLOT(goUpTo(int))); + + // Slideshow connections + connect( mSlideShow, SIGNAL(nextURL(const KURL&)), + SLOT( openURL(const KURL&)) ); + connect( mSlideShow, SIGNAL( stateChanged(bool)), + SLOT( slotSlideShowChanged(bool)) ); + + // Dir view connections + connect(mDirViewController, SIGNAL(urlChanged(const KURL&)), + mFileViewController, SLOT(setDirURL(const KURL&)) ); + connect(mDirViewController, SIGNAL(urlRenamed(const KURL&, const KURL&)), + this, SLOT(slotDirRenamed(const KURL&, const KURL&)) ); + + // Bookmark view connections + connect(mBookmarkViewController, SIGNAL(openURL(const KURL&)), + mFileViewController,SLOT(setDirURL(const KURL&)) ); + connect(mFileViewController, SIGNAL(directoryChanged(const KURL&)), + mBookmarkViewController, SLOT(setURL(const KURL&)) ); + + // Pixmap view connections + connect(mImageViewController, SIGNAL(selectPrevious()), + mFileViewController, SLOT(slotSelectPrevious()) ); + connect(mImageViewController, SIGNAL(selectNext()), + mFileViewController, SLOT(slotSelectNext()) ); + connect(mImageViewController, SIGNAL(doubleClicked()), + mToggleFullScreen, SLOT(activate()) ); + + // File view connections + connect(mFileViewController,SIGNAL(urlChanged(const KURL&)), + mDocument,SLOT(setURL(const KURL&)) ); + connect(mFileViewController,SIGNAL(directoryChanged(const KURL&)), + this,SLOT(slotDirURLChanged(const KURL&)) ); + connect(mFileViewController,SIGNAL(directoryChanged(const KURL&)), + mDirViewController,SLOT(setURL(const KURL&)) ); + connect(mFileViewController,SIGNAL(directoryChanged(const KURL&)), + mHistory,SLOT(addURLToHistory(const KURL&)) ); + + connect(mFileViewController,SIGNAL(completed()), + this,SLOT(updateStatusInfo()) ); + connect(mFileViewController,SIGNAL(canceled()), + this,SLOT(updateStatusInfo()) ); + connect(mFileViewController,SIGNAL(imageDoubleClicked()), + mToggleFullScreen,SLOT(activate()) ); + connect(mFileViewController,SIGNAL(shownFileItemRefreshed(const KFileItem*)), + this,SLOT(slotShownFileItemRefreshed(const KFileItem*)) ); + connect(mFileViewController,SIGNAL(sortingChanged()), + this, SLOT(updateStatusInfo()) ); + + // History connections + connect(mHistory, SIGNAL(urlChanged(const KURL&)), + mFileViewController, SLOT(setDirURL(const KURL&)) ); + + // Document connections + connect(mDocument,SIGNAL(loading()), + this,SLOT(slotImageLoading()) ); + connect(mDocument,SIGNAL(loaded(const KURL&)), + this,SLOT(slotImageLoaded()) ); + connect(mDocument,SIGNAL(saved(const KURL&)), + mFileViewController,SLOT(updateThumbnail(const KURL&)) ); + connect(mDocument,SIGNAL(reloaded(const KURL&)), + mFileViewController,SLOT(updateThumbnail(const KURL&)) ); + + // Location bar + connect(mURLEdit, SIGNAL(activated(const QString &)), + this,SLOT(slotGo()) ); + connect(mURLEdit, SIGNAL(returnPressed()), + this,SLOT(slotGo()) ); + + // Non configurable stop-fullscreen accel + QAccel* accel=new QAccel(this); + accel->connectItem(accel->insertItem(Key_Escape),this,SLOT(escapePressed())); + + // Dock related + connect(mDockArea->manager(), SIGNAL(change()), + this, SLOT(updateWindowActions()) ); + + // Plugin menu + QPopupMenu *popup = static_cast<QPopupMenu*>( + factory()->container( "plugins", this)); + connect(popup, SIGNAL(aboutToShow()), this, SLOT(loadPlugins()) ); +} + + +void MainWindow::createLocationToolBar() { + // URL Combo + mURLEdit=new KHistoryCombo(); + mURLEdit->setDuplicatesEnabled(false); + mURLEdit->setPixmapProvider(new KURLPixmapProvider); + mURLEdit->setMaxCount(HISTORY_MAX_COUNT); + mURLEdit->setHistoryItems(MiscConfig::history()); + + // Do not let the combobox get wider than available space, as this would + // hide the toolbuttons after it + mURLEdit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + // Avoid stealing focus + mURLEdit->setFocusPolicy(ClickFocus); + + mURLEditCompletion=new KURLCompletion(); + + mURLEdit->setCompletionObject(mURLEditCompletion); + mURLEdit->setAutoDeleteCompletionObject(true); + + KWidgetAction* comboAction=new KWidgetAction( mURLEdit, i18n("Location Bar"), 0, + 0, 0, actionCollection(), "location_url"); + comboAction->setShortcutConfigurable(false); + comboAction->setAutoSized(true); + + // Clear button + (void)new KAction( i18n("Clear Location Bar"), + QApplication::reverseLayout()?"clear_left" : "locationbar_erase", + 0, this, SLOT(clearLocationLabel()), actionCollection(), "clear_location"); + + // URL Label + KToolBarLabelAction* locationAction = new KToolBarLabelAction(i18n("L&ocation:"), + Key_F6, this, SLOT( activateLocationLabel()), actionCollection(), "location_label"); + locationAction->setBuddy(mURLEdit); + + // Go button + (void)new KAction(i18n("Go"), "key_enter", 0, this, SLOT(slotGo()), actionCollection(), "location_go"); + +} + + +void MainWindow::clearLocationLabel() { + mURLEdit->clearEdit(); + mURLEdit->setFocus(); +} + + +void MainWindow::activateLocationLabel() { + mURLEdit->setFocus(); + mURLEdit->lineEdit()->selectAll(); +} + + +#ifdef GV_HAVE_KIPI +void MainWindow::loadPlugins() { + // Already done + if (mPluginLoader) return; + + LOG("Load plugins"); + // Sets up the plugin interface, and load the plugins + KIPIInterface* interface = new KIPIInterface(this, mFileViewController); + mPluginLoader = new KIPI::PluginLoader(QStringList(), interface ); + connect( mPluginLoader, SIGNAL( replug() ), this, SLOT( slotReplug() ) ); + mPluginLoader->loadPlugins(); +} + + +// Helper class for slotReplug(), gcc does not want to instantiate templates +// with local classes, so this is declared outside of slotReplug() +struct MenuInfo { + QString mName; + QPtrList<KAction> mActions; + MenuInfo() {} + MenuInfo(const QString& name) : mName(name) {} +}; + +void MainWindow::slotReplug() { + typedef QMap<KIPI::Category, MenuInfo> CategoryMap; + CategoryMap categoryMap; + categoryMap[KIPI::IMAGESPLUGIN]=MenuInfo("image_actions"); + categoryMap[KIPI::EFFECTSPLUGIN]=MenuInfo("effect_actions"); + categoryMap[KIPI::TOOLSPLUGIN]=MenuInfo("tool_actions"); + categoryMap[KIPI::IMPORTPLUGIN]=MenuInfo("import_actions"); + categoryMap[KIPI::EXPORTPLUGIN]=MenuInfo("export_actions"); + categoryMap[KIPI::BATCHPLUGIN]=MenuInfo("batch_actions"); + categoryMap[KIPI::COLLECTIONSPLUGIN]=MenuInfo("collection_actions"); + + // Fill the mActions + KIPI::PluginLoader::PluginList pluginList=mPluginLoader->pluginList(); + KIPI::PluginLoader::PluginList::ConstIterator it(pluginList.begin()); + KIPI::PluginLoader::PluginList::ConstIterator itEnd(pluginList.end()); + for( ; it!=itEnd; ++it ) { + if (!(*it)->shouldLoad()) continue; + KIPI::Plugin* plugin = (*it)->plugin(); + Q_ASSERT(plugin); + if (!plugin) continue; + + plugin->setup(this); + KActionPtrList actions = plugin->actions(); + KActionPtrList::ConstIterator actionIt=actions.begin(), end=actions.end(); + for (; actionIt!=end; ++actionIt) { + KIPI::Category category = plugin->category(*actionIt); + + if (!categoryMap.contains(category)) { + kdWarning() << "Unknown category '" << category << "'\n"; + continue; + } + + categoryMap[category].mActions.append(*actionIt); + } + plugin->actionCollection()->readShortcutSettings(); + } + + // Create a dummy "no plugin" action list + KAction* noPlugin=new KAction(i18n("No Plugin"), 0, 0, 0, actionCollection(), "no_plugin"); + noPlugin->setShortcutConfigurable(false); + noPlugin->setEnabled(false); + QPtrList<KAction> noPluginList; + noPluginList.append(noPlugin); + + // Fill the menu + CategoryMap::ConstIterator catIt=categoryMap.begin(), catItEnd=categoryMap.end(); + for (; catIt!=catItEnd; ++catIt) { + const MenuInfo& info=catIt.data(); + unplugActionList(info.mName); + if (info.mActions.count()>0) { + plugActionList(info.mName, info.mActions); + } else { + plugActionList(info.mName, noPluginList); + } + } +} +#else +void MainWindow::loadPlugins() { + // Create a dummy "no KIPI" action list + KAction* noPlugin=new KAction(i18n("No KIPI support"), 0, 0, 0, actionCollection(), "no_plugin"); + noPlugin->setShortcutConfigurable(false); + noPlugin->setEnabled(false); + QPtrList<KAction> noPluginList; + noPluginList.append(noPlugin); + + QStringList lst; + lst << "image_actions" + << "effect_actions" + << "tool_actions" + << "import_actions" + << "export_actions" + << "batch_actions" + << "collection_actions"; + + // Fill the menu + QStringList::ConstIterator catIt=lst.begin(), catItEnd=lst.end(); + for (; catIt!=catItEnd; ++catIt) { + plugActionList(*catIt, noPluginList); + } +} + +void MainWindow::slotReplug() { +} +#endif + + +} // namespace diff --git a/src/app/mainwindow.h b/src/app/mainwindow.h new file mode 100644 index 0000000..a61d8ea --- /dev/null +++ b/src/app/mainwindow.h @@ -0,0 +1,222 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +// Qt +#include <qptrlist.h> + +// KDE +#include <kmainwindow.h> +#include <kurl.h> + +// Local +#include "config.h" +#ifdef GV_HAVE_KIPI +#include <libkipi/pluginloader.h> +#endif + +class QLabel; +class QTimer; +class QWidgetStack; + +class KAction; +class KDockArea; +class KDockWidget; +class KFileItem; +class KHistoryCombo; +class KListView; +class KRadioAction; +class KToggleAction; +class KToolBarLabelAction; +class KToolBarPopupAction; +class KURLCompletion; + +namespace Gwenview { +class BookmarkViewController; +class DirViewController; +class Document; +class FileViewController; +class History; +class MetaEdit; +class ImageViewController; +class SlideShow; + + +class MainWindow : public KMainWindow { +Q_OBJECT +public: + MainWindow(); + void setFullScreen(bool); + FileViewController* fileViewController() const { return mFileViewController; } + +public slots: + void openURL(const KURL&); + +protected: + bool queryClose(); + virtual void saveProperties( KConfig* ); + virtual void readProperties( KConfig* ); + +private: + QWidgetStack* mCentralStack; + QWidget* mViewModeWidget; + KDockArea* mDockArea; + KDockWidget* mFolderDock; + KDockWidget* mFileDock; + KDockWidget* mImageDock; + KDockWidget* mMetaDock; + QLabel* mSBDetailLabel; + QLabel* mSBHintLabel; + QTimer* mHintTimer; + + FileViewController* mFileViewController; + DirViewController* mDirViewController; + BookmarkViewController* mBookmarkViewController; + ImageViewController* mImageViewController; + MetaEdit *mMetaEdit; + + Document* mDocument; + History* mHistory; + SlideShow* mSlideShow; + + KRadioAction* mSwitchToBrowseMode; + KRadioAction* mSwitchToViewMode; + KToggleAction* mToggleFullScreen; + KToolBarLabelAction* mFullScreenLabelAction; + KAction* mRenameFile; + KAction* mCopyFiles; + KAction* mMoveFiles; + KAction* mLinkFiles; + KAction* mDeleteFiles; + KAction* mShowConfigDialog; + KAction* mShowKeyDialog; + KAction* mReload; + KToolBarPopupAction* mGoUp; + KAction* mShowFileProperties; + KAction* mToggleSlideShow; + KAction* mRotateLeft; + KAction* mRotateRight; + KAction* mMirror; + KAction* mFlip; + KAction* mSaveFile; + KAction* mSaveFileAs; + KAction* mFilePrint; + KAction* mResetDockWidgets; + + KHistoryCombo* mURLEdit; + KURLCompletion* mURLEditCompletion; + QPtrList<KAction> mWindowListActions; + +#ifdef GV_HAVE_KIPI + KIPI::PluginLoader* mPluginLoader; +#endif + + void hideToolBars(); + void showToolBars(); + void createWidgets(); + void createActions(); + void createLocationToolBar(); + void createObjectInteractions(); + void updateLocationURL(); + void updateFullScreenLabel(); + void createConnections(); + +private slots: + void goUp(); + void goUpTo(int); + + void makeDir(); + void goHome(); + void renameFile(); + void slotRenamed(const QString&); + void copyFiles(); + void moveFiles(); + void linkFiles(); + void deleteFiles(); + void showFileProperties(); + void showFileDialog(); + void printFile(); /** print the actual file */ + void clearLocationLabel(); + void activateLocationLabel(); + + void toggleFullScreen(); + void showConfigDialog(); + void showExternalToolDialog(); + void showKeyDialog(); + void showToolBarDialog(); + void applyMainWindowSettings(); + void slotImageLoading(); + void slotImageLoaded(); + void toggleSlideShow(); + void slotSlideShowChanged(bool); + void slotDirRenamed(const KURL& oldURL, const KURL& newURL); + void slotDirURLChanged(const KURL&); + void rotateLeft(); + void rotateRight(); + void mirror(); + void flip(); + void resetDockWidgets(); + + void slotToggleCentralStack(); + /** + * Update status bar and caption + */ + void updateStatusInfo(); + + /** + * Enable or disable image actions + */ + void updateImageActions(); + + void slotShownFileItemRefreshed(const KFileItem* item); + + /** + * Allow quitting full screen mode by pressing Escape key. + */ + void escapePressed(); + + /** + * Address bar related + */ + void slotGo(); + + void updateWindowActions(); + + void loadPlugins(); + + // Helper function for updateWindowActions() + void createHideShowAction(KDockWidget* dock); + + void slotReplug(); + + void showHint(const QString&); + + void fillGoUpMenu(); + + void openFileViewControllerContextMenu(const QPoint& pos, bool onItem); +}; + + +} // namespace +#endif + diff --git a/src/app/metaedit.cpp b/src/app/metaedit.cpp new file mode 100644 index 0000000..0d56f48 --- /dev/null +++ b/src/app/metaedit.cpp @@ -0,0 +1,138 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Copyright (c) 2003 Jos van den Oever + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Qt +#include <qlabel.h> +#include <qtextedit.h> +#include <qfileinfo.h> + +// KDE +#include <kdeversion.h> +#include <klocale.h> + +// Local +#include "gvcore/document.h" +#include "metaedit.moc" +namespace Gwenview { + +// FIXME: Why doesn't MetaEdit inherits from QTextEdit rather than QVBox? +MetaEdit::MetaEdit(QWidget *parent, Document *gvp, const char *name) +: QVBox(parent, name) +, mEmpty(true) +, mDocument(gvp) +{ + mCommentEdit=new QTextEdit(this); + mCommentEdit->installEventFilter(this); + connect(mCommentEdit, SIGNAL(modificationChanged(bool)), + this, SLOT(setModified(bool))); + connect(mDocument,SIGNAL(loaded(const KURL&)), + this,SLOT(updateContent()) ); + connect(mCommentEdit, SIGNAL(textChanged()), + this, SLOT(updateDoc()) ); + updateContent(); + mCommentEdit->setMinimumHeight(int (mCommentEdit->fontMetrics().height() * 1.5) ); +} + + +MetaEdit::~MetaEdit() { +} + + +bool MetaEdit::eventFilter(QObject*, QEvent *event) { + if (mEmpty + && (mDocument->commentState()==Document::WRITABLE) + && (event->type()==QEvent::FocusIn || event->type()==QEvent::FocusOut) + ) { + setEmptyText(); + } + return false; +} + + +void MetaEdit::setModified(bool m) { + if (m && mEmpty) { + mEmpty = false; + } +} + + +void MetaEdit::updateContent() { + if (mDocument->isNull()) { + setMessage(i18n("No image selected.")); + return; + } + + if (mDocument->commentState() == Document::NONE) { + setMessage(i18n("This image cannot be commented.")); + return; + } + + QString comment=mDocument->comment(); + mEmpty = comment.isEmpty(); + if (mEmpty) { + setEmptyText(); + return; + } + setComment(comment); +} + + +void MetaEdit::updateDoc() { + if ((mDocument->commentState()==Document::WRITABLE) && mCommentEdit->isModified()) { + mDocument->setComment(mCommentEdit->text()); + mCommentEdit->setModified(false); + } +} + + +void MetaEdit::setEmptyText() { + Q_ASSERT(mDocument->commentState()!=Document::NONE); + if (mDocument->commentState()==Document::WRITABLE) { + if (mCommentEdit->hasFocus()) { + setComment(""); + } else { + setMessage(i18n("Type here to add a comment to this image.")); + } + } else { + setMessage(i18n("No comment available.")); + } +} + + +/** + * Use mCommentEdit to show the comment and let the user edit it + */ +void MetaEdit::setComment(const QString& comment) { + Q_ASSERT(mDocument->commentState()!=Document::NONE); + mCommentEdit->setTextFormat(QTextEdit::PlainText); + mCommentEdit->setReadOnly(mDocument->commentState()==Document::READ_ONLY); + mCommentEdit->setText(comment); +} + + +/** + * Use mCommentEdit to display a read-only message + */ +void MetaEdit::setMessage(const QString& msg) { + mCommentEdit->setTextFormat(QTextEdit::RichText); + mCommentEdit->setReadOnly(true); + mCommentEdit->setText(QString("<i>%1</i>").arg(msg)); +} + +} // namespace diff --git a/src/app/metaedit.h b/src/app/metaedit.h new file mode 100644 index 0000000..c867eba --- /dev/null +++ b/src/app/metaedit.h @@ -0,0 +1,59 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Copyright (c) 2003 Jos van den Oever + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef METAEDIT_H +#define METAEDIT_H + +// Qt +#include <qvbox.h> + +// KDE +#include <kfilemetainfo.h> +class QTextEdit; + +namespace Gwenview { + +class Document; + +class MetaEdit : public QVBox { +Q_OBJECT +public: + MetaEdit(QWidget *parent, Document*, const char *name=""); + ~MetaEdit(); +protected: + bool eventFilter(QObject *, QEvent *); +private slots: + void updateContent(); + void updateDoc(); + void setModified(bool); + +private: + bool mEmpty; + Document* mDocument; + QTextEdit* mCommentEdit; + + void setComment(const QString&); + void setMessage(const QString&); + void setEmptyText(); +}; + + +} // namespace +#endif + diff --git a/src/app/testvtabwidget.cpp b/src/app/testvtabwidget.cpp new file mode 100644 index 0000000..1e5d835 --- /dev/null +++ b/src/app/testvtabwidget.cpp @@ -0,0 +1,48 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// Qt +#include <qlabel.h> + +// KDE +#include <kapplication.h> +#include <kaboutdata.h> +#include <kcmdlineargs.h> +#include <kiconloader.h> + +// Local +#include <vtabwidget.h> + +int main(int argc, char* argv[]) { + KAboutData aboutData("testvtabwidget", "testvtabwidget", "0"); + KCmdLineArgs::init( argc, argv, &aboutData ); + KApplication app; + + Gwenview::VTabWidget tabWidget(0); + QLabel* lbl=new QLabel("label 1", &tabWidget); + tabWidget.addTab(lbl, SmallIcon("text"), "tab1"); + lbl=new QLabel("label 2", &tabWidget); + tabWidget.addTab(lbl, SmallIcon("image"), "tab2"); + + app.setMainWidget(&tabWidget); + tabWidget.show(); + app.exec(); +} diff --git a/src/app/treeview.cpp b/src/app/treeview.cpp new file mode 100644 index 0000000..ddf24a5 --- /dev/null +++ b/src/app/treeview.cpp @@ -0,0 +1,342 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#include "treeview.moc" + +// Qt +#include <qheader.h> +#include <qtimer.h> + +// KDE +#include <kdebug.h> +#include <kiconloader.h> +#include <kmimetype.h> +#include <kurldrag.h> + +// Local +#include "../gvcore/fileoperation.h" + +namespace Gwenview { + +#undef ENABLE_LOG +#undef LOG +//#define ENABLE_LOG +#ifdef ENABLE_LOG +#define LOG(x) kdDebug() << k_funcinfo << x << endl +#else +#define LOG(x) ; +#endif + +const int AUTO_OPEN_DELAY=1000; +const int DND_ICON_COUNT=8; +const char* DND_PREFIX="dnd"; + + +struct TreeView::Private { + TreeView* mView; + KFileTreeBranch* mBranch; + KFileTreeViewItem* mDropTarget; + QTimer* mAutoOpenTimer; + + KFileTreeViewItem* findViewItem(KFileTreeViewItem* parent,const QString& text) { + QListViewItem* item; + + for (item=parent->firstChild();item;item=item->nextSibling()) { + if (item->text(0)==text) { + return static_cast<KFileTreeViewItem*>(item); + } + } + return 0L; + } + + void setURLInternal(const KURL& url) { + LOG(url.prettyURL() ); + QString path=url.path(); + + if (!mBranch || !mBranch->rootUrl().isParentOf(url)) { + mView->createBranch(url); + return; + } + + // The request URL is a child of the branch, expand the branch to reach + // the child + LOG("Expanding to reach child"); + if(mBranch->rootUrl().path()!="/") { + path.remove(0,mBranch->rootUrl().path().length()); + } + LOG("Path=" << path); + + // Finds the deepest existing view item + QStringList folderParts=QStringList::split('/',path); + QStringList::Iterator folderIter=folderParts.begin(); + QStringList::Iterator endFolderIter=folderParts.end(); + KFileTreeViewItem* viewItem=mBranch->root(); + for(;folderIter!=endFolderIter;++folderIter) { + + KFileTreeViewItem* nextViewItem=findViewItem(viewItem,*folderIter); + if (!nextViewItem) break; + viewItem=nextViewItem; + } + LOG("Deepest existing view item=" << viewItem->url()); + + // If this is the wanted item, select it, + // otherwise set the url as the next to select + if (viewItem->url().equals(url,true)) { + LOG("We are done"); + mView->setCurrentItem(viewItem); + mView->ensureItemVisible(viewItem); + mView->slotSetNextUrlToSelect(KURL()); + } else { + LOG("We continue"); + mView->slotSetNextUrlToSelect(url); + } + + LOG("Opening deepest existing view item"); + viewItem->setOpen(true); + } +}; + + +TreeView::TreeView(QWidget* parent) +: KFileTreeView(parent) { + d=new Private; + d->mView=this; + d->mBranch=0; + d->mDropTarget=0; + d->mAutoOpenTimer=new QTimer(this); + + // Look + addColumn(QString::null); + header()->hide(); + setAllColumnsShowFocus(true); + setRootIsDecorated(false); + setFullWidth(true); + + // Drag'n'drop + setDragEnabled(true); + setDropVisualizer(false); + setDropHighlighter(true); + setAcceptDrops(true); + + connect(d->mAutoOpenTimer, SIGNAL(timeout()), + this, SLOT(autoOpenDropTarget())); +} + + +TreeView::~TreeView() { + delete d; +} + + +void TreeView::setURL(const KURL& url) { + LOG(url.prettyURL()); + if (currentURL().equals(url,true)) return; + if (m_nextUrlToSelect.equals(url,true)) return; + slotSetNextUrlToSelect(url); + + // Do not update the view if it's hidden, the url has been stored with + // slotSetNextUrlToSelect. The view will expand to it next time it's shown. + if (!isVisible()) { + LOG("We are hidden, just store the url"); + return; + } + + d->setURLInternal(url); +} + + +void TreeView::slotTreeViewPopulateFinished(KFileTreeViewItem* item) { + QListViewItem* child; + if (!item) return; + KURL url=item->url(); + + if (d->mDropTarget) { + startAnimation(d->mDropTarget,DND_PREFIX,DND_ICON_COUNT); + } + + LOG("itemURL=" << url); + LOG("m_nextUrlToSelect=" << m_nextUrlToSelect); + + // We reached the URL to select, get out + if (url.equals(m_nextUrlToSelect, true)) { + slotSetNextUrlToSelect(KURL()); + return; + } + + // This URL is not a parent of a wanted URL, get out + if (!url.isParentOf(m_nextUrlToSelect)) return; + + // Find the next child item and open it + LOG("Looking for next child"); + for (child=item->firstChild(); child; child=child->nextSibling()) { + url=static_cast<KFileTreeViewItem*>(child)->url(); + if (url.isParentOf(m_nextUrlToSelect)) { + LOG("Opening child with URL=" << url); + ensureItemVisible(child); + child->setOpen(true); + return; + } + } +} + + +void TreeView::createBranch(const KURL& url) { + if (d->mBranch) { + removeBranch(d->mBranch); + } + QString title=url.prettyURL(0, KURL::StripFileProtocol); + d->mBranch=addBranch(url, title, SmallIcon(KMimeType::iconForURL(url)) ); + setDirOnlyMode(d->mBranch, true); + d->mBranch->setChildRecurse(false); + d->mBranch->root()->setOpen(true); + + connect(d->mBranch, SIGNAL(populateFinished(KFileTreeViewItem*) ), + this, SLOT(slotTreeViewPopulateFinished(KFileTreeViewItem*)) ); +} + + + +/** + * Override this method to make sure that the item is selected, opened and + * visible + */ +void TreeView::slotNewTreeViewItems(KFileTreeBranch* branch, const KFileTreeViewItemList& itemList) { + if( ! branch ) return; + LOG(""); + if(m_nextUrlToSelect.isEmpty()) return; + + KFileTreeViewItemListIterator it( itemList ); + + for(;it.current(); ++it ) { + KURL url = (*it)->url(); + + // This is an URL to select + // (We block signals to avoid simulating a click on the dir item) + if (m_nextUrlToSelect.equals(url,true)) { + blockSignals(true); + setCurrentItem(*it); + blockSignals(false); + + ensureItemVisible(*it); + (*it)->setOpen(true); + m_nextUrlToSelect = KURL(); + return; + } + } +} + + +/** + * Override showEvent to make sure the view shows the correct + * dir when it's shown. Since the view doesn't update if it's + * hidden + */ +void TreeView::showEvent(QShowEvent* event) { + LOG("m_nextUrlToSelect=" << m_nextUrlToSelect.pathOrURL()); + if (m_nextUrlToSelect.isValid() && !currentURL().equals(m_nextUrlToSelect,true)) { + d->setURLInternal(m_nextUrlToSelect); + } + QWidget::showEvent(event); +} + + +void TreeView::contentsDragMoveEvent(QDragMoveEvent* event) { + if (!KURLDrag::canDecode(event)) { + event->ignore(); + return; + } + + // Get a pointer to the new drop item + QPoint point(0,event->pos().y()); + KFileTreeViewItem* newDropTarget=static_cast<KFileTreeViewItem*>( itemAt(contentsToViewport(point)) ); + if (!newDropTarget) { + event->ignore(); + d->mAutoOpenTimer->stop(); + if (d->mDropTarget) { + stopAnimation(d->mDropTarget); + d->mDropTarget=0L; + } + return; + } + + event->accept(); + if (newDropTarget==d->mDropTarget) return; + if (d->mDropTarget) { + stopAnimation(d->mDropTarget); + } + + // Restart auto open timer if we are over a new item + d->mAutoOpenTimer->stop(); + d->mDropTarget=newDropTarget; + startAnimation(newDropTarget,DND_PREFIX,DND_ICON_COUNT); + d->mAutoOpenTimer->start(AUTO_OPEN_DELAY,true); +} + + +void TreeView::contentsDragLeaveEvent(QDragLeaveEvent*) { + d->mAutoOpenTimer->stop(); + if (d->mDropTarget) { + stopAnimation(d->mDropTarget); + d->mDropTarget=0L; + } +} + + +void TreeView::contentsDropEvent(QDropEvent* event) { + d->mAutoOpenTimer->stop(); + + // Get data from drop (do it before showing menu to avoid mDropTarget changes) + if (!d->mDropTarget) return; + KURL dest=d->mDropTarget->url(); + + KURL::List urls; + if (!KURLDrag::decode(event,urls)) return; + + // Show popup + bool wasMoved; + FileOperation::openDropURLMenu(this, urls, dest, &wasMoved); + + if (wasMoved) { + // If the current url was in the list, set the drop target as the new + // current item + KURL current=currentURL(); + KURL::List::ConstIterator it=urls.begin(); + for (; it!=urls.end(); ++it) { + if (current.equals(*it,true)) { + setCurrentItem(d->mDropTarget); + break; + } + } + } + + // Reset drop target + if (d->mDropTarget) { + stopAnimation(d->mDropTarget); + d->mDropTarget=0L; + } +} + + +void TreeView::autoOpenDropTarget() { + if (d->mDropTarget) { + d->mDropTarget->setOpen(true); + } +} +} // namespace diff --git a/src/app/treeview.h b/src/app/treeview.h new file mode 100644 index 0000000..e0c41c2 --- /dev/null +++ b/src/app/treeview.h @@ -0,0 +1,70 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef TREEVIEW_H +#define TREEVIEW_H + +// KDE +#include <kfiletreeview.h> + +class KURL; +class QShowEvent; + +namespace Gwenview { + + +class TreeView : public KFileTreeView { +Q_OBJECT +public: + TreeView(QWidget* parent); + ~TreeView(); + +public slots: + void setURL(const KURL&); + void createBranch(const KURL&); + +signals: + void urlChanged(const KURL&); + +protected: + virtual void showEvent(QShowEvent*); + virtual void contentsDragMoveEvent(QDragMoveEvent*); + virtual void contentsDragLeaveEvent(QDragLeaveEvent*); + virtual void contentsDropEvent(QDropEvent*); + +protected slots: + virtual void slotNewTreeViewItems(KFileTreeBranch*, const KFileTreeViewItemList&); + +private: + struct Private; + Private* d; + friend class Private; + +private slots: + // Do not name this slot "slotPopulateFinished", it will clash with + // "KFileTreeView::slotPopulateFinished". + void slotTreeViewPopulateFinished(KFileTreeViewItem*); + + void autoOpenDropTarget(); +}; + + +} // namespace +#endif diff --git a/src/app/truncatedtextlabel.h b/src/app/truncatedtextlabel.h new file mode 100644 index 0000000..81298fd --- /dev/null +++ b/src/app/truncatedtextlabel.h @@ -0,0 +1,79 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +/* +Gwenview - A simple image viewer for KDE +Copyright 2000-2004 Aur�ien G�eau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef TRUNCATEDTEXTLABEL_H +#define TRUNCATEDTEXTLABEL_H + +// Qt +#include <qlabel.h> +#include <qtooltip.h> + +// KDE +#include <kwordwrap.h> + +namespace Gwenview { + +/** + * A label which truncates it's text if it's too long, drawing it using + * KWordWrap::drawFadeoutText() + */ +class TruncatedTextLabel : public QLabel { +public: + TruncatedTextLabel(QWidget* parent) + : QLabel(parent) {} + + QSize minimumSizeHint() const { + QSize size=QLabel::minimumSizeHint(); + size.setWidth(-1); + return size; + } + + QSize sizeHint() const { + return QSize(contentsRect().width(), QLabel::sizeHint().height()); + } + + void setText(const QString& text) { + QLabel::setText(text); + updateToolTip(); + } + +protected: + void drawContents(QPainter* painter) { + KWordWrap::drawFadeoutText(painter, 0, fontMetrics().ascent(), width(), text()); + } + + void resizeEvent(QResizeEvent*) { + updateToolTip(); + } + + void updateToolTip() { + QString txt=text(); + QToolTip::remove(this); + if ( width() < fontMetrics().width(txt) ) { + QToolTip::add(this, txt); + } else { + QToolTip::hide(); + } + } +}; + +} // namespace + +#endif /* TRUNCATEDTEXTLABEL_H */ diff --git a/src/app/vtabwidget.cpp b/src/app/vtabwidget.cpp new file mode 100644 index 0000000..974dc00 --- /dev/null +++ b/src/app/vtabwidget.cpp @@ -0,0 +1,85 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ + +#include "vtabwidget.moc" + +// Qt +#include <qwidgetstack.h> + +// KDE +#include <kmultitabbar.h> + +namespace Gwenview { + + +struct VTabWidget::Private { + KMultiTabBar* mTabBar; + QWidgetStack* mStack; + bool mEmpty; +}; + + +VTabWidget::VTabWidget(QWidget* parent) +: QWidget(parent) +{ + d=new Private; + d->mEmpty=true; + d->mTabBar=new KMultiTabBar(KMultiTabBar::Vertical, this); + d->mTabBar->setPosition(KMultiTabBar::Left); + d->mTabBar->setStyle(KMultiTabBar::KDEV3ICON); + d->mStack=new QWidgetStack(this); + QHBoxLayout* layout=new QHBoxLayout(this); + layout->add(d->mTabBar); + layout->add(d->mStack); +} + + +VTabWidget::~VTabWidget() { + delete d; +} + + +void VTabWidget::addTab(QWidget* child, const QPixmap& pix, const QString& label) { + int id=d->mStack->addWidget(child); + d->mTabBar->appendTab(pix, id, label); + connect(d->mTabBar->tab(id), SIGNAL(clicked(int)), + this, SLOT(slotClicked(int)) ); + + if (d->mEmpty) { + d->mTabBar->tab(id)->setOn(true); + d->mEmpty=false; + } +} + + +void VTabWidget::slotClicked(int id) { + d->mStack->raiseWidget(id); + QPtrList<KMultiTabBarTab>* tabs=d->mTabBar->tabs(); + QPtrListIterator<KMultiTabBarTab> it(*tabs); + for (; it.current(); ++it) { + KMultiTabBarTab* tab=it.current(); + tab->setOn(tab->id()==id); + } +} + + +} // namespace diff --git a/src/app/vtabwidget.h b/src/app/vtabwidget.h new file mode 100644 index 0000000..0f177ec --- /dev/null +++ b/src/app/vtabwidget.h @@ -0,0 +1,52 @@ +// vim: set tabstop=4 shiftwidth=4 noexpandtab: +// kate: indent-mode csands; indent-width 4; replace-tabs-save off; replace-tabs off; replace-trailing-space-save off; space-indent off; tabs-indents on; tab-width 4; +/* +Gwenview - A simple image viewer for KDE +Copyright 2005 Aurelien Gateau + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +#ifndef VTABWIDGET_H +#define VTABWIDGET_H + +// Qt +#include <qwidget.h> + +class QPixmap; + +namespace Gwenview { + + +class VTabWidget : public QWidget { +Q_OBJECT +public: + VTabWidget(QWidget* parent); + virtual ~VTabWidget(); + void addTab(QWidget*, const QPixmap&, const QString& label); + +private slots: + void slotClicked(int id); + +private: + struct Private; + Private* d; +}; + + +} // namespace + + +#endif /* VTABWIDGET_H */ |