diff -Nru gwenview-4.12.0/app/CMakeLists.txt gwenview-4.11.5/app/CMakeLists.txt --- gwenview-4.12.0/app/CMakeLists.txt 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/CMakeLists.txt 2014-01-02 19:32:29.000000000 +0000 @@ -18,6 +18,7 @@ set(gwenview_SRCS abstractcontextmanageritem.cpp configdialog.cpp + contextmanager.cpp gvcore.cpp documentinfoprovider.cpp viewmainpage.cpp diff -Nru gwenview-4.12.0/app/abstractcontextmanageritem.cpp gwenview-4.11.5/app/abstractcontextmanageritem.cpp --- gwenview-4.12.0/app/abstractcontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/abstractcontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -20,7 +20,7 @@ #include "abstractcontextmanageritem.moc" // Local -#include +#include "contextmanager.h" namespace Gwenview { diff -Nru gwenview-4.12.0/app/contextmanager.cpp gwenview-4.11.5/app/contextmanager.cpp --- gwenview-4.12.0/app/contextmanager.cpp 1970-01-01 00:00:00.000000000 +0000 +++ gwenview-4.11.5/app/contextmanager.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -0,0 +1,262 @@ +/* +Gwenview: an image viewer +Copyright 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#include "contextmanager.moc" + +// Qt +#include +#include +#include + +// KDE +#include +#include + +// Local +#include "sidebar.h" +#include "abstractcontextmanageritem.h" +#include +#include + +namespace Gwenview +{ + +struct ContextManagerPrivate +{ + QList mList; + SortedDirModel* mDirModel; + QItemSelectionModel* mSelectionModel; + KUrl mCurrentDirUrl; + KUrl mCurrentUrl; + + bool mSelectedFileItemListNeedsUpdate; + QSet mQueuedSignals; + KFileItemList mSelectedFileItemList; + + QTimer* mQueuedSignalsTimer; + + void queueSignal(const QByteArray& signal) + { + mQueuedSignals << signal; + mQueuedSignalsTimer->start(); + } + + void updateSelectedFileItemList() + { + if (!mSelectedFileItemListNeedsUpdate) { + return; + } + mSelectedFileItemList.clear(); + QItemSelection selection = mSelectionModel->selection(); + Q_FOREACH(const QModelIndex & index, selection.indexes()) { + mSelectedFileItemList << mDirModel->itemForIndex(index); + } + + // At least add current url if it's valid (it may not be in + // the list if we are viewing a non-browsable url, for example + // using http protocol) + if (mSelectedFileItemList.isEmpty() && mCurrentUrl.isValid()) { + KFileItem item(KFileItem::Unknown, KFileItem::Unknown, mCurrentUrl); + mSelectedFileItemList << item; + } + + mSelectedFileItemListNeedsUpdate = false; + } +}; + +ContextManager::ContextManager(SortedDirModel* dirModel, QObject* parent) +: QObject(parent) +, d(new ContextManagerPrivate) +{ + d->mQueuedSignalsTimer = new QTimer(this); + d->mQueuedSignalsTimer->setInterval(100); + d->mQueuedSignalsTimer->setSingleShot(true); + connect(d->mQueuedSignalsTimer, SIGNAL(timeout()), + SLOT(emitQueuedSignals())); + + d->mDirModel = dirModel; + connect(d->mDirModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), + SLOT(slotDirModelDataChanged(QModelIndex,QModelIndex))); + + /* HACK! In extended-selection mode, when the current index is removed, + * QItemSelectionModel selects the previous index if there is one, if not it + * selects the next index. This is not what we want: when the user removes + * an image, he expects to go to the next one, not the previous one. + * + * To overcome this, we must connect to the mDirModel.rowsAboutToBeRemoved() + * signal *before* QItemSelectionModel connects to it, so that our slot is + * called before QItemSelectionModel slot. This allows us to pick a new + * current index ourself, leaving QItemSelectionModel slot with nothing to + * do. + * + * This is the reason ContextManager creates a QItemSelectionModel itself: + * doing so ensures QItemSelectionModel cannot be connected to the + * mDirModel.rowsAboutToBeRemoved() signal before us. + */ + connect(d->mDirModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); + + d->mSelectionModel = new QItemSelectionModel(d->mDirModel); + + connect(d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + SLOT(slotSelectionChanged())); + connect(d->mSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), + SLOT(slotCurrentChanged(QModelIndex))); + + d->mSelectedFileItemListNeedsUpdate = false; +} + +ContextManager::~ContextManager() +{ + qDeleteAll(d->mList); + delete d; +} + +QItemSelectionModel* ContextManager::selectionModel() const +{ + return d->mSelectionModel; +} + +void ContextManager::addItem(AbstractContextManagerItem* item) +{ + d->mList << item; +} + +void ContextManager::setCurrentUrl(const KUrl& currentUrl) +{ + if (d->mCurrentUrl == currentUrl) { + return; + } + + d->mCurrentUrl = currentUrl; + if (!d->mCurrentUrl.isEmpty()) { + Document::Ptr doc = DocumentFactory::instance()->load(currentUrl); + QUndoGroup* undoGroup = DocumentFactory::instance()->undoGroup(); + undoGroup->addStack(doc->undoStack()); + undoGroup->setActiveStack(doc->undoStack()); + } + + d->queueSignal("selectionChanged"); +} + +KFileItemList ContextManager::selectedFileItemList() const +{ + d->updateSelectedFileItemList(); + return d->mSelectedFileItemList; +} + +void ContextManager::setCurrentDirUrl(const KUrl& url) +{ + if (url.equals(d->mCurrentDirUrl, KUrl::CompareWithoutTrailingSlash)) { + return; + } + d->mCurrentDirUrl = url; + currentDirUrlChanged(); +} + +KUrl ContextManager::currentDirUrl() const +{ + return d->mCurrentDirUrl; +} + +KUrl ContextManager::currentUrl() const +{ + return d->mCurrentUrl; +} + +SortedDirModel* ContextManager::dirModel() const +{ + return d->mDirModel; +} + +void ContextManager::slotDirModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) +{ + // Data change can happen in the following cases: + // - items have been renamed + // - item bytes have been modified + // - item meta info has been retrieved or modified + // + // If a selected item is affected, schedule emission of a + // selectionDataChanged() signal. Don't emit it directly to avoid spamming + // the context items in case of a mass change. + QModelIndexList selectionList = d->mSelectionModel->selectedIndexes(); + if (selectionList.isEmpty()) { + return; + } + + QModelIndexList changedList; + for (int row = topLeft.row(); row <= bottomRight.row(); ++row) { + changedList << d->mDirModel->index(row, 0); + } + + QModelIndexList& shortList = selectionList; + QModelIndexList& longList = changedList; + if (shortList.length() > longList.length()) { + qSwap(shortList, longList); + } + Q_FOREACH(const QModelIndex & index, shortList) { + if (longList.contains(index)) { + d->mSelectedFileItemListNeedsUpdate = true; + d->queueSignal("selectionDataChanged"); + return; + } + } +} + +void ContextManager::slotSelectionChanged() +{ + d->mSelectedFileItemListNeedsUpdate = true; + d->queueSignal("selectionChanged"); +} + +void Gwenview::ContextManager::slotCurrentChanged(const QModelIndex& index) +{ + KUrl url = d->mDirModel->urlForIndex(index); + setCurrentUrl(url); +} + +void ContextManager::emitQueuedSignals() +{ + Q_FOREACH(const QByteArray & signal, d->mQueuedSignals) { + QMetaObject::invokeMethod(this, signal.data()); + } + d->mQueuedSignals.clear(); +} + +void Gwenview::ContextManager::slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end) +{ + QModelIndex oldCurrent = d->mSelectionModel->currentIndex(); + if (oldCurrent.row() < start || oldCurrent.row() > end) { + // currentIndex has not been removed + return; + } + QModelIndex newCurrent; + if (end + 1 < d->mDirModel->rowCount()) { + newCurrent = d->mDirModel->index(end + 1, 0); + } else if (start > 0) { + newCurrent = d->mDirModel->index(start - 1, 0); + } else { + // No index we can select, nothing to do + return; + } + d->mSelectionModel->select(oldCurrent, QItemSelectionModel::Deselect); + d->mSelectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::Select); +} + +} // namespace diff -Nru gwenview-4.12.0/app/contextmanager.h gwenview-4.11.5/app/contextmanager.h --- gwenview-4.12.0/app/contextmanager.h 1970-01-01 00:00:00.000000000 +0000 +++ gwenview-4.11.5/app/contextmanager.h 2014-01-02 19:32:29.000000000 +0000 @@ -0,0 +1,88 @@ +/* +Gwenview: an image viewer +Copyright 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +*/ +#ifndef CONTEXTMANAGER_H +#define CONTEXTMANAGER_H + +// Qt +#include + +// KDE +#include +#include + +class QItemSelectionModel; +class QModelIndex; + +namespace Gwenview +{ + +class SortedDirModel; + +class AbstractContextManagerItem; + +struct ContextManagerPrivate; + +/** + * Manage the update of the contextual parts of the applications, + * like the sidebar or the context menu. + */ +class ContextManager : public QObject +{ + Q_OBJECT +public: + ContextManager(SortedDirModel*, QObject* parent); + + ~ContextManager(); + + void addItem(AbstractContextManagerItem* item); + + KUrl currentUrl() const; + + void setCurrentDirUrl(const KUrl&); + + KUrl currentDirUrl() const; + + void setCurrentUrl(const KUrl& currentUrl); + + KFileItemList selectedFileItemList() const; + + SortedDirModel* dirModel() const; + + QItemSelectionModel* selectionModel() const; + +Q_SIGNALS: + void selectionChanged(); + void selectionDataChanged(); + void currentDirUrlChanged(); + +private Q_SLOTS: + void slotDirModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); + void slotSelectionChanged(); + void slotCurrentChanged(const QModelIndex&); + void emitQueuedSignals(); + void slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end); + +private: + ContextManagerPrivate* const d; +}; + +} // namespace + +#endif /* CONTEXTMANAGER_H */ diff -Nru gwenview-4.12.0/app/fileopscontextmanageritem.cpp gwenview-4.11.5/app/fileopscontextmanageritem.cpp --- gwenview-4.12.0/app/fileopscontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/fileopscontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -50,9 +50,9 @@ #include // Local -#include #include #include +#include "contextmanager.h" #include "fileoperations.h" #include "sidebar.h" @@ -159,7 +159,7 @@ connect(contextManager(), SIGNAL(selectionChanged()), SLOT(updateActions())); - connect(contextManager(), SIGNAL(currentDirUrlChanged(KUrl)), + connect(contextManager(), SIGNAL(currentDirUrlChanged()), SLOT(updateActions())); KActionCategory* file = new KActionCategory(i18nc("@title actions category", "File"), actionCollection); diff -Nru gwenview-4.12.0/app/folderviewcontextmanageritem.cpp gwenview-4.11.5/app/folderviewcontextmanageritem.cpp --- gwenview-4.12.0/app/folderviewcontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/folderviewcontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -31,8 +31,8 @@ #include // Local -#include #include +#include "contextmanager.h" #include "sidebar.h" #include "fileoperations.h" @@ -222,8 +222,8 @@ d->setupView(); - connect(contextManager(), SIGNAL(currentDirUrlChanged(KUrl)), - SLOT(slotCurrentDirUrlChanged(KUrl))); + connect(contextManager(), SIGNAL(currentDirUrlChanged()), + SLOT(slotCurrentDirUrlChanged())); } FolderViewContextManagerItem::~FolderViewContextManagerItem() @@ -231,8 +231,9 @@ delete d; } -void FolderViewContextManagerItem::slotCurrentDirUrlChanged(const KUrl& url) +void FolderViewContextManagerItem::slotCurrentDirUrlChanged() { + KUrl url = contextManager()->currentDirUrl(); if (url.isValid() && d->mUrlToSelect != url) { d->mUrlToSelect = url; d->mUrlToSelect.cleanPath(); diff -Nru gwenview-4.12.0/app/folderviewcontextmanageritem.h gwenview-4.11.5/app/folderviewcontextmanageritem.h --- gwenview-4.12.0/app/folderviewcontextmanageritem.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/folderviewcontextmanageritem.h 2014-01-02 19:32:29.000000000 +0000 @@ -47,7 +47,7 @@ void urlChanged(const KUrl&); private Q_SLOTS: - void slotCurrentDirUrlChanged(const KUrl&); + void slotCurrentDirUrlChanged(); void expandToSelectedUrl(); void slotRowsInserted(const QModelIndex&, int start, int end); void slotActivated(const QModelIndex&); diff -Nru gwenview-4.12.0/app/fullscreencontent.h gwenview-4.11.5/app/fullscreencontent.h --- gwenview-4.12.0/app/fullscreencontent.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/fullscreencontent.h 2014-01-02 19:32:29.000000000 +0000 @@ -56,13 +56,12 @@ ThumbnailBarView* thumbnailBar() const; + void setCurrentUrl(const KUrl&); + void setDistractionFreeMode(bool); void setFullScreenMode(bool); -public Q_SLOTS: - void setCurrentUrl(const KUrl&); - private Q_SLOTS: void updateCurrentUrlWidgets(); void updateInformationLabel(); diff -Nru gwenview-4.12.0/app/gvcore.cpp gwenview-4.11.5/app/gvcore.cpp --- gwenview-4.12.0/app/gvcore.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/gvcore.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -351,6 +351,24 @@ d->mDirModel->setData(index, rating, SemanticInfoDirModel::RatingRole); } +bool GvCore::ensureDocumentIsEditable(const KUrl& url) +{ + // FIXME: Replace with a CheckEditableJob? + // This way we can factorize the error message + Document::Ptr doc = DocumentFactory::instance()->load(url); + doc->startLoadingFullImage(); + doc->waitUntilLoaded(); + if (doc->isEditable()) { + return true; + } + + KMessageBox::sorry( + QApplication::activeWindow(), + i18nc("@info", "Gwenview cannot edit this kind of image.") + ); + return false; +} + static void clearModel(QAbstractItemModel* model) { model->removeRows(0, model->rowCount()); diff -Nru gwenview-4.12.0/app/gvcore.h gwenview-4.11.5/app/gvcore.h --- gwenview-4.12.0/app/gvcore.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/gvcore.h 2014-01-02 19:32:29.000000000 +0000 @@ -64,6 +64,13 @@ void addUrlToRecentFolders(KUrl); void addUrlToRecentUrls(const KUrl& url); + /** + * Checks if the document referenced by url is editable, shows a sorry + * dialog if it's not. + * @return true if editable, false if not + */ + static bool ensureDocumentIsEditable(const KUrl& url); + QPalette palette(PaletteType type) const; public Q_SLOTS: diff -Nru gwenview-4.12.0/app/imageopscontextmanageritem.cpp gwenview-4.11.5/app/imageopscontextmanageritem.cpp --- gwenview-4.12.0/app/imageopscontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/imageopscontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -22,7 +22,6 @@ #include "imageopscontextmanageritem.moc" // Qt -#include // KDE #include @@ -34,11 +33,11 @@ #include // Local +#include "contextmanager.h" #include "viewmainpage.h" #include "gvcore.h" #include "mainwindow.h" #include "sidebar.h" -#include #include #include #include @@ -130,18 +129,7 @@ bool ensureEditable() { KUrl url = q->contextManager()->currentUrl(); - Document::Ptr doc = DocumentFactory::instance()->load(url); - doc->startLoadingFullImage(); - doc->waitUntilLoaded(); - if (doc->isEditable()) { - return true; - } - - KMessageBox::sorry( - QApplication::activeWindow(), - i18nc("@info", "Gwenview cannot edit this kind of image.") - ); - return false; + return GvCore::ensureDocumentIsEditable(url); } }; @@ -185,7 +173,7 @@ void ImageOpsContextManagerItem::updateActions() { - bool canModify = contextManager()->currentUrlIsRasterImage(); + bool canModify = d->mMainWindow->currentDocumentIsRasterImage(); bool viewMainPageIsVisible = d->mMainWindow->viewMainPage()->isVisible(); if (!viewMainPageIsVisible) { // Since we only support image operations on one image for now, diff -Nru gwenview-4.12.0/app/infocontextmanageritem.cpp gwenview-4.11.5/app/infocontextmanageritem.cpp --- gwenview-4.12.0/app/infocontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/infocontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -37,12 +36,11 @@ #include // Local +#include "contextmanager.h" #include "imagemetainfodialog.h" #include "sidebar.h" #include -#include #include -#include #include #include #include @@ -61,26 +59,87 @@ #endif /** + * A label which fades out if its content does not fit. If the content is + * cropped, a tooltip is shown when the mouse hovers the widget. + */ +class FadingLabel : public QLabel +{ +public: + explicit FadingLabel(QWidget* parent = 0) + : QLabel(parent) + { + setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + setTextInteractionFlags(Qt::TextBrowserInteraction); + } + + QSize minimumSizeHint() const + { + return QSize(); + } + +protected: + void paintEvent(QPaintEvent* event) + { + QLabel::paintEvent(event); + if (!isCropped()) { + return; + } + + QLinearGradient gradient; + int gradientWidth = fontMetrics().averageCharWidth() * 4; + if (alignment() & Qt::AlignLeft) { + gradient.setStart(width() - gradientWidth, 0); + gradient.setFinalStop(width(), 0); + gradient.setColorAt(0, Qt::transparent); + gradient.setColorAt(1, palette().color(backgroundRole())); + } else { + gradient.setStart(0, 0); + gradient.setFinalStop(gradientWidth, 0); + gradient.setColorAt(0, palette().color(backgroundRole())); + gradient.setColorAt(1, Qt::transparent); + } + QPainter painter(this); + painter.fillRect(rect(), gradient); + } + + bool event(QEvent* event) + { + if (event->type() == QEvent::ToolTip) { + // Show tooltip if cropped + QHelpEvent* helpEvent = static_cast(event); + if (isCropped()) { + QToolTip::showText(helpEvent->globalPos(), text()); + } else { + QToolTip::hideText(); + event->ignore(); + } + return true; + } + return QLabel::event(event); + } + + inline bool isCropped() const + { + return sizeHint().width() > width(); + } +}; + +/** * This widget is capable of showing multiple lines of key/value pairs. */ class KeyValueWidget : public QWidget { struct Row { - Row(QWidget* parent) - : keyLabel(new QLabel(parent)) - , valueLabel(new QLabel(parent)) + Row() + : keyLabel(new FadingLabel) + , valueLabel(new FadingLabel) { - initLabel(keyLabel); - initLabel(valueLabel); - - QPalette pal = keyLabel->palette(); - QColor color = pal.color(QPalette::WindowText); - color.setAlphaF(0.65); - pal.setColor(QPalette::WindowText, color); - keyLabel->setPalette(pal); - - valueLabel->setContentsMargins(6, 0, 0, 6); + if (QApplication::isLeftToRight()) { + keyLabel->setAlignment(Qt::AlignRight); + } else { + valueLabel->setAlignment(Qt::AlignRight); + } } ~Row() @@ -89,102 +148,75 @@ delete valueLabel; } - int setLabelGeometries(int rowY, int labelWidth) - { - int labelHeight = keyLabel->heightForWidth(labelWidth); - keyLabel->setGeometry(0, rowY, labelWidth, labelHeight); - rowY += labelHeight; - labelHeight = valueLabel->heightForWidth(labelWidth); - valueLabel->setGeometry(0, rowY, labelWidth, labelHeight); - rowY += labelHeight; - return rowY; - } - - int heightForWidth(int width) const - { - return keyLabel->heightForWidth(width) + valueLabel->heightForWidth(width); - } - - static void initLabel(QLabel* label) - { - label->setWordWrap(true); - label->show(); - label->setTextInteractionFlags(Qt::TextSelectableByMouse | Qt::LinksAccessibleByMouse); - } - - QLabel* keyLabel; - QLabel* valueLabel; + FadingLabel* keyLabel; + FadingLabel* valueLabel; }; public: KeyValueWidget(QWidget* parent) : QWidget(parent) + , mLayout(new QGridLayout(this)) { - QSizePolicy policy(QSizePolicy::Preferred, QSizePolicy::Fixed); - policy.setHeightForWidth(true); - setSizePolicy(policy); + mLayout->setMargin(0); + mLayout->setVerticalSpacing(0); + mLayout->setHorizontalSpacing(4); + setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); } QSize sizeHint() const { - int width = 150; - int height = heightForWidth(width); - return QSize(width, height); - } - - int heightForWidth(int w) const - { - int height = 0; - Q_FOREACH(Row* row, mRows) { - height += row->heightForWidth(w); - } - return height; - } - - void clear() - { - qDeleteAll(mRows); - mRows.clear(); - updateGeometry(); + int height = fontMetrics().height() * mRows.count(); + return QSize(150, height); } void addRow(const QString& key, const QString& value) { - Row* row = new Row(this); + Row* row = new Row; row->keyLabel->setText(i18nc( - "@item:intext %1 is a key, we append a colon to it. A value is displayed after", - "%1:", key)); + "@item:intext %1 is a key, we append a colon to it. A value is displayed after", + "%1:", key)); row->valueLabel->setText(value); - mRows << row; + mRows.append(row); + + int rowCount = mLayout->rowCount(); + mLayout->addWidget(row->keyLabel, rowCount, 0); + mLayout->addWidget(row->valueLabel, rowCount, 1); + updateKeyColumnWidth(); updateGeometry(); } - void layoutRows() + void clear() { - // Layout labels manually: I tried to use a QVBoxLayout but for some - // reason when using software animations the widget blinks when going - // from one image to another - int rowY = 0; - const int labelWidth = width(); - Q_FOREACH(Row* row, mRows) { - rowY = row->setLabelGeometries(rowY, labelWidth); - } + qDeleteAll(mRows); + mRows.clear(); + updateGeometry(); } protected: - void showEvent(QShowEvent* event) - { - QWidget::showEvent(event); - layoutRows(); - } - void resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); - layoutRows(); + updateKeyColumnWidth(); + updateGeometry(); } private: - QVector mRows; + QList mRows; + QGridLayout* mLayout; + + void updateKeyColumnWidth() + { + const int maxWidth = width() / 2; + int keyWidth = 0; + Q_FOREACH(Row * row, mRows) { + int wantedWidth = row->keyLabel->sizeHint().width(); + if (wantedWidth > keyWidth) { + keyWidth = qMin(wantedWidth, maxWidth); + } + } + Q_FOREACH(Row * row, mRows) { + row->keyLabel->setFixedWidth(keyWidth); + } + } }; struct InfoContextManagerItemPrivate @@ -339,17 +371,20 @@ return; } - ImageMetaInfoModel* metaInfoModel = d->mDocument->metaInfo(); + QStringList list; d->mKeyValueWidget->clear(); + ImageMetaInfoModel* metaInfoModel = d->mDocument->metaInfo(); Q_FOREACH(const QString & key, GwenviewConfig::preferredMetaInfoKeyList()) { QString label; QString value; metaInfoModel->getInfoForKey(key, &label, &value); + if (!label.isEmpty() && !value.isEmpty()) { d->mKeyValueWidget->addRow(label, value); } } - d->mKeyValueWidget->layoutRows(); + + d->mKeyValueWidget->show(); } void InfoContextManagerItem::showMetaInfoDialog() diff -Nru gwenview-4.12.0/app/kipiinterface.cpp gwenview-4.11.5/app/kipiinterface.cpp --- gwenview-4.12.0/app/kipiinterface.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/kipiinterface.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -44,9 +44,9 @@ // local #include "mainwindow.h" +#include "contextmanager.h" #include "kipiimagecollectionselector.h" #include "kipiuploadwidget.h" -#include #include #include #include @@ -252,7 +252,7 @@ d->setupPluginsMenu(); QObject::connect(d->mMainWindow->contextManager(), SIGNAL(selectionChanged()), this, SLOT(slotSelectionChanged())); - QObject::connect(d->mMainWindow->contextManager(), SIGNAL(currentDirUrlChanged(KUrl)), + QObject::connect(d->mMainWindow->contextManager(), SIGNAL(currentDirUrlChanged()), this, SLOT(slotDirectoryChanged())); #if 0 //TODO instead of delaying can we load them all at start-up to use actions somewhere else? diff -Nru gwenview-4.12.0/app/mainwindow.cpp gwenview-4.11.5/app/mainwindow.cpp --- gwenview-4.12.0/app/mainwindow.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/mainwindow.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -62,6 +62,7 @@ // Local #include "configdialog.h" +#include "contextmanager.h" #include "documentinfoprovider.h" #include "viewmainpage.h" #include "fileopscontextmanageritem.h" @@ -88,7 +89,6 @@ #include "thumbnailviewhelper.h" #include "browsemainpage.h" #include -#include #include #include #include @@ -210,6 +210,8 @@ MainWindowState mStateBeforeFullScreen; + KUrl mUrlToSelect; + QString mCaption; MainPageId mCurrentMainPageId; @@ -217,19 +219,9 @@ QDateTime mFullScreenLeftAt; KNotificationRestrictions* mNotificationRestrictions; - void setupContextManager() - { - mContextManager = new ContextManager(mDirModel, q); - connect(mContextManager, SIGNAL(selectionChanged()), - q, SLOT(slotSelectionChanged())); - connect(mContextManager, SIGNAL(currentDirUrlChanged(KUrl)), - q, SLOT(slotCurrentDirUrlChanged(KUrl))); - } - void setupWidgets() { mFullScreenContent = new FullScreenContent(q); - connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mFullScreenContent, SLOT(setCurrentUrl(KUrl))); mCentralSplitter = new Splitter(Qt::Horizontal, q); q->setCentralWidget(mCentralSplitter); @@ -243,7 +235,6 @@ mContentWidget = new QWidget(mCentralSplitter); mSaveBar = new SaveBar(mContentWidget, q->actionCollection()); - connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mSaveBar, SLOT(setCurrentUrl(KUrl))); mViewStackedWidget = new QStackedWidget(mContentWidget); QVBoxLayout* layout = new QVBoxLayout(mContentWidget); layout->addWidget(mSaveBar); @@ -254,7 +245,6 @@ mStartSlideShowWhenDirListerCompleted = false; mSlideShow = new SlideShow(q); - connect(mContextManager, SIGNAL(currentUrlChanged(KUrl)), mSlideShow, SLOT(setCurrentUrl(KUrl))); setupThumbnailView(mViewStackedWidget); setupViewMainPage(mViewStackedWidget); @@ -289,8 +279,6 @@ mThumbnailView->setDocumentInfoProvider(mDocumentInfoProvider); mThumbnailViewHelper = new ThumbnailViewHelper(mDirModel, q->actionCollection()); - connect(mContextManager, SIGNAL(currentDirUrlChanged(KUrl)), - mThumbnailViewHelper, SLOT(setCurrentDirUrl(KUrl))); mThumbnailView->setThumbnailViewHelper(mThumbnailViewHelper); mThumbnailBarSelectionModel = new KLinkItemSelectionModel(mThumbnailBarModel, mContextManager->selectionModel(), q); @@ -298,6 +286,8 @@ // Connect thumbnail view connect(mThumbnailView, SIGNAL(indexActivated(QModelIndex)), q, SLOT(slotThumbnailViewIndexActivated(QModelIndex))); + connect(mThumbnailView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + q, SLOT(slotSelectionChanged())); // Connect delegate QAbstractItemDelegate* delegate = mThumbnailView->itemDelegate(); @@ -504,10 +494,12 @@ // Create context manager items FolderViewContextManagerItem* folderViewItem = new FolderViewContextManagerItem(mContextManager); + mContextManager->addItem(folderViewItem); connect(folderViewItem, SIGNAL(urlChanged(KUrl)), q, SLOT(openDirUrl(KUrl))); InfoContextManagerItem* infoItem = new InfoContextManagerItem(mContextManager); + mContextManager->addItem(infoItem); #ifndef GWENVIEW_SEMANTICINFO_BACKEND_NONE SemanticInfoContextManagerItem* semanticInfoItem = 0; @@ -521,12 +513,17 @@ #ifdef GWENVIEW_SEMANTICINFO_BACKEND_NEPOMUK } #endif + if (semanticInfoItem) { + mContextManager->addItem(semanticInfoItem); + } #endif ImageOpsContextManagerItem* imageOpsItem = new ImageOpsContextManagerItem(mContextManager, q); + mContextManager->addItem(imageOpsItem); FileOpsContextManagerItem* fileOpsItem = new FileOpsContextManagerItem(mContextManager, mThumbnailView, actionCollection, q); + mContextManager->addItem(fileOpsItem); // Fill sidebar SideBarPage* page; @@ -574,6 +571,8 @@ connect(mDirModel->dirLister(), SIGNAL(completed()), q, SLOT(slotDirListerCompleted())); + connect(mDirModel->dirLister(), SIGNAL(redirection(KUrl)), + q, SLOT(slotDirListerRedirection(KUrl))); } void setupThumbnailBarModel() @@ -582,6 +581,12 @@ mThumbnailBarModel->setSourceModel(mDirModel); } + QModelIndex currentIndex() const + { + KUrl url = currentUrl(); + return url.isValid() ? mDirModel->indexForUrl(url) : QModelIndex(); + } + bool indexIsDirOrArchive(const QModelIndex& index) const { Q_ASSERT(index.isValid()); @@ -601,7 +606,7 @@ void goTo(int offset) { mPreloadDirectionIsForward = offset > 0; - QModelIndex index = mContextManager->selectionModel()->currentIndex(); + QModelIndex index = currentIndex(); index = mDirModel->index(index.row() + offset, 0); if (index.isValid() && !indexIsDirOrArchive(index)) { goTo(index); @@ -656,6 +661,18 @@ mViewMainPage->showMessageWidget(hud, Qt::AlignCenter); } + void spreadCurrentDirUrl(const KUrl& url) + { + mContextManager->setCurrentDirUrl(url); + mThumbnailViewHelper->setCurrentDirUrl(url); + if (url.isValid()) { + mUrlNavigator->setLocationUrl(url); + mGoUpAction->setEnabled(url.path() != "/"); + } else { + mGoUpAction->setEnabled(false); + } + } + void setupFullScreenContent() { mFullScreenContent->init(q->actionCollection(), mViewMainPage, mSlideShow); @@ -690,10 +707,10 @@ bool isRasterImage = false; bool canSave = false; bool isModified = false; - const KUrl url = mContextManager->currentUrl(); + const KUrl url = currentUrl(); if (url.isValid()) { - isRasterImage = mContextManager->currentUrlIsRasterImage(); + isRasterImage = q->currentDocumentIsRasterImage(); canSave = isRasterImage; isModified = DocumentFactory::instance()->load(url)->isModified(); if (mCurrentMainPageId != ViewMainPageId) { @@ -712,6 +729,74 @@ actionCollection->action("file_print")->setEnabled(isRasterImage); } + KUrl currentUrl() const + { + if (mCurrentMainPageId == StartMainPageId) { + return KUrl(); + } + + if (mUrlToSelect.isValid()) { + // We are supposed to select this url whenever it appears in the + // dir model. For everyone it is as if it was already the current one + return mUrlToSelect; + } + + // mBrowseMainPage and mViewMainPage urls are almost always synced, but + // mBrowseMainPage can be more up-to-date because mViewMainPage + // url is only updated when the DocumentView starts to load the + // document. + // This is why we only thrust mViewMainPage url if it shows an url + // which can't be listed: in this case mBrowseMainPage url is + // empty. + if (mCurrentMainPageId == ViewMainPageId && !mViewMainPage->isEmpty()) { + KUrl url = mViewMainPage->url(); + if (!KProtocolManager::supportsListing(url)) { + return url; + } + } + + QModelIndex index = mThumbnailView->currentIndex(); + if (!index.isValid()) { + return KUrl(); + } + // Ignore the current index if it's not part of the selection. This + // situation can happen when you select an image, then click on the + // background of the thumbnail view. + if (mCurrentMainPageId == BrowseMainPageId && !mThumbnailView->selectionModel()->isSelected(index)) { + return KUrl(); + } + KFileItem item = mDirModel->itemForIndex(index); + Q_ASSERT(!item.isNull()); + return item.url(); + } + + void setUrlToSelect(const KUrl& url) + { + GV_RETURN_IF_FAIL(url.isValid()); + mUrlToSelect = url; + updateContextDependentComponents(); + selectUrlToSelect(); + } + + void selectUrlToSelect() + { + QModelIndex index = mDirModel->indexForUrl(mUrlToSelect); + if (index.isValid()) { + // Note: calling setCurrentIndex also takes care of selecting the index + mThumbnailView->setCurrentIndex(index); + mUrlToSelect = KUrl(); + } + } + + void updateContextDependentComponents() + { + KUrl url = currentUrl(); + mContextManager->setCurrentUrl(url); + mSaveBar->setCurrentUrl(url); + mSlideShow->setCurrentUrl(url); + mFullScreenContent->setCurrentUrl(url); + } + const char* sideBarConfigGroupName() const { const char* name = 0; @@ -802,7 +887,7 @@ d->q = this; d->mCurrentMainPageId = StartMainPageId; d->mDirModel = new SortedDirModel(this); - d->setupContextManager(); + d->mContextManager = new ContextManager(d->mDirModel, this); d->setupThumbnailBarModel(); d->mGvCore = new GvCore(this, d->mDirModel); d->mPreloader = new Preloader(this); @@ -848,6 +933,25 @@ return d->mViewMainPage; } +bool MainWindow::currentDocumentIsRasterImage() const +{ + if (d->mCurrentMainPageId == ViewMainPageId) { + Document::Ptr doc = d->mViewMainPage->currentDocument(); + if (!doc) { + return false; + } + return doc->kind() == MimeTypeUtils::KIND_RASTER_IMAGE; + } else { + QModelIndex index = d->mThumbnailView->currentIndex(); + if (!index.isValid()) { + return false; + } + KFileItem item = d->mDirModel->itemForIndex(index); + Q_ASSERT(!item.isNull()); + return MimeTypeUtils::fileItemKind(item) == MimeTypeUtils::KIND_RASTER_IMAGE; + } +} + void MainWindow::setCaption(const QString& caption) { // Keep a trace of caption to use it in slotModifiedDocumentListChanged() @@ -884,8 +988,9 @@ } else { d->mViewAction->trigger(); d->mViewMainPage->openUrl(url); - d->mContextManager->setUrlToSelect(url); + d->setUrlToSelect(url); } + d->updateContextDependentComponents(); } void MainWindow::startSlideShow() @@ -1016,7 +1121,7 @@ void MainWindow::goUp() { if (d->mCurrentMainPageId == BrowseMainPageId) { - KUrl url = d->mContextManager->currentDirUrl(); + KUrl url = d->mDirModel->dirLister()->url(); url = url.upUrl(); openDirUrl(url); } else { @@ -1031,14 +1136,14 @@ d->mCurrentMainPageId = StartMainPageId; } d->setActionsDisabledOnStartMainPageEnabled(false); + d->spreadCurrentDirUrl(KUrl()); d->mSideBar->hide(); d->mViewStackedWidget->setCurrentWidget(d->mStartMainPage); d->updateActions(); updatePreviousNextActions(); - d->mContextManager->setCurrentDirUrl(KUrl()); - d->mContextManager->setCurrentUrl(KUrl()); + d->updateContextDependentComponents(); d->autoAssignThumbnailProvider(); } @@ -1080,10 +1185,11 @@ const QString pathToSelect = currentPath.section(separator, 0, slashCount + 1); KUrl urlToSelect = url; urlToSelect.setPath(pathToSelect); - d->mContextManager->setUrlToSelect(urlToSelect); + d->setUrlToSelect(urlToSelect); } d->mThumbnailProvider->stop(); - d->mContextManager->setCurrentDirUrl(url); + d->mDirModel->dirLister()->openUrl(url); + d->spreadCurrentDirUrl(url); d->mGvCore->addUrlToRecentFolders(url); d->mViewMainPage->reset(); } @@ -1126,7 +1232,7 @@ KUrl dirUrl = url; dirUrl.setFileName(QString()); - if (dirUrl.equals(d->mContextManager->currentDirUrl(), KUrl::CompareWithoutTrailingSlash)) { + if (dirUrl.equals(d->mDirModel->dirLister()->url(), KUrl::CompareWithoutTrailingSlash)) { QModelIndex index = d->mDirModel->indexForUrl(url); QItemSelectionModel* selectionModel = d->mThumbnailView->selectionModel(); if (index.isValid() && !selectionModel->isSelected(index)) { @@ -1134,7 +1240,8 @@ //selectionModel->select(index, QItemSelectionModel::SelectCurrent); } } else { - d->mContextManager->setCurrentDirUrl(dirUrl); + d->mDirModel->dirLister()->openUrl(dirUrl); + d->spreadCurrentDirUrl(dirUrl); d->mGvCore->addUrlToRecentFolders(dirUrl); } } @@ -1167,24 +1274,18 @@ // Update UI d->updateActions(); updatePreviousNextActions(); + d->updateContextDependentComponents(); // Start preloading int preloadDelay = d->mCurrentMainPageId == ViewMainPageId ? VIEW_PRELOAD_DELAY : BROWSE_PRELOAD_DELAY; QTimer::singleShot(preloadDelay, this, SLOT(preloadNextUrl())); } -void MainWindow::slotCurrentDirUrlChanged(const KUrl& url) -{ - if (url.isValid()) { - d->mUrlNavigator->setLocationUrl(url); - d->mGoUpAction->setEnabled(url.path() != "/"); - } else { - d->mGoUpAction->setEnabled(false); - } -} - void MainWindow::slotDirModelNewItems() { + if (d->mUrlToSelect.isValid()) { + d->selectUrlToSelect(); + } if (d->mThumbnailView->selectionModel()->hasSelection()) { updatePreviousNextActions(); } @@ -1198,13 +1299,18 @@ } if (d->mThumbnailView->selectionModel()->hasSelection()) { updatePreviousNextActions(); - } else if (!d->mContextManager->urlToSelect().isValid()) { + } else if (!d->mUrlToSelect.isValid()) { d->goToFirstDocument(); } d->mThumbnailView->scrollToSelectedIndex(); d->mViewMainPage->thumbnailBar()->scrollToSelectedIndex(); } +void MainWindow::slotDirListerRedirection(const KUrl& newUrl) +{ + d->spreadCurrentDirUrl(newUrl); +} + void MainWindow::goToPrevious() { d->goTo(-1); @@ -1233,27 +1339,20 @@ KUrl dirUrl = url; dirUrl.setFileName(""); if (!dirUrl.equals(d->mContextManager->currentDirUrl(), KUrl::CompareWithoutTrailingSlash)) { - d->mContextManager->setCurrentDirUrl(dirUrl); + d->mDirModel->dirLister()->openUrl(dirUrl); + d->spreadCurrentDirUrl(dirUrl); d->mGvCore->addUrlToRecentFolders(dirUrl); } - d->mContextManager->setUrlToSelect(url); + d->setUrlToSelect(url); } void MainWindow::updatePreviousNextActions() { - bool hasPrevious; - bool hasNext; - QModelIndex currentIndex = d->mContextManager->selectionModel()->currentIndex(); - if (currentIndex.isValid() && !d->indexIsDirOrArchive(currentIndex)) { - int row = currentIndex.row(); - QModelIndex prevIndex = d->mDirModel->index(row - 1, 0); - QModelIndex nextIndex = d->mDirModel->index(row + 1, 0); - hasPrevious = prevIndex.isValid() && !d->indexIsDirOrArchive(prevIndex); - hasNext = nextIndex.isValid() && !d->indexIsDirOrArchive(nextIndex); - } else { - hasPrevious = false; - hasNext = false; - } + int row = d->currentIndex().row(); + QModelIndex prevIndex = d->mDirModel->index(row - 1, 0); + QModelIndex nextIndex = d->mDirModel->index(row + 1, 0); + bool hasPrevious = prevIndex.isValid() && !d->indexIsDirOrArchive(prevIndex); + bool hasNext = nextIndex.isValid() && !d->indexIsDirOrArchive(nextIndex); bool canBrowse = hasPrevious | hasNext; d->mGoToPreviousAction->setEnabled(canBrowse); @@ -1328,12 +1427,12 @@ void MainWindow::saveCurrent() { - d->mGvCore->save(d->mContextManager->currentUrl()); + d->mGvCore->save(d->currentUrl()); } void MainWindow::saveCurrentAs() { - d->mGvCore->saveAs(d->mContextManager->currentUrl()); + d->mGvCore->saveAs(d->currentUrl()); } void MainWindow::reload() @@ -1347,7 +1446,7 @@ void MainWindow::openFile() { - KUrl dirUrl = d->mContextManager->currentDirUrl(); + KUrl dirUrl = d->mDirModel->dirLister()->url(); KFileDialog dialog(dirUrl, QString(), this); dialog.setCaption(i18nc("@title:window", "Open Image")); @@ -1362,13 +1461,14 @@ KUrl url = dialog.selectedUrl(); d->mViewAction->trigger(); d->mViewMainPage->openUrl(url); - d->mContextManager->setUrlToSelect(url); + d->setUrlToSelect(url); + d->updateContextDependentComponents(); } void MainWindow::showDocumentInFullScreen(const KUrl& url) { d->mViewMainPage->openUrl(url); - d->mContextManager->setUrlToSelect(url); + d->setUrlToSelect(url); d->mFullScreenAction->trigger(); } @@ -1494,11 +1594,11 @@ void MainWindow::print() { - if (!d->mContextManager->currentUrlIsRasterImage()) { + if (!currentDocumentIsRasterImage()) { return; } - Document::Ptr doc = DocumentFactory::instance()->load(d->mContextManager->currentUrl()); + Document::Ptr doc = DocumentFactory::instance()->load(d->currentUrl()); PrintHelper printHelper(this); printHelper.print(doc); } @@ -1579,7 +1679,7 @@ void MainWindow::saveProperties(KConfigGroup& group) { group.writeEntry(SESSION_CURRENT_PAGE_KEY, int(d->mCurrentMainPageId)); - group.writeEntry(SESSION_URL_KEY, d->mContextManager->currentUrl()); + group.writeEntry(SESSION_URL_KEY, d->currentUrl()); } void MainWindow::readProperties(const KConfigGroup& group) diff -Nru gwenview-4.12.0/app/mainwindow.h gwenview-4.11.5/app/mainwindow.h --- gwenview-4.12.0/app/mainwindow.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/mainwindow.h 2014-01-02 19:32:29.000000000 +0000 @@ -53,6 +53,8 @@ ContextManager* contextManager() const; + bool currentDocumentIsRasterImage() const; + void setDistractionFreeMode(bool); public Q_SLOTS: @@ -91,12 +93,28 @@ void toggleSideBar(bool visible); void updateToggleSideBarAction(); void slotModifiedDocumentListChanged(); + + /** + * Init all the file list stuff. This should only be necessary when + * Gwenview is started with an image as a parameter (in this case we load + * the image before looking at the content of the image folder) + */ void slotPartCompleted(); + + /** + * If an image is loaded but there is no item selected for it in the file + * view, this function will select the corresponding item if it comes up in + * list. + */ void slotDirModelNewItems(); + + /** + * If no image is selected, select the first one available. + */ void slotDirListerCompleted(); + void slotDirListerRedirection(const KUrl& newUrl); void slotSelectionChanged(); - void slotCurrentDirUrlChanged(const KUrl& url); void goToPrevious(); void goToNext(); diff -Nru gwenview-4.12.0/app/savebar.h gwenview-4.11.5/app/savebar.h --- gwenview-4.12.0/app/savebar.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/savebar.h 2014-01-02 19:32:29.000000000 +0000 @@ -47,11 +47,10 @@ */ void initActionDependentWidgets(); - void setFullScreenMode(bool); - -public Q_SLOTS: void setCurrentUrl(const KUrl&); + void setFullScreenMode(bool); + Q_SIGNALS: void requestSaveAll(); void goToUrl(const KUrl&); diff -Nru gwenview-4.12.0/app/semanticinfocontextmanageritem.cpp gwenview-4.11.5/app/semanticinfocontextmanageritem.cpp --- gwenview-4.12.0/app/semanticinfocontextmanageritem.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/semanticinfocontextmanageritem.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -39,11 +39,11 @@ #include // Local +#include "contextmanager.h" #include "viewmainpage.h" #include "sidebar.h" #include "ui_semanticinfosidebaritem.h" #include "ui_semanticinfodialog.h" -#include #include #include #include @@ -265,7 +265,7 @@ SLOT(slotSelectionChanged())); connect(contextManager(), SIGNAL(selectionDataChanged()), SLOT(update())); - connect(contextManager(), SIGNAL(currentDirUrlChanged(KUrl)), + connect(contextManager(), SIGNAL(currentDirUrlChanged()), SLOT(update())); d->setupActions(); diff -Nru gwenview-4.12.0/app/thumbnailviewhelper.h gwenview-4.11.5/app/thumbnailviewhelper.h --- gwenview-4.12.0/app/thumbnailviewhelper.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/thumbnailviewhelper.h 2014-01-02 19:32:29.000000000 +0000 @@ -49,7 +49,6 @@ virtual void showMenuForUrlDroppedOnDir(QWidget* parent, const KUrl::List&, const KUrl&); -public Q_SLOTS: void setCurrentDirUrl(const KUrl&); private: diff -Nru gwenview-4.12.0/app/viewmainpage.cpp gwenview-4.11.5/app/viewmainpage.cpp --- gwenview-4.12.0/app/viewmainpage.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/app/viewmainpage.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -362,12 +362,11 @@ mSynchronizer->setCurrentView(view); QModelIndex index = indexForView(view); - if (index.isValid()) { - // Index may be invalid when Gwenview is started as - // `gwenview /foo/image.png` because in this situation it loads image.png - // *before* listing /foo (because it matters less to the user) - mThumbnailBar->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current); + if (!index.isValid()) { + kWarning() << "No index found for current view"; + return; } + mThumbnailBar->selectionModel()->setCurrentIndex(index, QItemSelectionModel::Current); Q_ASSERT(mActivityResources.contains(view)); mActivityResources.value(view)->notifyFocusedIn(); diff -Nru gwenview-4.12.0/debian/changelog gwenview-4.11.5/debian/changelog --- gwenview-4.12.0/debian/changelog 2013-12-15 09:53:33.000000000 +0000 +++ gwenview-4.11.5/debian/changelog 2014-01-06 16:38:11.000000000 +0000 @@ -1,43 +1,14 @@ -gwenview (4:4.12.0-0ubuntu1~ubuntu13.10~ppa1) saucy; urgency=low +gwenview (4:4.11.5-0ubuntu0.1~ubuntu13.10~ppa2) saucy; urgency=medium - * saucy backport + * New upstream bugfix release (LP: #1266285) - -- Jonathan Riddell Sun, 15 Dec 2013 09:53:33 +0000 + -- Philip Muškovac Sun, 05 Jan 2014 23:16:53 +0100 -gwenview (4:4.12.0-0ubuntu1~ubuntu14.04~ppa1) trusty; urgency=low +gwenview (4:4.11.3-0ubuntu0.1) saucy; urgency=low - * New upstream release - - -- Jonathan Riddell Thu, 12 Dec 2013 15:47:51 +0000 - -gwenview (4:4.11.97-0ubuntu1) trusty; urgency=low - - * New upstream RC release - - -- Jonathan Riddell Fri, 29 Nov 2013 12:29:35 +0000 - -gwenview (4:4.11.95-0ubuntu1) trusty; urgency=low - - [ Rohan Garg ] - * New upstream beta release - * Drop 0001-QWebView-include-was-leftover-drop-include.patch, applied upstream - - [ Harald Sitter ] - * Add kubuntu_install_kipi_plugins.patch to install kipi-plugins when no - plugins are available - + Recommend qapt-batch (when not installed, on-demand install is not - available) - - -- Harald Sitter Mon, 25 Nov 2013 18:57:29 +0100 - -gwenview (4:4.11.80-0ubuntu1) trusty; urgency=low - - * New upstream beta release - - Update install files - - Add 0001-QWebView-include-was-leftover-drop-include.patch to - fix build without QtWebkit + * New upstream bugfix release (LP: #1247235) - -- Rohan Garg Sat, 23 Nov 2013 17:26:08 +0100 + -- Philip Muškovac Fri, 29 Nov 2013 15:37:18 +0000 gwenview (4:4.11.2-0ubuntu1) saucy; urgency=low diff -Nru gwenview-4.12.0/debian/control gwenview-4.11.5/debian/control --- gwenview-4.12.0/debian/control 2013-12-15 09:53:33.000000000 +0000 +++ gwenview-4.11.5/debian/control 2014-01-06 16:38:11.000000000 +0000 @@ -6,14 +6,14 @@ Uploaders: Eshat Cakar , Sune Vuorela Build-Depends: kde-sc-dev-latest (>= 4:4.10.2), cmake, debhelper (>= 7.3.16), pkg-kde-tools (>= 0.12), - libexiv2-dev, libjpeg-dev, libkipi-dev (>= 4:4.12.0), libkonq5-dev (>= 4:4.12.0), + libexiv2-dev, libjpeg-dev, libkipi-dev (>= 4:4.11.2), libkonq5-dev (>= 4:4.11.3), shared-desktop-ontologies (>= 0.8), libqt4-opengl-dev, - libkactivities-dev (>= 4:4.12.0), libpng-dev, liblcms2-dev, - nepomuk-core-dev (>= 4:4.12.0) + libkactivities-dev (>= 4:4.11.3), libpng-dev, liblcms2-dev, + nepomuk-core-dev (>= 4:4.11.5) Standards-Version: 3.9.3 Homepage: http://www.kde.org/ -Vcs-Browser: http://bazaar.launchpad.net/~kubuntu-packagers/kubuntu-packaging/gwenview -Vcs-Bzr: https://code.launchpad.net/~kubuntu-packagers/kubuntu-packaging/gwenview +Vcs-Browser: http://bazaar.launchpad.net/~kubuntu-packagers/kubuntu-packaging/gwenview-13.10 +Vcs-Bzr: https://code.launchpad.net/~kubuntu-packagers/kubuntu-packaging/gwenview-13.10 X-Debian-Vcs-Browser: http://git.debian.org/?p=pkg-kde/kde-sc/gwenview.git X-Debian-Vcs-Git: git://git.debian.org/pkg-kde/kde-sc/gwenview.git @@ -23,7 +23,7 @@ Depends: ${shlibs:Depends}, ${misc:Depends} Replaces: kdegraphics-libs-data (<< 4:4.7.1~) Breaks: kdegraphics-libs-data (<< 4:4.7.1~) -Recommends: kamera, qapt-batch +Recommends: kamera Suggests: svgpart Description: image viewer Gwenview is an image viewer, ideal for browsing and displaying a collection of diff -Nru gwenview-4.12.0/debian/gwenview.install gwenview-4.11.5/debian/gwenview.install --- gwenview-4.12.0/debian/gwenview.install 2013-12-12 15:47:56.000000000 +0000 +++ gwenview-4.11.5/debian/gwenview.install 2014-01-06 16:38:11.000000000 +0000 @@ -2,7 +2,7 @@ usr/bin/gwenview_importer usr/lib/kde4/gvpart.so usr/lib/libgwenviewlib.so.4 -usr/lib/libgwenviewlib.so.4.12.* +usr/lib/libgwenviewlib.so.4.11.* usr/share/applications/kde4/gwenview.desktop usr/share/doc/kde/HTML/en/gwenview/browse_mode.png usr/share/doc/kde/HTML/en/gwenview/common diff -Nru gwenview-4.12.0/debian/patches/kubuntu_install_kipi_plugins.patch gwenview-4.11.5/debian/patches/kubuntu_install_kipi_plugins.patch --- gwenview-4.12.0/debian/patches/kubuntu_install_kipi_plugins.patch 2013-12-12 15:47:56.000000000 +0000 +++ gwenview-4.11.5/debian/patches/kubuntu_install_kipi_plugins.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,87 +0,0 @@ -diff --git a/app/kipiinterface.cpp b/app/kipiinterface.cpp -index d411c5b..f7207e4 100644 ---- a/app/kipiinterface.cpp -+++ b/app/kipiinterface.cpp -@@ -52,6 +52,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA - #include - #include - -+#include -+ - namespace Gwenview - { - #undef ENABLE_LOG -@@ -247,7 +249,16 @@ KIPIInterface::KIPIInterface(MainWindow* mainWindow) - d->mMainWindow = mainWindow; - d->mPluginLoader = 0; - d->mLoadingAction = d->createDummyPluginAction(i18n("Loading...")); -- d->mNoPluginAction = d->createDummyPluginAction(i18n("No Plugin Found")); -+ if (!QFile::exists("/usr/bin/qapt-batch")) { // Only allow on-demand install when qapt-batch is present. -+ d->mNoPluginAction = d->createDummyPluginAction(i18n("No Plugin Found")); -+ } else { -+ KAction* action = new KAction(this); -+ action->setText(i18n("Install Plugins")); -+ action->setShortcutConfigurable(false); -+ action->setEnabled(true); -+ QObject::connect(action, SIGNAL(triggered()), this, SLOT(installPlugins())); -+ d->mNoPluginAction = action; -+ } - - d->setupPluginsMenu(); - QObject::connect(d->mMainWindow->contextManager(), SIGNAL(selectionChanged()), -@@ -359,6 +370,41 @@ void KIPIInterface::loadOnePlugin() - loadingFinished(); - } - -+void KIPIInterface::installPlugins() -+{ -+ KProcess *proc = new KProcess(this); -+ proc->setProgram("/usr/bin/qapt-batch", -+ QStringList() -+ << "--install" << "kipi-plugins" -+ << "--attach" << QString::number(d->mMainWindow->winId())); -+ connect(proc, SIGNAL(finished(int)), this, SLOT(onInstallPluginsFinished(int))); -+ connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater())); -+ proc->start(); -+} -+ -+void KIPIInterface::onInstallPluginsFinished(int code) -+{ -+ if (code != 0) // Install failed, leave UI as it is (shows install option). -+ return; -+ -+ KProcess *proc = new KProcess(this); -+ proc->setProgram("/usr/bin/kbuildsycoca4"); -+ connect(proc, SIGNAL(finished(int)), this, SLOT(onSycocaUpdateFinished(int))); -+ connect(proc, SIGNAL(finished(int)), proc, SLOT(deleteLater())); -+ proc->start(); -+} -+ -+void KIPIInterface::onSycocaUpdateFinished(int /*code*/) -+{ -+ // Return code is disregarded as we may be lucky and it may have -+ // picked up the new desktop files by now automagically. -+ // Also when kbuildsycoca returns !0 something is terribly wrong. -+ d->mPluginLoader->deleteLater(); -+ d->mPluginLoader = 0; -+ d->mPluginMenu->clear(); -+ loadPlugins(); -+} -+ - QList KIPIInterface::pluginActions(KIPI::Category category) const - { - const_cast(this)->loadPlugins(); -diff --git a/app/kipiinterface.h b/app/kipiinterface.h -index 45fb03b..bcb5494 100644 ---- a/app/kipiinterface.h -+++ b/app/kipiinterface.h -@@ -71,6 +71,9 @@ private Q_SLOTS: - void slotDirectoryChanged(); - void init(); - void loadOnePlugin(); -+ void installPlugins(); -+ void onInstallPluginsFinished(int code); -+ void onSycocaUpdateFinished(int code); - - private: - KIPIInterfacePrivate* const d; diff -Nru gwenview-4.12.0/debian/patches/series gwenview-4.11.5/debian/patches/series --- gwenview-4.12.0/debian/patches/series 2013-12-12 15:47:56.000000000 +0000 +++ gwenview-4.11.5/debian/patches/series 1970-01-01 00:00:00.000000000 +0000 @@ -1 +0,0 @@ -kubuntu_install_kipi_plugins.patch diff -Nru gwenview-4.12.0/lib/CMakeLists.txt gwenview-4.11.5/lib/CMakeLists.txt --- gwenview-4.12.0/lib/CMakeLists.txt 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/CMakeLists.txt 2014-01-02 19:32:29.000000000 +0000 @@ -58,7 +58,6 @@ cms/iccjpeg.c cms/cmsprofile.cpp cms/cmsprofile_png.cpp - contextmanager.cpp crop/cropwidget.cpp crop/cropimageoperation.cpp crop/croptool.cpp diff -Nru gwenview-4.12.0/lib/contextmanager.cpp gwenview-4.11.5/lib/contextmanager.cpp --- gwenview-4.12.0/lib/contextmanager.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/contextmanager.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,317 +0,0 @@ -/* -Gwenview: an image viewer -Copyright 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -#include "contextmanager.moc" - -// Qt -#include -#include -#include - -// KDE -#include -#include -#include - -// Local -#include -#include -#include - -namespace Gwenview -{ - -struct ContextManagerPrivate -{ - SortedDirModel* mDirModel; - QItemSelectionModel* mSelectionModel; - KUrl mCurrentDirUrl; - KUrl mCurrentUrl; - - KUrl mUrlToSelect; - - bool mSelectedFileItemListNeedsUpdate; - QSet mQueuedSignals; - KFileItemList mSelectedFileItemList; - - QTimer* mQueuedSignalsTimer; - - void queueSignal(const QByteArray& signal) - { - mQueuedSignals << signal; - mQueuedSignalsTimer->start(); - } - - void updateSelectedFileItemList() - { - if (!mSelectedFileItemListNeedsUpdate) { - return; - } - mSelectedFileItemList.clear(); - QItemSelection selection = mSelectionModel->selection(); - Q_FOREACH(const QModelIndex & index, selection.indexes()) { - mSelectedFileItemList << mDirModel->itemForIndex(index); - } - - // At least add current url if it's valid (it may not be in - // the list if we are viewing a non-browsable url, for example - // using http protocol) - if (mSelectedFileItemList.isEmpty() && mCurrentUrl.isValid()) { - KFileItem item(KFileItem::Unknown, KFileItem::Unknown, mCurrentUrl); - mSelectedFileItemList << item; - } - - mSelectedFileItemListNeedsUpdate = false; - } -}; - -ContextManager::ContextManager(SortedDirModel* dirModel, QObject* parent) -: QObject(parent) -, d(new ContextManagerPrivate) -{ - d->mQueuedSignalsTimer = new QTimer(this); - d->mQueuedSignalsTimer->setInterval(100); - d->mQueuedSignalsTimer->setSingleShot(true); - connect(d->mQueuedSignalsTimer, SIGNAL(timeout()), - SLOT(emitQueuedSignals())); - - d->mDirModel = dirModel; - connect(d->mDirModel, SIGNAL(dataChanged(QModelIndex,QModelIndex)), - SLOT(slotDirModelDataChanged(QModelIndex,QModelIndex))); - - /* HACK! In extended-selection mode, when the current index is removed, - * QItemSelectionModel selects the previous index if there is one, if not it - * selects the next index. This is not what we want: when the user removes - * an image, he expects to go to the next one, not the previous one. - * - * To overcome this, we must connect to the mDirModel.rowsAboutToBeRemoved() - * signal *before* QItemSelectionModel connects to it, so that our slot is - * called before QItemSelectionModel slot. This allows us to pick a new - * current index ourself, leaving QItemSelectionModel slot with nothing to - * do. - * - * This is the reason ContextManager creates a QItemSelectionModel itself: - * doing so ensures QItemSelectionModel cannot be connected to the - * mDirModel.rowsAboutToBeRemoved() signal before us. - */ - connect(d->mDirModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - SLOT(slotRowsAboutToBeRemoved(QModelIndex,int,int))); - - connect(d->mDirModel, SIGNAL(rowsInserted(QModelIndex,int,int)), - SLOT(slotRowsInserted())); - - connect(d->mDirModel->dirLister(), SIGNAL(redirection(KUrl)), - SLOT(slotDirListerRedirection(KUrl))); - - d->mSelectionModel = new QItemSelectionModel(d->mDirModel); - - connect(d->mSelectionModel, SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - SLOT(slotSelectionChanged())); - connect(d->mSelectionModel, SIGNAL(currentChanged(QModelIndex,QModelIndex)), - SLOT(slotCurrentChanged(QModelIndex))); - - d->mSelectedFileItemListNeedsUpdate = false; -} - -ContextManager::~ContextManager() -{ - delete d; -} - -QItemSelectionModel* ContextManager::selectionModel() const -{ - return d->mSelectionModel; -} - -void ContextManager::setCurrentUrl(const KUrl& currentUrl) -{ - if (d->mCurrentUrl == currentUrl) { - return; - } - - d->mCurrentUrl = currentUrl; - if (!d->mCurrentUrl.isEmpty()) { - Document::Ptr doc = DocumentFactory::instance()->load(currentUrl); - QUndoGroup* undoGroup = DocumentFactory::instance()->undoGroup(); - undoGroup->addStack(doc->undoStack()); - undoGroup->setActiveStack(doc->undoStack()); - } - - currentUrlChanged(currentUrl); -} - -KFileItemList ContextManager::selectedFileItemList() const -{ - d->updateSelectedFileItemList(); - return d->mSelectedFileItemList; -} - -void ContextManager::setCurrentDirUrl(const KUrl& url) -{ - if (url.equals(d->mCurrentDirUrl, KUrl::CompareWithoutTrailingSlash)) { - return; - } - d->mCurrentDirUrl = url; - if (url.isValid()) { - d->mDirModel->dirLister()->openUrl(url); - } - currentDirUrlChanged(url); -} - -KUrl ContextManager::currentDirUrl() const -{ - return d->mCurrentDirUrl; -} - -KUrl ContextManager::currentUrl() const -{ - return d->mCurrentUrl; -} - -SortedDirModel* ContextManager::dirModel() const -{ - return d->mDirModel; -} - -void ContextManager::slotDirModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight) -{ - // Data change can happen in the following cases: - // - items have been renamed - // - item bytes have been modified - // - item meta info has been retrieved or modified - // - // If a selected item is affected, schedule emission of a - // selectionDataChanged() signal. Don't emit it directly to avoid spamming - // the context items in case of a mass change. - QModelIndexList selectionList = d->mSelectionModel->selectedIndexes(); - if (selectionList.isEmpty()) { - return; - } - - QModelIndexList changedList; - for (int row = topLeft.row(); row <= bottomRight.row(); ++row) { - changedList << d->mDirModel->index(row, 0); - } - - QModelIndexList& shortList = selectionList; - QModelIndexList& longList = changedList; - if (shortList.length() > longList.length()) { - qSwap(shortList, longList); - } - Q_FOREACH(const QModelIndex & index, shortList) { - if (longList.contains(index)) { - d->mSelectedFileItemListNeedsUpdate = true; - d->queueSignal("selectionDataChanged"); - return; - } - } -} - -void ContextManager::slotSelectionChanged() -{ - d->mSelectedFileItemListNeedsUpdate = true; - if (!d->mSelectionModel->hasSelection()) { - setCurrentUrl(KUrl()); - } - d->queueSignal("selectionChanged"); -} - -void Gwenview::ContextManager::slotCurrentChanged(const QModelIndex& index) -{ - KUrl url = d->mDirModel->urlForIndex(index); - setCurrentUrl(url); -} - -void ContextManager::emitQueuedSignals() -{ - Q_FOREACH(const QByteArray & signal, d->mQueuedSignals) { - QMetaObject::invokeMethod(this, signal.data()); - } - d->mQueuedSignals.clear(); -} - -void Gwenview::ContextManager::slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end) -{ - QModelIndex oldCurrent = d->mSelectionModel->currentIndex(); - if (oldCurrent.row() < start || oldCurrent.row() > end) { - // currentIndex has not been removed - return; - } - QModelIndex newCurrent; - if (end + 1 < d->mDirModel->rowCount()) { - newCurrent = d->mDirModel->index(end + 1, 0); - } else if (start > 0) { - newCurrent = d->mDirModel->index(start - 1, 0); - } else { - // No index we can select, nothing to do - return; - } - d->mSelectionModel->select(oldCurrent, QItemSelectionModel::Deselect); - d->mSelectionModel->setCurrentIndex(newCurrent, QItemSelectionModel::Select); -} - -bool ContextManager::currentUrlIsRasterImage() const -{ - return MimeTypeUtils::urlKind(currentUrl()) == MimeTypeUtils::KIND_RASTER_IMAGE; -} - -KUrl ContextManager::urlToSelect() const -{ - return d->mUrlToSelect; -} - -void ContextManager::setUrlToSelect(const KUrl& url) -{ - GV_RETURN_IF_FAIL(url.isValid()); - d->mUrlToSelect = url; - setCurrentUrl(url); - selectUrlToSelect(); -} - -void ContextManager::slotRowsInserted() -{ - // We reach this method when rows have been inserted in the model, but views - // may not have been updated yet and thus do not have the matching items. - // Delay the selection of mUrlToSelect so that the view items exist. - // - // Without this, when Gwenview is started with an image as argument and the - // thumbnail bar is visible, the image will not be selected in the thumbnail - // bar. - if (d->mUrlToSelect.isValid()) { - QMetaObject::invokeMethod(this, "selectUrlToSelect", Qt::QueuedConnection); - } -} - -void ContextManager::selectUrlToSelect() -{ - GV_RETURN_IF_FAIL(d->mUrlToSelect.isValid()); - QModelIndex index = d->mDirModel->indexForUrl(d->mUrlToSelect); - if (index.isValid()) { - d->mSelectionModel->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect); - d->mUrlToSelect = KUrl(); - } -} - -void ContextManager::slotDirListerRedirection(const KUrl& newUrl) -{ - setCurrentDirUrl(newUrl); -} - - -} // namespace diff -Nru gwenview-4.12.0/lib/contextmanager.h gwenview-4.11.5/lib/contextmanager.h --- gwenview-4.12.0/lib/contextmanager.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/contextmanager.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,96 +0,0 @@ -/* -Gwenview: an image viewer -Copyright 2007 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -#ifndef CONTEXTMANAGER_H -#define CONTEXTMANAGER_H - -#include - -// Qt -#include - -// KDE -#include -#include - -class QItemSelectionModel; -class QModelIndex; - -namespace Gwenview -{ - -class SortedDirModel; - -struct ContextManagerPrivate; - -/** - * Manages the state of the application. - * TODO: Most of GvCore should be merged in this class - */ -class GWENVIEWLIB_EXPORT ContextManager : public QObject -{ - Q_OBJECT -public: - ContextManager(SortedDirModel*, QObject* parent); - - ~ContextManager(); - - KUrl currentUrl() const; - - void setCurrentDirUrl(const KUrl&); - - KUrl currentDirUrl() const; - - void setCurrentUrl(const KUrl& currentUrl); - - KFileItemList selectedFileItemList() const; - - SortedDirModel* dirModel() const; - - QItemSelectionModel* selectionModel() const; - - bool currentUrlIsRasterImage() const; - - KUrl urlToSelect() const; - - void setUrlToSelect(const KUrl&); - -Q_SIGNALS: - void currentDirUrlChanged(const KUrl&); - void currentUrlChanged(const KUrl&); - void selectionChanged(); - void selectionDataChanged(); - -private Q_SLOTS: - void slotDirModelDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); - void slotSelectionChanged(); - void slotCurrentChanged(const QModelIndex&); - void emitQueuedSignals(); - void slotRowsAboutToBeRemoved(const QModelIndex& /*parent*/, int start, int end); - void slotRowsInserted(); - void selectUrlToSelect(); - void slotDirListerRedirection(const KUrl&); - -private: - ContextManagerPrivate* const d; -}; - -} // namespace - -#endif /* CONTEXTMANAGER_H */ diff -Nru gwenview-4.12.0/lib/documentview/documentview.cpp gwenview-4.11.5/lib/documentview/documentview.cpp --- gwenview-4.12.0/lib/documentview/documentview.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/documentview/documentview.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -126,8 +126,6 @@ q, SIGNAL(nextImageRequested())); QObject::connect(adapter, SIGNAL(toggleFullScreenRequested()), q, SIGNAL(toggleFullScreenRequested())); - QObject::connect(adapter, SIGNAL(completed()), - q, SLOT(slotCompleted())); adapter->loadConfig(); @@ -379,9 +377,6 @@ void DocumentView::openUrl(const KUrl& url, const DocumentView::Setup& setup) { if (d->mDocument) { - if (url == d->mDocument->url()) { - return; - } disconnect(d->mDocument.data(), 0, this, 0); } d->mSetup = setup; @@ -397,7 +392,7 @@ connect(d->mDocument.data(), SIGNAL(kindDetermined(KUrl)), SLOT(finishOpenUrl())); } else { - QMetaObject::invokeMethod(this, "finishOpenUrl", Qt::QueuedConnection); + finishOpenUrl(); } d->setupBirdEyeView(); } @@ -414,6 +409,8 @@ } createAdapterForDocument(); + connect(d->mAdapter.data(), SIGNAL(completed()), + SLOT(slotCompleted())); connect(d->mDocument.data(), SIGNAL(loadingFailed(KUrl)), SLOT(slotLoadingFailed())); d->mAdapter->setDocument(d->mDocument); diff -Nru gwenview-4.12.0/lib/documentview/rasterimageview.cpp gwenview-4.11.5/lib/documentview/rasterimageview.cpp --- gwenview-4.12.0/lib/documentview/rasterimageview.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/documentview/rasterimageview.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -254,7 +254,7 @@ void RasterImageView::slotDocumentMetaInfoLoaded() { if (document()->size().isValid()) { - QMetaObject::invokeMethod(this, "finishSetDocument", Qt::QueuedConnection); + finishSetDocument(); } else { // Could not retrieve image size from meta info, we need to load the // full image now. diff -Nru gwenview-4.12.0/lib/preferredimagemetainfomodel.cpp gwenview-4.11.5/lib/preferredimagemetainfomodel.cpp --- gwenview-4.12.0/lib/preferredimagemetainfomodel.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/preferredimagemetainfomodel.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -70,8 +70,6 @@ { d->mModel = model; setSourceModel(model); - sort(0); - setDynamicSortFilter(true); d->mPreferredMetaInfoKeyList = list; } @@ -129,15 +127,4 @@ return true; } -bool PreferredImageMetaInfoModel::lessThan(const QModelIndex& left, const QModelIndex& right) const -{ - if (!left.parent().isValid()) { - // Keep root entries in insertion order - return left.row() < right.row(); - } else { - // Sort leaf entries alphabetically - return QSortFilterProxyModel::lessThan(left, right); - } -} - } // namespace diff -Nru gwenview-4.12.0/lib/preferredimagemetainfomodel.h gwenview-4.11.5/lib/preferredimagemetainfomodel.h --- gwenview-4.12.0/lib/preferredimagemetainfomodel.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/preferredimagemetainfomodel.h 2014-01-02 19:32:29.000000000 +0000 @@ -51,9 +51,6 @@ Q_SIGNALS: void preferredMetaInfoKeyListChanged(const QStringList&); -protected: - bool lessThan(const QModelIndex& left, const QModelIndex& right) const; - private: PreferredImageMetaInfoModelPrivate* const d; friend struct PreferredImageMetaInfoModelPrivate; diff -Nru gwenview-4.12.0/lib/semanticinfo/sorteddirmodel.cpp gwenview-4.11.5/lib/semanticinfo/sorteddirmodel.cpp --- gwenview-4.12.0/lib/semanticinfo/sorteddirmodel.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/semanticinfo/sorteddirmodel.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -292,9 +292,4 @@ return false; } -void SortedDirModel::setDirLister(KDirLister* dirLister) -{ - d->mSourceModel->setDirLister(dirLister); -} - } //namespace diff -Nru gwenview-4.12.0/lib/semanticinfo/sorteddirmodel.h gwenview-4.11.5/lib/semanticinfo/sorteddirmodel.h --- gwenview-4.12.0/lib/semanticinfo/sorteddirmodel.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/semanticinfo/sorteddirmodel.h 2014-01-02 19:32:29.000000000 +0000 @@ -79,10 +79,6 @@ SortedDirModel(QObject* parent = 0); ~SortedDirModel(); KDirLister* dirLister() const; - /** - * Redefines the dir lister, useful for debugging - */ - void setDirLister(KDirLister*); KFileItem itemForIndex(const QModelIndex& index) const; KUrl urlForIndex(const QModelIndex& index) const; KFileItem itemForSourceIndex(const QModelIndex& sourceIndex) const; diff -Nru gwenview-4.12.0/lib/slideshow.h gwenview-4.11.5/lib/slideshow.h --- gwenview-4.12.0/lib/slideshow.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/slideshow.h 2014-01-02 19:32:29.000000000 +0000 @@ -51,9 +51,10 @@ /** @return true if the slideshow is running */ bool isRunning() const; + void setCurrentUrl(const KUrl& url); + public Q_SLOTS: void setInterval(int); - void setCurrentUrl(const KUrl& url); /** * Resume slideshow and go to next url. diff -Nru gwenview-4.12.0/lib/thumbnailview/previewitemdelegate.cpp gwenview-4.11.5/lib/thumbnailview/previewitemdelegate.cpp --- gwenview-4.12.0/lib/thumbnailview/previewitemdelegate.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/thumbnailview/previewitemdelegate.cpp 2014-01-02 19:32:29.000000000 +0000 @@ -65,9 +65,6 @@ #include #endif -//#define DEBUG_DRAW_BORDER -//#define DEBUG_DRAW_CURRENT - namespace Gwenview { @@ -688,7 +685,7 @@ const bool underMouse = option.state & QStyle::State_MouseOver; const QWidget* viewport = d->mView->viewport(); -#ifdef DEBUG_DRAW_BORDER +#ifdef DEBUG_RECT painter->setPen(Qt::red); painter->setBrush(Qt::NoBrush); painter->drawRect(rect); @@ -819,12 +816,6 @@ d->drawRating(painter, rect, index.data(SemanticInfoDirModel::RatingRole)); #endif } - -#ifdef DEBUG_DRAW_CURRENT - if (d->mView->currentIndex() == index) { - painter->fillRect(rect.left(), rect.top(), 12, 12, Qt::red); - } -#endif } void PreviewItemDelegate::setThumbnailSize(const QSize& value) diff -Nru gwenview-4.12.0/lib/version.h gwenview-4.11.5/lib/version.h --- gwenview-4.12.0/lib/version.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/lib/version.h 2014-01-02 19:32:29.000000000 +0000 @@ -33,6 +33,6 @@ https://bugs.kde.org/editversions.cgi?product=gwenview */ -#define GWENVIEW_VERSION "4.12.0" +#define GWENVIEW_VERSION "4.11.4" #endif /* VERSION_H */ diff -Nru gwenview-4.12.0/tests/auto/CMakeLists.txt gwenview-4.11.5/tests/auto/CMakeLists.txt --- gwenview-4.12.0/tests/auto/CMakeLists.txt 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/tests/auto/CMakeLists.txt 2014-01-02 19:32:29.000000000 +0000 @@ -48,4 +48,3 @@ gv_add_unit_test(imagemetainfomodeltest testutils.cpp) gv_add_unit_test(cmsprofiletest testutils.cpp) gv_add_unit_test(recursivedirmodeltest testutils.cpp) -gv_add_unit_test(contextmanagertest testutils.cpp) diff -Nru gwenview-4.12.0/tests/auto/contextmanagertest.cpp gwenview-4.11.5/tests/auto/contextmanagertest.cpp --- gwenview-4.12.0/tests/auto/contextmanagertest.cpp 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/tests/auto/contextmanagertest.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,117 +0,0 @@ -// vim: set tabstop=4 shiftwidth=4 expandtab: -/* -Gwenview: an image viewer -Copyright 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -// Self -#include - -// Local -#include -#include -#include - -// Qt -#include -#include - -// KDE -#include -#include -#include - -using namespace Gwenview; -using namespace TestUtils; - -QTEST_KDEMAIN(ContextManagerTest, GUI) - -void ContextManagerTest::testRemove() -{ - // When the current image is removed Gwenview must go to the next image if - // there is any, otherwise to the previous image. - - SandBoxDir sandBox; - sandBox.fill(QStringList() << "a" << "b" << "c"); - KUrl dirUrl = KUrl::fromPath(sandBox.absolutePath()); - - SortedDirModel dirModel; - { - QEventLoop loop; - connect(dirModel.dirLister(), SIGNAL(completed()), &loop, SLOT(quit())); - dirModel.dirLister()->openUrl(dirUrl); - loop.exec(); - } - - QCOMPARE(dirModel.rowCount(), 3); - - ContextManager manager(&dirModel, 0); - // Select second row - manager.selectionModel()->setCurrentIndex(dirModel.index(1, 0), QItemSelectionModel::Select); - - // Remove "b", `manager` should select "c" - sandBox.remove("b"); - dirModel.dirLister()->updateDirectory(dirUrl); - while (dirModel.rowCount() == 3) { - QTest::qWait(100); - } - - QModelIndex currentIndex = manager.selectionModel()->currentIndex(); - QCOMPARE(currentIndex.row(), 1); - QCOMPARE(currentIndex.data(Qt::DisplayRole).toString(), QString("c")); - - // Remove "c", `manager` should select "a" - sandBox.remove("c"); - dirModel.dirLister()->updateDirectory(dirUrl); - while (dirModel.rowCount() == 2) { - QTest::qWait(100); - } - - currentIndex = manager.selectionModel()->currentIndex(); - QCOMPARE(currentIndex.row(), 0); - QCOMPARE(currentIndex.data(Qt::DisplayRole).toString(), QString("a")); -} - -void ContextManagerTest::testInvalidDirUrl() -{ - class DirLister : public KDirLister - { - public: - DirLister() - : mOpenUrlCalled(false) - { - setAutoErrorHandlingEnabled(false, 0); - } - - bool openUrl(const KUrl& url, OpenUrlFlags flags = NoFlags) - { - mOpenUrlCalled = true; - return KDirLister::openUrl(url, flags); - } - - bool mOpenUrlCalled; - }; - - SortedDirModel dirModel; - DirLister* dirLister = new DirLister; - dirModel.setDirLister(dirLister); - ContextManager manager(&dirModel, 0); - - manager.setCurrentDirUrl(KUrl()); - QVERIFY(!dirLister->mOpenUrlCalled); -} - diff -Nru gwenview-4.12.0/tests/auto/contextmanagertest.h gwenview-4.11.5/tests/auto/contextmanagertest.h --- gwenview-4.12.0/tests/auto/contextmanagertest.h 2013-12-10 15:02:30.000000000 +0000 +++ gwenview-4.11.5/tests/auto/contextmanagertest.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,38 +0,0 @@ -// vim: set tabstop=4 shiftwidth=4 expandtab: -/* -Gwenview: an image viewer -Copyright 2013 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - -*/ -#ifndef CONTEXTMANAGERTEST_H -#define CONTEXTMANAGERTEST_H - -// Local -#include - -// Qt -#include - -class ContextManagerTest : public QObject -{ - Q_OBJECT -private Q_SLOTS: - void testRemove(); - void testInvalidDirUrl(); -}; - -#endif /* CONTEXTMANAGERTEST_H */