mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-23 18:32:53 +00:00
342 lines
10 KiB
C++
342 lines
10 KiB
C++
// vim: set tabstop=4 shiftwidth=4 expandtab:
|
|
/*
|
|
Gwenview: an image viewer
|
|
Copyright 2008 Aurélien Gâteau <agateau@kde.org>
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but 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, Cambridge, MA 02110-1301, USA.
|
|
|
|
*/
|
|
// Self
|
|
#include "gvcore.h"
|
|
|
|
// Qt
|
|
#include <QApplication>
|
|
#include <QStandardItemModel>
|
|
|
|
// KDE
|
|
#include <KFileDialog>
|
|
#include <KGlobalSettings>
|
|
#include <KImageIO>
|
|
#include <KIO/NetAccess>
|
|
#include <KLocale>
|
|
#include <KMessageBox>
|
|
#include <KStandardDirs>
|
|
#include <KUrl>
|
|
|
|
// Local
|
|
#include <lib/binder.h>
|
|
#include <lib/document/documentfactory.h>
|
|
#include <lib/document/documentjob.h>
|
|
#include <lib/document/savejob.h>
|
|
#include <lib/hud/hudbutton.h>
|
|
#include <lib/gwenviewconfig.h>
|
|
#include <lib/historymodel.h>
|
|
#include <lib/hud/hudmessagebubble.h>
|
|
#include <lib/mimetypeutils.h>
|
|
#include <lib/sorteddirmodel.h>
|
|
#include <lib/transformimageoperation.h>
|
|
#include <mainwindow.h>
|
|
#include <saveallhelper.h>
|
|
#include <viewmainpage.h>
|
|
|
|
namespace Gwenview
|
|
{
|
|
|
|
struct GvCorePrivate
|
|
{
|
|
GvCore* q;
|
|
MainWindow* mMainWindow;
|
|
SortedDirModel* mDirModel;
|
|
HistoryModel* mRecentFoldersModel;
|
|
HistoryModel* mRecentUrlsModel;
|
|
QPalette mPalettes[4];
|
|
|
|
bool showSaveAsDialog(const KUrl& url, KUrl* outUrl, QByteArray* format)
|
|
{
|
|
KFileDialog dialog(url, QString(), mMainWindow);
|
|
dialog.setOperationMode(KFileDialog::Saving);
|
|
dialog.setSelection(url.fileName());
|
|
dialog.setMimeFilter(
|
|
KImageIO::mimeTypes(KImageIO::Writing), // List
|
|
MimeTypeUtils::urlMimeType(url) // Default
|
|
);
|
|
|
|
// Show dialog
|
|
do {
|
|
if (!dialog.exec()) {
|
|
return false;
|
|
}
|
|
|
|
const QString mimeType = dialog.currentMimeFilter();
|
|
if (mimeType.isEmpty()) {
|
|
KMessageBox::sorry(
|
|
mMainWindow,
|
|
i18nc("@info", "No image format selected.")
|
|
);
|
|
continue;
|
|
}
|
|
|
|
const QString formatType = KImageIO::typeForMime(mimeType, KImageIO::Writing);
|
|
if (!formatType.isEmpty()) {
|
|
*format = formatType.toAscii();
|
|
break;
|
|
}
|
|
KMessageBox::sorry(
|
|
mMainWindow,
|
|
i18nc("@info", "Gwenview cannot save images as %1.", mimeType)
|
|
);
|
|
} while (true);
|
|
|
|
*outUrl = dialog.selectedUrl();
|
|
return true;
|
|
}
|
|
|
|
void setupPalettes()
|
|
{
|
|
QPalette pal;
|
|
int value = GwenviewConfig::viewBackgroundValue();
|
|
QColor fgColor = value > 128 ? Qt::black : Qt::white;
|
|
|
|
// Normal
|
|
mPalettes[GvCore::NormalPalette] = KGlobalSettings::createApplicationPalette();
|
|
|
|
pal = mPalettes[GvCore::NormalPalette];
|
|
pal.setColor(QPalette::Base, QColor::fromHsv(0, 0, value));
|
|
pal.setColor(QPalette::Text, fgColor);
|
|
mPalettes[GvCore::NormalViewPalette] = pal;
|
|
|
|
// Fullscreen
|
|
mPalettes[GvCore::FullScreenPalette] = mPalettes[GvCore::NormalPalette];
|
|
|
|
pal = mPalettes[GvCore::FullScreenPalette];
|
|
QString path = KStandardDirs::locate("data", "gwenview/images/background.png");
|
|
QPixmap bgTexture(path);
|
|
pal.setBrush(QPalette::Base, bgTexture);
|
|
mPalettes[GvCore::FullScreenViewPalette] = pal;
|
|
}
|
|
};
|
|
|
|
GvCore::GvCore(MainWindow* mainWindow, SortedDirModel* dirModel)
|
|
: QObject(mainWindow)
|
|
, d(new GvCorePrivate)
|
|
{
|
|
d->q = this;
|
|
d->mMainWindow = mainWindow;
|
|
d->mDirModel = dirModel;
|
|
d->mRecentFoldersModel = 0;
|
|
d->mRecentUrlsModel = 0;
|
|
|
|
d->setupPalettes();
|
|
|
|
connect(GwenviewConfig::self(), SIGNAL(configChanged()),
|
|
SLOT(slotConfigChanged()));
|
|
}
|
|
|
|
GvCore::~GvCore()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
QAbstractItemModel* GvCore::recentFoldersModel() const
|
|
{
|
|
if (!d->mRecentFoldersModel) {
|
|
d->mRecentFoldersModel = new HistoryModel(const_cast<GvCore*>(this), KStandardDirs::locateLocal("appdata", "recentfolders/"));
|
|
}
|
|
return d->mRecentFoldersModel;
|
|
}
|
|
|
|
QAbstractItemModel* GvCore::recentUrlsModel() const
|
|
{
|
|
if (!d->mRecentUrlsModel) {
|
|
d->mRecentUrlsModel = new HistoryModel(const_cast<GvCore*>(this), KStandardDirs::locateLocal("appdata", "recenturls/"));
|
|
}
|
|
return d->mRecentUrlsModel;
|
|
}
|
|
|
|
SortedDirModel* GvCore::sortedDirModel() const
|
|
{
|
|
return d->mDirModel;
|
|
}
|
|
|
|
void GvCore::addUrlToRecentFolders(KUrl url)
|
|
{
|
|
if (!GwenviewConfig::historyEnabled()) {
|
|
return;
|
|
}
|
|
if (!url.isValid()) {
|
|
return;
|
|
}
|
|
if (url.path() != "") { // This check is a workaraound for bug #312060
|
|
url.adjustPath(KUrl::AddTrailingSlash);
|
|
}
|
|
recentFoldersModel();
|
|
d->mRecentFoldersModel->addUrl(url);
|
|
}
|
|
|
|
void GvCore::addUrlToRecentUrls(const KUrl& url)
|
|
{
|
|
if (!GwenviewConfig::historyEnabled()) {
|
|
return;
|
|
}
|
|
recentUrlsModel();
|
|
d->mRecentUrlsModel->addUrl(url);
|
|
}
|
|
|
|
void GvCore::saveAll()
|
|
{
|
|
SaveAllHelper helper(d->mMainWindow);
|
|
helper.save();
|
|
}
|
|
|
|
void GvCore::save(const KUrl& url)
|
|
{
|
|
Document::Ptr doc = DocumentFactory::instance()->load(url);
|
|
QByteArray format = doc->format();
|
|
const QStringList availableTypes = KImageIO::types(KImageIO::Writing);
|
|
if (availableTypes.contains(QString(format))) {
|
|
DocumentJob* job = doc->save(url, format);
|
|
connect(job, SIGNAL(result(KJob*)), SLOT(slotSaveResult(KJob*)));
|
|
} else {
|
|
// We don't know how to save in 'format', ask the user for a format we can
|
|
// write to.
|
|
KGuiItem saveUsingAnotherFormat = KStandardGuiItem::saveAs();
|
|
saveUsingAnotherFormat.setText(i18n("Save using another format"));
|
|
int result = KMessageBox::warningContinueCancel(
|
|
d->mMainWindow,
|
|
i18n("Gwenview cannot save images in '%1' format.", QString(format)),
|
|
QString() /* caption */,
|
|
saveUsingAnotherFormat
|
|
);
|
|
if (result == KMessageBox::Continue) {
|
|
saveAs(url);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GvCore::saveAs(const KUrl& url)
|
|
{
|
|
QByteArray format;
|
|
KUrl saveAsUrl;
|
|
if (!d->showSaveAsDialog(url, &saveAsUrl, &format)) {
|
|
return;
|
|
}
|
|
|
|
// Check for overwrite
|
|
if (KIO::NetAccess::exists(saveAsUrl, KIO::NetAccess::DestinationSide, d->mMainWindow)) {
|
|
int answer = KMessageBox::warningContinueCancel(
|
|
d->mMainWindow,
|
|
i18nc("@info",
|
|
"A file named <tt>%1</tt> already exists.\n"
|
|
"Are you sure you want to overwrite it?",
|
|
saveAsUrl.fileName()),
|
|
QString(),
|
|
KStandardGuiItem::overwrite());
|
|
if (answer == KMessageBox::Cancel) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
// Start save
|
|
Document::Ptr doc = DocumentFactory::instance()->load(url);
|
|
KJob* job = doc->save(saveAsUrl, format.data());
|
|
if (!job) {
|
|
const QString name = saveAsUrl.fileName().isEmpty() ? saveAsUrl.pathOrUrl() : saveAsUrl.fileName();
|
|
const QString msg = i18nc("@info", "<b>Saving <tt>%1</tt> failed:</b><br>%2",
|
|
name, doc->errorString());
|
|
KMessageBox::sorry(QApplication::activeWindow(), msg);
|
|
} else {
|
|
connect(job, SIGNAL(result(KJob*)), SLOT(slotSaveResult(KJob*)));
|
|
}
|
|
}
|
|
|
|
static void applyTransform(const KUrl& url, Orientation orientation)
|
|
{
|
|
TransformImageOperation* op = new TransformImageOperation(orientation);
|
|
Document::Ptr doc = DocumentFactory::instance()->load(url);
|
|
op->applyToDocument(doc);
|
|
}
|
|
|
|
void GvCore::slotSaveResult(KJob* _job)
|
|
{
|
|
SaveJob* job = static_cast<SaveJob*>(_job);
|
|
KUrl oldUrl = job->oldUrl();
|
|
KUrl newUrl = job->newUrl();
|
|
|
|
if (job->error()) {
|
|
QString name = newUrl.fileName().isEmpty() ? newUrl.pathOrUrl() : newUrl.fileName();
|
|
QString msg = i18nc("@info", "<b>Saving <tt>%1</tt> failed:</b><br>%2",
|
|
name, job->errorString());
|
|
|
|
int result = KMessageBox::warningContinueCancel(
|
|
d->mMainWindow, msg,
|
|
QString() /* caption */,
|
|
KStandardGuiItem::saveAs());
|
|
|
|
if (result == KMessageBox::Continue) {
|
|
saveAs(newUrl);
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (oldUrl != newUrl) {
|
|
d->mMainWindow->goToUrl(newUrl);
|
|
|
|
ViewMainPage* page = d->mMainWindow->viewMainPage();
|
|
if (page->isVisible()) {
|
|
HudMessageBubble* bubble = new HudMessageBubble();
|
|
bubble->setText(i18n("You are now viewing the new document."));
|
|
KGuiItem item = KStandardGuiItem::back();
|
|
item.setText(i18n("Go back to the original"));
|
|
HudButton* button = bubble->addButton(item);
|
|
|
|
BinderRef<MainWindow, KUrl>::bind(button, SIGNAL(clicked()), d->mMainWindow, &MainWindow::goToUrl, oldUrl);
|
|
connect(button, SIGNAL(clicked()),
|
|
bubble, SLOT(deleteLater()));
|
|
|
|
page->showMessageWidget(bubble);
|
|
}
|
|
}
|
|
}
|
|
|
|
void GvCore::rotateLeft(const KUrl& url)
|
|
{
|
|
applyTransform(url, ROT_270);
|
|
}
|
|
|
|
void GvCore::rotateRight(const KUrl& url)
|
|
{
|
|
applyTransform(url, ROT_90);
|
|
}
|
|
|
|
static void clearModel(QAbstractItemModel* model)
|
|
{
|
|
model->removeRows(0, model->rowCount());
|
|
}
|
|
|
|
void GvCore::slotConfigChanged()
|
|
{
|
|
if (!GwenviewConfig::historyEnabled()) {
|
|
clearModel(recentFoldersModel());
|
|
clearModel(recentUrlsModel());
|
|
}
|
|
d->setupPalettes();
|
|
}
|
|
|
|
QPalette GvCore::palette(GvCore::PaletteType type) const
|
|
{
|
|
return d->mPalettes[type];
|
|
}
|
|
|
|
} // namespace
|