summaryrefslogtreecommitdiffstats
path: root/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/app')
-rw-r--r--src/app/.vimrc4
-rw-r--r--src/app/Makefile.am56
-rw-r--r--src/app/bookmarkdialog.cpp115
-rw-r--r--src/app/bookmarkdialog.h54
-rw-r--r--src/app/bookmarkdialogbase.ui109
-rw-r--r--src/app/bookmarkowner.cpp53
-rw-r--r--src/app/bookmarkowner.h53
-rw-r--r--src/app/bookmarkviewcontroller.cpp415
-rw-r--r--src/app/bookmarkviewcontroller.h93
-rw-r--r--src/app/configdialog.cpp306
-rw-r--r--src/app/configdialog.h65
-rw-r--r--src/app/configfileoperationspage.ui173
-rw-r--r--src/app/configfullscreenpage.ui144
-rw-r--r--src/app/configimagelistpage.ui294
-rw-r--r--src/app/configimageviewpage.ui330
-rw-r--r--src/app/configmiscpage.ui204
-rw-r--r--src/app/configslideshowpage.ui134
-rw-r--r--src/app/dirviewcontroller.cpp143
-rw-r--r--src/app/dirviewcontroller.h71
-rw-r--r--src/app/gwenviewui.rc133
-rw-r--r--src/app/history.cpp137
-rw-r--r--src/app/history.h71
-rw-r--r--src/app/kipiinterface.cpp224
-rw-r--r--src/app/kipiinterface.h62
-rw-r--r--src/app/main.cpp163
-rw-r--r--src/app/mainwindow.cpp1371
-rw-r--r--src/app/mainwindow.h222
-rw-r--r--src/app/metaedit.cpp138
-rw-r--r--src/app/metaedit.h59
-rw-r--r--src/app/testvtabwidget.cpp48
-rw-r--r--src/app/treeview.cpp342
-rw-r--r--src/app/treeview.h70
-rw-r--r--src/app/truncatedtextlabel.h79
-rw-r--r--src/app/vtabwidget.cpp85
-rw-r--r--src/app/vtabwidget.h52
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>&lt;b&gt;Moving &amp; Copying Files&lt;/b&gt;</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>&lt;b&gt;Deleting Files&lt;/b&gt;</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>&lt;b&gt;On Screen Display&lt;/b&gt;</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>&lt;qt&gt;
+You can use the following keywords to format the On Screen Display:
+&lt;ul&gt;
+&lt;li&gt;%f: filename&lt;/li&gt;
+&lt;li&gt;%p: filepath&lt;/li&gt;
+&lt;li&gt;%c: comment&lt;/li&gt;
+&lt;li&gt;%r: resolution&lt;/li&gt;
+&lt;li&gt;%n: current image position&lt;/li&gt;
+&lt;li&gt;%N: image count&lt;/li&gt;
+&lt;li&gt;%a: aperture&lt;/li&gt;
+&lt;li&gt;%t: exposure time&lt;/li&gt;
+&lt;li&gt;%i: iso&lt;/li&gt;
+&lt;li&gt;%l: focal length&lt;/li&gt;
+&lt;/ul&gt;
+&lt;/qt&gt;</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>&lt;b&gt;Thumbnail View&lt;/b&gt;</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>&lt;b&gt;Thumbnail Cache&lt;/b&gt;</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 &amp;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>&lt;b&gt;Smoothing&lt;/b&gt;</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>&lt;b&gt;Mouse Wheel Behavior over Image&lt;/b&gt;</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>&amp;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>&amp;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>&amp;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>&amp;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>&amp;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 */