Adding upstream version 0.5.0.
This commit is contained in:
parent
de1fa415b2
commit
d53be78755
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
build
|
||||||
|
*.kdev4
|
||||||
|
src/translations/lximage-qt
|
169
CHANGELOG
Normal file
169
CHANGELOG
Normal file
@ -0,0 +1,169 @@
|
|||||||
|
|
||||||
|
lximage-qt-0.5.0 / 2016-09-24
|
||||||
|
=============================
|
||||||
|
|
||||||
|
* Bump version to 0.5.0 (#67)
|
||||||
|
* Remove Core and Qt from Categories in desktop file (#64)
|
||||||
|
* Extend README.md
|
||||||
|
* Fix broken compatibility introduced by libfm-qt API changes. This closes lxde/lximage-qt#63.
|
||||||
|
* Add Catalan translations
|
||||||
|
* Quieten compiler warning
|
||||||
|
* Code cleanup
|
||||||
|
* Use LXQtCompilerSettings cmake module
|
||||||
|
* Treat SVG files separately as SVG images
|
||||||
|
* build: Update translations based on *.ui
|
||||||
|
* Fix typo in Portuguese translation for desktop file
|
||||||
|
* Fix typo in German translation for desktop file (#55)
|
||||||
|
* build: Use external translations (#54)
|
||||||
|
* ts-files removal (#53)
|
||||||
|
* Hide cursor smartly in fullscreen mode
|
||||||
|
* build: Use liblxqt's TranslateDesktop module
|
||||||
|
* Adds support for GIF animation.
|
||||||
|
* Implement an EOG-like behavior on starting By clicking on an image for the first time, the user wants to see it clearly with lximage-qt. So, the following behavior is implemented here:
|
||||||
|
* Add --version command line option
|
||||||
|
* Fix missing Russian translation in desktop file
|
||||||
|
* Fix memory leak if taking screenshot with cursor
|
||||||
|
* Polish translation updated
|
||||||
|
* Another update
|
||||||
|
* Improved Russian translation - thanks to uazure
|
||||||
|
* Fix typo
|
||||||
|
* Add Russian translation
|
||||||
|
* Italian translation update
|
||||||
|
* CMake: Adapt to libfm-qt Targets
|
||||||
|
* Turn on C++11 support. This closes bug lxde/lximage-qt #36.
|
||||||
|
* Exec should have an argument
|
||||||
|
* all GPL files are (or any later)
|
||||||
|
* Add release script
|
||||||
|
* Update translations
|
||||||
|
* Set the color table properly for scaled images
|
||||||
|
* Add Greek (el) translation Remove needless country variant from language code
|
||||||
|
* Corrected language code (de_DE -> de) of german translation, marked translations as done.
|
||||||
|
* replace tabs with spaces
|
||||||
|
* remove trailing spaces
|
||||||
|
* replace glib with Qt for command-line parsing
|
||||||
|
* Don't save file in private mode
|
||||||
|
* Prevents the slideshow timeout to be set to 0 in the UI
|
||||||
|
* Correctly include CMake modules in intree/superbuild mode
|
||||||
|
* Remove lximage-qt from the Utilities category
|
||||||
|
* Update README
|
||||||
|
* Update .gitignore
|
||||||
|
* Hungarian translations added
|
||||||
|
* save and restore window size and maximized state
|
||||||
|
|
||||||
|
0.4.0 / 2015-02-18
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Release v0.4.0
|
||||||
|
* src/CMakeLists.txt: do not completely overwrite CMAKE_CXX_FLAGS
|
||||||
|
* Create lximage-qt_it.desktop
|
||||||
|
* Create lximage-qt_it.ts
|
||||||
|
* CMakeLists cleanups
|
||||||
|
* Portuguese update
|
||||||
|
* Added german translation, re-generated all other .ts files.
|
||||||
|
* Added keyboard shortcut to print.
|
||||||
|
* Adds .desktop translation support
|
||||||
|
* Portuguese language update
|
||||||
|
* Remove debian directory (Close #9)
|
||||||
|
* Fix typo Zoomo -> Zoom
|
||||||
|
* Use proper naming conventions for translations
|
||||||
|
* Clean up CMakeLists, dropping support for Qt 5
|
||||||
|
|
||||||
|
0.3.0 / 2014-10-15
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Release v0.3.0
|
||||||
|
* Rename preferencedialog.ui to preferencesdialog.ui
|
||||||
|
* Ignore build dir.
|
||||||
|
* debian: enable qt5 by default
|
||||||
|
* Fix lxde/lxde-qt #269 - Screenshots are not saved aedequately unless file extension is chosen manually.
|
||||||
|
* Support Qt5 and libfm-qt5.
|
||||||
|
* Make sure all enums are handled in switch
|
||||||
|
|
||||||
|
0.2.0 / 2014-05-09
|
||||||
|
==================
|
||||||
|
|
||||||
|
* Release 0.2.0
|
||||||
|
* Update desktop files
|
||||||
|
* Update README/COPYING/AUTHORS
|
||||||
|
* Add some missing link_directories()
|
||||||
|
* Commit from LXDE Pootle server by user yinghua_wang.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Add CPack rules for creating tarball
|
||||||
|
* Avoid creating a scaled image cache if current scale factor is 1.0 (original size).
|
||||||
|
* Rewrite the scaled image caching code in LxImage::ImageView to improve its readability and correctness.
|
||||||
|
* Add LxImage::Job class as a base class for multi-threading jobs.
|
||||||
|
* Avoid copying subimages to speed up scaling images.
|
||||||
|
* Limit the size of pixmap cache.
|
||||||
|
* Limit the size of pixmap cache.
|
||||||
|
* Create a cache for the high-quality scaled image of the currently viewport and use it to override the default paintEvent() of QGraphicsView as needed. This improves the image quality a lot when we scale down large photos.
|
||||||
|
* Cancel autoZoomFit when calling zoomOriginal(), zoomIn(), and zoomOut().
|
||||||
|
* Add copy and paste buttons to the toolbar.
|
||||||
|
* Automatically zoom to fit current window size by default.
|
||||||
|
* Make the preferences dialog non-modal and apply the settings to all existing windows.
|
||||||
|
* Add "Delete file" and "File properties" actions to the file menu.
|
||||||
|
* Add a very basic thumbnails pane based on Fm::FolderView of libfm-qt.
|
||||||
|
* Implement the preferences dialog. * Enable keyboard shortcuts in fullscreen mode.
|
||||||
|
* Implement very basic slide show functionality.
|
||||||
|
* Jump to the previous or the next image by using mouse wheel.
|
||||||
|
* Avoid scaling up an image while zoomFit() if it's smaller than the current view.
|
||||||
|
* Support grabbing mouse cursor when taking a screenshot.
|
||||||
|
* Add very basic printing support.
|
||||||
|
* Commit from LXDE Pootle server by user adrianoh2.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user Fitoschido.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user hirkmt.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Remove xsettings support and add an option in the preference dialog to set a fallback icon theme instead.
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Improve cmake integration for translations. The *.ts files are only updated when UPDATE_TRANSLATIONS cmake option is turned on.
|
||||||
|
* Commit from LXDE Pootle server by user zvacet.: 65 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user zvacet.: 50 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user wwycheuk.: 65 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user mbouzada.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Commit from LXDE Pootle server by user Fitoschido.: 68 of 70 strings translated (0 fuzzy).
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Corrected caml cased string toolBar.
|
||||||
|
* Commit from LXDE Pootle server by user smarquespt.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user brother.: 24 of 24 strings translated (0 fuzzy).
|
||||||
|
* Correct misspelled 'Zoom'.
|
||||||
|
* Commit from LXDE Pootle server by user andika.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Commit from LXDE Pootle server by user strebski.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Commit from LXDE Pootle server by user LStranger.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user brother.: 70 of 70 strings translated (0 fuzzy).
|
||||||
|
* Commit from LXDE Pootle server by user LStranger.: 2 of 70 strings translated (0 fuzzy).
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* New files added from LXDE Pootle server based on templates
|
||||||
|
* Add zh_TW translation and a template ts file.
|
||||||
|
* Add a desktop entry file for the built-in screenshot tool.
|
||||||
|
* Add --screenshot command line argument to launch the built-in screenshot utility.
|
||||||
|
* Improve the screenshot tool. Implement pasting from clipboard.
|
||||||
|
* Add ability to taking screenshots to lximage-qt.
|
||||||
|
* debian : Add missing libx11 build-depend
|
||||||
|
* Add missing files.
|
||||||
|
* Add Xdg::DesktopSettings for detecting desktop-specific settings. Get icon theme name via XSettings or config files when available.
|
||||||
|
* Supporting saving files. (needs some more polishing, though).
|
||||||
|
* Add a basic debian directory to enable daily builds.
|
||||||
|
* Add a context menu.
|
||||||
|
* Use libexif to read EXIF orientation tags then apply them to images loaded.
|
||||||
|
* Refactor - move image loading code to LxImage::LoadImageJob class.
|
||||||
|
* Remove unused data member.
|
||||||
|
* Add a preferences dialog (not working yet). Little adjustment for menu positions and add placeholders for features not implemented.
|
||||||
|
* Fix filename encoding handling so non-English filenames can be passed correctly from command line arguments.
|
||||||
|
* Canonicalize filenames passed through command line arguments. Add an icon borrowed from GPicView. Rearrange menus and implement "fullscreen" and "copy to clipboard".
|
||||||
|
* Implement basic single instance support and command line argument parsing.
|
||||||
|
* Properly cancel pending tasks and make going back/forward more smooth. Enhance window title display.
|
||||||
|
* Little fix to avoid loading a cancelled image.
|
||||||
|
* Supports rotation of images.
|
||||||
|
* Use the latest libfm-qt APIs to filter out non-image files. Implement jumping to first and last file in the folder.
|
||||||
|
* Fix incorrect reference couting of GCancellable objects to avoid crashes. Add some shortcut keys to improve usability.
|
||||||
|
* Use glib/gio GInputStream + GIOSchedulerJob to load the images with multi-threading. Refactor, simplify class methods of LxImage::MainWindow.
|
||||||
|
* Use libfm to load folders containing the specified image. Add dependency on libexif for future implementation of EXIF related stuff. Add LxImage::Applcation class to handle application initiation.
|
||||||
|
* Initial import into git
|
@ -5,7 +5,7 @@ project(lximage-qt)
|
|||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(MAJOR_VERSION 0)
|
set(MAJOR_VERSION 0)
|
||||||
set(MINOR_VERSION 4)
|
set(MINOR_VERSION 5)
|
||||||
set(PATCH_VERSION 0)
|
set(PATCH_VERSION 0)
|
||||||
set(LXIMAGE_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION})
|
set(LXIMAGE_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION})
|
||||||
|
|
||||||
@ -13,35 +13,18 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
# C++ 11 support
|
|
||||||
if (CMAKE_VERSION VERSION_LESS "3.1")
|
|
||||||
include(CheckCXXCompilerFlag)
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
|
|
||||||
if(COMPILER_SUPPORTS_CXX11)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
|
||||||
else()
|
|
||||||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
|
|
||||||
# -std=c++0x is deprecated but some tools e.g. qmake or older gcc are still using it
|
|
||||||
if(COMPILER_SUPPORTS_CXX0X)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Compiler ${CMAKE_CXX_COMPILER} does not support c++11/c++0x")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
find_package(Qt5Widgets REQUIRED)
|
find_package(Qt5Widgets REQUIRED)
|
||||||
find_package(Qt5DBus REQUIRED)
|
find_package(Qt5DBus REQUIRED)
|
||||||
find_package(Qt5PrintSupport REQUIRED QUIET)
|
find_package(Qt5PrintSupport REQUIRED QUIET)
|
||||||
find_package(Qt5X11Extras REQUIRED QUIET)
|
find_package(Qt5X11Extras REQUIRED QUIET)
|
||||||
find_package(Qt5LinguistTools REQUIRED QUIET)
|
find_package(Qt5LinguistTools REQUIRED QUIET)
|
||||||
|
find_package(Qt5Svg REQUIRED QUIET)
|
||||||
find_package(fm-qt REQUIRED QUIET)
|
find_package(fm-qt REQUIRED QUIET)
|
||||||
find_package(lxqt REQUIRED) #just a build dependency for .desktop files translation
|
find_package(lxqt REQUIRED) #just a build dependency for .desktop files translation
|
||||||
message(STATUS "Building with Qt ${Qt5Core_VERSION_STRING}")
|
message(STATUS "Building with Qt ${Qt5Core_VERSION_STRING}")
|
||||||
|
|
||||||
|
include(LXQtCompilerSettings NO_POLICY_SCOPE)
|
||||||
|
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
|
||||||
# FIXME: we'll need this to provide detail info for photos in the future
|
# FIXME: we'll need this to provide detail info for photos in the future
|
||||||
|
26
README.md
26
README.md
@ -1,3 +1,25 @@
|
|||||||
# lximage-qt
|
# LXImage-Qt
|
||||||
|
|
||||||
The Qt port of LXImage, a simple and fast image viewer.
|
## Overview
|
||||||
|
|
||||||
|
LXImage-Qt is the Qt port of LXImage, a simple and fast image viewer.
|
||||||
|
|
||||||
|
In addition it features a tool to take screenshots.
|
||||||
|
|
||||||
|
It is maintained by the LXQt project but can be used independently from this desktop environment.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### Compiling source code
|
||||||
|
|
||||||
|
Runtime dependencies are qtx11extras and [libfm-qt](https://github.com/lxde/libfm-qt) (LXImage-Qt used to depend on [PCManFM-Qt](https://github.com/lxde/pcmanfm-qt) but the relevant code belongs to what was outsourced in libfm-qt).
|
||||||
|
Additional build dependencies are CMake and optionally Git to pull latest VCS checkouts. The localization files were outsourced to repository [lxqt-l10n](https://github.com/lxde/lxqt-l10n) so the corresponding dependencies are needed, too. Please refer to this repository's `README.md` for further information.
|
||||||
|
|
||||||
|
Code configuration is handled by CMake. CMake variable `CMAKE_INSTALL_PREFIX` has to be set to `/usr` on most operating systems.
|
||||||
|
|
||||||
|
To build run `make`, to install `make install` which accepts variable `DESTDIR` as usual.
|
||||||
|
|
||||||
|
### Binary packages
|
||||||
|
|
||||||
|
Official binary packages are available in Arch Linux, Debian (as of Debian stretch), Fedora and openSUSE (Leap 42.1 and Tumbleweed).
|
||||||
|
Just use the distributions' package manager to search for string 'lximage'.
|
||||||
|
@ -7,5 +7,5 @@ Icon=lximage-qt
|
|||||||
Exec=lximage-qt %F
|
Exec=lximage-qt %F
|
||||||
StartupNotify=true
|
StartupNotify=true
|
||||||
Terminal=false
|
Terminal=false
|
||||||
Categories=Graphics;Core;Qt;Viewer;RasterGraphics;2DGraphics;Photography;
|
Categories=Graphics;Viewer;RasterGraphics;2DGraphics;Photography;
|
||||||
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-pcx;image/x-tga;image/x-portable-pixmap;image/x-portable-bitmap;image/x-targa;image/x-portable-greymap;application/pcx;image/svg+xml;image/svg-xml;
|
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-pcx;image/x-tga;image/x-portable-pixmap;image/x-portable-bitmap;image/x-targa;image/x-portable-greymap;application/pcx;image/svg+xml;image/svg-xml;
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
# set visibility to hidden to hide symbols, unlesss they're exporeted manually in the code
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-exceptions")
|
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${X11_INCLUDE_DIR}
|
${X11_INCLUDE_DIR}
|
||||||
${XFIXES_INCLUDE_DIRS}
|
${XFIXES_INCLUDE_DIRS}
|
||||||
@ -81,7 +78,7 @@ add_definitions(
|
|||||||
-DLXIMAGE_VERSION="${LXIMAGE_VERSION}"
|
-DLXIMAGE_VERSION="${LXIMAGE_VERSION}"
|
||||||
)
|
)
|
||||||
|
|
||||||
set(QT_LIBRARIES Qt5::Widgets Qt5::Core Qt5::DBus Qt5::PrintSupport Qt5::X11Extras)
|
set(QT_LIBRARIES Qt5::Widgets Qt5::Core Qt5::DBus Qt5::PrintSupport Qt5::X11Extras Qt5::Svg)
|
||||||
|
|
||||||
target_link_libraries(lximage-qt
|
target_link_libraries(lximage-qt
|
||||||
fm-qt
|
fm-qt
|
||||||
|
@ -35,8 +35,8 @@ static const char* ifaceName = "org.lxde.LxImage.Application";
|
|||||||
|
|
||||||
Application::Application(int& argc, char** argv):
|
Application::Application(int& argc, char** argv):
|
||||||
QApplication(argc, argv),
|
QApplication(argc, argv),
|
||||||
windowCount_(0),
|
libFm(),
|
||||||
libFm() {
|
windowCount_(0) {
|
||||||
setApplicationVersion(LXIMAGE_VERSION);
|
setApplicationVersion(LXIMAGE_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ bool Application::init(int argc, char** argv) {
|
|||||||
new ApplicationAdaptor(this);
|
new ApplicationAdaptor(this);
|
||||||
dbus.registerObject("/Application", this);
|
dbus.registerObject("/Application", this);
|
||||||
|
|
||||||
connect(this, SIGNAL(aboutToQuit()), SLOT(onAboutToQuit()));
|
connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit);
|
||||||
|
|
||||||
if(settings_.useFallbackIconTheme())
|
if(settings_.useFallbackIconTheme())
|
||||||
QIcon::setThemeName(settings_.fallbackIconTheme());
|
QIcon::setThemeName(settings_.fallbackIconTheme());
|
||||||
@ -179,6 +179,5 @@ void Application::editPreferences() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Application::onAboutToQuit() {
|
void Application::onAboutToQuit() {
|
||||||
qDebug("aboutToQuit");
|
|
||||||
settings_.save();
|
settings_.save();
|
||||||
}
|
}
|
||||||
|
@ -41,11 +41,9 @@ public:
|
|||||||
|
|
||||||
void addWindow() { // call this when you create a new toplevel window
|
void addWindow() { // call this when you create a new toplevel window
|
||||||
++windowCount_;
|
++windowCount_;
|
||||||
qDebug("add window");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeWindow() { // call this when you destroy a toplevel window
|
void removeWindow() { // call this when you destroy a toplevel window
|
||||||
qDebug("remove window");
|
|
||||||
--windowCount_;
|
--windowCount_;
|
||||||
if(0 == windowCount_)
|
if(0 == windowCount_)
|
||||||
quit();
|
quit();
|
||||||
|
@ -24,21 +24,25 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QPolygon>
|
#include <QPolygon>
|
||||||
#include <QDebug>
|
|
||||||
#include <QStyle>
|
#include <QStyle>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QGraphicsProxyWidget>
|
#include <QGraphicsProxyWidget>
|
||||||
|
#include <QGraphicsSvgItem>
|
||||||
|
|
||||||
|
#define CURSOR_HIDE_DELY 3000
|
||||||
|
|
||||||
namespace LxImage {
|
namespace LxImage {
|
||||||
|
|
||||||
ImageView::ImageView(QWidget* parent):
|
ImageView::ImageView(QWidget* parent):
|
||||||
QGraphicsView(parent),
|
QGraphicsView(parent),
|
||||||
imageItem_(new QGraphicsRectItem()),
|
|
||||||
scene_(new QGraphicsScene(this)),
|
scene_(new QGraphicsScene(this)),
|
||||||
gifMovie_(NULL),
|
imageItem_(new QGraphicsRectItem()),
|
||||||
|
gifMovie_(nullptr),
|
||||||
|
cacheTimer_(nullptr),
|
||||||
|
cursorTimer_(nullptr),
|
||||||
|
scaleFactor_(1.0),
|
||||||
autoZoomFit_(false),
|
autoZoomFit_(false),
|
||||||
cacheTimer_(NULL),
|
isSVG(false) {
|
||||||
scaleFactor_(1.0) {
|
|
||||||
|
|
||||||
setViewportMargins(0, 0, 0, 0);
|
setViewportMargins(0, 0, 0, 0);
|
||||||
setContentsMargins(0, 0, 0, 0);
|
setContentsMargins(0, 0, 0, 0);
|
||||||
@ -58,6 +62,10 @@ ImageView::~ImageView() {
|
|||||||
cacheTimer_->stop();
|
cacheTimer_->stop();
|
||||||
delete cacheTimer_;
|
delete cacheTimer_;
|
||||||
}
|
}
|
||||||
|
if(cursorTimer_) {
|
||||||
|
cursorTimer_->stop();
|
||||||
|
delete cursorTimer_;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -88,6 +96,34 @@ void ImageView::mouseDoubleClickEvent(QMouseEvent* event) {
|
|||||||
QAbstractScrollArea::mouseDoubleClickEvent(event);
|
QAbstractScrollArea::mouseDoubleClickEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageView::mousePressEvent(QMouseEvent * event) {
|
||||||
|
QGraphicsView::mousePressEvent(event);
|
||||||
|
if(cursorTimer_) cursorTimer_->stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::mouseReleaseEvent(QMouseEvent* event) {
|
||||||
|
QGraphicsView::mouseReleaseEvent(event);
|
||||||
|
if(cursorTimer_) cursorTimer_->start(CURSOR_HIDE_DELY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::mouseMoveEvent(QMouseEvent* event) {
|
||||||
|
QGraphicsView::mouseMoveEvent(event);
|
||||||
|
if(cursorTimer_ && (viewport()->cursor().shape() == Qt::BlankCursor
|
||||||
|
|| viewport()->cursor().shape() == Qt::OpenHandCursor)) {
|
||||||
|
cursorTimer_->start(CURSOR_HIDE_DELY); // restart timer
|
||||||
|
viewport()->setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::focusInEvent(QFocusEvent* event) {
|
||||||
|
QGraphicsView::focusInEvent(event);
|
||||||
|
if(cursorTimer_ && (viewport()->cursor().shape() == Qt::BlankCursor
|
||||||
|
|| viewport()->cursor().shape() == Qt::OpenHandCursor)) {
|
||||||
|
cursorTimer_->start(CURSOR_HIDE_DELY); // restart timer
|
||||||
|
viewport()->setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ImageView::resizeEvent(QResizeEvent* event) {
|
void ImageView::resizeEvent(QResizeEvent* event) {
|
||||||
QGraphicsView::resizeEvent(event);
|
QGraphicsView::resizeEvent(event);
|
||||||
if(autoZoomFit_)
|
if(autoZoomFit_)
|
||||||
@ -136,10 +172,13 @@ void ImageView::zoomOriginal() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageView::setImage(QImage image, bool show) {
|
void ImageView::setImage(QImage image, bool show) {
|
||||||
if(gifMovie_ && show) { // a gif animation was shown
|
if(show && (gifMovie_ || isSVG)) { // a gif animation or SVG file was shown before
|
||||||
scene_->clear();
|
scene_->clear();
|
||||||
delete gifMovie_;
|
isSVG = false;
|
||||||
gifMovie_ = NULL;
|
if(gifMovie_) { // should be deleted explicitly
|
||||||
|
delete gifMovie_;
|
||||||
|
gifMovie_ = nullptr;
|
||||||
|
}
|
||||||
// recreate the rect item
|
// recreate the rect item
|
||||||
imageItem_ = new QGraphicsRectItem();
|
imageItem_ = new QGraphicsRectItem();
|
||||||
imageItem_->hide();
|
imageItem_->hide();
|
||||||
@ -168,21 +207,24 @@ void ImageView::setImage(QImage image, bool show) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageView::setGifAnimation(QString fileName) {
|
void ImageView::setGifAnimation(QString fileName) {
|
||||||
QImage image(fileName);
|
/* the built-in gif reader gives the first frame, which won't
|
||||||
if(image.isNull()) {
|
be shown but is used for tracking position and dimensions */
|
||||||
image_ = QImage();
|
image_ = QImage(fileName);
|
||||||
imageItem_->hide();
|
if(image_.isNull()) {
|
||||||
imageItem_->setBrush(QBrush());
|
if(imageItem_) {
|
||||||
|
imageItem_->hide();
|
||||||
|
imageItem_->setBrush(QBrush());
|
||||||
|
}
|
||||||
scene_->setSceneRect(0, 0, 0, 0);
|
scene_->setSceneRect(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scene_->clear();
|
scene_->clear();
|
||||||
imageItem_ = NULL; // it's deleted by clear();
|
imageItem_ = nullptr; // it's deleted by clear();
|
||||||
if(gifMovie_) {
|
if(gifMovie_) {
|
||||||
delete gifMovie_;
|
delete gifMovie_;
|
||||||
gifMovie_ = NULL;
|
gifMovie_ = nullptr;
|
||||||
}
|
}
|
||||||
QPixmap pix(image.size());
|
QPixmap pix(image_.size());
|
||||||
pix.fill(Qt::transparent);
|
pix.fill(Qt::transparent);
|
||||||
QGraphicsItem *gifItem = new QGraphicsPixmapItem(pix);
|
QGraphicsItem *gifItem = new QGraphicsPixmapItem(pix);
|
||||||
QLabel *gifLabel = new QLabel();
|
QLabel *gifLabel = new QLabel();
|
||||||
@ -192,9 +234,6 @@ void ImageView::setGifAnimation(QString fileName) {
|
|||||||
gifLabel->setMovie(gifMovie_);
|
gifLabel->setMovie(gifMovie_);
|
||||||
gifWidget->setWidget(gifLabel);
|
gifWidget->setWidget(gifLabel);
|
||||||
gifMovie_->start();
|
gifMovie_->start();
|
||||||
/* the first frame won't be shown but will be
|
|
||||||
used for tracking position and dimensions */
|
|
||||||
image_ = gifMovie_->currentImage();
|
|
||||||
scene_->addItem(gifItem);
|
scene_->addItem(gifItem);
|
||||||
scene_->setSceneRect(gifItem->boundingRect());
|
scene_->setSceneRect(gifItem->boundingRect());
|
||||||
}
|
}
|
||||||
@ -204,6 +243,29 @@ void ImageView::setGifAnimation(QString fileName) {
|
|||||||
queueGenerateCache(); // deletes the cache timer in this case
|
queueGenerateCache(); // deletes the cache timer in this case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageView::setSVG(QString fileName) {
|
||||||
|
image_ = QImage(fileName); // for tracking position and dimensions
|
||||||
|
if(image_.isNull()) {
|
||||||
|
if(imageItem_) {
|
||||||
|
imageItem_->hide();
|
||||||
|
imageItem_->setBrush(QBrush());
|
||||||
|
}
|
||||||
|
scene_->setSceneRect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scene_->clear();
|
||||||
|
imageItem_ = nullptr;
|
||||||
|
isSVG = true;
|
||||||
|
QGraphicsSvgItem *svgItem = new QGraphicsSvgItem(fileName);
|
||||||
|
scene_->addItem(svgItem);
|
||||||
|
scene_->setSceneRect(svgItem->boundingRect());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(autoZoomFit_)
|
||||||
|
zoomFit();
|
||||||
|
queueGenerateCache(); // deletes the cache timer in this case
|
||||||
|
}
|
||||||
|
|
||||||
void ImageView::setScaleFactor(double factor) {
|
void ImageView::setScaleFactor(double factor) {
|
||||||
if(factor != scaleFactor_) {
|
if(factor != scaleFactor_) {
|
||||||
scaleFactor_ = factor;
|
scaleFactor_ = factor;
|
||||||
@ -215,7 +277,7 @@ void ImageView::setScaleFactor(double factor) {
|
|||||||
|
|
||||||
void ImageView::paintEvent(QPaintEvent* event) {
|
void ImageView::paintEvent(QPaintEvent* event) {
|
||||||
// if the image is scaled and we have a high quality cached image
|
// if the image is scaled and we have a high quality cached image
|
||||||
if(scaleFactor_ != 1.0 && !cachedPixmap_.isNull()) {
|
if(imageItem_ && scaleFactor_ != 1.0 && !cachedPixmap_.isNull()) {
|
||||||
// rectangle of the whole image in viewport coordinate
|
// rectangle of the whole image in viewport coordinate
|
||||||
QRect viewportImageRect = sceneToViewport(imageItem_->rect());
|
QRect viewportImageRect = sceneToViewport(imageItem_->rect());
|
||||||
// the visible part of the image.
|
// the visible part of the image.
|
||||||
@ -244,20 +306,20 @@ void ImageView::queueGenerateCache() {
|
|||||||
cachedPixmap_ = QPixmap();
|
cachedPixmap_ = QPixmap();
|
||||||
|
|
||||||
// we don't need to cache the scaled image if its the same as the original image (scale:1.0)
|
// we don't need to cache the scaled image if its the same as the original image (scale:1.0)
|
||||||
// no cache for gif animations either
|
// no cache for gif animations or SVG images either
|
||||||
if(scaleFactor_ == 1.0 || gifMovie_) {
|
if(scaleFactor_ == 1.0 || gifMovie_ || isSVG) {
|
||||||
if(cacheTimer_) {
|
if(cacheTimer_) {
|
||||||
cacheTimer_->stop();
|
cacheTimer_->stop();
|
||||||
delete cacheTimer_;
|
delete cacheTimer_;
|
||||||
cacheTimer_ = NULL;
|
cacheTimer_ = nullptr;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!cacheTimer_ && !gifMovie_) {
|
if(!cacheTimer_) {
|
||||||
cacheTimer_ = new QTimer();
|
cacheTimer_ = new QTimer();
|
||||||
cacheTimer_->setSingleShot(true);
|
cacheTimer_->setSingleShot(true);
|
||||||
connect(cacheTimer_, SIGNAL(timeout()), SLOT(generateCache()));
|
connect(cacheTimer_, &QTimer::timeout, this, &ImageView::generateCache);
|
||||||
}
|
}
|
||||||
if(cacheTimer_)
|
if(cacheTimer_)
|
||||||
cacheTimer_->start(200); // restart the timer
|
cacheTimer_->start(200); // restart the timer
|
||||||
@ -267,7 +329,9 @@ void ImageView::queueGenerateCache() {
|
|||||||
void ImageView::generateCache() {
|
void ImageView::generateCache() {
|
||||||
// disable the one-shot timer
|
// disable the one-shot timer
|
||||||
cacheTimer_->deleteLater();
|
cacheTimer_->deleteLater();
|
||||||
cacheTimer_ = NULL;
|
cacheTimer_ = nullptr;
|
||||||
|
|
||||||
|
if(!imageItem_ || image_.isNull()) return;
|
||||||
|
|
||||||
// generate a cache for "the visible part" of the scaled image
|
// generate a cache for "the visible part" of the scaled image
|
||||||
// rectangle of the whole image in viewport coordinate
|
// rectangle of the whole image in viewport coordinate
|
||||||
@ -295,12 +359,6 @@ void ImageView::generateCache() {
|
|||||||
// convert the cached scaled image to pixmap
|
// convert the cached scaled image to pixmap
|
||||||
cachedPixmap_ = QPixmap::fromImage(scaled);
|
cachedPixmap_ = QPixmap::fromImage(scaled);
|
||||||
viewport()->update();
|
viewport()->update();
|
||||||
/*
|
|
||||||
qDebug() << "viewportImageRect" << viewportImageRect
|
|
||||||
<< "cachedRect_" << cachedRect_
|
|
||||||
<< "cachedSceneRect_" << cachedSceneRect_
|
|
||||||
<< "subRect" << subRect;
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// convert viewport coordinate to the original image (not scaled).
|
// convert viewport coordinate to the original image (not scaled).
|
||||||
@ -317,5 +375,26 @@ QRect ImageView::sceneToViewport(const QRectF& rect) {
|
|||||||
return QRect(topLeft, bottomRight);
|
return QRect(topLeft, bottomRight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageView::blankCursor() {
|
||||||
|
viewport()->setCursor(Qt::BlankCursor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageView::hideCursor(bool enable) {
|
||||||
|
if(enable) {
|
||||||
|
if(cursorTimer_) delete cursorTimer_;
|
||||||
|
cursorTimer_ = new QTimer(this);
|
||||||
|
cursorTimer_->setSingleShot(true);
|
||||||
|
connect(cursorTimer_, &QTimer::timeout, this, &ImageView::blankCursor);
|
||||||
|
if(viewport()->cursor().shape() == Qt::OpenHandCursor)
|
||||||
|
cursorTimer_->start(CURSOR_HIDE_DELY);
|
||||||
|
}
|
||||||
|
else if (cursorTimer_) {
|
||||||
|
cursorTimer_->stop();
|
||||||
|
delete cursorTimer_;
|
||||||
|
cursorTimer_ = nullptr;
|
||||||
|
if(viewport()->cursor().shape() == Qt::BlankCursor)
|
||||||
|
viewport()->setCursor(Qt::OpenHandCursor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace LxImage
|
} // namespace LxImage
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
|
|
||||||
void setImage(QImage image, bool show = true);
|
void setImage(QImage image, bool show = true);
|
||||||
void setGifAnimation(QString fileName);
|
void setGifAnimation(QString fileName);
|
||||||
|
void setSVG(QString fileName);
|
||||||
|
|
||||||
QImage image() {
|
QImage image() {
|
||||||
return image_;
|
return image_;
|
||||||
@ -67,9 +68,16 @@ public:
|
|||||||
autoZoomFit_ = value;
|
autoZoomFit_ = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if set to true, hides the cursor after 3s of inactivity
|
||||||
|
void hideCursor(bool enable);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void wheelEvent(QWheelEvent* event);
|
virtual void wheelEvent(QWheelEvent* event);
|
||||||
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
virtual void mouseDoubleClickEvent(QMouseEvent* event);
|
||||||
|
virtual void mousePressEvent(QMouseEvent* event);
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent* event);
|
||||||
|
virtual void mouseMoveEvent(QMouseEvent* event);
|
||||||
|
virtual void focusInEvent(QFocusEvent* event);
|
||||||
virtual void resizeEvent(QResizeEvent* event);
|
virtual void resizeEvent(QResizeEvent* event);
|
||||||
virtual void paintEvent(QPaintEvent* event);
|
virtual void paintEvent(QPaintEvent* event);
|
||||||
|
|
||||||
@ -80,6 +88,7 @@ private:
|
|||||||
|
|
||||||
private Q_SLOTS:
|
private Q_SLOTS:
|
||||||
void generateCache();
|
void generateCache();
|
||||||
|
void blankCursor();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QGraphicsScene* scene_; // the topmost container of all graphic items
|
QGraphicsScene* scene_; // the topmost container of all graphic items
|
||||||
@ -90,8 +99,10 @@ private:
|
|||||||
QRect cachedRect_; // rectangle containing the cached region (in viewport coordinate)
|
QRect cachedRect_; // rectangle containing the cached region (in viewport coordinate)
|
||||||
QRect cachedSceneRect_; // rectangle containing the cached region (in scene/original image coordinate)
|
QRect cachedSceneRect_; // rectangle containing the cached region (in scene/original image coordinate)
|
||||||
QTimer* cacheTimer_;
|
QTimer* cacheTimer_;
|
||||||
|
QTimer *cursorTimer_; // for hiding cursor in fullscreen mode
|
||||||
double scaleFactor_;
|
double scaleFactor_;
|
||||||
bool autoZoomFit_;
|
bool autoZoomFit_;
|
||||||
|
bool isSVG; // is the image an SVG file?
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ Job::~Job() {
|
|||||||
|
|
||||||
// This is called from the worker thread, not main thread
|
// This is called from the worker thread, not main thread
|
||||||
gboolean Job::_jobThread(GIOSchedulerJob* job, GCancellable* cancellable, Job* pThis) {
|
gboolean Job::_jobThread(GIOSchedulerJob* job, GCancellable* cancellable, Job* pThis) {
|
||||||
bool ret = pThis->run();
|
pThis->run();
|
||||||
// do final step in the main thread
|
// do final step in the main thread
|
||||||
if(!g_cancellable_is_cancelled(pThis->cancellable_))
|
if(!g_cancellable_is_cancelled(pThis->cancellable_))
|
||||||
g_io_scheduler_job_send_to_mainloop(job, GSourceFunc(_finish), pThis, NULL);
|
g_io_scheduler_job_send_to_mainloop(job, GSourceFunc(_finish), pThis, NULL);
|
||||||
|
@ -29,8 +29,8 @@ using namespace LxImage;
|
|||||||
|
|
||||||
LoadImageJob::LoadImageJob(MainWindow* window, FmPath* filePath):
|
LoadImageJob::LoadImageJob(MainWindow* window, FmPath* filePath):
|
||||||
Job(),
|
Job(),
|
||||||
path_(fm_path_ref(filePath)),
|
mainWindow_(window),
|
||||||
mainWindow_(window) {
|
path_(fm_path_ref(filePath)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadImageJob::~LoadImageJob() {
|
LoadImageJob::~LoadImageJob() {
|
||||||
@ -71,7 +71,7 @@ bool LoadImageJob::run() {
|
|||||||
// use libexif to extract additional info embedded in jpeg files
|
// use libexif to extract additional info embedded in jpeg files
|
||||||
ExifLoader *exif_loader = exif_loader_new();
|
ExifLoader *exif_loader = exif_loader_new();
|
||||||
// write image data to exif loader
|
// write image data to exif loader
|
||||||
int ret = exif_loader_write(exif_loader, (unsigned char*)imageBuffer.data().constData(), (unsigned int)imageBuffer.size());
|
exif_loader_write(exif_loader, (unsigned char*)imageBuffer.data().constData(), (unsigned int)imageBuffer.size());
|
||||||
ExifData *exif_data = exif_loader_get_data(exif_loader);
|
ExifData *exif_data = exif_loader_get_data(exif_loader);
|
||||||
exif_loader_unref(exif_loader);
|
exif_loader_unref(exif_loader);
|
||||||
if(exif_data) {
|
if(exif_data) {
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPrintDialog>
|
#include <QPrintDialog>
|
||||||
#include <QPrinter>
|
#include <QPrinter>
|
||||||
#include <QDebug>
|
|
||||||
#include <QWheelEvent>
|
#include <QWheelEvent>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@ -36,6 +35,7 @@
|
|||||||
#include <QDockWidget>
|
#include <QDockWidget>
|
||||||
#include <QScrollBar>
|
#include <QScrollBar>
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
#include <QGraphicsSvgItem>
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include <libfm-qt/path.h>
|
#include <libfm-qt/path.h>
|
||||||
#include <libfm-qt/folderview.h>
|
#include <libfm-qt/folderview.h>
|
||||||
@ -46,21 +46,21 @@ using namespace LxImage;
|
|||||||
|
|
||||||
MainWindow::MainWindow():
|
MainWindow::MainWindow():
|
||||||
QMainWindow(),
|
QMainWindow(),
|
||||||
currentFile_(NULL),
|
contextMenu_(new QMenu(this)),
|
||||||
slideShowTimer_(NULL),
|
slideShowTimer_(nullptr),
|
||||||
// currentFileInfo_(NULL),
|
image_(),
|
||||||
loadJob_(NULL),
|
currentFile_(nullptr),
|
||||||
saveJob_(NULL),
|
// currentFileInfo_(nullptr),
|
||||||
folder_(NULL),
|
imageModified_(false),
|
||||||
folderPath_(NULL),
|
folder_(nullptr),
|
||||||
|
folderPath_(nullptr),
|
||||||
folderModel_(new Fm::FolderModel()),
|
folderModel_(new Fm::FolderModel()),
|
||||||
proxyModel_(new Fm::ProxyFolderModel()),
|
proxyModel_(new Fm::ProxyFolderModel()),
|
||||||
modelFilter_(new ModelFilter()),
|
modelFilter_(new ModelFilter()),
|
||||||
imageModified_(false),
|
thumbnailsDock_(nullptr),
|
||||||
contextMenu_(new QMenu(this)),
|
thumbnailsView_(nullptr),
|
||||||
thumbnailsDock_(NULL),
|
loadJob_(nullptr),
|
||||||
thumbnailsView_(NULL),
|
saveJob_(nullptr) {
|
||||||
image_() {
|
|
||||||
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose); // FIXME: check if current image is saved before close
|
setAttribute(Qt::WA_DeleteOnClose); // FIXME: check if current image is saved before close
|
||||||
|
|
||||||
@ -70,8 +70,8 @@ MainWindow::MainWindow():
|
|||||||
Settings& settings = app->settings();
|
Settings& settings = app->settings();
|
||||||
|
|
||||||
ui.setupUi(this);
|
ui.setupUi(this);
|
||||||
connect(ui.actionScreenshot, SIGNAL(triggered(bool)), app, SLOT(screenshot()));
|
connect(ui.actionScreenshot, &QAction::triggered, app, &Application::screenshot);
|
||||||
connect(ui.actionPreferences, SIGNAL(triggered(bool)), app ,SLOT(editPreferences()));
|
connect(ui.actionPreferences, &QAction::triggered, app , &Application::editPreferences);
|
||||||
|
|
||||||
proxyModel_->addFilter(modelFilter_);
|
proxyModel_->addFilter(modelFilter_);
|
||||||
proxyModel_->sort(Fm::FolderModel::ColumnFileName, Qt::AscendingOrder);
|
proxyModel_->sort(Fm::FolderModel::ColumnFileName, Qt::AscendingOrder);
|
||||||
@ -79,7 +79,7 @@ MainWindow::MainWindow():
|
|||||||
|
|
||||||
// build context menu
|
// build context menu
|
||||||
ui.view->setContextMenuPolicy(Qt::CustomContextMenu);
|
ui.view->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
connect(ui.view, SIGNAL(customContextMenuRequested(QPoint)), SLOT(onContextMenu(QPoint)));
|
connect(ui.view, &QWidget::customContextMenuRequested, this, &MainWindow::onContextMenu);
|
||||||
|
|
||||||
// install an event filter on the image view
|
// install an event filter on the image view
|
||||||
ui.view->installEventFilter(this);
|
ui.view->installEventFilter(this);
|
||||||
@ -107,11 +107,11 @@ MainWindow::MainWindow():
|
|||||||
|
|
||||||
// create shortcuts
|
// create shortcuts
|
||||||
QShortcut* shortcut = new QShortcut(Qt::Key_Left, this);
|
QShortcut* shortcut = new QShortcut(Qt::Key_Left, this);
|
||||||
connect(shortcut, SIGNAL(activated()), SLOT(on_actionPrevious_triggered()));
|
connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionPrevious_triggered);
|
||||||
shortcut = new QShortcut(Qt::Key_Right, this);
|
shortcut = new QShortcut(Qt::Key_Right, this);
|
||||||
connect(shortcut, SIGNAL(activated()), SLOT(on_actionNext_triggered()));
|
connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionNext_triggered);
|
||||||
shortcut = new QShortcut(Qt::Key_Escape, this);
|
shortcut = new QShortcut(Qt::Key_Escape, this);
|
||||||
connect(shortcut, SIGNAL(activated()), SLOT(onExitFullscreen()));
|
connect(shortcut, &QShortcut::activated, this, &MainWindow::onExitFullscreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow() {
|
MainWindow::~MainWindow() {
|
||||||
@ -174,7 +174,6 @@ void MainWindow::on_actionZoomOut_triggered() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::onFolderLoaded(FmFolder* folder) {
|
void MainWindow::onFolderLoaded(FmFolder* folder) {
|
||||||
qDebug("Finish loading: %d files", proxyModel_->rowCount());
|
|
||||||
// if currently we're showing a file, get its index in the folder now
|
// if currently we're showing a file, get its index in the folder now
|
||||||
// since the folder is fully loaded.
|
// since the folder is fully loaded.
|
||||||
if(currentFile_ && !currentIndex_.isValid()) {
|
if(currentFile_ && !currentIndex_.isValid()) {
|
||||||
@ -207,14 +206,14 @@ void MainWindow::pasteImage(QImage newImage) {
|
|||||||
// cancel loading of current image
|
// cancel loading of current image
|
||||||
if(loadJob_) {
|
if(loadJob_) {
|
||||||
loadJob_->cancel(); // the job object will be freed automatically later
|
loadJob_->cancel(); // the job object will be freed automatically later
|
||||||
loadJob_ = NULL;
|
loadJob_ = nullptr;
|
||||||
}
|
}
|
||||||
setModified(true);
|
setModified(true);
|
||||||
|
|
||||||
currentIndex_ = QModelIndex(); // invaludate current index since we don't have a folder model now
|
currentIndex_ = QModelIndex(); // invaludate current index since we don't have a folder model now
|
||||||
if(currentFile_)
|
if(currentFile_)
|
||||||
fm_path_unref(currentFile_);
|
fm_path_unref(currentFile_);
|
||||||
currentFile_ = NULL;
|
currentFile_ = nullptr;
|
||||||
|
|
||||||
image_ = newImage;
|
image_ = newImage;
|
||||||
ui.view->setImage(image_);
|
ui.view->setImage(image_);
|
||||||
@ -302,7 +301,13 @@ void MainWindow::on_actionSave_triggered() {
|
|||||||
void MainWindow::on_actionSaveAs_triggered() {
|
void MainWindow::on_actionSaveAs_triggered() {
|
||||||
if(saveJob_) // if we're currently saving another file
|
if(saveJob_) // if we're currently saving another file
|
||||||
return;
|
return;
|
||||||
QString fileName = saveFileName(currentFile_ ? Fm::Path(currentFile_).displayName() : QString());
|
QString baseName;
|
||||||
|
if(currentFile_) {
|
||||||
|
char* dispName = fm_path_display_name(currentFile_, false);
|
||||||
|
baseName = QString::fromUtf8(dispName);
|
||||||
|
g_free(dispName);
|
||||||
|
}
|
||||||
|
QString fileName = saveFileName(baseName);
|
||||||
if(!fileName.isEmpty()) {
|
if(!fileName.isEmpty()) {
|
||||||
FmPath* path = fm_path_new_for_str(qPrintable(fileName));
|
FmPath* path = fm_path_new_for_str(qPrintable(fileName));
|
||||||
// save the image file asynchronously
|
// save the image file asynchronously
|
||||||
@ -354,7 +359,6 @@ void MainWindow::on_actionNext_triggered() {
|
|||||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||||
if(info) {
|
if(info) {
|
||||||
FmPath* path = fm_file_info_get_path(info);
|
FmPath* path = fm_file_info_get_path(info);
|
||||||
qDebug("try load: %s", fm_path_get_basename(path));
|
|
||||||
loadImage(path, index);
|
loadImage(path, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -365,7 +369,6 @@ void MainWindow::on_actionPrevious_triggered() {
|
|||||||
return;
|
return;
|
||||||
if(currentIndex_.isValid()) {
|
if(currentIndex_.isValid()) {
|
||||||
QModelIndex index;
|
QModelIndex index;
|
||||||
qDebug("current row: %d", currentIndex_.row());
|
|
||||||
if(currentIndex_.row() > 0)
|
if(currentIndex_.row() > 0)
|
||||||
index = proxyModel_->index(currentIndex_.row() - 1, 0);
|
index = proxyModel_->index(currentIndex_.row() - 1, 0);
|
||||||
else
|
else
|
||||||
@ -373,7 +376,6 @@ void MainWindow::on_actionPrevious_triggered() {
|
|||||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||||
if(info) {
|
if(info) {
|
||||||
FmPath* path = fm_file_info_get_path(info);
|
FmPath* path = fm_file_info_get_path(info);
|
||||||
qDebug("try load: %s", fm_path_get_basename(path));
|
|
||||||
loadImage(path, index);
|
loadImage(path, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -385,7 +387,6 @@ void MainWindow::on_actionFirst_triggered() {
|
|||||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||||
if(info) {
|
if(info) {
|
||||||
FmPath* path = fm_file_info_get_path(info);
|
FmPath* path = fm_file_info_get_path(info);
|
||||||
qDebug("try load: %s", fm_path_get_basename(path));
|
|
||||||
loadImage(path, index);
|
loadImage(path, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -396,8 +397,7 @@ void MainWindow::on_actionLast_triggered() {
|
|||||||
if(index.isValid()) {
|
if(index.isValid()) {
|
||||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||||
if(info) {
|
if(info) {
|
||||||
FmPath* path = fm_file_info_get_path(info);
|
FmPath* path = fm_file_info_get_path(info);;
|
||||||
qDebug("try load: %s", fm_path_get_basename(path));
|
|
||||||
loadImage(path, index);
|
loadImage(path, index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -423,7 +423,7 @@ void MainWindow::loadFolder(FmPath* newFolderPath) {
|
|||||||
|
|
||||||
// the image is loaded (the method is only called if the loading is not cancelled)
|
// the image is loaded (the method is only called if the loading is not cancelled)
|
||||||
void MainWindow::onImageLoaded(LoadImageJob* job) {
|
void MainWindow::onImageLoaded(LoadImageJob* job) {
|
||||||
loadJob_ = NULL; // the job object will be freed later automatically
|
loadJob_ = nullptr; // the job object will be freed later automatically
|
||||||
|
|
||||||
image_ = job->image();
|
image_ = job->image();
|
||||||
ui.view->setAutoZoomFit(true);
|
ui.view->setAutoZoomFit(true);
|
||||||
@ -448,12 +448,11 @@ void MainWindow::onImageSaved(SaveImageJob* job) {
|
|||||||
if(!job->error()) {
|
if(!job->error()) {
|
||||||
setModified(false);
|
setModified(false);
|
||||||
}
|
}
|
||||||
saveJob_ = NULL;
|
saveJob_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// filter events of other objects, mainly the image view.
|
// filter events of other objects, mainly the image view.
|
||||||
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
|
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
|
||||||
// qDebug() << event;
|
|
||||||
if(watched == ui.view) { // we got an event for the image view
|
if(watched == ui.view) { // we got an event for the image view
|
||||||
switch(event->type()) {
|
switch(event->type()) {
|
||||||
case QEvent::Wheel: { // mouse wheel event
|
case QEvent::Wheel: { // mouse wheel event
|
||||||
@ -585,7 +584,7 @@ void MainWindow::loadImage(FmPath* filePath, QModelIndex index) {
|
|||||||
// cancel loading of current image
|
// cancel loading of current image
|
||||||
if(loadJob_) {
|
if(loadJob_) {
|
||||||
loadJob_->cancel(); // the job object will be freed automatically later
|
loadJob_->cancel(); // the job object will be freed automatically later
|
||||||
loadJob_ = NULL;
|
loadJob_ = nullptr;
|
||||||
}
|
}
|
||||||
if(imageModified_) {
|
if(imageModified_) {
|
||||||
// TODO: ask the user to save the modified image?
|
// TODO: ask the user to save the modified image?
|
||||||
@ -601,21 +600,27 @@ void MainWindow::loadImage(FmPath* filePath, QModelIndex index) {
|
|||||||
image_ = QImage();
|
image_ = QImage();
|
||||||
|
|
||||||
const char* basename = fm_path_get_basename(currentFile_);
|
const char* basename = fm_path_get_basename(currentFile_);
|
||||||
char* mimeType = g_content_type_guess(basename, NULL, 0, NULL);
|
char* mime_type = g_content_type_guess(basename, NULL, 0, NULL);
|
||||||
if(mimeType && strcmp(mimeType, "image/gif") == 0) {
|
QString mimeType;
|
||||||
g_free(mimeType);
|
if (mime_type) {
|
||||||
char *file_Name = fm_path_to_str(currentFile_);
|
mimeType = QString(mime_type);
|
||||||
QString fileName(file_Name);
|
g_free(mime_type);
|
||||||
g_free(file_Name);
|
}
|
||||||
|
if(mimeType == "image/gif"
|
||||||
|
|| mimeType == "image/svg+xml" || mimeType == "image/svg+xml-compressed") {
|
||||||
|
char *file_name = fm_path_to_str(currentFile_);
|
||||||
|
QString fileName(file_name);
|
||||||
|
g_free(file_name);
|
||||||
ui.view->setAutoZoomFit(true); // like in onImageLoaded()
|
ui.view->setAutoZoomFit(true); // like in onImageLoaded()
|
||||||
ui.view->setGifAnimation(fileName);
|
if(mimeType == "image/gif")
|
||||||
|
ui.view->setGifAnimation(fileName);
|
||||||
|
else
|
||||||
|
ui.view->setSVG(fileName);
|
||||||
image_ = ui.view->image();
|
image_ = ui.view->image();
|
||||||
updateUI();
|
updateUI();
|
||||||
show();
|
show();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(mimeType)
|
|
||||||
g_free(mimeType);
|
|
||||||
// start a new gio job to load the specified image
|
// start a new gio job to load the specified image
|
||||||
loadJob_ = new LoadImageJob(this, filePath);
|
loadJob_ = new LoadImageJob(this, filePath);
|
||||||
loadJob_->start();
|
loadJob_->start();
|
||||||
@ -633,55 +638,55 @@ void MainWindow::saveImage(FmPath* filePath) {
|
|||||||
// FIXME: add a cancel button to the UI? update status bar?
|
// FIXME: add a cancel button to the UI? update status bar?
|
||||||
}
|
}
|
||||||
|
|
||||||
QGraphicsItem* MainWindow::getGifItem() {
|
QGraphicsItem* MainWindow::getGraphicsItem() {
|
||||||
if(!ui.view->items().isEmpty()) {
|
if(!ui.view->items().isEmpty())
|
||||||
QGraphicsItem *gifItem = ui.view->items().at(0);
|
return ui.view->items().at(0);
|
||||||
if(gifItem->isWidget()) // we have gif animation
|
return nullptr;
|
||||||
return gifItem;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionRotateClockwise_triggered() {
|
void MainWindow::on_actionRotateClockwise_triggered() {
|
||||||
QGraphicsItem *gifItem = getGifItem();
|
QGraphicsItem *graphItem = getGraphicsItem();
|
||||||
if(!image_.isNull()) {
|
if(!image_.isNull()) {
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.rotate(90.0);
|
transform.rotate(90.0);
|
||||||
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
||||||
/* when this is a gif animation, we need to rotate the first frame
|
/* when this is GIF or SVG, we need to rotate its corresponding QImage
|
||||||
without showing it to have the right measure for auto-zooming */
|
without showing it to have the right measure for auto-zooming */
|
||||||
ui.view->setImage(image_, gifItem ? false : true);
|
ui.view->setImage(image_, graphItem->isWidget() // we have gif animation
|
||||||
|
|| static_cast<QGraphicsSvgItem*>(graphItem) // an SVG image
|
||||||
|
? false : true);
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gifItem) {
|
if(graphItem) {
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.translate(gifItem->sceneBoundingRect().height(), 0);
|
transform.translate(graphItem->sceneBoundingRect().height(), 0);
|
||||||
transform.rotate(90);
|
transform.rotate(90);
|
||||||
// we need to apply transformations in the reverse order
|
// we need to apply transformations in the reverse order
|
||||||
QTransform prevTrans = gifItem->transform();
|
QTransform prevTrans = graphItem->transform();
|
||||||
gifItem->setTransform(transform, false);
|
graphItem->setTransform(transform, false);
|
||||||
gifItem->setTransform(prevTrans, true);
|
graphItem->setTransform(prevTrans, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionRotateCounterclockwise_triggered() {
|
void MainWindow::on_actionRotateCounterclockwise_triggered() {
|
||||||
QGraphicsItem *gifItem = getGifItem();
|
QGraphicsItem *graphItem = getGraphicsItem();
|
||||||
if(!image_.isNull()) {
|
if(!image_.isNull()) {
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.rotate(-90.0);
|
transform.rotate(-90.0);
|
||||||
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
||||||
ui.view->setImage(image_, gifItem ? false : true);
|
ui.view->setImage(image_, graphItem->isWidget() || static_cast<QGraphicsSvgItem*>(graphItem)
|
||||||
|
? false : true);
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(gifItem) {
|
if(graphItem) {
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.translate(0, gifItem->sceneBoundingRect().width());
|
transform.translate(0, graphItem->sceneBoundingRect().width());
|
||||||
transform.rotate(-90);
|
transform.rotate(-90);
|
||||||
QTransform prevTrans = gifItem->transform();
|
QTransform prevTrans = graphItem->transform();
|
||||||
gifItem->setTransform(transform, false);
|
graphItem->setTransform(transform, false);
|
||||||
gifItem->setTransform(prevTrans, true);
|
graphItem->setTransform(prevTrans, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -708,37 +713,37 @@ void MainWindow::on_actionPaste_triggered() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionFlipVertical_triggered() {
|
void MainWindow::on_actionFlipVertical_triggered() {
|
||||||
if(QGraphicsItem *gifItem = getGifItem()) {
|
bool hasQGraphicsItem(false);
|
||||||
|
if(QGraphicsItem *graphItem = getGraphicsItem()) {
|
||||||
|
hasQGraphicsItem = true;
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.scale(1, -1);
|
transform.scale(1, -1);
|
||||||
transform.translate(0, -gifItem->sceneBoundingRect().height());
|
transform.translate(0, -graphItem->sceneBoundingRect().height());
|
||||||
QTransform prevTrans = gifItem->transform();
|
QTransform prevTrans = graphItem->transform();
|
||||||
gifItem->setTransform(transform, false);
|
graphItem->setTransform(transform, false);
|
||||||
gifItem->setTransform(prevTrans, true);
|
graphItem->setTransform(prevTrans, true);
|
||||||
setModified(true);
|
|
||||||
/* we don't need to flip the first frame because its position
|
|
||||||
and dimensions are the same as before while it isn't shown */
|
|
||||||
}
|
}
|
||||||
else if(!image_.isNull()) {
|
if(!image_.isNull()) {
|
||||||
image_ = image_.mirrored(false, true);
|
image_ = image_.mirrored(false, true);
|
||||||
ui.view->setImage(image_);
|
ui.view->setImage(image_, !hasQGraphicsItem);
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::on_actionFlipHorizontal_triggered() {
|
void MainWindow::on_actionFlipHorizontal_triggered() {
|
||||||
if(QGraphicsItem *gifItem = getGifItem()) {
|
bool hasQGraphicsItem(false);
|
||||||
|
if(QGraphicsItem *graphItem = getGraphicsItem()) {
|
||||||
|
hasQGraphicsItem = true;
|
||||||
QTransform transform;
|
QTransform transform;
|
||||||
transform.scale(-1, 1);
|
transform.scale(-1, 1);
|
||||||
transform.translate(-gifItem->sceneBoundingRect().width(), 0);
|
transform.translate(-graphItem->sceneBoundingRect().width(), 0);
|
||||||
QTransform prevTrans = gifItem->transform();
|
QTransform prevTrans = graphItem->transform();
|
||||||
gifItem->setTransform(transform, false);
|
graphItem->setTransform(transform, false);
|
||||||
gifItem->setTransform(prevTrans, true);
|
graphItem->setTransform(prevTrans, true);
|
||||||
setModified(true);
|
|
||||||
}
|
}
|
||||||
else if(!image_.isNull()) {
|
if(!image_.isNull()) {
|
||||||
image_ = image_.mirrored(true, false);
|
image_ = image_.mirrored(true, true);
|
||||||
ui.view->setImage(image_);
|
ui.view->setImage(image_, !hasQGraphicsItem);
|
||||||
setModified(true);
|
setModified(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -767,11 +772,9 @@ void MainWindow::on_actionPrint_triggered() {
|
|||||||
QRect pageRect = printer.pageRect();
|
QRect pageRect = printer.pageRect();
|
||||||
int cols = (image_.width() / pageRect.width()) + (image_.width() % pageRect.width() ? 1 : 0);
|
int cols = (image_.width() / pageRect.width()) + (image_.width() % pageRect.width() ? 1 : 0);
|
||||||
int rows = (image_.height() / pageRect.height()) + (image_.height() % pageRect.height() ? 1 : 0);
|
int rows = (image_.height() / pageRect.height()) + (image_.height() % pageRect.height() ? 1 : 0);
|
||||||
// qDebug() << "page:" << printer.pageRect() << "image:" << image_.size() << "cols, rows:" << cols << rows;
|
|
||||||
for(int row = 0; row < rows; ++row) {
|
for(int row = 0; row < rows; ++row) {
|
||||||
for(int col = 0; col < cols; ++col) {
|
for(int col = 0; col < cols; ++col) {
|
||||||
QRect srcRect(pageRect.width() * col, pageRect.height() * row, pageRect.width(), pageRect.height());
|
QRect srcRect(pageRect.width() * col, pageRect.height() * row, pageRect.width(), pageRect.height());
|
||||||
// qDebug() << "row:" << row << "col:" << col << "src:" << srcRect << "page:" << printer.pageRect();
|
|
||||||
painter.drawImage(QPoint(0, 0), image_, srcRect);
|
painter.drawImage(QPoint(0, 0), image_, srcRect);
|
||||||
if(col + 1 == cols && row + 1 == rows) // this is the last page
|
if(col + 1 == cols && row + 1 == rows) // this is the last page
|
||||||
break;
|
break;
|
||||||
@ -795,7 +798,7 @@ void MainWindow::on_actionSlideShow_triggered(bool checked) {
|
|||||||
if(!slideShowTimer_) {
|
if(!slideShowTimer_) {
|
||||||
slideShowTimer_ = new QTimer();
|
slideShowTimer_ = new QTimer();
|
||||||
// switch to the next image when timeout
|
// switch to the next image when timeout
|
||||||
connect(slideShowTimer_, SIGNAL(timeout()), SLOT(on_actionNext_triggered()));
|
connect(slideShowTimer_, &QTimer::timeout, this, &MainWindow::on_actionNext_triggered);
|
||||||
}
|
}
|
||||||
Application* app = static_cast<Application*>(qApp);
|
Application* app = static_cast<Application*>(qApp);
|
||||||
slideShowTimer_->start(app->settings().slideShowInterval() * 1000);
|
slideShowTimer_->start(app->settings().slideShowInterval() * 1000);
|
||||||
@ -805,7 +808,7 @@ void MainWindow::on_actionSlideShow_triggered(bool checked) {
|
|||||||
else {
|
else {
|
||||||
if(slideShowTimer_) {
|
if(slideShowTimer_) {
|
||||||
delete slideShowTimer_;
|
delete slideShowTimer_;
|
||||||
slideShowTimer_ = NULL;
|
slideShowTimer_ = nullptr;
|
||||||
ui.actionSlideShow->setIcon(QIcon::fromTheme("media-playback-start"));
|
ui.actionSlideShow->setIcon(QIcon::fromTheme("media-playback-start"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -838,15 +841,16 @@ void MainWindow::setShowThumbnails(bool show) {
|
|||||||
QCoreApplication::processEvents();
|
QCoreApplication::processEvents();
|
||||||
listView->scrollTo(currentIndex_, QAbstractItemView::PositionAtCenter);
|
listView->scrollTo(currentIndex_, QAbstractItemView::PositionAtCenter);
|
||||||
}
|
}
|
||||||
connect(thumbnailsView_->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)), SLOT(onThumbnailSelChanged(QItemSelection,QItemSelection)));
|
connect(thumbnailsView_->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
this, &MainWindow::onThumbnailSelChanged);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(thumbnailsDock_) {
|
if(thumbnailsDock_) {
|
||||||
delete thumbnailsView_;
|
delete thumbnailsView_;
|
||||||
thumbnailsView_ = NULL;
|
thumbnailsView_ = nullptr;
|
||||||
delete thumbnailsDock_;
|
delete thumbnailsDock_;
|
||||||
thumbnailsDock_ = NULL;
|
thumbnailsDock_ = nullptr;
|
||||||
}
|
}
|
||||||
proxyModel_->setShowThumbnails(false);
|
proxyModel_->setShowThumbnails(false);
|
||||||
}
|
}
|
||||||
@ -876,6 +880,7 @@ void MainWindow::changeEvent(QEvent* event) {
|
|||||||
addAction(action);
|
addAction(action);
|
||||||
}
|
}
|
||||||
addActions(ui.menubar->actions());
|
addActions(ui.menubar->actions());
|
||||||
|
ui.view->hideCursor(true);
|
||||||
}
|
}
|
||||||
else { // restore to normal window mode
|
else { // restore to normal window mode
|
||||||
ui.view->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken);
|
ui.view->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken);
|
||||||
@ -890,6 +895,7 @@ void MainWindow::changeEvent(QEvent* event) {
|
|||||||
ui.statusBar->show();
|
ui.statusBar->show();
|
||||||
if(thumbnailsDock_)
|
if(thumbnailsDock_)
|
||||||
thumbnailsDock_->show();
|
thumbnailsDock_->show();
|
||||||
|
ui.view->hideCursor(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QWidget::changeEvent(event);
|
QWidget::changeEvent(event);
|
||||||
|
@ -126,7 +126,7 @@ private:
|
|||||||
void updateUI();
|
void updateUI();
|
||||||
void setModified(bool modified);
|
void setModified(bool modified);
|
||||||
QModelIndex indexFromPath(FmPath* filePath);
|
QModelIndex indexFromPath(FmPath* filePath);
|
||||||
QGraphicsItem* getGifItem();
|
QGraphicsItem* getGraphicsItem();
|
||||||
|
|
||||||
// GObject related signal handers and callbacks
|
// GObject related signal handers and callbacks
|
||||||
static void _onFolderLoaded(FmFolder* folder, MainWindow* _this) {
|
static void _onFolderLoaded(FmFolder* folder, MainWindow* _this) {
|
||||||
|
@ -221,7 +221,7 @@
|
|||||||
<string>Zoom &In</string>
|
<string>Zoom &In</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="shortcut">
|
<property name="shortcut">
|
||||||
<string>Ctrl++</string>
|
<string>Ctrl+=</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionZoomOut">
|
<action name="actionZoomOut">
|
||||||
@ -288,6 +288,9 @@
|
|||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Original Size</string>
|
<string>Original Size</string>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="shortcut">
|
||||||
|
<string>Ctrl+0</string>
|
||||||
|
</property>
|
||||||
</action>
|
</action>
|
||||||
<action name="actionZoomFit">
|
<action name="actionZoomFit">
|
||||||
<property name="icon">
|
<property name="icon">
|
||||||
|
@ -96,8 +96,6 @@ static void findIconThemesInDir(QHash<QString, QString>& iconThemes, QString dir
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PreferencesDialog::initIconThemes(Settings& settings) {
|
void PreferencesDialog::initIconThemes(Settings& settings) {
|
||||||
Application* app = static_cast<Application*>(qApp);
|
|
||||||
|
|
||||||
// check if auto-detection is done (for example, from xsettings)
|
// check if auto-detection is done (for example, from xsettings)
|
||||||
if(settings.useFallbackIconTheme()) { // auto-detection failed
|
if(settings.useFallbackIconTheme()) { // auto-detection failed
|
||||||
// load xdg icon themes and select the current one
|
// load xdg icon themes and select the current one
|
||||||
|
@ -28,8 +28,8 @@ using namespace LxImage;
|
|||||||
|
|
||||||
SaveImageJob::SaveImageJob(MainWindow* window, FmPath* filePath):
|
SaveImageJob::SaveImageJob(MainWindow* window, FmPath* filePath):
|
||||||
Job(),
|
Job(),
|
||||||
path_(fm_path_ref(filePath)),
|
|
||||||
mainWindow_(window),
|
mainWindow_(window),
|
||||||
|
path_(fm_path_ref(filePath)),
|
||||||
image_(window->image()) {
|
image_(window->image()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include "application.h"
|
#include "application.h"
|
||||||
#include <QDesktopWidget>
|
#include <QDesktopWidget>
|
||||||
|
#include <QScreen>
|
||||||
|
|
||||||
#include <QX11Info>
|
#include <QX11Info>
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@ -83,7 +84,7 @@ QRect ScreenshotDialog::windowFrame(WId wid) {
|
|||||||
int x, y;
|
int x, y;
|
||||||
// translate to root coordinate
|
// translate to root coordinate
|
||||||
XTranslateCoordinates(QX11Info::display(), wid, wa.root, 0, 0, &x, &y, &child);
|
XTranslateCoordinates(QX11Info::display(), wid, wa.root, 0, 0, &x, &y, &child);
|
||||||
qDebug("%d, %d, %d, %d", x, y, wa.width, wa.height);
|
//qDebug("%d, %d, %d, %d", x, y, wa.width, wa.height);
|
||||||
result.setRect(x, y, wa.width, wa.height);
|
result.setRect(x, y, wa.width, wa.height);
|
||||||
|
|
||||||
// get the frame widths added by the window manager
|
// get the frame widths added by the window manager
|
||||||
@ -140,38 +141,42 @@ void ScreenshotDialog::doScreenshot() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPixmap pixmap;
|
QImage image;
|
||||||
pixmap = QPixmap::grabWindow(wid, x, y, width, height);
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
QImage image = pixmap.toImage();
|
if(screen) {
|
||||||
|
QPixmap pixmap = screen->grabWindow(wid, x, y, width, height);
|
||||||
|
image = pixmap.toImage();
|
||||||
|
|
||||||
if(hasXfixes_ && ui.includeCursor->isChecked()) {
|
if(hasXfixes_ && ui.includeCursor->isChecked()) {
|
||||||
// capture the cursor if needed
|
// capture the cursor if needed
|
||||||
XFixesCursorImage* cursor = XFixesGetCursorImage(QX11Info::display());
|
XFixesCursorImage* cursor = XFixesGetCursorImage(QX11Info::display());
|
||||||
if(cursor) {
|
if(cursor) {
|
||||||
if(cursor->pixels) { // pixles should be an ARGB array
|
if(cursor->pixels) { // pixles should be an ARGB array
|
||||||
QImage cursorImage;
|
QImage cursorImage;
|
||||||
if(sizeof(long) == 4) {
|
if(sizeof(long) == 4) {
|
||||||
// FIXME: will we encounter byte-order problems here?
|
// FIXME: will we encounter byte-order problems here?
|
||||||
cursorImage = QImage((uchar*)cursor->pixels, cursor->width, cursor->height, QImage::Format_ARGB32);
|
cursorImage = QImage((uchar*)cursor->pixels, cursor->width, cursor->height, QImage::Format_ARGB32);
|
||||||
|
}
|
||||||
|
else { // XFixes returns long integers which is not 32 bit on 64 bit systems.
|
||||||
|
long len = cursor->width * cursor->height;
|
||||||
|
quint32* buf = new quint32[len];
|
||||||
|
for(long i = 0; i < len; ++i)
|
||||||
|
buf[i] = (quint32)cursor->pixels[i];
|
||||||
|
cursorImage = QImage((uchar*)buf, cursor->width, cursor->height, QImage::Format_ARGB32, [](void* b) { delete[] (quint32*)b; }, buf);
|
||||||
|
}
|
||||||
|
// paint the cursor on the current image
|
||||||
|
QPainter painter(&image);
|
||||||
|
painter.drawImage(cursor->x - cursor->xhot, cursor->y - cursor->yhot, cursorImage);
|
||||||
}
|
}
|
||||||
else { // XFixes returns long integers which is not 32 bit on 64 bit systems.
|
XFree(cursor);
|
||||||
long len = cursor->width * cursor->height;
|
|
||||||
quint32* buf = new quint32[len];
|
|
||||||
for(long i = 0; i < len; ++i)
|
|
||||||
buf[i] = (quint32)cursor->pixels[i];
|
|
||||||
cursorImage = QImage((uchar*)buf, cursor->width, cursor->height, QImage::Format_ARGB32, [](void* b) { delete[] (quint32*)b; }, buf);
|
|
||||||
}
|
|
||||||
// paint the cursor on the current image
|
|
||||||
QPainter painter(&image);
|
|
||||||
painter.drawImage(cursor->x - cursor->xhot, cursor->y - cursor->yhot, cursorImage);
|
|
||||||
}
|
}
|
||||||
XFree(cursor);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Application* app = static_cast<Application*>(qApp);
|
Application* app = static_cast<Application*>(qApp);
|
||||||
MainWindow* window = app->createWindow();
|
MainWindow* window = app->createWindow();
|
||||||
window->pasteImage(image);
|
if(!image.isNull())
|
||||||
|
window->pasteImage(image);
|
||||||
window->show();
|
window->show();
|
||||||
|
|
||||||
deleteLater(); // destroy ourself
|
deleteLater(); // destroy ourself
|
||||||
|
@ -27,11 +27,11 @@ using namespace LxImage;
|
|||||||
Settings::Settings():
|
Settings::Settings():
|
||||||
useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == "hicolor"),
|
useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == "hicolor"),
|
||||||
bgColor_(255, 255, 255),
|
bgColor_(255, 255, 255),
|
||||||
|
fullScreenBgColor_(0, 0, 0),
|
||||||
showThumbnails_(false),
|
showThumbnails_(false),
|
||||||
showSidePane_(false),
|
showSidePane_(false),
|
||||||
fullScreenBgColor_(0, 0, 0),
|
|
||||||
fallbackIconTheme_("oxygen"),
|
|
||||||
slideShowInterval_(5),
|
slideShowInterval_(5),
|
||||||
|
fallbackIconTheme_("oxygen"),
|
||||||
fixedWindowWidth_(640),
|
fixedWindowWidth_(640),
|
||||||
fixedWindowHeight_(480),
|
fixedWindowHeight_(480),
|
||||||
lastWindowWidth_(640),
|
lastWindowWidth_(640),
|
||||||
@ -49,7 +49,7 @@ bool Settings::load() {
|
|||||||
fullScreenBgColor_ = settings.value("fullScreenBgColor", fullScreenBgColor_).value<QColor>();
|
fullScreenBgColor_ = settings.value("fullScreenBgColor", fullScreenBgColor_).value<QColor>();
|
||||||
// showThumbnails_;
|
// showThumbnails_;
|
||||||
// showSidePane_;
|
// showSidePane_;
|
||||||
int slideShowInterval_ = settings.value("slideShowInterval", slideShowInterval_).toInt();
|
slideShowInterval_ = settings.value("slideShowInterval", slideShowInterval_).toInt();
|
||||||
|
|
||||||
settings.beginGroup("Window");
|
settings.beginGroup("Window");
|
||||||
fixedWindowWidth_ = settings.value("FixedWidth", 640).toInt();
|
fixedWindowWidth_ = settings.value("FixedWidth", 640).toInt();
|
||||||
|
4
src/translations/lximage-qt-screenshot_ca.desktop
Normal file
4
src/translations/lximage-qt-screenshot_ca.desktop
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#Translations
|
||||||
|
Name[ca]=Captura de pantalla
|
||||||
|
GenericName[ca]=Captura de pantalla
|
||||||
|
Comment[ca]=Preneu una captura de pantalla
|
4
src/translations/lximage-qt_ca.desktop
Normal file
4
src/translations/lximage-qt_ca.desktop
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
#Translations
|
||||||
|
Name[ca]=LXImage
|
||||||
|
GenericName[ca]=Visualitzador d'imatges
|
||||||
|
Comment[ca]=El visualitzador d'imatges de LXQt
|
Loading…
x
Reference in New Issue
Block a user