Compare commits
7 Commits
ubuntu/plu
...
upstream/0
Author | SHA1 | Date | |
---|---|---|---|
|
4a8f2ba14a | ||
|
d53be78755 | ||
|
de1fa415b2 | ||
|
4ac585f605 | ||
|
bc98f04c8a | ||
|
7a6ecc3364 | ||
|
95a2f6c084 |
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,7 +0,0 @@
|
||||
debian/*.debhelper
|
||||
debian/*.log
|
||||
debian/*.substvars
|
||||
debian/debhelper-build-stamp
|
||||
debian/files
|
||||
|
||||
debian/lximage-qt/
|
9
AUTHORS
Normal file
9
AUTHORS
Normal file
@ -0,0 +1,9 @@
|
||||
Upstream Authors:
|
||||
LXQt team: http://lxqt.org
|
||||
Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
|
||||
Copyright:
|
||||
Copyright (c) 2013-2015 LXQt team
|
||||
|
||||
License: GPL-2+ and LGPL-2.1+
|
||||
The full text of the licenses can be found in the 'COPYING' file.
|
184
CHANGELOG
Normal file
184
CHANGELOG
Normal file
@ -0,0 +1,184 @@
|
||||
|
||||
lximage-qt-0.5.1 / 2016-12-21
|
||||
=============================
|
||||
|
||||
* Bump patch version and (#82)
|
||||
* Create lximage-qt-screenshot_it.desktop (#83)
|
||||
* Add *da.desktop files
|
||||
* Desktop entry files: Fix typo in French translation
|
||||
* [MRG] Display first image when loading a directory (v2) (#75)
|
||||
* Desktop entry files: Add French translation
|
||||
* Use lxqt-build-tools
|
||||
* Use the new lxqt-build-tools package
|
||||
* Fixed A Cast (#71)
|
||||
* Remove cpack (#70)
|
||||
|
||||
0.5.0 / 2016-09-24
|
||||
==================
|
||||
|
||||
* Release 0.5.0: Add changelog
|
||||
* 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
|
49
CMakeLists.txt
Normal file
49
CMakeLists.txt
Normal file
@ -0,0 +1,49 @@
|
||||
cmake_minimum_required(VERSION 3.0.2)
|
||||
project(lximage-qt)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
|
||||
set(MAJOR_VERSION 0)
|
||||
set(MINOR_VERSION 5)
|
||||
set(PATCH_VERSION 1)
|
||||
set(LXIMAGE_VERSION ${MAJOR_VERSION}.${MINOR_VERSION}.${PATCH_VERSION})
|
||||
|
||||
set(LXQTBT_MINIMUM_VERSION "0.3.0")
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
find_package(Qt5Widgets REQUIRED)
|
||||
find_package(Qt5DBus REQUIRED)
|
||||
find_package(Qt5PrintSupport REQUIRED QUIET)
|
||||
find_package(Qt5X11Extras REQUIRED QUIET)
|
||||
find_package(Qt5LinguistTools REQUIRED QUIET)
|
||||
find_package(Qt5Svg REQUIRED QUIET)
|
||||
find_package(fm-qt REQUIRED QUIET)
|
||||
find_package(lxqt-build-tools ${LXQTBT_MINIMUM_VERSION} REQUIRED)
|
||||
message(STATUS "Building with Qt ${Qt5Core_VERSION_STRING}")
|
||||
|
||||
include(LXQtCompilerSettings NO_POLICY_SCOPE)
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
# FIXME: we'll need this to provide detail info for photos in the future
|
||||
pkg_check_modules(EXIF REQUIRED libexif)
|
||||
|
||||
# TODO: make the X11 stuff optional.
|
||||
# for screenshot support
|
||||
find_package(X11 REQUIRED)
|
||||
|
||||
# Xfixes is needed to capture the mouse cursor image
|
||||
pkg_check_modules(XFIXES REQUIRED xfixes)
|
||||
|
||||
# add src subdirectory
|
||||
add_subdirectory(src)
|
||||
|
||||
# install an icon for the application
|
||||
install(
|
||||
FILES data/lximage-qt.png
|
||||
DESTINATION "${CMAKE_INSTALL_DATADIR}/icons/hicolor/48x48/apps"
|
||||
)
|
||||
|
280
COPYING
Normal file
280
COPYING
Normal file
@ -0,0 +1,280 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
25
README.md
Normal file
25
README.md
Normal file
@ -0,0 +1,25 @@
|
||||
# LXImage-Qt
|
||||
|
||||
## 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'.
|
9
data/lximage-qt-screenshot.desktop.in
Normal file
9
data/lximage-qt-screenshot.desktop.in
Normal file
@ -0,0 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Screenshot
|
||||
GenericName=Screenshot
|
||||
Comment=Take a screenshot
|
||||
Exec=lximage-qt --screenshot
|
||||
Icon=camera-photo
|
||||
Categories=Graphics;Core;Qt;
|
||||
StartupNotify=true
|
11
data/lximage-qt.desktop.in
Normal file
11
data/lximage-qt.desktop.in
Normal file
@ -0,0 +1,11 @@
|
||||
[Desktop Entry]
|
||||
Type=Application
|
||||
Name=LXImage
|
||||
GenericName=Image Viewer
|
||||
Comment=The LXQt image viewer
|
||||
Icon=lximage-qt
|
||||
Exec=lximage-qt %F
|
||||
StartupNotify=true
|
||||
Terminal=false
|
||||
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;
|
BIN
data/lximage-qt.png
Normal file
BIN
data/lximage-qt.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.8 KiB |
311
debian/changelog
vendored
311
debian/changelog
vendored
@ -1,311 +0,0 @@
|
||||
lximage-qt (2.1.1-0ubuntu2) plucky; urgency=medium
|
||||
|
||||
* Update Standards-Version to 4.7.1, no changes needed.
|
||||
|
||||
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 21 Feb 2025 17:03:55 -0600
|
||||
|
||||
lximage-qt (2.1.1-0ubuntu1) plucky; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
|
||||
-- Simon Quigley <tsimonq2@ubuntu.com> Tue, 04 Feb 2025 15:27:05 -0600
|
||||
|
||||
lximage-qt (2.1.0-0ubuntu1) plucky; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
- Bump build dependencies.
|
||||
|
||||
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 15 Nov 2024 15:32:14 -0600
|
||||
|
||||
lximage-qt (2.0.1-0ubuntu1) oracular; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
* Update copyright file.
|
||||
* Bump Standards-Version to 4.7.0, no changes necessary.
|
||||
* Adjust dependencies.
|
||||
|
||||
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Thu, 15 Aug 2024 16:51:12 -0500
|
||||
|
||||
lximage-qt (1.4.0-0ubuntu1) noble; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
* Updated copyright file.
|
||||
* Bumped build dependency versions.
|
||||
* Ran wrap-and-sort.
|
||||
|
||||
-- Aaron Rainbolt <arraybolt3@gmail.com> Sun, 12 Nov 2023 17:36:16 -0600
|
||||
|
||||
lximage-qt (1.3.0-0ubuntu1) mantic; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
* Bump build dependencies.
|
||||
|
||||
-- Simon Quigley <tsimonq2@ubuntu.com> Fri, 11 Aug 2023 09:48:31 -0500
|
||||
|
||||
lximage-qt (1.2.0-2ubuntu1) lunar; urgency=medium
|
||||
|
||||
* Revert a sync from Debian.
|
||||
* Bumped build dependencies.
|
||||
* Added 'Rules-Requires-Root: no' to debian/control.
|
||||
* Bumped Standards-Version to 4.6.2, no changes necessary.
|
||||
* Overhauled copyright file.
|
||||
|
||||
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Fri, 10 Feb 2023 14:19:56 -0600
|
||||
|
||||
lximage-qt (1.2.0-0ubuntu2) lunar; urgency=medium
|
||||
|
||||
* No-change rebuild against libfm-qt 1.2.1.
|
||||
|
||||
-- Aaron Rainbolt <arraybolt3@ubuntu.com> Fri, 27 Jan 2023 15:46:45 -0600
|
||||
|
||||
lximage-qt (1.2.0-0ubuntu1) lunar; urgency=medium
|
||||
|
||||
* New upstream release.
|
||||
* Fix the watch file, for real this time.
|
||||
* Lubuntuify the package slightly, to make debhelper happy.
|
||||
* Bump build dependencies in debian/control.
|
||||
* Remove reverse-applicable patch.
|
||||
|
||||
-- Simon Quigley <tsimonq2@ubuntu.com> Thu, 17 Nov 2022 17:52:27 -0600
|
||||
|
||||
lximage-qt (1.1.0-2) unstable; urgency=medium
|
||||
|
||||
[ Debian Janitor ]
|
||||
* Remove constraints unnecessary since buster (oldstable):
|
||||
+ lximage-qt-l10n: Drop versioned constraint on lximage-qt in Replaces.
|
||||
+ lximage-qt-l10n: Drop versioned constraint on lximage-qt in Breaks.
|
||||
|
||||
[ Andrew Lee (李健秋) ]
|
||||
* debian/changelog: clean triming whitespaces.
|
||||
* debian/control: Bumped Standards-Version to 4.6.1, no changes needed.
|
||||
* Reorganize changes from experimental:
|
||||
* debian/copyright: update. fetched from experimental branch.
|
||||
* debian/lintian-overrides: fix overrides for no-manual-page.
|
||||
* Upstreamed patches directory
|
||||
* Upstreamd signing key
|
||||
* debian/lximage-qt.install: ship lximage-qt.metainfo.xml.
|
||||
* debian/lximage-qt.install: sort shipped files.
|
||||
* debian/rules: Remove unnecessary -Wl,--as-needed.
|
||||
* debian/rules: Drop --fail-missing argument to dh_missing which is now
|
||||
default in debhelper 13.
|
||||
* debian/upstream/metadata: Change Repository-Browser field to
|
||||
Repository-Browse.
|
||||
|
||||
-- Andrew Lee (李健秋) <ajqlee@debian.org> Fri, 28 Oct 2022 14:40:53 +0800
|
||||
|
||||
lximage-qt (1.1.0-1) experimental; urgency=medium
|
||||
|
||||
[ S. 7 ]
|
||||
* New upstream release
|
||||
* Bumped Standards-Version to 4.6.0, no changes needed
|
||||
* Update debian/copyright
|
||||
|
||||
[ Aaron Rainbolt ]
|
||||
* New upstream release.
|
||||
* Removed trailing whitespace from changelog.
|
||||
* Upstreamed packaging changes from Ubuntu, modifying the following files:
|
||||
- control
|
||||
- copyright
|
||||
- lintian-overrides
|
||||
- lximage-qt.install
|
||||
- rules
|
||||
- upstream/*
|
||||
- patches directory
|
||||
|
||||
-- Aaron Rainbolt <arraybolt3@gmail.com> Wed, 13 Jul 2022 19:06:28 -0500
|
||||
|
||||
lximage-qt (1.0.0-1) unstable; urgency=medium
|
||||
|
||||
* New upstream release
|
||||
* Bumped Standards-Version to 4.6.0, no changes needed
|
||||
* Update debian/copyright
|
||||
|
||||
-- S. 7 <severusseptimius7@gmail.com> Thu, 25 Nov 2021 18:19:55 +0200
|
||||
|
||||
lximage-qt (0.16.0-1) unstable; urgency=medium
|
||||
|
||||
[ Alf Gaida ]
|
||||
* Switched to gbp
|
||||
* Bumped Standards-Version to 4.4.0, no changes needed
|
||||
|
||||
[ Andrew Lee (李健秋) ]
|
||||
* New upstream release. (Closes: #978178)
|
||||
|
||||
-- Andrew Lee (李健秋) <ajqlee@debian.org> Thu, 07 Jan 2021 18:12:17 +0800
|
||||
|
||||
lximage-qt (0.14.1-1) unstable; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.14.1.
|
||||
* Bumped minimum version libfm-qt-dev (>= 0.14.1~)
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Tue, 26 Feb 2019 01:15:27 +0100
|
||||
|
||||
lximage-qt (0.14.0-1) unstable; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.14.0.
|
||||
* Bumped Standards to 4.3.0, no changes needed
|
||||
* Dropped d/compat, use debhelper-compat = 12, no changes needed
|
||||
* Fixed years in d/copyright
|
||||
* Bumped minimum version lxqt-build-tools (>= 0.6.0~)
|
||||
* Bumped minimum version libfm-qt-dev (>= 0.14.0~)
|
||||
* Removed obsolete PULL_TRANSLATIONS= OFF from dh_auto_configure
|
||||
* Added l10n-package, moved from lxqt-l10n
|
||||
* Added d/upstream/metadata
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Sun, 27 Jan 2019 15:45:53 +0100
|
||||
|
||||
lximage-qt (0.7.0-2) unstable; urgency=medium
|
||||
|
||||
* Switch to unstable
|
||||
* Bumped build dependency libfm-qt-def to >= 0.13.1~
|
||||
* Bumped Standards to 4.1.5, no changes needed
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Sat, 07 Jul 2018 13:20:23 +0200
|
||||
|
||||
lximage-qt (0.7.0-1) experimental; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.7.0.
|
||||
* Removed build dependency libfm-dev
|
||||
* Removed build dependency libmenu-cache-dev
|
||||
* Bumped build dependency libfm-qt-def to >= 0.13.0~
|
||||
* Bumped build dependency lxqt-build-tools to >= 0.5.0~
|
||||
* Moved debian/.gitignore to ./.gitignore
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Fri, 25 May 2018 19:36:29 +0200
|
||||
|
||||
lximage-qt (0.6.0-4) unstable; urgency=medium
|
||||
|
||||
* Bumped compat to 11
|
||||
* Bumped debhelper to >= 11~
|
||||
* Bumped Standards to 4.1.4, no changes needed
|
||||
* Changed VCS fields for salsa
|
||||
* Changed Homepage, Source and watch to lxqt
|
||||
* Bumped years in copyright
|
||||
* Removed trailing whitespaces in changelog
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Sun, 29 Apr 2018 12:36:49 +0200
|
||||
|
||||
lximage-qt (0.6.0-3) unstable; urgency=medium
|
||||
|
||||
* Bumped Standards to 4.1.2
|
||||
* Removed branch from VCS fields
|
||||
* Removed debian/gbp.conf
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Thu, 14 Dec 2017 17:28:58 +0100
|
||||
|
||||
lximage-qt (0.6.0-2) unstable; urgency=medium
|
||||
|
||||
* Transition to unstable
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Mon, 04 Dec 2017 20:25:33 +0100
|
||||
|
||||
lximage-qt (0.6.0-1) experimental; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.6.0.
|
||||
* Switched to experimental
|
||||
* Bumped libfm-qt-dev to >=0.12.0
|
||||
* Bumped build-tools to >= 0.4.0
|
||||
* Bumped Standards to 4.1.1
|
||||
* Bumped years in copyright
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Tue, 24 Oct 2017 23:03:31 +0200
|
||||
|
||||
lximage-qt (0.5.1-1) unstable; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.5.1.
|
||||
* Removed build dependencies:
|
||||
- cmake
|
||||
- liblxqt0-dev
|
||||
- libqt5xdg-dev
|
||||
- pkg-config
|
||||
- qttools5-dev
|
||||
- qttools5-dev-tools
|
||||
* Bumped minimum version libfm-qt-dev (>= 0.11.2)
|
||||
* Added build dependency lxqt-build-tools (>= 0.3.0)
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Thu, 22 Dec 2016 02:59:30 +0100
|
||||
|
||||
lximage-qt (0.5.0-4) unstable; urgency=medium
|
||||
|
||||
* Fixes Recommends lxqtimage-qt-l10n to lximage-qt-l10n
|
||||
Thanks Armin Haas <armin@awawa.de> (Closes: #841426)
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Thu, 20 Oct 2016 18:08:37 +0200
|
||||
|
||||
lximage-qt (0.5.0-3) unstable; urgency=medium
|
||||
|
||||
* Cherry-picking upstream release 0.5.0.
|
||||
* Bumped Standards to 3.9.8, no changes needed
|
||||
* Bumped compat to 10
|
||||
* Removed --parallel from rules, standard compat 10
|
||||
* Bumped minimum version debhelper (>= 10)
|
||||
* Bumped minimum version libfm-qt-dev (>= 0.11.1)
|
||||
* Added build dependency libkf5windowsystem-dev
|
||||
* Added build dependency liblxqt0-dev (>= 0.11.0)
|
||||
* Added build dependency libqt5svg5-dev
|
||||
* Added build dependency libqt5xdg-dev (>= 2.0.0)
|
||||
* Added Recommends lxqtimage-qt-l10n
|
||||
* Added Recommends qt5-image-formats-plugins
|
||||
* Fixed copyrights Format field to https
|
||||
* Dropped patches, applied upstream
|
||||
* Added translation control to rules
|
||||
* Set CMAKE_BUILD_TYPE=RelWithDebInfo
|
||||
* Exported LC_ALL=C.UTF-8, make builds reproducible
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Tue, 18 Oct 2016 21:40:48 +0200
|
||||
|
||||
lximage-qt (0.4.0+20160108-3) unstable; urgency=medium
|
||||
|
||||
* Add missing patch from 0.4.0+20160108-2.
|
||||
|
||||
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Thu, 25 Feb 2016 23:50:39 +0800
|
||||
|
||||
lximage-qt (0.4.0+20160108-2) unstable; urgency=medium
|
||||
|
||||
[ Eduard Sanou ]
|
||||
* Fix misdetection as binary input in grep when LC_ALL=C
|
||||
|
||||
[ ChangZhuo Chen (陳昌倬) ]
|
||||
* Merge patch from Eduard Sanou to make reproducible build
|
||||
(Closes: #815898).
|
||||
|
||||
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Thu, 25 Feb 2016 23:18:22 +0800
|
||||
|
||||
lximage-qt (0.4.0+20160108-1) unstable; urgency=medium
|
||||
|
||||
* Cherry-picked new upstream version 0.4.0+20160108.
|
||||
* Removed outdated build dependency libfm-qt5-dev,
|
||||
* Added build dependencies libfm-qt-dev and libmenu-cache-dev.
|
||||
* Bump Standards to 3.9.7
|
||||
* Changed the VCS-fields to https://
|
||||
* Fix Years in copyright
|
||||
* Enable hardening=+all
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Sun, 07 Feb 2016 22:55:06 +0100
|
||||
|
||||
lximage-qt (0.4.0+20151117-2) unstable; urgency=medium
|
||||
|
||||
* Remove dbg package in favor of dbgsym.
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Sat, 26 Dec 2015 17:26:11 +0100
|
||||
|
||||
lximage-qt (0.4.0+20151117-1) unstable; urgency=medium
|
||||
|
||||
* Cherry-picked new upstream version 0.4.0+201511117.
|
||||
* Added lintian-overrride
|
||||
* Fixed VCS-Fields
|
||||
* Removed not used GPL2 from copyright
|
||||
|
||||
-- Alf Gaida <agaida@siduction.org> Thu, 19 Nov 2015 19:57:17 +0100
|
||||
|
||||
lximage-qt (0.4.0+20150828-2) unstable; urgency=medium
|
||||
|
||||
* Add -fPIE -pie for lintian warning.
|
||||
|
||||
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Thu, 22 Oct 2015 20:18:27 +0800
|
||||
|
||||
lximage-qt (0.4.0+20150828-1) unstable; urgency=medium
|
||||
|
||||
* Initial release (Closes: #795802)
|
||||
|
||||
-- ChangZhuo Chen (陳昌倬) <czchen@debian.org> Thu, 24 Sep 2015 18:50:12 +0800
|
70
debian/control
vendored
70
debian/control
vendored
@ -1,70 +0,0 @@
|
||||
Source: lximage-qt
|
||||
Maintainer: Lubuntu Developers <lubuntu-devel@lists.ubuntu.com>
|
||||
Original-Maintainer: LXQt Packaging Team <pkg-lxqt-devel@lists.alioth.debian.org>
|
||||
Uploaders: Alf Gaida <agaida@siduction.org>,
|
||||
ChangZhuo Chen (陳昌倬) <czchen@debian.org>,
|
||||
Andrew Lee (李健秋) <ajqlee@debian.org>
|
||||
Section: x11
|
||||
Priority: optional
|
||||
Build-Depends: debhelper-compat (= 13),
|
||||
libexif-dev,
|
||||
libfm-qt6-dev (>= 2.1.0),
|
||||
libx11-dev,
|
||||
libxcb-composite0-dev,
|
||||
libxcb-cursor-dev,
|
||||
libxcb-damage0-dev,
|
||||
libxcb-dpms0-dev,
|
||||
libxcb-dri2-0-dev,
|
||||
libxcb-dri3-dev,
|
||||
libxcb-ewmh-dev,
|
||||
libxcb-glx0-dev,
|
||||
libxcb-icccm4-dev,
|
||||
libxcb-keysyms1-dev,
|
||||
libxcb-present-dev,
|
||||
libxcb-record0-dev,
|
||||
libxcb-render0-dev,
|
||||
libxcb-res0-dev,
|
||||
libxcb-screensaver0-dev,
|
||||
libxcb-shape0-dev,
|
||||
libxcb-shm0-dev,
|
||||
libxcb-util-dev,
|
||||
libxcb-xf86dri0-dev,
|
||||
libxcb-xfixes0-dev,
|
||||
libxcb-xinerama0-dev,
|
||||
libxcb-xinput-dev,
|
||||
libxcb-xkb-dev,
|
||||
libxcb-xtest0-dev,
|
||||
libxcb-xv0-dev,
|
||||
libxcb-xvmc0-dev,
|
||||
libxfixes-dev,
|
||||
libxkbcommon-dev (>= 0.5.0),
|
||||
lxqt-build-tools (>= 2.1.0),
|
||||
qt6-svg-dev (>= 6.6.0)
|
||||
Standards-Version: 4.7.1
|
||||
Vcs-Browser: https://git.lubuntu.me/Lubuntu/lxqt-about-packaging
|
||||
Vcs-Git: https://git.lubuntu.me/Lubuntu/lxqt-about-packaging.git
|
||||
Debian-Vcs-Browser: https://salsa.debian.org/lxqt-team/lxqt-about
|
||||
Debian-Vcs-Git: https://salsa.debian.org/lxqt-team/lxqt-about.git
|
||||
Homepage: https://github.com/lxqt/lximage-qt
|
||||
Rules-Requires-Root: no
|
||||
|
||||
Package: lximage-qt
|
||||
Architecture: any
|
||||
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||
Recommends: lximage-qt-l10n, qt6-image-formats-plugins
|
||||
Description: Image viewer for LXQt
|
||||
A simple image viewer for LXQt. Additional file formats can be processed if
|
||||
one install qt5-image-formats-plugins.
|
||||
.
|
||||
This package contain the program files.
|
||||
|
||||
Package: lximage-qt-l10n
|
||||
Architecture: all
|
||||
Multi-Arch: foreign
|
||||
Section: localization
|
||||
Depends: qt6-translations-l10n, ${misc:Depends}
|
||||
Description: Language-package for lximage-qt
|
||||
A simple image viewer for LXQt. Additional file formats can be processed if
|
||||
one install qt6-image-formats-plugins.
|
||||
.
|
||||
This package contains the l10n files needed by the lximage-qt.
|
470
debian/copyright
vendored
470
debian/copyright
vendored
@ -1,470 +0,0 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: lximage-qt
|
||||
Source: https://github.com/lxqt/lximage-qt
|
||||
|
||||
Files: *
|
||||
Copyright: 2013-2016 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
2013-2024 LXQt team
|
||||
License: GPL-2+ and LGPL-2.1+
|
||||
|
||||
Files: src/application.*
|
||||
src/graphicsscene.*
|
||||
src/imageview.cpp
|
||||
src/loadimagejob.*
|
||||
src/lximage-qt.*
|
||||
src/mainwindow.*
|
||||
src/modelfilter.*
|
||||
src/mrumenu.*
|
||||
src/preferencesdialog.*
|
||||
src/resizeimagedialog.*
|
||||
src/saveimagejob.*
|
||||
src/screenshotdialog.*
|
||||
src/screenshotselectarea.*
|
||||
src/screenshotselectareagraphicsview.*
|
||||
src/settings.*
|
||||
src/statusbar.*
|
||||
src/upload/*
|
||||
Copyright: 2013 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
2013 Pedram Pourang <tsujan2000@gmail.com>
|
||||
2017 Nathan Osman <nathan@quickmediasolutions.com>
|
||||
2010 Aurélien Gâteau <agateau@kde.org>
|
||||
2018 Nathan Osman <nathan@quickmediasolutions.com>
|
||||
2020 Andrea Diamantini <adjam@protonmail.com>
|
||||
License: GPL-2+
|
||||
|
||||
Files: src/upload/uploaddialog.ui
|
||||
Copyright: 2013-2016 Hong Jen Yee (PCMan) <pcman.tw@gmail.com> ?
|
||||
2013-2022 LXQt team
|
||||
License: GPL-2+ and LGPL-2.1+
|
||||
|
||||
Files: data/lximage-qt.metainfo.xml
|
||||
Copyright: 2022 LXQt team
|
||||
License: CC-BY-4.0
|
||||
|
||||
Files: debian/*
|
||||
Copyright: 2014-2019 Alf Gaida <agaida@siduction.org>
|
||||
2015-2022 Andrew Lee (李健秋) <ajqlee@debian.org>
|
||||
2015 ChangZhuo Chen (陳昌倬) <czchen@debian.org>
|
||||
2023-2025 Lubuntu Developers <lubuntu-devel@lists.ubuntu.com>
|
||||
License: LGPL-2.1+
|
||||
|
||||
License: LGPL-2.1+
|
||||
This program or library is free software; you can redistribute it
|
||||
and/or modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 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
|
||||
Lesser General Public License for more details.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU Lesser General
|
||||
Public License version 2.1 can be found in "/usr/share/common-licenses/LGPL-2.1".
|
||||
|
||||
License: GPL-2+
|
||||
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.
|
||||
.
|
||||
On Debian systems, the complete text of the GNU General Public License
|
||||
version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||
|
||||
License: CC-BY-4.0
|
||||
Creative Commons Corporation ("Creative Commons") is not a law firm and
|
||||
does not provide legal services or legal advice. Distribution of
|
||||
Creative Commons public licenses does not create a lawyer-client or
|
||||
other relationship. Creative Commons makes its licenses and related
|
||||
information available on an "as-is" basis. Creative Commons gives no
|
||||
warranties regarding its licenses, any material licensed under their
|
||||
terms and conditions, or any related information. Creative Commons
|
||||
disclaims all liability for damages resulting from their use to the
|
||||
fullest extent possible.
|
||||
.
|
||||
Using Creative Commons Public Licenses
|
||||
.
|
||||
Creative Commons public licenses provide a standard set of terms and
|
||||
conditions that creators and other rights holders may use to share
|
||||
original works of authorship and other material subject to copyright
|
||||
and certain other rights specified in the public license below. The
|
||||
following considerations are for informational purposes only, are not
|
||||
exhaustive, and do not form part of our licenses.
|
||||
.
|
||||
Considerations for licensors: Our public licenses are
|
||||
intended for use by those authorized to give the public
|
||||
permission to use material in ways otherwise restricted by
|
||||
copyright and certain other rights. Our licenses are
|
||||
irrevocable. Licensors should read and understand the terms
|
||||
and conditions of the license they choose before applying it.
|
||||
Licensors should also secure all rights necessary before
|
||||
applying our licenses so that the public can reuse the
|
||||
material as expected. Licensors should clearly mark any
|
||||
material not subject to the license. This includes other CC-
|
||||
licensed material, or material used under an exception or
|
||||
limitation to copyright. More considerations for licensors:
|
||||
wiki.creativecommons.org/Considerations_for_licensors
|
||||
.
|
||||
Considerations for the public: By using one of our public
|
||||
licenses, a licensor grants the public permission to use the
|
||||
licensed material under specified terms and conditions. If
|
||||
the licensor's permission is not necessary for any reason--for
|
||||
example, because of any applicable exception or limitation to
|
||||
copyright--then that use is not regulated by the license. Our
|
||||
licenses grant only permissions under copyright and certain
|
||||
other rights that a licensor has authority to grant. Use of
|
||||
the licensed material may still be restricted for other
|
||||
reasons, including because others have copyright or other
|
||||
rights in the material. A licensor may make special requests,
|
||||
such as asking that all changes be marked or described.
|
||||
Although not required by our licenses, you are encouraged to
|
||||
respect those requests where reasonable. More considerations
|
||||
for the public:
|
||||
wiki.creativecommons.org/Considerations_for_licensees
|
||||
.
|
||||
=======================================================================
|
||||
.
|
||||
Creative Commons Attribution 4.0 International Public License
|
||||
.
|
||||
By exercising the Licensed Rights (defined below), You accept and agree
|
||||
to be bound by the terms and conditions of this Creative Commons
|
||||
Attribution 4.0 International Public License ("Public License"). To the
|
||||
extent this Public License may be interpreted as a contract, You are
|
||||
granted the Licensed Rights in consideration of Your acceptance of
|
||||
these terms and conditions, and the Licensor grants You such rights in
|
||||
consideration of benefits the Licensor receives from making the
|
||||
Licensed Material available under these terms and conditions.
|
||||
.
|
||||
.
|
||||
Section 1 -- Definitions.
|
||||
.
|
||||
a. Adapted Material means material subject to Copyright and Similar
|
||||
Rights that is derived from or based upon the Licensed Material
|
||||
and in which the Licensed Material is translated, altered,
|
||||
arranged, transformed, or otherwise modified in a manner requiring
|
||||
permission under the Copyright and Similar Rights held by the
|
||||
Licensor. For purposes of this Public License, where the Licensed
|
||||
Material is a musical work, performance, or sound recording,
|
||||
Adapted Material is always produced where the Licensed Material is
|
||||
synched in timed relation with a moving image.
|
||||
.
|
||||
b. Adapter's License means the license You apply to Your Copyright
|
||||
and Similar Rights in Your contributions to Adapted Material in
|
||||
accordance with the terms and conditions of this Public License.
|
||||
.
|
||||
c. Copyright and Similar Rights means copyright and/or similar rights
|
||||
closely related to copyright including, without limitation,
|
||||
performance, broadcast, sound recording, and Sui Generis Database
|
||||
Rights, without regard to how the rights are labeled or
|
||||
categorized. For purposes of this Public License, the rights
|
||||
specified in Section 2(b)(1)-(2) are not Copyright and Similar
|
||||
Rights.
|
||||
.
|
||||
d. Effective Technological Measures means those measures that, in the
|
||||
absence of proper authority, may not be circumvented under laws
|
||||
fulfilling obligations under Article 11 of the WIPO Copyright
|
||||
Treaty adopted on December 20, 1996, and/or similar international
|
||||
agreements.
|
||||
.
|
||||
e. Exceptions and Limitations means fair use, fair dealing, and/or
|
||||
any other exception or limitation to Copyright and Similar Rights
|
||||
that applies to Your use of the Licensed Material.
|
||||
.
|
||||
f. Licensed Material means the artistic or literary work, database,
|
||||
or other material to which the Licensor applied this Public
|
||||
License.
|
||||
.
|
||||
g. Licensed Rights means the rights granted to You subject to the
|
||||
terms and conditions of this Public License, which are limited to
|
||||
all Copyright and Similar Rights that apply to Your use of the
|
||||
Licensed Material and that the Licensor has authority to license.
|
||||
.
|
||||
h. Licensor means the individual(s) or entity(ies) granting rights
|
||||
under this Public License.
|
||||
.
|
||||
i. Share means to provide material to the public by any means or
|
||||
process that requires permission under the Licensed Rights, such
|
||||
as reproduction, public display, public performance, distribution,
|
||||
dissemination, communication, or importation, and to make material
|
||||
available to the public including in ways that members of the
|
||||
public may access the material from a place and at a time
|
||||
individually chosen by them.
|
||||
.
|
||||
j. Sui Generis Database Rights means rights other than copyright
|
||||
resulting from Directive 96/9/EC of the European Parliament and of
|
||||
the Council of 11 March 1996 on the legal protection of databases,
|
||||
as amended and/or succeeded, as well as other essentially
|
||||
equivalent rights anywhere in the world.
|
||||
.
|
||||
k. You means the individual or entity exercising the Licensed Rights
|
||||
under this Public License. Your has a corresponding meaning.
|
||||
.
|
||||
.
|
||||
Section 2 -- Scope.
|
||||
.
|
||||
a. License grant.
|
||||
.
|
||||
1. Subject to the terms and conditions of this Public License,
|
||||
the Licensor hereby grants You a worldwide, royalty-free,
|
||||
non-sublicensable, non-exclusive, irrevocable license to
|
||||
exercise the Licensed Rights in the Licensed Material to:
|
||||
.
|
||||
a. reproduce and Share the Licensed Material, in whole or
|
||||
in part; and
|
||||
.
|
||||
b. produce, reproduce, and Share Adapted Material.
|
||||
.
|
||||
2. Exceptions and Limitations. For the avoidance of doubt, where
|
||||
Exceptions and Limitations apply to Your use, this Public
|
||||
License does not apply, and You do not need to comply with
|
||||
its terms and conditions.
|
||||
.
|
||||
3. Term. The term of this Public License is specified in Section
|
||||
6(a).
|
||||
.
|
||||
4. Media and formats; technical modifications allowed. The
|
||||
Licensor authorizes You to exercise the Licensed Rights in
|
||||
all media and formats whether now known or hereafter created,
|
||||
and to make technical modifications necessary to do so. The
|
||||
Licensor waives and/or agrees not to assert any right or
|
||||
authority to forbid You from making technical modifications
|
||||
necessary to exercise the Licensed Rights, including
|
||||
technical modifications necessary to circumvent Effective
|
||||
Technological Measures. For purposes of this Public License,
|
||||
simply making modifications authorized by this Section 2(a)
|
||||
(4) never produces Adapted Material.
|
||||
.
|
||||
5. Downstream recipients.
|
||||
.
|
||||
a. Offer from the Licensor -- Licensed Material. Every
|
||||
recipient of the Licensed Material automatically
|
||||
receives an offer from the Licensor to exercise the
|
||||
Licensed Rights under the terms and conditions of this
|
||||
Public License.
|
||||
.
|
||||
b. No downstream restrictions. You may not offer or impose
|
||||
any additional or different terms or conditions on, or
|
||||
apply any Effective Technological Measures to, the
|
||||
Licensed Material if doing so restricts exercise of the
|
||||
Licensed Rights by any recipient of the Licensed
|
||||
Material.
|
||||
.
|
||||
6. No endorsement. Nothing in this Public License constitutes or
|
||||
may be construed as permission to assert or imply that You
|
||||
are, or that Your use of the Licensed Material is, connected
|
||||
with, or sponsored, endorsed, or granted official status by,
|
||||
the Licensor or others designated to receive attribution as
|
||||
provided in Section 3(a)(1)(A)(i).
|
||||
.
|
||||
b. Other rights.
|
||||
.
|
||||
1. Moral rights, such as the right of integrity, are not
|
||||
licensed under this Public License, nor are publicity,
|
||||
privacy, and/or other similar personality rights; however, to
|
||||
the extent possible, the Licensor waives and/or agrees not to
|
||||
assert any such rights held by the Licensor to the limited
|
||||
extent necessary to allow You to exercise the Licensed
|
||||
Rights, but not otherwise.
|
||||
.
|
||||
2. Patent and trademark rights are not licensed under this
|
||||
Public License.
|
||||
.
|
||||
3. To the extent possible, the Licensor waives any right to
|
||||
collect royalties from You for the exercise of the Licensed
|
||||
Rights, whether directly or through a collecting society
|
||||
under any voluntary or waivable statutory or compulsory
|
||||
licensing scheme. In all other cases the Licensor expressly
|
||||
reserves any right to collect such royalties.
|
||||
.
|
||||
.
|
||||
Section 3 -- License Conditions.
|
||||
.
|
||||
Your exercise of the Licensed Rights is expressly made subject to the
|
||||
following conditions.
|
||||
.
|
||||
a. Attribution.
|
||||
.
|
||||
1. If You Share the Licensed Material (including in modified
|
||||
form), You must:
|
||||
.
|
||||
a. retain the following if it is supplied by the Licensor
|
||||
with the Licensed Material:
|
||||
.
|
||||
i. identification of the creator(s) of the Licensed
|
||||
Material and any others designated to receive
|
||||
attribution, in any reasonable manner requested by
|
||||
the Licensor (including by pseudonym if
|
||||
designated);
|
||||
.
|
||||
ii. a copyright notice;
|
||||
.
|
||||
iii. a notice that refers to this Public License;
|
||||
.
|
||||
iv. a notice that refers to the disclaimer of
|
||||
warranties;
|
||||
.
|
||||
v. a URI or hyperlink to the Licensed Material to the
|
||||
extent reasonably practicable;
|
||||
.
|
||||
b. indicate if You modified the Licensed Material and
|
||||
retain an indication of any previous modifications; and
|
||||
.
|
||||
c. indicate the Licensed Material is licensed under this
|
||||
Public License, and include the text of, or the URI or
|
||||
hyperlink to, this Public License.
|
||||
.
|
||||
2. You may satisfy the conditions in Section 3(a)(1) in any
|
||||
reasonable manner based on the medium, means, and context in
|
||||
which You Share the Licensed Material. For example, it may be
|
||||
reasonable to satisfy the conditions by providing a URI or
|
||||
hyperlink to a resource that includes the required
|
||||
information.
|
||||
.
|
||||
3. If requested by the Licensor, You must remove any of the
|
||||
information required by Section 3(a)(1)(A) to the extent
|
||||
reasonably practicable.
|
||||
.
|
||||
4. If You Share Adapted Material You produce, the Adapter's
|
||||
License You apply must not prevent recipients of the Adapted
|
||||
Material from complying with this Public License.
|
||||
.
|
||||
.
|
||||
Section 4 -- Sui Generis Database Rights.
|
||||
.
|
||||
Where the Licensed Rights include Sui Generis Database Rights that
|
||||
apply to Your use of the Licensed Material:
|
||||
.
|
||||
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
|
||||
to extract, reuse, reproduce, and Share all or a substantial
|
||||
portion of the contents of the database;
|
||||
.
|
||||
b. if You include all or a substantial portion of the database
|
||||
contents in a database in which You have Sui Generis Database
|
||||
Rights, then the database in which You have Sui Generis Database
|
||||
Rights (but not its individual contents) is Adapted Material; and
|
||||
.
|
||||
c. You must comply with the conditions in Section 3(a) if You Share
|
||||
all or a substantial portion of the contents of the database.
|
||||
.
|
||||
For the avoidance of doubt, this Section 4 supplements and does not
|
||||
replace Your obligations under this Public License where the Licensed
|
||||
Rights include other Copyright and Similar Rights.
|
||||
.
|
||||
.
|
||||
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
|
||||
.
|
||||
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
|
||||
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
|
||||
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
|
||||
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
|
||||
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
|
||||
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
|
||||
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
|
||||
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
|
||||
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
|
||||
.
|
||||
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
|
||||
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
|
||||
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
|
||||
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
|
||||
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
|
||||
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
|
||||
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
|
||||
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
|
||||
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
|
||||
.
|
||||
c. The disclaimer of warranties and limitation of liability provided
|
||||
above shall be interpreted in a manner that, to the extent
|
||||
possible, most closely approximates an absolute disclaimer and
|
||||
waiver of all liability.
|
||||
.
|
||||
.
|
||||
Section 6 -- Term and Termination.
|
||||
.
|
||||
a. This Public License applies for the term of the Copyright and
|
||||
Similar Rights licensed here. However, if You fail to comply with
|
||||
this Public License, then Your rights under this Public License
|
||||
terminate automatically.
|
||||
.
|
||||
b. Where Your right to use the Licensed Material has terminated under
|
||||
Section 6(a), it reinstates:
|
||||
.
|
||||
1. automatically as of the date the violation is cured, provided
|
||||
it is cured within 30 days of Your discovery of the
|
||||
violation; or
|
||||
.
|
||||
2. upon express reinstatement by the Licensor.
|
||||
.
|
||||
For the avoidance of doubt, this Section 6(b) does not affect any
|
||||
right the Licensor may have to seek remedies for Your violations
|
||||
of this Public License.
|
||||
.
|
||||
c. For the avoidance of doubt, the Licensor may also offer the
|
||||
Licensed Material under separate terms or conditions or stop
|
||||
distributing the Licensed Material at any time; however, doing so
|
||||
will not terminate this Public License.
|
||||
.
|
||||
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
|
||||
License.
|
||||
.
|
||||
.
|
||||
Section 7 -- Other Terms and Conditions.
|
||||
.
|
||||
a. The Licensor shall not be bound by any additional or different
|
||||
terms or conditions communicated by You unless expressly agreed.
|
||||
.
|
||||
b. Any arrangements, understandings, or agreements regarding the
|
||||
Licensed Material not stated herein are separate from and
|
||||
independent of the terms and conditions of this Public License.
|
||||
.
|
||||
.
|
||||
Section 8 -- Interpretation.
|
||||
.
|
||||
a. For the avoidance of doubt, this Public License does not, and
|
||||
shall not be interpreted to, reduce, limit, restrict, or impose
|
||||
conditions on any use of the Licensed Material that could lawfully
|
||||
be made without permission under this Public License.
|
||||
.
|
||||
b. To the extent possible, if any provision of this Public License is
|
||||
deemed unenforceable, it shall be automatically reformed to the
|
||||
minimum extent necessary to make it enforceable. If the provision
|
||||
cannot be reformed, it shall be severed from this Public License
|
||||
without affecting the enforceability of the remaining terms and
|
||||
conditions.
|
||||
.
|
||||
c. No term or condition of this Public License will be waived and no
|
||||
failure to comply consented to unless expressly agreed to by the
|
||||
Licensor.
|
||||
.
|
||||
d. Nothing in this Public License constitutes or may be interpreted
|
||||
as a limitation upon, or waiver of, any privileges and immunities
|
||||
that apply to the Licensor or You, including from the legal
|
||||
processes of any jurisdiction or authority.
|
||||
.
|
||||
.
|
||||
=======================================================================
|
||||
.
|
||||
Creative Commons is not a party to its public
|
||||
licenses. Notwithstanding, Creative Commons may elect to apply one of
|
||||
its public licenses to material it publishes and in those instances
|
||||
will be considered the “Licensor.” The text of the Creative Commons
|
||||
public licenses is dedicated to the public domain under the CC0 Public
|
||||
Domain Dedication. Except for the limited purpose of indicating that
|
||||
material is shared under a Creative Commons public license or as
|
||||
otherwise permitted by the Creative Commons policies published at
|
||||
creativecommons.org/policies, Creative Commons does not authorize the
|
||||
use of the trademark "Creative Commons" or any other trademark or logo
|
||||
of Creative Commons without its prior written consent including,
|
||||
without limitation, in connection with any unauthorized modifications
|
||||
to any of its public licenses or any other arrangements,
|
||||
understandings, or agreements concerning use of licensed material. For
|
||||
the avoidance of doubt, this paragraph does not form part of the
|
||||
public licenses.
|
||||
.
|
||||
Creative Commons may be contacted at creativecommons.org.
|
2
debian/docs
vendored
2
debian/docs
vendored
@ -1,2 +0,0 @@
|
||||
AUTHORS
|
||||
README.md
|
6
debian/gbp.conf
vendored
6
debian/gbp.conf
vendored
@ -1,6 +0,0 @@
|
||||
[DEFAULT]
|
||||
debian-branch = debian/sid
|
||||
upstream-branch = upstream/latest
|
||||
pristine-tar = True
|
||||
compression = xz
|
||||
|
3
debian/lintian-overrides
vendored
3
debian/lintian-overrides
vendored
@ -1,3 +0,0 @@
|
||||
# there will be a man page within the next release eventually
|
||||
no-manual-page [usr/bin/lximage-qt]
|
||||
|
1
debian/lximage-qt-l10n.install
vendored
1
debian/lximage-qt-l10n.install
vendored
@ -1 +0,0 @@
|
||||
usr/share/lximage-qt/translations
|
4
debian/lximage-qt.install
vendored
4
debian/lximage-qt.install
vendored
@ -1,4 +0,0 @@
|
||||
usr/bin/lximage-qt
|
||||
usr/share/applications
|
||||
usr/share/icons/hicolor
|
||||
usr/share/metainfo/lximage-qt.metainfo.xml
|
4
debian/lximage-qt.lintian-overrides
vendored
4
debian/lximage-qt.lintian-overrides
vendored
@ -1,4 +0,0 @@
|
||||
# This is expected
|
||||
lximage-qt: desktop-entry-lacks-keywords-entry [usr/share/applications/*.desktop]
|
||||
lximage-qt: appstream-metadata-validation-failed *
|
||||
lximage-qt: no-manual-page [usr/bin/*]
|
13
debian/rules
vendored
13
debian/rules
vendored
@ -1,13 +0,0 @@
|
||||
#!/usr/bin/make -f
|
||||
# export DH_VERBOSE=1
|
||||
|
||||
export LC_ALL=C.UTF-8
|
||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||
|
||||
%:
|
||||
dh ${@} --buildsystem cmake
|
||||
|
||||
override_dh_auto_configure:
|
||||
dh_auto_configure -- \
|
||||
-DUPDATE_TRANSLATIONS=OFF\
|
||||
-DCMAKE_BUILD_TYPE=RelWithDebInfo
|
12
debian/salsa-ci.yml
vendored
12
debian/salsa-ci.yml
vendored
@ -1,12 +0,0 @@
|
||||
# For more information on what jobs are run see:
|
||||
# https://salsa.debian.org/salsa-ci-team/pipeline
|
||||
#
|
||||
# To enable the jobs, go to your repository (at salsa.debian.org)
|
||||
# and click over Settings > CI/CD > Expand (in General pipelines).
|
||||
# In "Custom CI config path" write debian/salsa-ci.yml and click
|
||||
# in "Save Changes". The CI tests will run after the next commit.
|
||||
---
|
||||
include:
|
||||
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/salsa-ci.yml
|
||||
- https://salsa.debian.org/salsa-ci-team/pipeline/raw/master/pipeline-jobs.yml
|
||||
|
1
debian/source/format
vendored
1
debian/source/format
vendored
@ -1 +0,0 @@
|
||||
3.0 (quilt)
|
1
debian/source/options
vendored
1
debian/source/options
vendored
@ -1 +0,0 @@
|
||||
tar-ignore = .gitignore
|
7
debian/upstream/metadata
vendored
7
debian/upstream/metadata
vendored
@ -1,7 +0,0 @@
|
||||
Name: lximage-qt
|
||||
Bug-Database: https://github.com/lxqt/lximage-qt/issues
|
||||
Bug-Submit: https://github.com/lxqt/lximage-qt/issues/new
|
||||
Changelog: https://github.com/lxqt/lximage-qt/blob/master/CHANGELOG
|
||||
Repository: https://github.com/lxqt/lximage-qt
|
||||
Repository-Browse: https://github.com/lxqt/lximage-qt
|
||||
|
52
debian/upstream/signing-key.asc
vendored
52
debian/upstream/signing-key.asc
vendored
@ -1,52 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
mQINBF6cxrwBEADfl3ydxNfLBbWGPesXty2baQgixZ3D6aCxadI2kX+aikmT8rd0
|
||||
ttDKN18cXV52Ssxnj0qhgf4hwnu/b0be6BzqSEyGM+UQR3X2CYpxrMakfW32Q18K
|
||||
X5ec0RPR2ucBq9G0r9t6FYC8FkJ4uQUU3xxrLW3z302S0Makjgzm8BV9WrFQ7oFF
|
||||
uJQj0BHbHYC4RyaZb2AfxY4Y92BPGTjtGekWqgw6vEXCCnvAbGYVQzvxZt3nw21/
|
||||
1YmV4g7xhGFQPbOf9v3ejFUJeJIGzuJf5NAh7kvfCdUBAGYH0gnj0GpOve4ftnaG
|
||||
sAId2CQwm3oYF4Tu7yBPTOBpkaKkNaT+UdwTyeKERuCZ9ocZWX++/YF9ItRkJ5mM
|
||||
zoP1GluWn2atNWpRh/K97gyAGgr2fSmrAA4d1JrVbMujZAHoHAOKwJKqX9jPziPZ
|
||||
BFHfhcIOzG3ZhXAuumHsd7uwfPBVt20g+G+cOjBghbSSu9EOtMkAZl1g3ybvZixu
|
||||
Jtxa5exZWEmU7vtytEb8eq9Dj5XcGoTDbErE2RpJ/20HPzhyRKg9RN4iGS+0OiHS
|
||||
oRbDi5IEOizvQjp2bsBmfa3rsoDSOqF2pevp+u8I56I6bU1GFpxxNC5IGvgo2Q79
|
||||
quz0oIk5hs3eLlUdEYsLGwR6pWJaJyf36vuDsq7iLrLyvHI5irAowO4r1QARAQAB
|
||||
tCVQZWRyYW0gUG91cmFuZyA8dHN1amFuMjAwMEBnbWFpbC5jb20+iQJOBBMBCAA4
|
||||
FiEEGd/fOleb1QnbtXLYvnkwB60i334FAl6cxrwCGwMFCwkIBwIGFQoJCAsCBBYC
|
||||
AwECHgECF4AACgkQvnkwB60i335f9RAAgRpn8gUa/l10UkVAnpM2Cz0MuNMwwCOq
|
||||
IfVnuZuPBtYYiTU5Su++/aPZe3fF5B4v61F+XjNi7qeVL2t52X3jZ/iIx9Syasb+
|
||||
vDAIfQ5t6lKXvOptWxf6vteOg6CHbXwpGHbPjUkUS2vQwRikjBnR0SnkrMoXtgSX
|
||||
amPFqsitNrOhEJfeDfo0NzKESZuliWrCFt2v8c5q18G8cCZAvPLBlGuwRl58cDep
|
||||
3EIibMI/9MUSJbKoiHlK+LcHtG7BQTNis/e7Pe1PkRmExfhxe1lNajtOx8FO72Tq
|
||||
B6zY6drippM9VaIc1M+zp9BRpsFu8whOmapCqlXHRgAK8xTdQRIGInQFqLWPOxSC
|
||||
f0B6N+EvQvgkyFQ1rW+u91OJBma46uKkhrwf+mDttVRncaIAkgE6e6pqm18yIPFk
|
||||
D42rt/yHcOl+2qkcJS3gPcg5UvlCzqOwg1rKZQIk+TcPuDx3r2UghDEYZN9X6vw3
|
||||
zCBufr7ygZNf4tkbnVARFWTR4GzyCseFkWgOVZL9DccAhs8NeMy1WLkUzB75adeR
|
||||
3LONmEL7xOI8FuknKY4e6EcWhmstNIDgXfRe0hwO0VBdW3unoZC/K2ZM/ZuZyMdK
|
||||
TFjvYJrNewmymKge68wo0054bGZn8oz17i2AosJz7kW+ITsxmxhVcpfl4bav9Neq
|
||||
RpQwhnhK9bC5Ag0EXpzGvAEQANbeRHFbpgQVIqV9WVOVnTj4FIqrTPTPKKa02vJA
|
||||
7tGpgFapgvjdxnMxJfV6wuwOBUUFLR7DrXlV8EVFAYc5qTIeSQXvJsWw6gQ3+f0D
|
||||
z13oGOhZPBIzIKnV/MZI/jhIio8kSPWAuM5hR2X9Hvw3/CLo+H+hZZ6cFYoCxrQS
|
||||
tTzcKMkdQizLLa+WNbqUSxg6I/P5k/smUDY9gKW7RtI5t/PupA3WTnsVD6CYWa3Q
|
||||
c1O/1mUgqT6nQ5N9KCPpjZQRT6D6eIMmePtS85z4PPeYMJxPsKRYWPGRxKhCSdZl
|
||||
/0wsC8aRtmwYT729e0ZgTAmUnj+rQp5hboF/ZPFjIoXR9G+0HnoY0a/nqVO4lUON
|
||||
AV25GnMFGVyiHHlbH/0gboywwnzEg8BZbk+Z/61oOzBIW09sfG8fn8bsbkpL+nHf
|
||||
Mi/Vauge6wSfw7I5AfSiwrSDNHmKVsu39koWV6JGxEeFr2MffF+CuaoJCNOr/ZII
|
||||
SYR5ku3Y/lMKyUH1Oas0RWzFrdRcInqYK90A0x083zP4V445MvCwbRPzQAkm9wOP
|
||||
kILLhE5FW+9/O0/9bpx4joJUDLV4d3hFZy7GSHKiZUs1QW6BV75JQKqoi+cVt+/L
|
||||
+o1S8CMNekjqdC2mWRosM3doo51zT/FWNzQA1QcoZP2hORJDfw66y+4wPq6o8y1W
|
||||
jR35ABEBAAGJAjYEGAEIACAWIQQZ3986V5vVCdu1cti+eTAHrSLffgUCXpzGvAIb
|
||||
DAAKCRC+eTAHrSLffgbJD/4qW5YOo/BayBhaUh2L7VP7JNlECb/2xNNOFKI1NjNr
|
||||
nOmgSJLzf74Uhmt5W+iVjmJBHrDceprIPkizmPrn90kIsPIMtHIDNxzUgKZHbnza
|
||||
j1vZyAeC+JV79X1hOVpprj1TJwy65lpxXNyYnGqeIOgyFokn9fOHXv8aMQwpNuUr
|
||||
bdUJ1C75jYrvwy/NR1DczIFFYgsbkDGDtjVBjyMc5JAgvUBz37/iVPJfWP6dKVnf
|
||||
abRnUVzHgvgK7bnab00SA1TiWvjHURGjo+5rnRtv8X/AgStc2Phjq68TMIgMn0F2
|
||||
kjUVvfQotNqzo9madNshvUDmsGtAzKh4e0dS1ear7u3nRp4Z7fqSrTEtXKNbEPwZ
|
||||
wdWrWmmQLacNQBSe/FtcMzGF6xIVr4lnrL0bFjqBdQpdTC7vns3QSKk8/GFiEfpv
|
||||
kzXrDbGV7jX2OWDjNHKcmXX2+E1CsNaJgS7zOgZw5jvbvlTLJUwyYNlM1VLI2OFW
|
||||
Oa86l8pqli+B7rpTbsAE9Ut8qUaWjm87oUNSJbaKgqNnMaE+b/8VJaEeWHgQJwsD
|
||||
bJSJ/O/vzlRtDjOJ1JDlMRLs7TnOFeUh5pgwyaJoidYbJEiGlMGJbI6BjwhDTBFO
|
||||
NLJtd3SsRjc7ICtGdCvej59IvCDTjxtkhx5okF03APi1aXpHQrE18/arFD7BpoGO
|
||||
sw==
|
||||
=gSIv
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
5
debian/watch
vendored
5
debian/watch
vendored
@ -1,5 +0,0 @@
|
||||
version=4
|
||||
opts="searchmode=plain, \
|
||||
pgpsigurlmangle=s/$/.asc/, \
|
||||
uversionmangle=s/(\d+\.\d+\.\d+).*/$1/" \
|
||||
https://api.github.com/repos/lxqt/@PACKAGE@/releases https:\/\/github.com\/lxqt\/@PACKAGE@\/releases\/download\/@ANY_VERSION@\/@PACKAGE@-@ANY_VERSION@.tar.xz
|
28
release.sh
Executable file
28
release.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bin/bash
|
||||
|
||||
PROJECT="lximage-qt"
|
||||
version="$1"
|
||||
prefix=$PROJECT-$version
|
||||
shift
|
||||
|
||||
if [[ -z $version ]]; then
|
||||
>&2 echo "USAGE: $0 <tag>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "dist/$version"
|
||||
echo "Creating $prefix.tar.gz"
|
||||
git archive -9 --format tar.gz $version --prefix="$prefix/" > "dist/$version/$prefix.tar.gz"
|
||||
gpg --armor --detach-sign "dist/$version/$prefix.tar.gz"
|
||||
echo "Creating $prefix.tar.xz"
|
||||
git archive -9 --format tar.xz $version --prefix="$prefix/" > "dist/$version/$prefix.tar.xz"
|
||||
gpg --armor --detach-sign "dist/$version/$prefix.tar.xz"
|
||||
cd "dist/$version"
|
||||
|
||||
sha1sum --tag *.tar.gz *.tar.xz >> CHECKSUMS
|
||||
sha256sum --tag *.tar.gz *.tar.xz >> CHECKSUMS
|
||||
|
||||
cd ..
|
||||
echo "Uploading to lxqt.org..."
|
||||
|
||||
scp -r "$version" "downloads.lxqt.org:/srv/downloads.lxqt.org/$PROJECT/"
|
91
src/CMakeLists.txt
Normal file
91
src/CMakeLists.txt
Normal file
@ -0,0 +1,91 @@
|
||||
include_directories(
|
||||
${X11_INCLUDE_DIR}
|
||||
${XFIXES_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
# For some unknown reasons these are required for build on FreeBSD
|
||||
link_directories(
|
||||
${QT_LIBRARY_DIR}
|
||||
${GLIB_LIBRARY_DIRS}
|
||||
)
|
||||
|
||||
set(lximage-qt_SRCS
|
||||
lximage-qt.cpp
|
||||
mainwindow.cpp
|
||||
preferencesdialog.cpp
|
||||
application.cpp
|
||||
imageview.cpp
|
||||
modelfilter.cpp
|
||||
job.cpp
|
||||
loadimagejob.cpp
|
||||
saveimagejob.cpp
|
||||
screenshotdialog.cpp
|
||||
settings.cpp
|
||||
)
|
||||
|
||||
qt5_add_dbus_adaptor(lximage-qt_SRCS
|
||||
org.lxde.LxImage.Application.xml
|
||||
application.h
|
||||
LxImage::Application
|
||||
applicationadaptor
|
||||
ApplicationAdaptor
|
||||
)
|
||||
|
||||
set(lximage-qt_UIS
|
||||
mainwindow.ui
|
||||
preferencesdialog.ui
|
||||
screenshotdialog.ui
|
||||
)
|
||||
qt5_wrap_ui(lximage-qt_UI_H ${lximage-qt_UIS})
|
||||
|
||||
# add translation for lximage-qt
|
||||
include(LXQtTranslateTs)
|
||||
lxqt_translate_ts(QM_FILES
|
||||
UPDATE_TRANSLATIONS ${UPDATE_TRANSLATIONS}
|
||||
SOURCES
|
||||
${lximage-qt_SRCS}
|
||||
${lximage-qt_UIS}
|
||||
INSTALL_DIR
|
||||
"${CMAKE_INSTALL_DATADIR}/${PROJECT_NAME}/translations"
|
||||
PULL_TRANSLATIONS
|
||||
${PULL_TRANSLATIONS}
|
||||
CLEAN_TRANSLATIONS
|
||||
${CLEAN_TRANSLATIONS}
|
||||
TRANSLATIONS_REPO
|
||||
${TRANSLATIONS_REPO}
|
||||
TRANSLATIONS_REFSPEC
|
||||
${TRANSLATIONS_REFSPEC}
|
||||
)
|
||||
# prevent the generated files from being deleted during make clean
|
||||
set_directory_properties(PROPERTIES CLEAN_NO_CUSTOM true)
|
||||
|
||||
# process desktop entry files
|
||||
include(LXQtTranslateDesktop)
|
||||
|
||||
file(GLOB desktop_files_in ../data/*.desktop.in)
|
||||
lxqt_translate_desktop(desktop_files SOURCES ${desktop_files_in})
|
||||
install(FILES ${desktop_files} DESTINATION share/applications)
|
||||
|
||||
add_executable(lximage-qt
|
||||
${lximage-qt_SRCS}
|
||||
${lximage-qt_UI_H}
|
||||
${desktop_files}
|
||||
${QM_FILES}
|
||||
)
|
||||
|
||||
add_definitions(
|
||||
-DLXIMAGE_DATA_DIR="${CMAKE_INSTALL_PREFIX}/share/lximage-qt"
|
||||
-DLXIMAGE_VERSION="${LXIMAGE_VERSION}"
|
||||
)
|
||||
|
||||
set(QT_LIBRARIES Qt5::Widgets Qt5::Core Qt5::DBus Qt5::PrintSupport Qt5::X11Extras Qt5::Svg)
|
||||
|
||||
target_link_libraries(lximage-qt
|
||||
fm-qt
|
||||
${QT_LIBRARIES}
|
||||
${EXIF_LIBRARIES}
|
||||
${X11_LIBRARIES}
|
||||
${XFIXES_LIBRARIES}
|
||||
)
|
||||
|
||||
install(TARGETS lximage-qt RUNTIME DESTINATION bin)
|
183
src/application.cpp
Normal file
183
src/application.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "application.h"
|
||||
#include <QCommandLineParser>
|
||||
#include <QDBusConnection>
|
||||
#include <QDBusInterface>
|
||||
#include <QPixmapCache>
|
||||
#include "applicationadaptor.h"
|
||||
#include "screenshotdialog.h"
|
||||
#include "preferencesdialog.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
static const char* serviceName = "org.lxde.LxImage";
|
||||
static const char* ifaceName = "org.lxde.LxImage.Application";
|
||||
|
||||
Application::Application(int& argc, char** argv):
|
||||
QApplication(argc, argv),
|
||||
libFm(),
|
||||
windowCount_(0) {
|
||||
setApplicationVersion(LXIMAGE_VERSION);
|
||||
}
|
||||
|
||||
bool Application::init(int argc, char** argv) {
|
||||
// install the translations built-into Qt itself
|
||||
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
installTranslator(&qtTranslator);
|
||||
|
||||
// install libfm-qt translator
|
||||
installTranslator(libFm.translator());
|
||||
|
||||
// install our own tranlations
|
||||
translator.load("lximage-qt_" + QLocale::system().name(), LXIMAGE_DATA_DIR "/translations");
|
||||
installTranslator(&translator);
|
||||
|
||||
// initialize dbus
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
if(dbus.registerService(serviceName)) {
|
||||
settings_.load(); // load settings
|
||||
// we successfully registered the service
|
||||
isPrimaryInstance = true;
|
||||
setQuitOnLastWindowClosed(false); // do not quit even when there're no windows
|
||||
|
||||
new ApplicationAdaptor(this);
|
||||
dbus.registerObject("/Application", this);
|
||||
|
||||
connect(this, &Application::aboutToQuit, this, &Application::onAboutToQuit);
|
||||
|
||||
if(settings_.useFallbackIconTheme())
|
||||
QIcon::setThemeName(settings_.fallbackIconTheme());
|
||||
}
|
||||
else {
|
||||
// an service of the same name is already registered.
|
||||
// we're not the first instance
|
||||
isPrimaryInstance = false;
|
||||
}
|
||||
|
||||
QPixmapCache::setCacheLimit(1024); // avoid pixmap caching.
|
||||
|
||||
return parseCommandLineArgs();
|
||||
}
|
||||
|
||||
bool Application::parseCommandLineArgs() {
|
||||
QCommandLineParser parser;
|
||||
parser.addHelpOption();
|
||||
parser.addVersionOption();
|
||||
|
||||
QCommandLineOption screenshotOption(
|
||||
QStringList() << "s" << "screenshot",
|
||||
tr("Take a screenshot")
|
||||
);
|
||||
parser.addOption(screenshotOption);
|
||||
|
||||
const QString files = tr("[FILE1, FILE2,...]");
|
||||
parser.addPositionalArgument("files", files, files);
|
||||
|
||||
parser.process(*this);
|
||||
|
||||
const QStringList args = parser.positionalArguments();
|
||||
const bool screenshotTool = parser.isSet(screenshotOption);
|
||||
|
||||
QStringList paths;
|
||||
Q_FOREACH(QString arg, args) {
|
||||
QFileInfo info(arg);
|
||||
paths.push_back(info.absoluteFilePath());
|
||||
}
|
||||
|
||||
bool keepRunning = false;
|
||||
if(isPrimaryInstance) {
|
||||
settings_.load();
|
||||
keepRunning = true;
|
||||
if(screenshotTool) {
|
||||
screenshot();
|
||||
}
|
||||
else {
|
||||
newWindow(paths);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we're not the primary instance.
|
||||
// call the primary instance via dbus to do operations
|
||||
QDBusConnection dbus = QDBusConnection::sessionBus();
|
||||
QDBusInterface iface(serviceName, "/Application", ifaceName, dbus, this);
|
||||
if(screenshotTool)
|
||||
iface.call("screenshot");
|
||||
else
|
||||
iface.call("newWindow", paths);
|
||||
}
|
||||
return keepRunning;
|
||||
}
|
||||
|
||||
MainWindow* Application::createWindow() {
|
||||
LxImage::MainWindow* window;
|
||||
window = new LxImage::MainWindow();
|
||||
return window;
|
||||
}
|
||||
|
||||
void Application::newWindow(QStringList files) {
|
||||
LxImage::MainWindow* window;
|
||||
if(files.empty()) {
|
||||
window = createWindow();
|
||||
|
||||
window->resize(settings_.windowWidth(), settings_.windowHeight());
|
||||
if(settings_.windowMaximized())
|
||||
window->setWindowState(window->windowState() | Qt::WindowMaximized);
|
||||
|
||||
window->show();
|
||||
}
|
||||
else {
|
||||
Q_FOREACH(QString fileName, files) {
|
||||
window = createWindow();
|
||||
window->openImageFile(fileName);
|
||||
|
||||
window->resize(settings_.windowWidth(), settings_.windowHeight());
|
||||
if(settings_.windowMaximized())
|
||||
window->setWindowState(window->windowState() | Qt::WindowMaximized);
|
||||
|
||||
/* when there's an image, we show the window AFTER resizing
|
||||
and centering it appropriately at MainWindow::updateUI() */
|
||||
//window->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::applySettings() {
|
||||
Q_FOREACH(QWidget* window, topLevelWidgets()) {
|
||||
if(window->inherits("LxImage::MainWindow"))
|
||||
static_cast<MainWindow*>(window)->applySettings();
|
||||
}
|
||||
}
|
||||
|
||||
void Application::screenshot() {
|
||||
ScreenshotDialog* dlg = new ScreenshotDialog();
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
void Application::editPreferences() {
|
||||
PreferencesDialog* dlg = new PreferencesDialog();
|
||||
dlg->show();
|
||||
}
|
||||
|
||||
void Application::onAboutToQuit() {
|
||||
settings_.save();
|
||||
}
|
76
src/application.h
Normal file
76
src/application.h
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_APPLICATION_H
|
||||
#define LXIMAGE_APPLICATION_H
|
||||
|
||||
#include <QApplication>
|
||||
#include <libfm-qt/libfmqt.h>
|
||||
#include "mainwindow.h"
|
||||
#include "settings.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class Application : public QApplication {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Application(int& argc, char** argv);
|
||||
bool init(int argc, char** argv);
|
||||
bool parseCommandLineArgs();
|
||||
|
||||
void newWindow(QStringList files = QStringList());
|
||||
MainWindow* createWindow();
|
||||
|
||||
void addWindow() { // call this when you create a new toplevel window
|
||||
++windowCount_;
|
||||
}
|
||||
|
||||
void removeWindow() { // call this when you destroy a toplevel window
|
||||
--windowCount_;
|
||||
if(0 == windowCount_)
|
||||
quit();
|
||||
}
|
||||
|
||||
Settings& settings() {
|
||||
return settings_;
|
||||
}
|
||||
|
||||
void applySettings();
|
||||
|
||||
public Q_SLOTS:
|
||||
void editPreferences();
|
||||
void screenshot();
|
||||
|
||||
protected Q_SLOTS:
|
||||
void onAboutToQuit();
|
||||
|
||||
private:
|
||||
Fm::LibFmQt libFm;
|
||||
bool isPrimaryInstance;
|
||||
QTranslator translator;
|
||||
QTranslator qtTranslator;
|
||||
Settings settings_;
|
||||
int windowCount_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_APPLICATION_H
|
400
src/imageview.cpp
Normal file
400
src/imageview.cpp
Normal file
@ -0,0 +1,400 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 <copyright holder> <email>
|
||||
|
||||
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 "imageview.h"
|
||||
#include <QWheelEvent>
|
||||
#include <QPaintEvent>
|
||||
#include <QPainter>
|
||||
#include <QTimer>
|
||||
#include <QPolygon>
|
||||
#include <QStyle>
|
||||
#include <QLabel>
|
||||
#include <QGraphicsProxyWidget>
|
||||
#include <QGraphicsSvgItem>
|
||||
|
||||
#define CURSOR_HIDE_DELY 3000
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
ImageView::ImageView(QWidget* parent):
|
||||
QGraphicsView(parent),
|
||||
scene_(new QGraphicsScene(this)),
|
||||
imageItem_(new QGraphicsRectItem()),
|
||||
gifMovie_(nullptr),
|
||||
cacheTimer_(nullptr),
|
||||
cursorTimer_(nullptr),
|
||||
scaleFactor_(1.0),
|
||||
autoZoomFit_(false),
|
||||
isSVG(false) {
|
||||
|
||||
setViewportMargins(0, 0, 0, 0);
|
||||
setContentsMargins(0, 0, 0, 0);
|
||||
setLineWidth(0);
|
||||
|
||||
setScene(scene_);
|
||||
imageItem_->hide();
|
||||
imageItem_->setPen(QPen(Qt::NoPen)); // remove the border
|
||||
scene_->addItem(imageItem_);
|
||||
}
|
||||
|
||||
ImageView::~ImageView() {
|
||||
scene_->clear(); // deletes all items
|
||||
if(gifMovie_)
|
||||
delete gifMovie_;
|
||||
if(cacheTimer_) {
|
||||
cacheTimer_->stop();
|
||||
delete cacheTimer_;
|
||||
}
|
||||
if(cursorTimer_) {
|
||||
cursorTimer_->stop();
|
||||
delete cursorTimer_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ImageView::wheelEvent(QWheelEvent* event) {
|
||||
int delta = event->delta();
|
||||
// Ctrl key is pressed
|
||||
if(event->modifiers() & Qt::ControlModifier) {
|
||||
if(delta > 0) { // forward
|
||||
zoomIn();
|
||||
}
|
||||
else { // backward
|
||||
zoomOut();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The default handler QGraphicsView::wheelEvent(event) tries to
|
||||
// scroll the view, which is not what we need.
|
||||
// Skip the default handler and use its parent QWidget's handler here.
|
||||
QWidget::wheelEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::mouseDoubleClickEvent(QMouseEvent* event) {
|
||||
// The default behaviour of QGraphicsView::mouseDoubleClickEvent() is
|
||||
// not needed for us. We call its parent class instead so the event can be
|
||||
// filtered by event filter installed on the view.
|
||||
// QGraphicsView::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) {
|
||||
QGraphicsView::resizeEvent(event);
|
||||
if(autoZoomFit_)
|
||||
zoomFit();
|
||||
}
|
||||
|
||||
void ImageView::zoomFit() {
|
||||
if(!image_.isNull()) {
|
||||
// if the image is smaller than our view, use its original size
|
||||
// instead of scaling it up.
|
||||
if(image_.width() <= width() && image_.height() <= height()) {
|
||||
zoomOriginal();
|
||||
return;
|
||||
}
|
||||
}
|
||||
fitInView(scene_->sceneRect(), Qt::KeepAspectRatio);
|
||||
scaleFactor_ = transform().m11();
|
||||
queueGenerateCache();
|
||||
}
|
||||
|
||||
void ImageView::zoomIn() {
|
||||
autoZoomFit_ = false;
|
||||
if(!image_.isNull()) {
|
||||
resetTransform();
|
||||
scaleFactor_ *= 1.1;
|
||||
scale(scaleFactor_, scaleFactor_);
|
||||
queueGenerateCache();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::zoomOut() {
|
||||
autoZoomFit_ = false;
|
||||
if(!image_.isNull()) {
|
||||
resetTransform();
|
||||
scaleFactor_ /= 1.1;
|
||||
scale(scaleFactor_, scaleFactor_);
|
||||
queueGenerateCache();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::zoomOriginal() {
|
||||
resetTransform();
|
||||
scaleFactor_ = 1.0;
|
||||
autoZoomFit_ = false;
|
||||
queueGenerateCache();
|
||||
}
|
||||
|
||||
void ImageView::setImage(QImage image, bool show) {
|
||||
if(show && (gifMovie_ || isSVG)) { // a gif animation or SVG file was shown before
|
||||
scene_->clear();
|
||||
isSVG = false;
|
||||
if(gifMovie_) { // should be deleted explicitly
|
||||
delete gifMovie_;
|
||||
gifMovie_ = nullptr;
|
||||
}
|
||||
// recreate the rect item
|
||||
imageItem_ = new QGraphicsRectItem();
|
||||
imageItem_->hide();
|
||||
imageItem_->setPen(QPen(Qt::NoPen));
|
||||
scene_->addItem(imageItem_);
|
||||
}
|
||||
|
||||
image_ = image;
|
||||
if(image.isNull()) {
|
||||
imageItem_->hide();
|
||||
imageItem_->setBrush(QBrush());
|
||||
scene_->setSceneRect(0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
if(show) {
|
||||
imageItem_->setRect(0, 0, image_.width(), image_.height());
|
||||
imageItem_->setBrush(image_);
|
||||
imageItem_->show();
|
||||
}
|
||||
scene_->setSceneRect(0, 0, image_.width(), image_.height());
|
||||
}
|
||||
|
||||
if(autoZoomFit_)
|
||||
zoomFit();
|
||||
queueGenerateCache();
|
||||
}
|
||||
|
||||
void ImageView::setGifAnimation(QString fileName) {
|
||||
/* the built-in gif reader gives the first frame, which won't
|
||||
be shown but is used for tracking position and dimensions */
|
||||
image_ = QImage(fileName);
|
||||
if(image_.isNull()) {
|
||||
if(imageItem_) {
|
||||
imageItem_->hide();
|
||||
imageItem_->setBrush(QBrush());
|
||||
}
|
||||
scene_->setSceneRect(0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
scene_->clear();
|
||||
imageItem_ = nullptr; // it's deleted by clear();
|
||||
if(gifMovie_) {
|
||||
delete gifMovie_;
|
||||
gifMovie_ = nullptr;
|
||||
}
|
||||
QPixmap pix(image_.size());
|
||||
pix.fill(Qt::transparent);
|
||||
QGraphicsItem *gifItem = new QGraphicsPixmapItem(pix);
|
||||
QLabel *gifLabel = new QLabel();
|
||||
gifMovie_ = new QMovie(fileName);
|
||||
QGraphicsProxyWidget* gifWidget = new QGraphicsProxyWidget(gifItem);
|
||||
gifLabel->setAttribute(Qt::WA_NoSystemBackground);
|
||||
gifLabel->setMovie(gifMovie_);
|
||||
gifWidget->setWidget(gifLabel);
|
||||
gifMovie_->start();
|
||||
scene_->addItem(gifItem);
|
||||
scene_->setSceneRect(gifItem->boundingRect());
|
||||
}
|
||||
|
||||
if(autoZoomFit_)
|
||||
zoomFit();
|
||||
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) {
|
||||
if(factor != scaleFactor_) {
|
||||
scaleFactor_ = factor;
|
||||
resetTransform();
|
||||
scale(factor, factor);
|
||||
queueGenerateCache();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageView::paintEvent(QPaintEvent* event) {
|
||||
// if the image is scaled and we have a high quality cached image
|
||||
if(imageItem_ && scaleFactor_ != 1.0 && !cachedPixmap_.isNull()) {
|
||||
// rectangle of the whole image in viewport coordinate
|
||||
QRect viewportImageRect = sceneToViewport(imageItem_->rect());
|
||||
// the visible part of the image.
|
||||
QRect desiredCachedRect = viewportToScene(viewportImageRect.intersected(viewport()->rect()));
|
||||
// check if the cached area is what we need and if the cache is out of date
|
||||
if(cachedSceneRect_ == desiredCachedRect) {
|
||||
// rect of the image area that needs repaint, in viewport coordinate
|
||||
QRect repaintImageRect = viewportImageRect.intersected(event->rect());
|
||||
// see if the part asking for repaint is contained by our cache.
|
||||
if(cachedRect_.contains(repaintImageRect)) {
|
||||
QPainter painter(viewport());
|
||||
painter.fillRect(event->rect(), backgroundBrush());
|
||||
painter.drawPixmap(repaintImageRect, cachedPixmap_);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!image_.isNull()) { // we don't have a cache yet or it's out of date already, generate one
|
||||
queueGenerateCache();
|
||||
}
|
||||
QGraphicsView::paintEvent(event);
|
||||
}
|
||||
|
||||
void ImageView::queueGenerateCache() {
|
||||
if(!cachedPixmap_.isNull()) // clear the old pixmap if there's any
|
||||
cachedPixmap_ = QPixmap();
|
||||
|
||||
// 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 or SVG images either
|
||||
if(scaleFactor_ == 1.0 || gifMovie_ || isSVG) {
|
||||
if(cacheTimer_) {
|
||||
cacheTimer_->stop();
|
||||
delete cacheTimer_;
|
||||
cacheTimer_ = nullptr;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if(!cacheTimer_) {
|
||||
cacheTimer_ = new QTimer();
|
||||
cacheTimer_->setSingleShot(true);
|
||||
connect(cacheTimer_, &QTimer::timeout, this, &ImageView::generateCache);
|
||||
}
|
||||
if(cacheTimer_)
|
||||
cacheTimer_->start(200); // restart the timer
|
||||
}
|
||||
|
||||
// really generate the cache
|
||||
void ImageView::generateCache() {
|
||||
// disable the one-shot timer
|
||||
cacheTimer_->deleteLater();
|
||||
cacheTimer_ = nullptr;
|
||||
|
||||
if(!imageItem_ || image_.isNull()) return;
|
||||
|
||||
// generate a cache for "the visible part" of the scaled image
|
||||
// rectangle of the whole image in viewport coordinate
|
||||
QRect viewportImageRect = sceneToViewport(imageItem_->rect());
|
||||
// rect of the image area that's visible in the viewport (in viewport coordinate)
|
||||
cachedRect_ = viewportImageRect.intersected(viewport()->rect());
|
||||
|
||||
// convert to the coordinate of the original image
|
||||
cachedSceneRect_ = viewportToScene(cachedRect_);
|
||||
// create a sub image of the visible without real data copy
|
||||
// Reference: http://stackoverflow.com/questions/12681554/dividing-qimage-to-smaller-pieces
|
||||
QRect subRect = image_.rect().intersected(cachedSceneRect_);
|
||||
const uchar* bits = image_.constBits();
|
||||
unsigned int offset = subRect.x() * image_.depth() / 8 + subRect.y() * image_.bytesPerLine();
|
||||
QImage subImage = QImage(bits + offset, subRect.width(), subRect.height(), image_.bytesPerLine(), image_.format());
|
||||
|
||||
// If the original image has a color table, also use it for the subImage
|
||||
QVector<QRgb> colorTable = image_.colorTable();
|
||||
if (!colorTable.empty())
|
||||
subImage.setColorTable(colorTable);
|
||||
|
||||
// QImage scaled = subImage.scaled(subRect.width() * scaleFactor_, subRect.height() * scaleFactor_, Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
QImage scaled = subImage.scaled(cachedRect_.width(), cachedRect_.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
// convert the cached scaled image to pixmap
|
||||
cachedPixmap_ = QPixmap::fromImage(scaled);
|
||||
viewport()->update();
|
||||
}
|
||||
|
||||
// convert viewport coordinate to the original image (not scaled).
|
||||
QRect ImageView::viewportToScene(const QRect& rect) {
|
||||
// QPolygon poly = mapToScene(imageItem_->rect());
|
||||
QPoint topLeft = mapToScene(rect.topLeft()).toPoint();
|
||||
QPoint bottomRight = mapToScene(rect.bottomRight()).toPoint();
|
||||
return QRect(topLeft, bottomRight);
|
||||
}
|
||||
|
||||
QRect ImageView::sceneToViewport(const QRectF& rect) {
|
||||
QPoint topLeft = mapFromScene(rect.topLeft());
|
||||
QPoint bottomRight = mapFromScene(rect.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
|
110
src/imageview.h
Normal file
110
src/imageview.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 <copyright holder> <email>
|
||||
|
||||
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 LXIMAGE_IMAGEVIEW_H
|
||||
#define LXIMAGE_IMAGEVIEW_H
|
||||
|
||||
#include <QGraphicsView>
|
||||
#include <QGraphicsScene>
|
||||
#include <QGraphicsRectItem>
|
||||
#include <QImage>
|
||||
#include <QPixmap>
|
||||
#include <QMovie>
|
||||
#include <QRect>
|
||||
|
||||
class QTimer;
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class ImageView : public QGraphicsView {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ImageView(QWidget* parent = 0);
|
||||
virtual ~ImageView();
|
||||
|
||||
void setImage(QImage image, bool show = true);
|
||||
void setGifAnimation(QString fileName);
|
||||
void setSVG(QString fileName);
|
||||
|
||||
QImage image() {
|
||||
return image_;
|
||||
}
|
||||
|
||||
void setScaleFactor(double scale);
|
||||
|
||||
double scaleFactor() {
|
||||
return scaleFactor_;
|
||||
}
|
||||
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
void zoomFit();
|
||||
void zoomOriginal();
|
||||
|
||||
bool autoZoomFit() {
|
||||
return autoZoomFit_;
|
||||
}
|
||||
|
||||
// if set to true, zoomFit() is done automatically when the size of the window is changed.
|
||||
void setAutoZoomFit(bool value) {
|
||||
autoZoomFit_ = value;
|
||||
}
|
||||
|
||||
// if set to true, hides the cursor after 3s of inactivity
|
||||
void hideCursor(bool enable);
|
||||
|
||||
protected:
|
||||
virtual void wheelEvent(QWheelEvent* 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 paintEvent(QPaintEvent* event);
|
||||
|
||||
private:
|
||||
void queueGenerateCache();
|
||||
QRect viewportToScene(const QRect& rect);
|
||||
QRect sceneToViewport(const QRectF& rect);
|
||||
|
||||
private Q_SLOTS:
|
||||
void generateCache();
|
||||
void blankCursor();
|
||||
|
||||
private:
|
||||
QGraphicsScene* scene_; // the topmost container of all graphic items
|
||||
QGraphicsRectItem* imageItem_; // the rect item used to draw the image
|
||||
QImage image_; // image to show
|
||||
QMovie *gifMovie_; // gif animation to show (should be deleted explicitly)
|
||||
QPixmap cachedPixmap_; // caching of current viewport content (high quality scaled image)
|
||||
QRect cachedRect_; // rectangle containing the cached region (in viewport coordinate)
|
||||
QRect cachedSceneRect_; // rectangle containing the cached region (in scene/original image coordinate)
|
||||
QTimer* cacheTimer_;
|
||||
QTimer *cursorTimer_; // for hiding cursor in fullscreen mode
|
||||
double scaleFactor_;
|
||||
bool autoZoomFit_;
|
||||
bool isSVG; // is the image an SVG file?
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_IMAGEVIEW_H
|
64
src/job.cpp
Normal file
64
src/job.cpp
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* <one line to give the library's name and an idea of what it does.>
|
||||
* Copyright (C) 2014 <copyright holder> <email>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#include "job.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
Job::Job():
|
||||
cancellable_(g_cancellable_new()),
|
||||
error_(NULL) {
|
||||
}
|
||||
|
||||
Job::~Job() {
|
||||
g_object_unref(cancellable_);
|
||||
if(error_)
|
||||
g_error_free(error_);
|
||||
}
|
||||
|
||||
// This is called from the worker thread, not main thread
|
||||
gboolean Job::_jobThread(GIOSchedulerJob* job, GCancellable* cancellable, Job* pThis) {
|
||||
pThis->run();
|
||||
// do final step in the main thread
|
||||
if(!g_cancellable_is_cancelled(pThis->cancellable_))
|
||||
g_io_scheduler_job_send_to_mainloop(job, GSourceFunc(_finish), pThis, NULL);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void Job::start() {
|
||||
g_io_scheduler_push_job(GIOSchedulerJobFunc(_jobThread),
|
||||
this, GDestroyNotify(_freeMe),
|
||||
G_PRIORITY_DEFAULT, cancellable_);
|
||||
}
|
||||
|
||||
// this function is called from main thread only
|
||||
gboolean Job::_finish(Job* pThis) {
|
||||
// only do processing if the job is not cancelled
|
||||
if(!g_cancellable_is_cancelled(pThis->cancellable_)) {
|
||||
pThis->finish();
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void Job::_freeMe(Job* pThis) {
|
||||
delete pThis;
|
||||
}
|
||||
|
||||
}
|
62
src/job.h
Normal file
62
src/job.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* <one line to give the library's name and an idea of what it does.>
|
||||
* Copyright (C) 2014 <copyright holder> <email>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LXIMAGE_JOB_H
|
||||
#define LXIMAGE_JOB_H
|
||||
|
||||
#include <gio/gio.h>
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class Job {
|
||||
public:
|
||||
Job();
|
||||
virtual ~Job();
|
||||
|
||||
void cancel() {
|
||||
g_cancellable_cancel(cancellable_);
|
||||
}
|
||||
void start();
|
||||
|
||||
GError* error() const {
|
||||
return error_;
|
||||
}
|
||||
|
||||
bool isCancelled() const {
|
||||
return bool(g_cancellable_is_cancelled(cancellable_));
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool run() = 0;
|
||||
virtual void finish() = 0;
|
||||
|
||||
protected:
|
||||
GCancellable* cancellable_;
|
||||
GError* error_;
|
||||
|
||||
private:
|
||||
static gboolean _jobThread(GIOSchedulerJob* job, GCancellable* cancellable, Job* pThis);
|
||||
static gboolean _finish(Job* pThis);
|
||||
static void _freeMe(Job* pThis);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_JOB_H
|
124
src/loadimagejob.cpp
Normal file
124
src/loadimagejob.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "loadimagejob.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
#include <qvarlengtharray.h>
|
||||
#include <libexif/exif-loader.h>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
LoadImageJob::LoadImageJob(MainWindow* window, FmPath* filePath):
|
||||
Job(),
|
||||
mainWindow_(window),
|
||||
path_(fm_path_ref(filePath)) {
|
||||
}
|
||||
|
||||
LoadImageJob::~LoadImageJob() {
|
||||
fm_path_unref(path_);
|
||||
}
|
||||
|
||||
// This is called from the worker thread, not main thread
|
||||
bool LoadImageJob::run() {
|
||||
GFile* gfile = fm_path_to_gfile(path_);
|
||||
GFileInputStream* fileStream = g_file_read(gfile, cancellable_, &error_);
|
||||
g_object_unref(gfile);
|
||||
|
||||
if(fileStream) { // if the file stream is successfually opened
|
||||
QBuffer imageBuffer;
|
||||
GInputStream* inputStream = G_INPUT_STREAM(fileStream);
|
||||
while(!g_cancellable_is_cancelled(cancellable_)) {
|
||||
char buffer[4096];
|
||||
gssize readSize = g_input_stream_read(inputStream,
|
||||
buffer, 4096,
|
||||
cancellable_, &error_);
|
||||
if(readSize == -1 || readSize == 0) // error or EOF
|
||||
break;
|
||||
// append the bytes read to the image buffer
|
||||
imageBuffer.buffer().append(buffer, readSize);
|
||||
}
|
||||
g_input_stream_close(inputStream, NULL, NULL);
|
||||
|
||||
// FIXME: maybe it's a better idea to implement a GInputStream based QIODevice.
|
||||
if(!error_ && !g_cancellable_is_cancelled(cancellable_)) { // load the image from buffer if there are no errors
|
||||
image_ = QImage::fromData(imageBuffer.buffer());
|
||||
|
||||
if(!image_.isNull()) { // if the image is loaded correctly
|
||||
// check if this file is a jpeg file
|
||||
// FIXME: can we use FmFileInfo instead if it's available?
|
||||
const char* basename = fm_path_get_basename(path_);
|
||||
char* mime_type = g_content_type_guess(basename, NULL, 0, NULL);
|
||||
if(mime_type && strcmp(mime_type, "image/jpeg") == 0) { // this is a jpeg file
|
||||
// use libexif to extract additional info embedded in jpeg files
|
||||
ExifLoader *exif_loader = exif_loader_new();
|
||||
// write image data to exif loader
|
||||
exif_loader_write(exif_loader, (unsigned char*)imageBuffer.data().constData(), (unsigned int)imageBuffer.size());
|
||||
ExifData *exif_data = exif_loader_get_data(exif_loader);
|
||||
exif_loader_unref(exif_loader);
|
||||
if(exif_data) {
|
||||
/* reference for EXIF orientation tag:
|
||||
* http://www.impulseadventure.com/photo/exif-orientation.html */
|
||||
ExifEntry* orient_ent = exif_data_get_entry(exif_data, EXIF_TAG_ORIENTATION);
|
||||
if(orient_ent) { /* orientation flag found in EXIF */
|
||||
gushort orient;
|
||||
ExifByteOrder bo = exif_data_get_byte_order(exif_data);
|
||||
/* bo == EXIF_BYTE_ORDER_INTEL ; */
|
||||
orient = exif_get_short (orient_ent->data, bo);
|
||||
qreal rotate_degrees = 0.0;
|
||||
switch(orient) {
|
||||
case 1: /* no rotation */
|
||||
break;
|
||||
case 8:
|
||||
rotate_degrees = 270.0;
|
||||
break;
|
||||
case 3:
|
||||
rotate_degrees = 180.0;
|
||||
break;
|
||||
case 6:
|
||||
rotate_degrees = 90.0;
|
||||
break;
|
||||
}
|
||||
// rotate the image according to EXIF orientation tag
|
||||
if(rotate_degrees != 0.0) {
|
||||
QTransform transform;
|
||||
transform.rotate(rotate_degrees);
|
||||
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
||||
}
|
||||
// TODO: handle other EXIF tags as well
|
||||
}
|
||||
exif_data_unref(exif_data);
|
||||
}
|
||||
}
|
||||
g_free(mime_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this function is called from main thread only
|
||||
void LoadImageJob::finish() {
|
||||
// only do processing if the job is not cancelled
|
||||
if(!g_cancellable_is_cancelled(cancellable_)) {
|
||||
mainWindow_->onImageLoaded(this);
|
||||
}
|
||||
}
|
60
src/loadimagejob.h
Normal file
60
src/loadimagejob.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_LOADIMAGEJOB_H
|
||||
#define LXIMAGE_LOADIMAGEJOB_H
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <libfm/fm.h>
|
||||
#include <QImage>
|
||||
#include "job.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class LoadImageJob : public Job {
|
||||
|
||||
public:
|
||||
LoadImageJob(MainWindow* window, FmPath* filePath);
|
||||
|
||||
QImage image() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
FmPath* filePath() const {
|
||||
return path_;
|
||||
}
|
||||
|
||||
private:
|
||||
~LoadImageJob(); // prevent direct deletion
|
||||
|
||||
virtual bool run();
|
||||
virtual void finish();
|
||||
|
||||
public:
|
||||
MainWindow* mainWindow_;
|
||||
FmPath* path_;
|
||||
QImage image_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_LOADIMAGEJOB_H
|
10
src/lximage-qt.cpp
Normal file
10
src/lximage-qt.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
#include <QApplication>
|
||||
#include <QIcon>
|
||||
#include "application.h"
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
LxImage::Application app(argc, argv);
|
||||
if(!app.init(argc, argv))
|
||||
return 0;
|
||||
return app.exec();
|
||||
}
|
8
src/lximage-qt.h
Normal file
8
src/lximage-qt.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef lximage_qt_H
|
||||
#define lximage_qt_H
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
};
|
||||
|
||||
#endif // lximage_qt_H
|
991
src/mainwindow.cpp
Normal file
991
src/mainwindow.cpp
Normal file
@ -0,0 +1,991 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 - 2014 Hong Jen Yee (PCMan) <pcman.tw@gmail.com>
|
||||
|
||||
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 "mainwindow.h"
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
#include <QMessageBox>
|
||||
#include <QFileDialog>
|
||||
#include <QImage>
|
||||
#include <QImageReader>
|
||||
#include <QImageWriter>
|
||||
#include <QClipboard>
|
||||
#include <QPainter>
|
||||
#include <QPrintDialog>
|
||||
#include <QPrinter>
|
||||
#include <QWheelEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QTimer>
|
||||
#include <QShortcut>
|
||||
#include <QDockWidget>
|
||||
#include <QScrollBar>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGraphicsSvgItem>
|
||||
#include "application.h"
|
||||
#include <libfm-qt/path.h>
|
||||
#include <libfm-qt/folderview.h>
|
||||
#include <libfm-qt/filepropsdialog.h>
|
||||
#include <libfm-qt/fileoperation.h>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
MainWindow::MainWindow():
|
||||
QMainWindow(),
|
||||
contextMenu_(new QMenu(this)),
|
||||
slideShowTimer_(nullptr),
|
||||
image_(),
|
||||
currentFile_(nullptr),
|
||||
// currentFileInfo_(nullptr),
|
||||
imageModified_(false),
|
||||
folder_(nullptr),
|
||||
folderPath_(nullptr),
|
||||
folderModel_(new Fm::FolderModel()),
|
||||
proxyModel_(new Fm::ProxyFolderModel()),
|
||||
modelFilter_(new ModelFilter()),
|
||||
thumbnailsDock_(nullptr),
|
||||
thumbnailsView_(nullptr),
|
||||
loadJob_(nullptr),
|
||||
saveJob_(nullptr) {
|
||||
|
||||
setAttribute(Qt::WA_DeleteOnClose); // FIXME: check if current image is saved before close
|
||||
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
app->addWindow();
|
||||
|
||||
Settings& settings = app->settings();
|
||||
|
||||
ui.setupUi(this);
|
||||
connect(ui.actionScreenshot, &QAction::triggered, app, &Application::screenshot);
|
||||
connect(ui.actionPreferences, &QAction::triggered, app , &Application::editPreferences);
|
||||
|
||||
proxyModel_->addFilter(modelFilter_);
|
||||
proxyModel_->sort(Fm::FolderModel::ColumnFileName, Qt::AscendingOrder);
|
||||
proxyModel_->setSourceModel(folderModel_);
|
||||
|
||||
// build context menu
|
||||
ui.view->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui.view, &QWidget::customContextMenuRequested, this, &MainWindow::onContextMenu);
|
||||
|
||||
// install an event filter on the image view
|
||||
ui.view->installEventFilter(this);
|
||||
ui.view->setBackgroundBrush(QBrush(settings.bgColor()));
|
||||
|
||||
if(settings.showThumbnails())
|
||||
setShowThumbnails(true);
|
||||
|
||||
contextMenu_->addAction(ui.actionPrevious);
|
||||
contextMenu_->addAction(ui.actionNext);
|
||||
contextMenu_->addSeparator();
|
||||
contextMenu_->addAction(ui.actionZoomOut);
|
||||
contextMenu_->addAction(ui.actionZoomIn);
|
||||
contextMenu_->addAction(ui.actionOriginalSize);
|
||||
contextMenu_->addAction(ui.actionZoomFit);
|
||||
contextMenu_->addSeparator();
|
||||
contextMenu_->addAction(ui.actionSlideShow);
|
||||
contextMenu_->addAction(ui.actionFullScreen);
|
||||
contextMenu_->addSeparator();
|
||||
contextMenu_->addAction(ui.actionRotateClockwise);
|
||||
contextMenu_->addAction(ui.actionRotateCounterclockwise);
|
||||
contextMenu_->addAction(ui.actionFlipHorizontal);
|
||||
contextMenu_->addAction(ui.actionFlipVertical);
|
||||
contextMenu_->addAction(ui.actionFlipVertical);
|
||||
|
||||
// create shortcuts
|
||||
QShortcut* shortcut = new QShortcut(Qt::Key_Left, this);
|
||||
connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionPrevious_triggered);
|
||||
shortcut = new QShortcut(Qt::Key_Right, this);
|
||||
connect(shortcut, &QShortcut::activated, this, &MainWindow::on_actionNext_triggered);
|
||||
shortcut = new QShortcut(Qt::Key_Escape, this);
|
||||
connect(shortcut, &QShortcut::activated, this, &MainWindow::onExitFullscreen);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() {
|
||||
if(slideShowTimer_)
|
||||
delete slideShowTimer_;
|
||||
if(thumbnailsView_)
|
||||
delete thumbnailsView_;
|
||||
if(thumbnailsDock_)
|
||||
delete thumbnailsDock_;
|
||||
|
||||
if(loadJob_) {
|
||||
loadJob_->cancel();
|
||||
// we don't need to do delete here. It will be done automatically
|
||||
}
|
||||
if(currentFile_)
|
||||
fm_path_unref(currentFile_);
|
||||
//if(currentFileInfo_)
|
||||
// fm_file_info_unref(currentFileInfo_);
|
||||
if(folder_) {
|
||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(_onFolderLoaded), this);
|
||||
g_object_unref(folder_);
|
||||
}
|
||||
if(folderPath_)
|
||||
fm_path_unref(folderPath_);
|
||||
delete folderModel_;
|
||||
delete proxyModel_;
|
||||
delete modelFilter_;
|
||||
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
app->removeWindow();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionAbout_triggered() {
|
||||
QMessageBox::about(this, tr("About"),
|
||||
tr("LXImage - a simple and fast image viewer\n\n"
|
||||
"Copyright (C) 2013\n"
|
||||
"LXDE Project: http://lxde.org/\n\n"
|
||||
"Authors:\n"
|
||||
"Hong Jen Yee (PCMan) <pcman.tw@gmail.com>"));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOriginalSize_triggered() {
|
||||
ui.view->setAutoZoomFit(false);
|
||||
ui.view->zoomOriginal();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionZoomFit_triggered() {
|
||||
ui.view->setAutoZoomFit(true);
|
||||
ui.view->zoomFit();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionZoomIn_triggered() {
|
||||
ui.view->setAutoZoomFit(false);
|
||||
ui.view->zoomIn();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionZoomOut_triggered() {
|
||||
ui.view->setAutoZoomFit(false);
|
||||
ui.view->zoomOut();
|
||||
}
|
||||
|
||||
void MainWindow::onFolderLoaded(FmFolder* folder) {
|
||||
// if currently we're showing a file, get its index in the folder now
|
||||
// since the folder is fully loaded.
|
||||
if(currentFile_ && !currentIndex_.isValid()) {
|
||||
currentIndex_ = indexFromPath(currentFile_);
|
||||
if(thumbnailsView_) { // showing thumbnails
|
||||
// select current file in the thumbnails view
|
||||
thumbnailsView_->childView()->setCurrentIndex(currentIndex_);
|
||||
thumbnailsView_->childView()->scrollTo(currentIndex_, QAbstractItemView::EnsureVisible);
|
||||
}
|
||||
}
|
||||
// this is used to open the first image of a folder
|
||||
else if (currentFile_ == nullptr)
|
||||
on_actionFirst_triggered();
|
||||
}
|
||||
|
||||
void MainWindow::openImageFile(QString fileName) {
|
||||
FmPath* path = fm_path_new_for_str(qPrintable(fileName));
|
||||
if(currentFile_ && fm_path_equal(currentFile_, path)) {
|
||||
// the same file! do not load it again
|
||||
fm_path_unref(path);
|
||||
return;
|
||||
}
|
||||
if (QFileInfo(fileName).isDir()) {
|
||||
if(fm_path_equal(path, folderPath_)) {
|
||||
fm_path_unref(path);
|
||||
return;
|
||||
}
|
||||
QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||
QStringList formatsFilters;
|
||||
for (const QByteArray& format: formats)
|
||||
formatsFilters << QString("*.") + format;
|
||||
QDir dir(fileName);
|
||||
dir.setNameFilters(formatsFilters);
|
||||
dir.setFilter(QDir::Files | QDir::NoDotAndDotDot);
|
||||
if(dir.entryList().isEmpty()) {
|
||||
fm_path_unref(path);
|
||||
return;
|
||||
}
|
||||
if(currentFile_)
|
||||
fm_path_unref(currentFile_);
|
||||
currentFile_ = nullptr;
|
||||
loadFolder(path);
|
||||
} else {
|
||||
// load the image file asynchronously
|
||||
loadImage(path);
|
||||
loadFolder(fm_path_get_parent(path));
|
||||
}
|
||||
fm_path_unref(path);
|
||||
}
|
||||
|
||||
// paste the specified image into the current view,
|
||||
// reset the window, remove loaded folders, and
|
||||
// invalidate current file name.
|
||||
void MainWindow::pasteImage(QImage newImage) {
|
||||
// cancel loading of current image
|
||||
if(loadJob_) {
|
||||
loadJob_->cancel(); // the job object will be freed automatically later
|
||||
loadJob_ = nullptr;
|
||||
}
|
||||
setModified(true);
|
||||
|
||||
currentIndex_ = QModelIndex(); // invaludate current index since we don't have a folder model now
|
||||
if(currentFile_)
|
||||
fm_path_unref(currentFile_);
|
||||
currentFile_ = nullptr;
|
||||
|
||||
image_ = newImage;
|
||||
ui.view->setImage(image_);
|
||||
ui.view->zoomOriginal();
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
// popup a file dialog and retrieve the selected image file name
|
||||
QString MainWindow::openFileName() {
|
||||
QString filterStr;
|
||||
QList<QByteArray> formats = QImageReader::supportedImageFormats();
|
||||
QList<QByteArray>::iterator it = formats.begin();
|
||||
for(;;) {
|
||||
filterStr += "*.";
|
||||
filterStr += (*it).toLower();
|
||||
++it;
|
||||
if(it != formats.end())
|
||||
filterStr += ' ';
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
QString fileName = QFileDialog::getOpenFileName(
|
||||
this, tr("Open File"), QString(),
|
||||
tr("Image files (%1)").arg(filterStr));
|
||||
return fileName;
|
||||
}
|
||||
|
||||
QString MainWindow::openDirectory() {
|
||||
QString directory = QFileDialog::getExistingDirectory(this,
|
||||
tr("Open directory"), QString());
|
||||
return directory;
|
||||
}
|
||||
|
||||
// popup a file dialog and retrieve the selected image file name
|
||||
QString MainWindow::saveFileName(QString defaultName) {
|
||||
QString filterStr;
|
||||
QList<QByteArray> formats = QImageWriter::supportedImageFormats();
|
||||
QList<QByteArray>::iterator it = formats.begin();
|
||||
for(;;) {
|
||||
filterStr += "*.";
|
||||
filterStr += (*it).toLower();
|
||||
++it;
|
||||
if(it != formats.end())
|
||||
filterStr += ' ';
|
||||
else
|
||||
break;
|
||||
}
|
||||
// FIXME: should we generate better filter strings? one format per item?
|
||||
|
||||
QString fileName = QFileDialog::getSaveFileName(
|
||||
this, tr("Save File"), defaultName, tr("Image files (%1)").arg(filterStr));
|
||||
|
||||
// use png format by default if the extension is not set
|
||||
if(!fileName.isEmpty() && fileName.indexOf('.') == -1)
|
||||
fileName += ".png";
|
||||
return fileName;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOpenFile_triggered() {
|
||||
QString fileName = openFileName();
|
||||
if(!fileName.isEmpty()) {
|
||||
openImageFile(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionOpenDirectory_triggered() {
|
||||
QString directory = openDirectory();
|
||||
if(!directory.isEmpty()) {
|
||||
openImageFile(directory);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionNewWindow_triggered() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
MainWindow* window = new MainWindow();
|
||||
window->resize(app->settings().windowWidth(), app->settings().windowHeight());
|
||||
|
||||
if(app->settings().windowMaximized())
|
||||
window->setWindowState(window->windowState() | Qt::WindowMaximized);
|
||||
|
||||
window->show();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSave_triggered() {
|
||||
if(saveJob_) // if we're currently saving another file
|
||||
return;
|
||||
|
||||
if(!image_.isNull()) {
|
||||
if(currentFile_)
|
||||
saveImage(currentFile_);
|
||||
else
|
||||
on_actionSaveAs_triggered();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSaveAs_triggered() {
|
||||
if(saveJob_) // if we're currently saving another file
|
||||
return;
|
||||
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()) {
|
||||
FmPath* path = fm_path_new_for_str(qPrintable(fileName));
|
||||
// save the image file asynchronously
|
||||
saveImage(path);
|
||||
|
||||
if(!currentFile_) { // if we haven't load any file yet
|
||||
currentFile_ = path;
|
||||
loadFolder(fm_path_get_parent(path));
|
||||
}
|
||||
else
|
||||
fm_path_unref(path);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionDelete_triggered() {
|
||||
// delete the current file
|
||||
if(currentFile_) {
|
||||
FmPathList* paths = fm_path_list_new();
|
||||
fm_path_list_push_tail(paths, currentFile_);
|
||||
Fm::FileOperation::deleteFiles(paths);
|
||||
fm_path_list_unref(paths);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFileProperties_triggered() {
|
||||
if(currentIndex_.isValid()) {
|
||||
FmFileInfo* file = proxyModel_->fileInfoFromIndex(currentIndex_);
|
||||
// it's better to use an async job to query the file info since it's
|
||||
// possible that loading of the folder is not finished and the file info is
|
||||
// not available yet, but it's overkill for a rarely used function.
|
||||
if(file)
|
||||
Fm::FilePropsDialog::showForFile(file);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionClose_triggered() {
|
||||
deleteLater();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionNext_triggered() {
|
||||
if(proxyModel_->rowCount() <= 1)
|
||||
return;
|
||||
if(currentIndex_.isValid()) {
|
||||
QModelIndex index;
|
||||
if(currentIndex_.row() < proxyModel_->rowCount() - 1)
|
||||
index = proxyModel_->index(currentIndex_.row() + 1, 0);
|
||||
else
|
||||
index = proxyModel_->index(0, 0);
|
||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||
if(info) {
|
||||
FmPath* path = fm_file_info_get_path(info);
|
||||
loadImage(path, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPrevious_triggered() {
|
||||
if(proxyModel_->rowCount() <= 1)
|
||||
return;
|
||||
if(currentIndex_.isValid()) {
|
||||
QModelIndex index;
|
||||
if(currentIndex_.row() > 0)
|
||||
index = proxyModel_->index(currentIndex_.row() - 1, 0);
|
||||
else
|
||||
index = proxyModel_->index(proxyModel_->rowCount() - 1, 0);
|
||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||
if(info) {
|
||||
FmPath* path = fm_file_info_get_path(info);
|
||||
loadImage(path, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFirst_triggered() {
|
||||
QModelIndex index = proxyModel_->index(0, 0);
|
||||
if(index.isValid()) {
|
||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||
if(info) {
|
||||
FmPath* path = fm_file_info_get_path(info);
|
||||
loadImage(path, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionLast_triggered() {
|
||||
QModelIndex index = proxyModel_->index(proxyModel_->rowCount() - 1, 0);
|
||||
if(index.isValid()) {
|
||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||
if(info) {
|
||||
FmPath* path = fm_file_info_get_path(info);;
|
||||
loadImage(path, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::loadFolder(FmPath* newFolderPath) {
|
||||
if(folder_) { // an folder is already loaded
|
||||
if(fm_path_equal(newFolderPath, folderPath_)) // same folder, ignore
|
||||
return;
|
||||
// free current folder
|
||||
g_signal_handlers_disconnect_by_func(folder_, gpointer(_onFolderLoaded), this);
|
||||
g_object_unref(folder_);
|
||||
fm_path_unref(folderPath_);
|
||||
}
|
||||
|
||||
folderPath_ = fm_path_ref(newFolderPath);
|
||||
folder_ = fm_folder_from_path(newFolderPath);
|
||||
g_signal_connect(folder_, "finish-loading", G_CALLBACK(_onFolderLoaded), this);
|
||||
|
||||
folderModel_->setFolder(folder_);
|
||||
currentIndex_ = QModelIndex(); // set current index to invalid
|
||||
}
|
||||
|
||||
// the image is loaded (the method is only called if the loading is not cancelled)
|
||||
void MainWindow::onImageLoaded(LoadImageJob* job) {
|
||||
loadJob_ = nullptr; // the job object will be freed later automatically
|
||||
|
||||
image_ = job->image();
|
||||
ui.view->setAutoZoomFit(true);
|
||||
ui.view->setImage(image_);
|
||||
|
||||
if(!currentIndex_.isValid())
|
||||
currentIndex_ = indexFromPath(currentFile_);
|
||||
|
||||
updateUI();
|
||||
|
||||
if(job->error()) {
|
||||
// if there are errors
|
||||
// TODO: show a info bar?
|
||||
}
|
||||
|
||||
/* we resized and moved the window without showing
|
||||
it in updateUI(), so we need to show it here */
|
||||
show();
|
||||
}
|
||||
|
||||
void MainWindow::onImageSaved(SaveImageJob* job) {
|
||||
if(!job->error()) {
|
||||
setModified(false);
|
||||
}
|
||||
saveJob_ = nullptr;
|
||||
}
|
||||
|
||||
// filter events of other objects, mainly the image view.
|
||||
bool MainWindow::eventFilter(QObject* watched, QEvent* event) {
|
||||
if(watched == ui.view) { // we got an event for the image view
|
||||
switch(event->type()) {
|
||||
case QEvent::Wheel: { // mouse wheel event
|
||||
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
|
||||
if(wheelEvent->modifiers() == 0) {
|
||||
int delta = wheelEvent->delta();
|
||||
if(delta < 0)
|
||||
on_actionNext_triggered(); // next image
|
||||
else
|
||||
on_actionPrevious_triggered(); // previous image
|
||||
}
|
||||
break;
|
||||
}
|
||||
case QEvent::MouseButtonDblClick: {
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if(mouseEvent->button() == Qt::LeftButton)
|
||||
ui.actionFullScreen->trigger();
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
else if(thumbnailsView_ && watched == thumbnailsView_->childView()) {
|
||||
// scroll the thumbnail view with mouse wheel
|
||||
switch(event->type()) {
|
||||
case QEvent::Wheel: { // mouse wheel event
|
||||
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
|
||||
if(wheelEvent->modifiers() == 0) {
|
||||
int delta = wheelEvent->delta();
|
||||
QScrollBar* hscroll = thumbnailsView_->childView()->horizontalScrollBar();
|
||||
if(hscroll)
|
||||
hscroll->setValue(hscroll->value() - delta);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:;
|
||||
}
|
||||
}
|
||||
return QObject::eventFilter(watched, event);
|
||||
}
|
||||
|
||||
QModelIndex MainWindow::indexFromPath(FmPath* filePath) {
|
||||
// if the folder is already loaded, figure out our index
|
||||
// otherwise, it will be done again in onFolderLoaded() when the folder is fully loaded.
|
||||
if(folder_ && fm_folder_is_loaded(folder_)) {
|
||||
QModelIndex index;
|
||||
int count = proxyModel_->rowCount();
|
||||
for(int row = 0; row < count; ++row) {
|
||||
index = proxyModel_->index(row, 0);
|
||||
FmFileInfo* info = proxyModel_->fileInfoFromIndex(index);
|
||||
if(info && fm_path_equal(filePath, fm_file_info_get_path(info))) {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
}
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::updateUI() {
|
||||
if(currentIndex_.isValid()) {
|
||||
if(thumbnailsView_) { // showing thumbnails
|
||||
// select current file in the thumbnails view
|
||||
thumbnailsView_->childView()->setCurrentIndex(currentIndex_);
|
||||
thumbnailsView_->childView()->scrollTo(currentIndex_, QAbstractItemView::EnsureVisible);
|
||||
}
|
||||
}
|
||||
|
||||
QString title;
|
||||
if(currentFile_) {
|
||||
char* dispName = fm_path_display_basename(currentFile_);
|
||||
if(loadJob_) { // if loading is in progress
|
||||
title = tr("[*]%1 (Loading...) - Image Viewer")
|
||||
.arg(QString::fromUtf8(dispName));
|
||||
}
|
||||
else {
|
||||
if(image_.isNull()) {
|
||||
title = tr("[*]%1 (Failed to Load) - Image Viewer")
|
||||
.arg(QString::fromUtf8(dispName));
|
||||
}
|
||||
else {
|
||||
title = tr("[*]%1 (%2x%3) - Image Viewer")
|
||||
.arg(QString::fromUtf8(dispName))
|
||||
.arg(image_.width())
|
||||
.arg(image_.height());
|
||||
/* Here we try to implement the following behavior as far as possible:
|
||||
(1) A minimum size of 400x400 is assumed;
|
||||
(2) The window is scaled to fit the image;
|
||||
(3) But for too big images, the window is scaled down;
|
||||
(4) The window is centered on the screen. */
|
||||
if (!isVisible()) {
|
||||
/* To have a correct position, we should move the window BEFORE
|
||||
it's shown but we also need to know the dimensions of its view.
|
||||
Therefore, we use show() without really showing the window. */
|
||||
setAttribute(Qt::WA_DontShowOnScreen);
|
||||
show();
|
||||
int scrollThickness = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
|
||||
QSize newSize = size() + image_.size() - ui.view->size() + QSize(scrollThickness, scrollThickness);
|
||||
QRect ag = QApplication::desktop()->availableGeometry();
|
||||
// since the window isn't decorated yet, we have to assume a max thickness for its frame
|
||||
QSize maxFrame = QSize(50, 100);
|
||||
if (newSize.width() > ag.width() - maxFrame.width() || newSize.height() > ag.height() - maxFrame.height())
|
||||
newSize.scale (ag.width() - maxFrame.width(), ag.height() - maxFrame.height(), Qt::KeepAspectRatio);
|
||||
// a minimum size of 400x400 is good
|
||||
if (newSize.width() < 400) newSize.rwidth() = 400;
|
||||
if (newSize.height() < 400 ) newSize.rheight() = 400;
|
||||
move (ag.x() + (ag.width() - newSize.width())/2,
|
||||
ag.y() + (ag.height() - newSize.height())/2);
|
||||
resize(newSize);
|
||||
hide(); // hide it to show it again later, at onImageLoaded()
|
||||
setAttribute(Qt::WA_DontShowOnScreen, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_free(dispName);
|
||||
// TODO: update status bar, show current index in the folder
|
||||
}
|
||||
else {
|
||||
title = tr("[*]Image Viewer");
|
||||
}
|
||||
setWindowTitle(title);
|
||||
setWindowModified(imageModified_);
|
||||
}
|
||||
|
||||
// Load the specified image file asynchronously in a worker thread.
|
||||
// When the loading is finished, onImageLoaded() will be called.
|
||||
void MainWindow::loadImage(FmPath* filePath, QModelIndex index) {
|
||||
// cancel loading of current image
|
||||
if(loadJob_) {
|
||||
loadJob_->cancel(); // the job object will be freed automatically later
|
||||
loadJob_ = nullptr;
|
||||
}
|
||||
if(imageModified_) {
|
||||
// TODO: ask the user to save the modified image?
|
||||
// this should be made optional
|
||||
setModified(false);
|
||||
}
|
||||
|
||||
currentIndex_ = index;
|
||||
if(currentFile_)
|
||||
fm_path_unref(currentFile_);
|
||||
currentFile_ = fm_path_ref(filePath);
|
||||
// clear current image, but do not update the view now to prevent flickers
|
||||
image_ = QImage();
|
||||
|
||||
const char* basename = fm_path_get_basename(currentFile_);
|
||||
char* mime_type = g_content_type_guess(basename, NULL, 0, NULL);
|
||||
QString mimeType;
|
||||
if (mime_type) {
|
||||
mimeType = QString(mime_type);
|
||||
g_free(mime_type);
|
||||
}
|
||||
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()
|
||||
if(mimeType == "image/gif")
|
||||
ui.view->setGifAnimation(fileName);
|
||||
else
|
||||
ui.view->setSVG(fileName);
|
||||
image_ = ui.view->image();
|
||||
updateUI();
|
||||
show();
|
||||
}
|
||||
else {
|
||||
// start a new gio job to load the specified image
|
||||
loadJob_ = new LoadImageJob(this, filePath);
|
||||
loadJob_->start();
|
||||
|
||||
updateUI();
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::saveImage(FmPath* filePath) {
|
||||
if(saveJob_) // do not launch a new job if the current one is still in progress
|
||||
return;
|
||||
// start a new gio job to save current image to the specified path
|
||||
saveJob_ = new SaveImageJob(this, filePath);
|
||||
saveJob_->start();
|
||||
// FIXME: add a cancel button to the UI? update status bar?
|
||||
}
|
||||
|
||||
QGraphicsItem* MainWindow::getGraphicsItem() {
|
||||
if(!ui.view->items().isEmpty())
|
||||
return ui.view->items().at(0);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRotateClockwise_triggered() {
|
||||
QGraphicsItem *graphItem = getGraphicsItem();
|
||||
bool isGifOrSvg (graphItem->isWidget() // we have gif animation
|
||||
|| dynamic_cast<QGraphicsSvgItem*>(graphItem)); // an SVG image;
|
||||
if(!image_.isNull()) {
|
||||
QTransform transform;
|
||||
transform.rotate(90.0);
|
||||
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
||||
/* when this is GIF or SVG, we need to rotate its corresponding QImage
|
||||
without showing it to have the right measure for auto-zooming */
|
||||
ui.view->setImage(image_, isGifOrSvg ? false : true);
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
if(isGifOrSvg) {
|
||||
QTransform transform;
|
||||
transform.translate(graphItem->sceneBoundingRect().height(), 0);
|
||||
transform.rotate(90);
|
||||
// we need to apply transformations in the reverse order
|
||||
QTransform prevTrans = graphItem->transform();
|
||||
graphItem->setTransform(transform, false);
|
||||
graphItem->setTransform(prevTrans, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionRotateCounterclockwise_triggered() {
|
||||
QGraphicsItem *graphItem = getGraphicsItem();
|
||||
bool isGifOrSvg (graphItem->isWidget()
|
||||
|| dynamic_cast<QGraphicsSvgItem*>(graphItem));
|
||||
if(!image_.isNull()) {
|
||||
QTransform transform;
|
||||
transform.rotate(-90.0);
|
||||
image_ = image_.transformed(transform, Qt::SmoothTransformation);
|
||||
ui.view->setImage(image_, isGifOrSvg ? false : true);
|
||||
setModified(true);
|
||||
}
|
||||
|
||||
if(isGifOrSvg) {
|
||||
QTransform transform;
|
||||
transform.translate(0, graphItem->sceneBoundingRect().width());
|
||||
transform.rotate(-90);
|
||||
QTransform prevTrans = graphItem->transform();
|
||||
graphItem->setTransform(transform, false);
|
||||
graphItem->setTransform(prevTrans, true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionCopy_triggered() {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
QImage copiedImage = image_;
|
||||
// FIXME: should we copy the currently scaled result instead of the original image?
|
||||
/*
|
||||
double factor = ui.view->scaleFactor();
|
||||
if(factor == 1.0)
|
||||
copiedImage = image_;
|
||||
else
|
||||
copiedImage = image_.scaled();
|
||||
*/
|
||||
clipboard->setImage(copiedImage);
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPaste_triggered() {
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
QImage image = clipboard->image();
|
||||
if(!image.isNull()) {
|
||||
pasteImage(image);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFlipVertical_triggered() {
|
||||
bool hasQGraphicsItem(false);
|
||||
if(QGraphicsItem *graphItem = getGraphicsItem()) {
|
||||
hasQGraphicsItem = true;
|
||||
QTransform transform;
|
||||
transform.scale(1, -1);
|
||||
transform.translate(0, -graphItem->sceneBoundingRect().height());
|
||||
QTransform prevTrans = graphItem->transform();
|
||||
graphItem->setTransform(transform, false);
|
||||
graphItem->setTransform(prevTrans, true);
|
||||
}
|
||||
if(!image_.isNull()) {
|
||||
image_ = image_.mirrored(false, true);
|
||||
ui.view->setImage(image_, !hasQGraphicsItem);
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionFlipHorizontal_triggered() {
|
||||
bool hasQGraphicsItem(false);
|
||||
if(QGraphicsItem *graphItem = getGraphicsItem()) {
|
||||
hasQGraphicsItem = true;
|
||||
QTransform transform;
|
||||
transform.scale(-1, 1);
|
||||
transform.translate(-graphItem->sceneBoundingRect().width(), 0);
|
||||
QTransform prevTrans = graphItem->transform();
|
||||
graphItem->setTransform(transform, false);
|
||||
graphItem->setTransform(prevTrans, true);
|
||||
}
|
||||
if(!image_.isNull()) {
|
||||
image_ = image_.mirrored(true, true);
|
||||
ui.view->setImage(image_, !hasQGraphicsItem);
|
||||
setModified(true);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setModified(bool modified) {
|
||||
imageModified_ = modified;
|
||||
updateUI();
|
||||
}
|
||||
|
||||
void MainWindow::applySettings() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
Settings& settings = app->settings();
|
||||
if(isFullScreen())
|
||||
ui.view->setBackgroundBrush(QBrush(settings.fullScreenBgColor()));
|
||||
else
|
||||
ui.view->setBackgroundBrush(QBrush(settings.bgColor()));
|
||||
}
|
||||
|
||||
void MainWindow::on_actionPrint_triggered() {
|
||||
// QPrinter printer(QPrinter::HighResolution);
|
||||
QPrinter printer;
|
||||
QPrintDialog dlg(&printer);
|
||||
if(dlg.exec() == QDialog::Accepted) {
|
||||
QPainter painter;
|
||||
painter.begin(&printer);
|
||||
QRect pageRect = printer.pageRect();
|
||||
int cols = (image_.width() / pageRect.width()) + (image_.width() % pageRect.width() ? 1 : 0);
|
||||
int rows = (image_.height() / pageRect.height()) + (image_.height() % pageRect.height() ? 1 : 0);
|
||||
for(int row = 0; row < rows; ++row) {
|
||||
for(int col = 0; col < cols; ++col) {
|
||||
QRect srcRect(pageRect.width() * col, pageRect.height() * row, pageRect.width(), pageRect.height());
|
||||
painter.drawImage(QPoint(0, 0), image_, srcRect);
|
||||
if(col + 1 == cols && row + 1 == rows) // this is the last page
|
||||
break;
|
||||
printer.newPage();
|
||||
}
|
||||
}
|
||||
painter.end();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This can later be used for doing slide show
|
||||
void MainWindow::on_actionFullScreen_triggered(bool checked) {
|
||||
if(checked)
|
||||
showFullScreen();
|
||||
else
|
||||
showNormal();
|
||||
}
|
||||
|
||||
void MainWindow::on_actionSlideShow_triggered(bool checked) {
|
||||
if(checked) {
|
||||
if(!slideShowTimer_) {
|
||||
slideShowTimer_ = new QTimer();
|
||||
// switch to the next image when timeout
|
||||
connect(slideShowTimer_, &QTimer::timeout, this, &MainWindow::on_actionNext_triggered);
|
||||
}
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
slideShowTimer_->start(app->settings().slideShowInterval() * 1000);
|
||||
// showFullScreen();
|
||||
ui.actionSlideShow->setIcon(QIcon::fromTheme("media-playback-stop"));
|
||||
}
|
||||
else {
|
||||
if(slideShowTimer_) {
|
||||
delete slideShowTimer_;
|
||||
slideShowTimer_ = nullptr;
|
||||
ui.actionSlideShow->setIcon(QIcon::fromTheme("media-playback-start"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::setShowThumbnails(bool show) {
|
||||
if(show) {
|
||||
if(!thumbnailsDock_) {
|
||||
thumbnailsDock_ = new QDockWidget(this);
|
||||
thumbnailsDock_->setFeatures(QDockWidget::NoDockWidgetFeatures); // FIXME: should use DockWidgetClosable
|
||||
thumbnailsDock_->setWindowTitle(tr("Thumbnails"));
|
||||
thumbnailsView_ = new Fm::FolderView(Fm::FolderView::IconMode);
|
||||
thumbnailsDock_->setWidget(thumbnailsView_);
|
||||
addDockWidget(Qt::BottomDockWidgetArea, thumbnailsDock_);
|
||||
QListView* listView = static_cast<QListView*>(thumbnailsView_->childView());
|
||||
listView->setFlow(QListView::TopToBottom);
|
||||
listView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
listView->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
listView->installEventFilter(this);
|
||||
// FIXME: optimize the size of the thumbnail view
|
||||
// FIXME if the thumbnail view is docked elsewhere, update the settings.
|
||||
int scrollHeight = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
|
||||
thumbnailsView_->setFixedHeight(listView->gridSize().height() + scrollHeight);
|
||||
thumbnailsView_->setModel(proxyModel_);
|
||||
proxyModel_->setShowThumbnails(true);
|
||||
if (currentFile_) { // select the loaded image
|
||||
currentIndex_ = indexFromPath(currentFile_);
|
||||
listView->setCurrentIndex(currentIndex_);
|
||||
// wait to center the selection
|
||||
QCoreApplication::processEvents();
|
||||
listView->scrollTo(currentIndex_, QAbstractItemView::PositionAtCenter);
|
||||
}
|
||||
connect(thumbnailsView_->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||
this, &MainWindow::onThumbnailSelChanged);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(thumbnailsDock_) {
|
||||
delete thumbnailsView_;
|
||||
thumbnailsView_ = nullptr;
|
||||
delete thumbnailsDock_;
|
||||
thumbnailsDock_ = nullptr;
|
||||
}
|
||||
proxyModel_->setShowThumbnails(false);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::on_actionShowThumbnails_triggered(bool checked) {
|
||||
setShowThumbnails(checked);
|
||||
}
|
||||
|
||||
void MainWindow::changeEvent(QEvent* event) {
|
||||
// TODO: hide menu/toolbars in full screen mode and make the background black.
|
||||
if(event->type() == QEvent::WindowStateChange) {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
if(isFullScreen()) { // changed to fullscreen mode
|
||||
ui.view->setFrameStyle(QFrame::NoFrame);
|
||||
ui.view->setBackgroundBrush(QBrush(app->settings().fullScreenBgColor()));
|
||||
ui.toolBar->hide();
|
||||
ui.statusBar->hide();
|
||||
if(thumbnailsDock_)
|
||||
thumbnailsDock_->hide();
|
||||
// NOTE: in fullscreen mode, all shortcut keys in the menu are disabled since the menu
|
||||
// is disabled. We needs to add the actions to the main window manually to enable the
|
||||
// shortcuts again.
|
||||
ui.menubar->hide();
|
||||
Q_FOREACH(QAction* action, ui.menubar->actions()) {
|
||||
if(!action->shortcut().isEmpty())
|
||||
addAction(action);
|
||||
}
|
||||
addActions(ui.menubar->actions());
|
||||
ui.view->hideCursor(true);
|
||||
}
|
||||
else { // restore to normal window mode
|
||||
ui.view->setFrameStyle(QFrame::StyledPanel|QFrame::Sunken);
|
||||
ui.view->setBackgroundBrush(QBrush(app->settings().bgColor()));
|
||||
// now we're going to re-enable the menu, so remove the actions previously added.
|
||||
Q_FOREACH(QAction* action, ui.menubar->actions()) {
|
||||
if(!action->shortcut().isEmpty())
|
||||
removeAction(action);
|
||||
}
|
||||
ui.menubar->show();
|
||||
ui.toolBar->show();
|
||||
ui.statusBar->show();
|
||||
if(thumbnailsDock_)
|
||||
thumbnailsDock_->show();
|
||||
ui.view->hideCursor(false);
|
||||
}
|
||||
}
|
||||
QWidget::changeEvent(event);
|
||||
}
|
||||
|
||||
void MainWindow::resizeEvent(QResizeEvent *event) {
|
||||
QMainWindow::resizeEvent(event);
|
||||
Settings& settings = static_cast<Application*>(qApp)->settings();
|
||||
if(settings.rememberWindowSize()) {
|
||||
settings.setLastWindowMaximized(isMaximized());
|
||||
|
||||
if(!isMaximized()) {
|
||||
settings.setLastWindowWidth(width());
|
||||
settings.setLastWindowHeight(height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QWidget::closeEvent(event);
|
||||
Settings& settings = static_cast<Application*>(qApp)->settings();
|
||||
if(settings.rememberWindowSize()) {
|
||||
settings.setLastWindowMaximized(isMaximized());
|
||||
|
||||
if(!isMaximized()) {
|
||||
settings.setLastWindowWidth(width());
|
||||
settings.setLastWindowHeight(height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::onContextMenu(QPoint pos) {
|
||||
contextMenu_->exec(ui.view->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
void MainWindow::onExitFullscreen() {
|
||||
if(isFullScreen())
|
||||
showNormal();
|
||||
}
|
||||
|
||||
void MainWindow::onThumbnailSelChanged(const QItemSelection& selected, const QItemSelection& deselected) {
|
||||
// the selected item of thumbnail view is changed
|
||||
if(!selected.isEmpty()) {
|
||||
QModelIndex index = selected.first().topLeft();
|
||||
if(index.isValid() && index != currentIndex_) {
|
||||
FmFileInfo* file = proxyModel_->fileInfoFromIndex(index);
|
||||
if(file)
|
||||
loadImage(fm_file_info_get_path(file), index);
|
||||
}
|
||||
}
|
||||
}
|
166
src/mainwindow.h
Normal file
166
src/mainwindow.h
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 <copyright holder> <email>
|
||||
|
||||
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 LXIMAGE_MAINWINDOW_H
|
||||
#define LXIMAGE_MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "imageview.h"
|
||||
#include <QImage>
|
||||
|
||||
#include <libfm/fm-folder.h>
|
||||
#include <libfm-qt/foldermodel.h>
|
||||
#include <libfm-qt/proxyfoldermodel.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
#include "modelfilter.h"
|
||||
#include "loadimagejob.h"
|
||||
#include "saveimagejob.h"
|
||||
|
||||
class QTimer;
|
||||
class QDockWidget;
|
||||
|
||||
namespace Fm {
|
||||
class FolderView;
|
||||
}
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class MainWindow : public QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
friend class LoadImageJob;
|
||||
friend class SaveImageJob;
|
||||
|
||||
MainWindow();
|
||||
virtual ~MainWindow();
|
||||
|
||||
void openImageFile(QString fileName);
|
||||
|
||||
QImage image() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
void pasteImage(QImage newImage);
|
||||
|
||||
FmPath* currentFile() const {
|
||||
return currentFile_;
|
||||
}
|
||||
|
||||
void setShowThumbnails(bool show);
|
||||
void applySettings();
|
||||
|
||||
protected:
|
||||
void loadImage(FmPath* filePath, QModelIndex index = QModelIndex());
|
||||
void saveImage(FmPath* filePath); // save current image to a file
|
||||
void loadFolder(FmPath* newFolderPath);
|
||||
QString openFileName();
|
||||
QString openDirectory();
|
||||
QString saveFileName(QString defaultName = QString());
|
||||
virtual void changeEvent(QEvent * event);
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
|
||||
void onImageLoaded(LoadImageJob* job);
|
||||
void onImageSaved(SaveImageJob* job);
|
||||
|
||||
virtual bool eventFilter(QObject* watched, QEvent* event);
|
||||
private Q_SLOTS:
|
||||
void on_actionAbout_triggered();
|
||||
|
||||
void on_actionOpenFile_triggered();
|
||||
void on_actionOpenDirectory_triggered();
|
||||
void on_actionNewWindow_triggered();
|
||||
void on_actionSave_triggered();
|
||||
void on_actionSaveAs_triggered();
|
||||
void on_actionPrint_triggered();
|
||||
void on_actionDelete_triggered();
|
||||
void on_actionFileProperties_triggered();
|
||||
void on_actionClose_triggered();
|
||||
|
||||
void on_actionRotateClockwise_triggered();
|
||||
void on_actionRotateCounterclockwise_triggered();
|
||||
void on_actionFlipVertical_triggered();
|
||||
void on_actionFlipHorizontal_triggered();
|
||||
void on_actionCopy_triggered();
|
||||
void on_actionPaste_triggered();
|
||||
|
||||
void on_actionShowThumbnails_triggered(bool checked);
|
||||
void on_actionFullScreen_triggered(bool checked);
|
||||
void on_actionSlideShow_triggered(bool checked);
|
||||
|
||||
void on_actionPrevious_triggered();
|
||||
void on_actionNext_triggered();
|
||||
void on_actionFirst_triggered();
|
||||
void on_actionLast_triggered();
|
||||
|
||||
void on_actionZoomIn_triggered();
|
||||
void on_actionZoomOut_triggered();
|
||||
void on_actionOriginalSize_triggered();
|
||||
void on_actionZoomFit_triggered();
|
||||
|
||||
void onContextMenu(QPoint pos);
|
||||
void onExitFullscreen();
|
||||
|
||||
void onThumbnailSelChanged(const QItemSelection & selected, const QItemSelection & deselected);
|
||||
|
||||
private:
|
||||
void onFolderLoaded(FmFolder* folder);
|
||||
void updateUI();
|
||||
void setModified(bool modified);
|
||||
QModelIndex indexFromPath(FmPath* filePath);
|
||||
QGraphicsItem* getGraphicsItem();
|
||||
|
||||
// GObject related signal handers and callbacks
|
||||
static void _onFolderLoaded(FmFolder* folder, MainWindow* _this) {
|
||||
_this->onFolderLoaded(folder);
|
||||
}
|
||||
|
||||
private:
|
||||
Ui::MainWindow ui;
|
||||
QMenu* contextMenu_;
|
||||
QTimer* slideShowTimer_;
|
||||
|
||||
QImage image_; // the image currently shown
|
||||
FmPath* currentFile_; // path to current image file
|
||||
// FmFileInfo* currentFileInfo_; // info of the current file, can be NULL
|
||||
bool imageModified_; // the current image is modified by rotation, flip, or others and needs to be saved
|
||||
|
||||
// folder browsing
|
||||
FmFolder* folder_;
|
||||
FmPath* folderPath_;
|
||||
Fm::FolderModel* folderModel_;
|
||||
Fm::ProxyFolderModel* proxyModel_;
|
||||
ModelFilter* modelFilter_;
|
||||
QModelIndex currentIndex_;
|
||||
|
||||
QDockWidget* thumbnailsDock_;
|
||||
Fm::FolderView* thumbnailsView_;
|
||||
|
||||
// multi-threading loading of images
|
||||
LoadImageJob* loadJob_;
|
||||
SaveImageJob* saveJob_;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // LXIMAGE_MAINWINDOW_H
|
479
src/mainwindow.ui
Normal file
479
src/mainwindow.ui
Normal file
@ -0,0 +1,479 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>543</width>
|
||||
<height>425</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Image Viewer</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="lximage-qt">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="LxImage::ImageView" name="view">
|
||||
<property name="renderHints">
|
||||
<set>QPainter::Antialiasing|QPainter::HighQualityAntialiasing|QPainter::TextAntialiasing</set>
|
||||
</property>
|
||||
<property name="dragMode">
|
||||
<enum>QGraphicsView::ScrollHandDrag</enum>
|
||||
</property>
|
||||
<property name="transformationAnchor">
|
||||
<enum>QGraphicsView::AnchorUnderMouse</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>543</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
<property name="title">
|
||||
<string>&File</string>
|
||||
</property>
|
||||
<addaction name="actionNewWindow"/>
|
||||
<addaction name="actionOpenFile"/>
|
||||
<addaction name="actionOpenDirectory"/>
|
||||
<addaction name="actionScreenshot"/>
|
||||
<addaction name="actionSave"/>
|
||||
<addaction name="actionSaveAs"/>
|
||||
<addaction name="actionDelete"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFileProperties"/>
|
||||
<addaction name="actionPrint"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionClose"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
<string>&Help</string>
|
||||
</property>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuGo">
|
||||
<property name="title">
|
||||
<string>Go</string>
|
||||
</property>
|
||||
<addaction name="actionPrevious"/>
|
||||
<addaction name="actionNext"/>
|
||||
<addaction name="actionFirst"/>
|
||||
<addaction name="actionLast"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_View">
|
||||
<property name="title">
|
||||
<string>&View</string>
|
||||
</property>
|
||||
<addaction name="actionZoomIn"/>
|
||||
<addaction name="actionZoomOut"/>
|
||||
<addaction name="actionOriginalSize"/>
|
||||
<addaction name="actionZoomFit"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionShowThumbnails"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionFullScreen"/>
|
||||
<addaction name="actionSlideShow"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Edit">
|
||||
<property name="title">
|
||||
<string>&Edit</string>
|
||||
</property>
|
||||
<addaction name="actionRotateClockwise"/>
|
||||
<addaction name="actionRotateCounterclockwise"/>
|
||||
<addaction name="actionFlipHorizontal"/>
|
||||
<addaction name="actionFlipVertical"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPreferences"/>
|
||||
</widget>
|
||||
<addaction name="menu_File"/>
|
||||
<addaction name="menu_Edit"/>
|
||||
<addaction name="menu_View"/>
|
||||
<addaction name="menuGo"/>
|
||||
<addaction name="menu_Help"/>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>Toolbar</string>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonIconOnly</enum>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>TopToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionPrevious"/>
|
||||
<addaction name="actionNext"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionOpenFile"/>
|
||||
<addaction name="actionSaveAs"/>
|
||||
<addaction name="actionCopy"/>
|
||||
<addaction name="actionPaste"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionRotateClockwise"/>
|
||||
<addaction name="actionRotateCounterclockwise"/>
|
||||
<addaction name="actionZoomIn"/>
|
||||
<addaction name="actionZoomOut"/>
|
||||
<addaction name="actionZoomFit"/>
|
||||
<addaction name="actionOriginalSize"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionSlideShow"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusBar"/>
|
||||
<action name="actionAbout">
|
||||
<property name="icon">
|
||||
<iconset theme="help-about">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&About</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenFile">
|
||||
<property name="icon">
|
||||
<iconset theme="document-open">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Open File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="icon">
|
||||
<iconset theme="document-save">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Save</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveAs">
|
||||
<property name="icon">
|
||||
<iconset theme="document-save-as">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save &As</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+A</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClose">
|
||||
<property name="icon">
|
||||
<iconset theme="application-exit">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Close</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+W</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoomIn">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-in">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom &In</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+=</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoomOut">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-out">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Zoom &Out</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+-</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCopy">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-copy">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Copy to Clipboard</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNext">
|
||||
<property name="icon">
|
||||
<iconset theme="go-next">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Next File</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Next File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>PgDown</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrevious">
|
||||
<property name="icon">
|
||||
<iconset theme="go-previous">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Previous File</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Previous File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>PgUp</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOriginalSize">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-original">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Original Size</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+0</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionZoomFit">
|
||||
<property name="icon">
|
||||
<iconset theme="zoom-fit-best">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Fit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRotateClockwise">
|
||||
<property name="icon">
|
||||
<iconset theme="object-rotate-right">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Rotate Clockwise</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRotateCounterclockwise">
|
||||
<property name="icon">
|
||||
<iconset theme="object-rotate-left">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Rotate &Counterclockwise</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPreferences">
|
||||
<property name="text">
|
||||
<string>P&references</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrint">
|
||||
<property name="text">
|
||||
<string>&Print</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+P</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFirst">
|
||||
<property name="icon">
|
||||
<iconset theme="go-first">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>First File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Home</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionLast">
|
||||
<property name="icon">
|
||||
<iconset theme="go-last">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Last File</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>End</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNewWindow">
|
||||
<property name="icon">
|
||||
<iconset theme="document-new">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&New Window</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+N</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFlipHorizontal">
|
||||
<property name="text">
|
||||
<string>Flip &Horizontally</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionScreenshot">
|
||||
<property name="icon">
|
||||
<iconset theme="camera-photo">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Capture Screenshot</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFullScreen">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>F&ull Screen</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F11</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFlipVertical">
|
||||
<property name="text">
|
||||
<string>Flip &Vertically</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPaste">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-paste">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Paste from Clipboard</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSlideShow">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="media-playback-start">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Slide Show</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionDelete">
|
||||
<property name="icon">
|
||||
<iconset theme="edit-delete">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>&Delete</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Del</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionShowThumbnails">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Show Thumbnails</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionFileProperties">
|
||||
<property name="text">
|
||||
<string>File Properties</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpenDirectory">
|
||||
<property name="icon">
|
||||
<iconset theme="document-open"/>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Open &Directory</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+D</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>LxImage::ImageView</class>
|
||||
<extends>QGraphicsView</extends>
|
||||
<header>imageview.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
39
src/modelfilter.cpp
Normal file
39
src/modelfilter.cpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "modelfilter.h"
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
ModelFilter::ModelFilter() {
|
||||
|
||||
}
|
||||
|
||||
ModelFilter::~ModelFilter() {
|
||||
|
||||
}
|
||||
|
||||
bool ModelFilter::filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const {
|
||||
// filter out non-image files and formats that we don't support.
|
||||
if(!fm_file_info_is_image(info))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
37
src/modelfilter.h
Normal file
37
src/modelfilter.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_MODELFILTER_H
|
||||
#define LXIMAGE_MODELFILTER_H
|
||||
|
||||
#include <libfm-qt/proxyfoldermodel.h>
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class ModelFilter: public Fm::ProxyFolderModelFilter {
|
||||
public:
|
||||
ModelFilter();
|
||||
virtual bool filterAcceptsRow(const Fm::ProxyFolderModel* model, FmFileInfo* info) const;
|
||||
virtual ~ModelFilter();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_MODELFILTER_H
|
15
src/org.lxde.LxImage.Application.xml
Normal file
15
src/org.lxde.LxImage.Application.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
||||
<node>
|
||||
<interface name="org.lxde.LxImage.Application">
|
||||
|
||||
<!-- ask lximage to open a new window -->
|
||||
<method name="newWindow">
|
||||
<!-- file paths to open in new windows -->
|
||||
<arg type="as" direction="in"/>
|
||||
</method>
|
||||
|
||||
<!-- launch a tool to take a screenshot -->
|
||||
<method name="screenshot" />
|
||||
|
||||
</interface>
|
||||
</node>
|
142
src/preferencesdialog.cpp
Normal file
142
src/preferencesdialog.cpp
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "preferencesdialog.h"
|
||||
#include "application.h"
|
||||
#include <QDir>
|
||||
#include <QStringBuilder>
|
||||
#include <glib.h>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
PreferencesDialog::PreferencesDialog(QWidget* parent):
|
||||
QDialog(parent) {
|
||||
ui.setupUi(this);
|
||||
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
Settings& settings = app->settings();
|
||||
app->addWindow();
|
||||
|
||||
initIconThemes(settings);
|
||||
ui.bgColor->setColor(settings.bgColor());
|
||||
ui.fullScreenBgColor->setColor(settings.fullScreenBgColor());
|
||||
ui.slideShowInterval->setValue(settings.slideShowInterval());
|
||||
}
|
||||
|
||||
PreferencesDialog::~PreferencesDialog() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
app->removeWindow();
|
||||
}
|
||||
|
||||
void PreferencesDialog::accept() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
Settings& settings = app->settings();
|
||||
|
||||
// apply icon theme
|
||||
if(settings.useFallbackIconTheme()) {
|
||||
// only apply the value if icon theme combo box is in use
|
||||
// the combo box is hidden when auto-detection of icon theme by qt works.
|
||||
QString newIconTheme = ui.iconTheme->itemData(ui.iconTheme->currentIndex()).toString();
|
||||
if(newIconTheme != settings.fallbackIconTheme()) {
|
||||
settings.setFallbackIconTheme(newIconTheme);
|
||||
QIcon::setThemeName(newIconTheme);
|
||||
// update the UI by emitting a style change event
|
||||
Q_FOREACH(QWidget *widget, QApplication::allWidgets()) {
|
||||
QEvent event(QEvent::StyleChange);
|
||||
QApplication::sendEvent(widget, &event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
settings.setBgColor(ui.bgColor->color());
|
||||
settings.setFullScreenBgColor(ui.fullScreenBgColor->color());
|
||||
settings.setSlideShowInterval(ui.slideShowInterval->value());
|
||||
|
||||
settings.save();
|
||||
QDialog::accept();
|
||||
app->applySettings();
|
||||
}
|
||||
|
||||
static void findIconThemesInDir(QHash<QString, QString>& iconThemes, QString dirName) {
|
||||
QDir dir(dirName);
|
||||
QStringList subDirs = dir.entryList(QDir::AllDirs);
|
||||
GKeyFile* kf = g_key_file_new();
|
||||
Q_FOREACH(QString subDir, subDirs) {
|
||||
QString indexFile = dirName % '/' % subDir % "/index.theme";
|
||||
if(g_key_file_load_from_file(kf, indexFile.toLocal8Bit().constData(), GKeyFileFlags(0), NULL)) {
|
||||
// FIXME: skip hidden ones
|
||||
// icon theme must have this key, so it has icons if it has this key
|
||||
// otherwise, it might be a cursor theme or any other kind of theme.
|
||||
if(g_key_file_has_key(kf, "Icon Theme", "Directories", NULL)) {
|
||||
char* dispName = g_key_file_get_locale_string(kf, "Icon Theme", "Name", NULL, NULL);
|
||||
// char* comment = g_key_file_get_locale_string(kf, "Icon Theme", "Comment", NULL, NULL);
|
||||
iconThemes[subDir] = dispName;
|
||||
g_free(dispName);
|
||||
}
|
||||
}
|
||||
}
|
||||
g_key_file_free(kf);
|
||||
}
|
||||
|
||||
void PreferencesDialog::initIconThemes(Settings& settings) {
|
||||
// check if auto-detection is done (for example, from xsettings)
|
||||
if(settings.useFallbackIconTheme()) { // auto-detection failed
|
||||
// load xdg icon themes and select the current one
|
||||
QHash<QString, QString> iconThemes;
|
||||
// user customed icon themes
|
||||
findIconThemesInDir(iconThemes, QString(g_get_home_dir()) % "/.icons");
|
||||
|
||||
// search for icons in system data dir
|
||||
const char* const* dataDirs = g_get_system_data_dirs();
|
||||
for(const char* const* dataDir = dataDirs; *dataDir; ++dataDir) {
|
||||
findIconThemesInDir(iconThemes, QString(*dataDir) % "/icons");
|
||||
}
|
||||
|
||||
iconThemes.remove("hicolor"); // remove hicolor, which is only a fallback
|
||||
QHash<QString, QString>::const_iterator it;
|
||||
for(it = iconThemes.begin(); it != iconThemes.end(); ++it) {
|
||||
ui.iconTheme->addItem(it.value(), it.key());
|
||||
}
|
||||
ui.iconTheme->model()->sort(0); // sort the list of icon theme names
|
||||
|
||||
// select current theme name
|
||||
int n = ui.iconTheme->count();
|
||||
int i;
|
||||
for(i = 0; i < n; ++i) {
|
||||
QVariant itemData = ui.iconTheme->itemData(i);
|
||||
if(itemData == settings.fallbackIconTheme()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i >= n)
|
||||
i = 0;
|
||||
ui.iconTheme->setCurrentIndex(i);
|
||||
}
|
||||
else { // auto-detection of icon theme works, hide the fallback icon theme combo box.
|
||||
ui.iconThemeLabel->hide();
|
||||
ui.iconTheme->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void PreferencesDialog::done(int r) {
|
||||
QDialog::done(r);
|
||||
deleteLater();
|
||||
}
|
||||
|
49
src/preferencesdialog.h
Normal file
49
src/preferencesdialog.h
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_PREFERENCESDIALOG_H
|
||||
#define LXIMAGE_PREFERENCESDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "ui_preferencesdialog.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class Settings;
|
||||
|
||||
class PreferencesDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PreferencesDialog(QWidget* parent = 0);
|
||||
virtual ~PreferencesDialog();
|
||||
|
||||
virtual void accept();
|
||||
virtual void done(int r);
|
||||
|
||||
private:
|
||||
void initIconThemes(Settings& settings);
|
||||
|
||||
private:
|
||||
Ui::PreferencesDialog ui;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_PREFERENCESDIALOG_H
|
140
src/preferencesdialog.ui
Normal file
140
src/preferencesdialog.ui
Normal file
@ -0,0 +1,140 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PreferencesDialog</class>
|
||||
<widget class="QDialog" name="PreferencesDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>331</width>
|
||||
<height>225</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Preferences</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab">
|
||||
<attribute name="title">
|
||||
<string>General</string>
|
||||
</attribute>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="iconThemeLabel">
|
||||
<property name="text">
|
||||
<string>Icon theme:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="iconTheme"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Normal background color:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Fullscreen background color:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Fm::ColorButton" name="bgColor">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Fm::ColorButton" name="fullScreenBgColor">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Slide show interval (seconds):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="slideShowInterval">
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Fm::ColorButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header location="global">libfm-qt/colorbutton.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>PreferencesDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>PreferencesDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
72
src/saveimagejob.cpp
Normal file
72
src/saveimagejob.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "saveimagejob.h"
|
||||
#include "mainwindow.h"
|
||||
#include <QImageReader>
|
||||
#include <QBuffer>
|
||||
#include <qvarlengtharray.h>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
SaveImageJob::SaveImageJob(MainWindow* window, FmPath* filePath):
|
||||
Job(),
|
||||
mainWindow_(window),
|
||||
path_(fm_path_ref(filePath)),
|
||||
image_(window->image()) {
|
||||
}
|
||||
|
||||
SaveImageJob::~SaveImageJob() {
|
||||
fm_path_unref(path_);
|
||||
}
|
||||
|
||||
// This is called from the worker thread, not main thread
|
||||
bool SaveImageJob::run() {
|
||||
GFile* gfile = fm_path_to_gfile(path_);
|
||||
GFileOutputStream* fileStream = g_file_replace(gfile, NULL, false, G_FILE_CREATE_NONE, cancellable_, &error_);
|
||||
g_object_unref(gfile);
|
||||
|
||||
if(fileStream) { // if the file stream is successfually opened
|
||||
const char* format = fm_path_get_basename(path_);
|
||||
format = strrchr(format, '.');
|
||||
if(format) // use filename extension as the image format
|
||||
++format;
|
||||
|
||||
QBuffer imageBuffer;
|
||||
image_.save(&imageBuffer, format); // save the image to buffer
|
||||
GOutputStream* outputStream = G_OUTPUT_STREAM(fileStream);
|
||||
g_output_stream_write_all(outputStream,
|
||||
imageBuffer.data().constData(),
|
||||
imageBuffer.size(),
|
||||
NULL,
|
||||
cancellable_,
|
||||
&error_);
|
||||
g_output_stream_close(outputStream, NULL, NULL);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// this function is called from main thread only
|
||||
void SaveImageJob::finish() {
|
||||
// only do processing if the job is not cancelled
|
||||
if(!g_cancellable_is_cancelled(cancellable_)) {
|
||||
mainWindow_->onImageSaved(this);
|
||||
}
|
||||
}
|
61
src/saveimagejob.h
Normal file
61
src/saveimagejob.h
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_SAVEIMAGEJOB_H
|
||||
#define LXIMAGE_SAVEIMAGEJOB_H
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <libfm/fm.h>
|
||||
#include <QImage>
|
||||
#include "job.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class MainWindow;
|
||||
|
||||
class SaveImageJob : public Job {
|
||||
|
||||
public:
|
||||
SaveImageJob(MainWindow* window, FmPath* filePath);
|
||||
|
||||
QImage image() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
FmPath* filePath() const {
|
||||
return path_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool run();
|
||||
virtual void finish();
|
||||
|
||||
private:
|
||||
~SaveImageJob(); // prevent direct deletion
|
||||
|
||||
public:
|
||||
MainWindow* mainWindow_;
|
||||
FmPath* path_;
|
||||
QImage image_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_SAVEIMAGEJOB_H
|
183
src/screenshotdialog.cpp
Normal file
183
src/screenshotdialog.cpp
Normal file
@ -0,0 +1,183 @@
|
||||
/*
|
||||
<one line to give the library's name and an idea of what it does.>
|
||||
Copyright (C) 2013 <copyright holder> <email>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#include "screenshotdialog.h"
|
||||
#include <QTimer>
|
||||
#include <QPixmap>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include "application.h"
|
||||
#include <QDesktopWidget>
|
||||
#include <QScreen>
|
||||
|
||||
#include <QX11Info>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <X11/extensions/Xfixes.h>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
ScreenshotDialog::ScreenshotDialog(QWidget* parent, Qt::WindowFlags f): QDialog(parent, f) {
|
||||
ui.setupUi(this);
|
||||
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
app->addWindow();
|
||||
|
||||
int event_base, error_base;
|
||||
hasXfixes_ = XFixesQueryExtension(QX11Info::display(), &event_base, &error_base) ? true : false;
|
||||
if(!hasXfixes_)
|
||||
ui.includeCursor->hide();
|
||||
}
|
||||
|
||||
ScreenshotDialog::~ScreenshotDialog() {
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
app->removeWindow();
|
||||
}
|
||||
|
||||
void ScreenshotDialog::done(int r) {
|
||||
if(r == QDialog::Accepted) {
|
||||
hide();
|
||||
QDialog::done(r);
|
||||
XSync(QX11Info::display(), 0); // is this useful?
|
||||
|
||||
int delay = ui.delay->value();
|
||||
if(delay == 0) {
|
||||
// NOTE:
|
||||
// Well, we need to give X and the window manager some time to
|
||||
// really hide our own dialog from the screen.
|
||||
// Nobody knows how long it will take, and there is no reliable
|
||||
// way to ensure that. Let's wait for 400 ms here for it.
|
||||
delay = 400;
|
||||
}
|
||||
else
|
||||
delay *= 1000;
|
||||
// the dialog object will be deleted in doScreenshot().
|
||||
QTimer::singleShot(delay, this, SLOT(doScreenshot()));
|
||||
}
|
||||
else {
|
||||
deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
QRect ScreenshotDialog::windowFrame(WId wid) {
|
||||
QRect result;
|
||||
XWindowAttributes wa;
|
||||
if(XGetWindowAttributes(QX11Info::display(), wid, &wa)) {
|
||||
Window child;
|
||||
int x, y;
|
||||
// translate to root coordinate
|
||||
XTranslateCoordinates(QX11Info::display(), wid, wa.root, 0, 0, &x, &y, &child);
|
||||
//qDebug("%d, %d, %d, %d", x, y, wa.width, wa.height);
|
||||
result.setRect(x, y, wa.width, wa.height);
|
||||
|
||||
// get the frame widths added by the window manager
|
||||
Atom atom = XInternAtom(QX11Info::display(), "_NET_FRAME_EXTENTS", false);
|
||||
unsigned long type, resultLen, rest;
|
||||
int format;
|
||||
unsigned char* data = NULL;
|
||||
if(XGetWindowProperty(QX11Info::display(), wid, atom, 0, G_MAXLONG, false,
|
||||
XA_CARDINAL, &type, &format, &resultLen, &rest, &data) == Success) {
|
||||
}
|
||||
if(data) { // left, right, top, bottom
|
||||
long* offsets = reinterpret_cast<long*>(data);
|
||||
result.setLeft(result.left() - offsets[0]);
|
||||
result.setRight(result.right() + offsets[1]);
|
||||
result.setTop(result.top() - offsets[2]);
|
||||
result.setBottom(result.bottom() + offsets[3]);
|
||||
XFree(data);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
WId ScreenshotDialog::activeWindowId() {
|
||||
WId root = WId(QX11Info::appRootWindow());
|
||||
Atom atom = XInternAtom(QX11Info::display(), "_NET_ACTIVE_WINDOW", false);
|
||||
unsigned long type, resultLen, rest;
|
||||
int format;
|
||||
WId result = 0;
|
||||
unsigned char* data = NULL;
|
||||
if(XGetWindowProperty(QX11Info::display(), root, atom, 0, 1, false,
|
||||
XA_WINDOW, &type, &format, &resultLen, &rest, &data) == Success) {
|
||||
result = *reinterpret_cast<long*>(data);
|
||||
XFree(data);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void ScreenshotDialog::doScreenshot() {
|
||||
WId wid = 0;
|
||||
int x = 0, y = 0, width = -1, height = -1;
|
||||
wid = QApplication::desktop()->winId(); // get desktop window
|
||||
if(ui.currentWindow->isChecked()) {
|
||||
WId activeWid = activeWindowId();
|
||||
if(activeWid) {
|
||||
if(ui.includeFrame->isChecked()) {
|
||||
QRect rect = windowFrame(activeWid);
|
||||
x = rect.x();
|
||||
y = rect.y();
|
||||
width = rect.width();
|
||||
height = rect.height();
|
||||
}
|
||||
else
|
||||
wid = activeWid;
|
||||
}
|
||||
}
|
||||
|
||||
QImage image;
|
||||
QScreen *screen = QGuiApplication::primaryScreen();
|
||||
if(screen) {
|
||||
QPixmap pixmap = screen->grabWindow(wid, x, y, width, height);
|
||||
image = pixmap.toImage();
|
||||
|
||||
if(hasXfixes_ && ui.includeCursor->isChecked()) {
|
||||
// capture the cursor if needed
|
||||
XFixesCursorImage* cursor = XFixesGetCursorImage(QX11Info::display());
|
||||
if(cursor) {
|
||||
if(cursor->pixels) { // pixles should be an ARGB array
|
||||
QImage cursorImage;
|
||||
if(sizeof(long) == 4) {
|
||||
// FIXME: will we encounter byte-order problems here?
|
||||
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);
|
||||
}
|
||||
XFree(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Application* app = static_cast<Application*>(qApp);
|
||||
MainWindow* window = app->createWindow();
|
||||
if(!image.isNull())
|
||||
window->pasteImage(image);
|
||||
window->show();
|
||||
|
||||
deleteLater(); // destroy ourself
|
||||
}
|
51
src/screenshotdialog.h
Normal file
51
src/screenshotdialog.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
<one line to give the library's name and an idea of what it does.>
|
||||
Copyright (C) 2013 <copyright holder> <email>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
|
||||
#ifndef LXIMAGE_SCREENSHOTDIALOG_H
|
||||
#define LXIMAGE_SCREENSHOTDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "ui_screenshotdialog.h"
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class ScreenshotDialog : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ScreenshotDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||
virtual ~ScreenshotDialog();
|
||||
|
||||
virtual void done(int r);
|
||||
|
||||
private:
|
||||
WId activeWindowId();
|
||||
QRect windowFrame(WId wid);
|
||||
|
||||
private Q_SLOTS:
|
||||
void doScreenshot();
|
||||
|
||||
private:
|
||||
Ui::ScreenshotDialog ui;
|
||||
bool hasXfixes_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_SCREENSHOTDIALOG_H
|
155
src/screenshotdialog.ui
Normal file
155
src/screenshotdialog.ui
Normal file
@ -0,0 +1,155 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ScreenshotDialog</class>
|
||||
<widget class="QDialog" name="ScreenshotDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>348</width>
|
||||
<height>261</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Screenshot</string>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset theme="camera-photo">
|
||||
<normaloff/>
|
||||
</iconset>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Take a screenshot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Region</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="wholeScreen">
|
||||
<property name="text">
|
||||
<string>Whole screen</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="currentWindow">
|
||||
<property name="text">
|
||||
<string>Current window only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="includeCursor">
|
||||
<property name="text">
|
||||
<string>Include mouse cursor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="delay">
|
||||
<property name="suffix">
|
||||
<string> seconds</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Delay:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="includeFrame">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Include window title and frame</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>ScreenshotDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>257</x>
|
||||
<y>231</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>ScreenshotDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>291</x>
|
||||
<y>231</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
<connection>
|
||||
<sender>currentWindow</sender>
|
||||
<signal>toggled(bool)</signal>
|
||||
<receiver>includeFrame</receiver>
|
||||
<slot>setEnabled(bool)</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>87</x>
|
||||
<y>82</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>91</x>
|
||||
<y>122</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
86
src/settings.cpp
Normal file
86
src/settings.cpp
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 "settings.h"
|
||||
#include <QSettings>
|
||||
#include <QIcon>
|
||||
|
||||
using namespace LxImage;
|
||||
|
||||
Settings::Settings():
|
||||
useFallbackIconTheme_(QIcon::themeName().isEmpty() || QIcon::themeName() == "hicolor"),
|
||||
bgColor_(255, 255, 255),
|
||||
fullScreenBgColor_(0, 0, 0),
|
||||
showThumbnails_(false),
|
||||
showSidePane_(false),
|
||||
slideShowInterval_(5),
|
||||
fallbackIconTheme_("oxygen"),
|
||||
fixedWindowWidth_(640),
|
||||
fixedWindowHeight_(480),
|
||||
lastWindowWidth_(640),
|
||||
lastWindowHeight_(480),
|
||||
lastWindowMaximized_(false) {
|
||||
}
|
||||
|
||||
Settings::~Settings() {
|
||||
}
|
||||
|
||||
bool Settings::load() {
|
||||
QSettings settings("lximage-qt", "settings");
|
||||
fallbackIconTheme_ = settings.value("fallbackIconTheme", fallbackIconTheme_).toString();
|
||||
bgColor_ = settings.value("bgColor", bgColor_).value<QColor>();
|
||||
fullScreenBgColor_ = settings.value("fullScreenBgColor", fullScreenBgColor_).value<QColor>();
|
||||
// showThumbnails_;
|
||||
// showSidePane_;
|
||||
slideShowInterval_ = settings.value("slideShowInterval", slideShowInterval_).toInt();
|
||||
|
||||
settings.beginGroup("Window");
|
||||
fixedWindowWidth_ = settings.value("FixedWidth", 640).toInt();
|
||||
fixedWindowHeight_ = settings.value("FixedHeight", 480).toInt();
|
||||
lastWindowWidth_ = settings.value("LastWindowWidth", 640).toInt();
|
||||
lastWindowHeight_ = settings.value("LastWindowHeight", 480).toInt();
|
||||
lastWindowMaximized_ = settings.value("LastWindowMaximized", false).toBool();
|
||||
rememberWindowSize_ = settings.value("RememberWindowSize", true).toBool();
|
||||
settings.endGroup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Settings::save() {
|
||||
QSettings settings("lximage-qt", "settings");
|
||||
|
||||
settings.setValue("fallbackIconTheme", fallbackIconTheme_);
|
||||
settings.setValue("bgColor", bgColor_);
|
||||
settings.setValue("fullScreenBgColor", fullScreenBgColor_);
|
||||
settings.setValue("slideShowInterval", slideShowInterval_);
|
||||
|
||||
settings.beginGroup("Window");
|
||||
settings.setValue("FixedWidth", fixedWindowWidth_);
|
||||
settings.setValue("FixedHeight", fixedWindowHeight_);
|
||||
settings.setValue("LastWindowWidth", lastWindowWidth_);
|
||||
settings.setValue("LastWindowHeight", lastWindowHeight_);
|
||||
settings.setValue("LastWindowMaximized", lastWindowMaximized_);
|
||||
settings.setValue("RememberWindowSize", rememberWindowSize_);
|
||||
settings.endGroup();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
158
src/settings.h
Normal file
158
src/settings.h
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 2013 PCMan <email>
|
||||
|
||||
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 LXIMAGE_SETTINGS_H
|
||||
#define LXIMAGE_SETTINGS_H
|
||||
|
||||
#include <QString>
|
||||
#include <qcache.h>
|
||||
#include <QColor>
|
||||
|
||||
namespace LxImage {
|
||||
|
||||
class Settings {
|
||||
public:
|
||||
|
||||
Settings();
|
||||
~Settings();
|
||||
|
||||
bool load();
|
||||
bool save();
|
||||
|
||||
bool useFallbackIconTheme() const {
|
||||
return useFallbackIconTheme_;
|
||||
};
|
||||
|
||||
QString fallbackIconTheme() {
|
||||
return fallbackIconTheme_;
|
||||
}
|
||||
void setFallbackIconTheme(QString value) {
|
||||
fallbackIconTheme_ = value;
|
||||
}
|
||||
|
||||
QColor bgColor() {
|
||||
return bgColor_;
|
||||
}
|
||||
void setBgColor(QColor color) {
|
||||
bgColor_ = color;
|
||||
}
|
||||
|
||||
QColor fullScreenBgColor() {
|
||||
return fullScreenBgColor_;
|
||||
}
|
||||
void setFullScreenBgColor(QColor color) {
|
||||
fullScreenBgColor_ = color;
|
||||
}
|
||||
|
||||
bool showThumbnails() {
|
||||
return showThumbnails_;
|
||||
}
|
||||
void setShowThumbnails(bool show) {
|
||||
showThumbnails_ = show;
|
||||
}
|
||||
|
||||
bool showSidePane() {
|
||||
return showSidePane_;
|
||||
}
|
||||
|
||||
int slideShowInterval() {
|
||||
return slideShowInterval_;
|
||||
}
|
||||
void setSlideShowInterval(int interval) {
|
||||
slideShowInterval_ = interval;
|
||||
}
|
||||
|
||||
bool rememberWindowSize() const {
|
||||
return rememberWindowSize_;
|
||||
}
|
||||
|
||||
void setRememberWindowSize(bool rememberWindowSize) {
|
||||
rememberWindowSize_ = rememberWindowSize;
|
||||
}
|
||||
|
||||
int windowWidth() const {
|
||||
if(rememberWindowSize_)
|
||||
return lastWindowWidth_;
|
||||
else
|
||||
return fixedWindowWidth_;
|
||||
}
|
||||
|
||||
int windowHeight() const {
|
||||
if(rememberWindowSize_)
|
||||
return lastWindowHeight_;
|
||||
else
|
||||
return fixedWindowHeight_;
|
||||
}
|
||||
|
||||
bool windowMaximized() const {
|
||||
if(rememberWindowSize_)
|
||||
return lastWindowMaximized_;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
int fixedWindowWidth() const {
|
||||
return fixedWindowWidth_;
|
||||
}
|
||||
|
||||
void setFixedWindowWidth(int fixedWindowWidth) {
|
||||
fixedWindowWidth_ = fixedWindowWidth;
|
||||
}
|
||||
|
||||
int fixedWindowHeight() const {
|
||||
return fixedWindowHeight_;
|
||||
}
|
||||
|
||||
void setFixedWindowHeight(int fixedWindowHeight) {
|
||||
fixedWindowHeight_ = fixedWindowHeight;
|
||||
}
|
||||
|
||||
void setLastWindowWidth(int lastWindowWidth) {
|
||||
lastWindowWidth_ = lastWindowWidth;
|
||||
}
|
||||
|
||||
void setLastWindowHeight(int lastWindowHeight) {
|
||||
lastWindowHeight_ = lastWindowHeight;
|
||||
}
|
||||
|
||||
void setLastWindowMaximized(bool lastWindowMaximized) {
|
||||
lastWindowMaximized_ = lastWindowMaximized;
|
||||
}
|
||||
|
||||
private:
|
||||
bool useFallbackIconTheme_;
|
||||
QColor bgColor_;
|
||||
QColor fullScreenBgColor_;
|
||||
bool showThumbnails_;
|
||||
bool showSidePane_;
|
||||
int slideShowInterval_;
|
||||
QString fallbackIconTheme_;
|
||||
|
||||
bool rememberWindowSize_;
|
||||
int fixedWindowWidth_;
|
||||
int fixedWindowHeight_;
|
||||
int lastWindowWidth_;
|
||||
int lastWindowHeight_;
|
||||
bool lastWindowMaximized_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // LXIMAGE_SETTINGS_H
|
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
|
3
src/translations/lximage-qt-screenshot_da.desktop
Normal file
3
src/translations/lximage-qt-screenshot_da.desktop
Normal file
@ -0,0 +1,3 @@
|
||||
Name[da]=Skærmbillede
|
||||
GenericName[da]=Skærmbillede
|
||||
Comment[da]=Tag et skærmbillede
|
6
src/translations/lximage-qt-screenshot_de.desktop
Normal file
6
src/translations/lximage-qt-screenshot_de.desktop
Normal file
@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name[de]=Bildschirmfoto
|
||||
GenericName[de]=Bildschirmfoto
|
||||
Comment[de]=Erstelle ein Bildschirmfoto
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
4
src/translations/lximage-qt-screenshot_el.desktop
Normal file
4
src/translations/lximage-qt-screenshot_el.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[el]=Στιγμιότυπο οθόνης
|
||||
GenericName[el]=Στιγμιότυπο οθόνης
|
||||
Comment[el]=Λήψη ενός στιγμιότυπου της οθόνης
|
4
src/translations/lximage-qt-screenshot_fr.desktop
Normal file
4
src/translations/lximage-qt-screenshot_fr.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[fr]=Copie d'écran
|
||||
GenericName[fr]=Copie d'écran
|
||||
Comment[fr]=Faire une copie d'écran
|
6
src/translations/lximage-qt-screenshot_hu.desktop
Normal file
6
src/translations/lximage-qt-screenshot_hu.desktop
Normal file
@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name[hu]=LXQt képernyőfotó
|
||||
GenericName[hu]=Képrnyőfénykép
|
||||
Comment[hu]=Képernyőkép készítés
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
4
src/translations/lximage-qt-screenshot_it.desktop
Normal file
4
src/translations/lximage-qt-screenshot_it.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[it]=Cattura schermata
|
||||
GenericName[it]=Cattura una schermata
|
||||
Comment[it]=Catturare una schermata
|
6
src/translations/lximage-qt-screenshot_pl.desktop
Normal file
6
src/translations/lximage-qt-screenshot_pl.desktop
Normal file
@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name[pl]=Zrzut ekranu
|
||||
GenericName[pl]=Zrzut ekranu
|
||||
Comment[pl]=Wykonaj zrzut ekranu
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
4
src/translations/lximage-qt-screenshot_pt.desktop
Normal file
4
src/translations/lximage-qt-screenshot_pt.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[pt]=Captura de ecrã
|
||||
GenericName[pt]=Captura de ecrã
|
||||
Comment[pt]=Obter uma captura de ecrã
|
4
src/translations/lximage-qt-screenshot_ru.desktop
Normal file
4
src/translations/lximage-qt-screenshot_ru.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[ru]=Снимок экрана
|
||||
GenericName[ru]=Снимок экрана
|
||||
Comment[ru]=Сделать снимок экрана
|
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
|
3
src/translations/lximage-qt_da.desktop
Normal file
3
src/translations/lximage-qt_da.desktop
Normal file
@ -0,0 +1,3 @@
|
||||
Name[da]=LXImage
|
||||
GenericName[da]=Billedfremviser
|
||||
Comment[da]=LXQt-billedfremviseren
|
5
src/translations/lximage-qt_de.desktop
Normal file
5
src/translations/lximage-qt_de.desktop
Normal file
@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
GenericName[de]=Bildbetrachter
|
||||
Comment[de]=Der LXQt-Bildbetrachter
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
4
src/translations/lximage-qt_el.desktop
Normal file
4
src/translations/lximage-qt_el.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[el]=LXImage
|
||||
GenericName[el]=Προβολέας εικόνων
|
||||
Comment[el]=Ο προβολέας εικόνων του LXQt
|
4
src/translations/lximage-qt_fr.desktop
Normal file
4
src/translations/lximage-qt_fr.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translation
|
||||
Name[fr]=LXImage
|
||||
GenericName[fr]=Visionneuse d'images
|
||||
Comment[fr]=Visionneuse d'images de LXQt
|
6
src/translations/lximage-qt_hu.desktop
Normal file
6
src/translations/lximage-qt_hu.desktop
Normal file
@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name[hu]=LXQt képnéző
|
||||
GenericName[hu]=Képmegjelenítő
|
||||
Comment[hu]=Az LXQt képnézegetője
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
3
src/translations/lximage-qt_it.desktop
Normal file
3
src/translations/lximage-qt_it.desktop
Normal file
@ -0,0 +1,3 @@
|
||||
#Translations
|
||||
Name[it]=Visualizzatore immagini
|
||||
Comment[it]=Il visualizzatore immagini di LXQt
|
5
src/translations/lximage-qt_pl.desktop
Normal file
5
src/translations/lximage-qt_pl.desktop
Normal file
@ -0,0 +1,5 @@
|
||||
[Desktop Entry]
|
||||
GenericName[pl]=Przeglądarka obrazów
|
||||
Comment[pl]=Przeglądarka obrazów LXQt
|
||||
|
||||
#TRANSLATIONS_DIR=translations
|
4
src/translations/lximage-qt_pt.desktop
Normal file
4
src/translations/lximage-qt_pt.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[pt]=LXImage-Qt
|
||||
GenericName[pt]=Visualizador de imagens
|
||||
Comment[pt]=O visualizador de imagens do LXQt
|
4
src/translations/lximage-qt_ru.desktop
Normal file
4
src/translations/lximage-qt_ru.desktop
Normal file
@ -0,0 +1,4 @@
|
||||
#Translations
|
||||
Name[ru]=LXImage
|
||||
GenericName[ru]=Просмотрщик изображений
|
||||
Comment[ru]=Просмотрщик изображений LXQt
|
Loading…
x
Reference in New Issue
Block a user