Merge branch 'master-flameshotorg' into master_nc_merge_upstream
# Conflicts: # .travis.yml # appveyor.yml # data/graphics.qrc # data/img/app/keyboard.svg # data/img/material/black/delete.png # data/img/material/black/delete.svg # data/img/material/black/filepath.svg # data/img/material/black/shortcut.svg # data/img/material/white/filepath.svg # data/img/material/white/shortcut.svg # data/translations/Internationalization_hu.ts # data/translations/Internationalization_ka.ts # external/Qt-Color-Widgets/src/color_wheel.cpp # external/singleapplication/singleapplication.cpp # flameshot.pro # src/cli/commandlineparser.cpp # src/config/buttonlistview.cpp # src/config/configwindow.cpp # src/config/configwindow.h # src/config/geneneralconf.cpp # src/config/geneneralconf.h # src/config/uicoloreditor.cpp # src/config/uicoloreditor.h # src/core/controller.cpp # src/core/globalshortcutfilter.cpp # src/main.cpp # src/third-party/Qt-Color-Widgets/src/color_utils.cpp # src/tools/abstractactiontool.h # src/tools/abstractpathtool.h # src/tools/arrow/arrowtool.cpp # src/tools/arrow/arrowtool.h # src/tools/blur/blurtool.cpp # src/tools/capturetool.h # src/tools/circle/circletool.cpp # src/tools/circle/circletool.h # src/tools/copy/copytool.cpp # src/tools/copy/copytool.h # src/tools/exit/exittool.cpp # src/tools/exit/exittool.h # src/tools/imgur/imguruploader.cpp # src/tools/launcher/applaunchertool.cpp # src/tools/launcher/applaunchertool.h # src/tools/launcher/applauncherwidget.cpp # src/tools/launcher/openwithprogram.cpp # src/tools/line/linetool.cpp # src/tools/line/linetool.h # src/tools/marker/markertool.cpp # src/tools/marker/markertool.h # src/tools/move/movetool.cpp # src/tools/pencil/penciltool.cpp # src/tools/pencil/penciltool.h # src/tools/pin/pintool.cpp # src/tools/pin/pintool.h # src/tools/pin/pinwidget.cpp # src/tools/pixelate/pixelatetool.h # src/tools/rectangle/rectangletool.cpp # src/tools/rectangle/rectangletool.h # src/tools/redo/redotool.cpp # src/tools/redo/redotool.h # src/tools/save/savetool.cpp # src/tools/save/savetool.h # src/tools/selection/selectiontool.cpp # src/tools/selection/selectiontool.h # src/tools/sizeindicator/sizeindicatortool.cpp # src/tools/sizeindicator/sizeindicatortool.h # src/tools/storage/imgur/imguruploader.h # src/tools/storage/imgur/imguruploadertool.cpp # src/tools/storage/imgur/imguruploadertool.h # src/tools/text/textconfig.cpp # src/tools/text/texttool.cpp # src/tools/text/texttool.h # src/tools/toolfactory.cpp # src/tools/toolfactory.h # src/tools/undo/undotool.cpp # src/tools/undo/undotool.h # src/utils/confighandler.cpp # src/utils/confighandler.h # src/utils/dbusutils.cpp # src/utils/screenshotsaver.cpp # src/utils/screenshotsaver.h # src/widgets/capture/buttonhandler.cpp # src/widgets/capture/buttonhandler.h # src/widgets/capture/capturebutton.cpp # src/widgets/capture/capturebutton.h # src/widgets/capture/capturewidget.cpp # src/widgets/capture/capturewidget.h # src/widgets/capture/colorpicker.cpp # src/widgets/capturelauncher.cpp # src/widgets/infowindow.cpp # src/widgets/infowindow.h # src/widgets/panel/sidepanelwidget.cpp # src/widgets/panel/utilitypanel.cpp # src/widgets/panel/utilitypanel.h # translations/Internationalization_ca.ts # translations/Internationalization_de_DE.ts # translations/Internationalization_es.ts # translations/Internationalization_fr.ts # translations/Internationalization_ja.ts # translations/Internationalization_nl.ts # translations/Internationalization_pl.ts # translations/Internationalization_pt_br.ts # translations/Internationalization_ru.ts # translations/Internationalization_sk.ts # translations/Internationalization_sr.ts # translations/Internationalization_tr.ts # translations/Internationalization_uk.ts # translations/Internationalization_zh_CN.ts # translations/Internationalization_zh_TW.ts
This commit is contained in:
208
src/CMakeLists.txt
Normal file
208
src/CMakeLists.txt
Normal file
@@ -0,0 +1,208 @@
|
||||
find_package(
|
||||
Qt5
|
||||
CONFIG
|
||||
REQUIRED
|
||||
Core
|
||||
Gui
|
||||
Widgets
|
||||
Network
|
||||
Svg
|
||||
DBus
|
||||
LinguistTools)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
set(CMAKE_AUTORCC ON)
|
||||
set(CMAKE_AUTOUIC ON)
|
||||
|
||||
add_executable(flameshot)
|
||||
|
||||
add_executable(Flameshot::flameshot ALIAS flameshot)
|
||||
|
||||
if(WIN32)
|
||||
set_property(TARGET flameshot PROPERTY WIN32_EXECUTABLE true)
|
||||
endif()
|
||||
|
||||
add_subdirectory(cli)
|
||||
add_subdirectory(config)
|
||||
add_subdirectory(core)
|
||||
add_subdirectory(utils)
|
||||
add_subdirectory(widgets)
|
||||
add_subdirectory(tools)
|
||||
|
||||
set(FLAMESHOT_TS_FILES
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_ca.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_cs.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_de_DE.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_es.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_eu_ES.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_fr.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_hu.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_it_IT.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_ja.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_ka.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_ko.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_nl.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_nl_NL.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_pl.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_pt_BR.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_ru.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_sk.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_sr_SP.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_sv_SE.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_tr.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_uk.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_zh_CN.ts
|
||||
${CMAKE_SOURCE_DIR}/data/translations/Internationalization_zh_TW.ts)
|
||||
|
||||
if(GENERATE_TS)
|
||||
qt5_create_translation(QM_FILES ${CMAKE_SOURCE_DIR} ${FLAMESHOT_TS_FILES})
|
||||
else()
|
||||
qt5_add_translation(QM_FILES ${FLAMESHOT_TS_FILES})
|
||||
endif()
|
||||
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../external/singleapplication/singleapplication.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../external/Qt-Color-Widgets/src/color_utils.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../external/Qt-Color-Widgets/src/color_wheel.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../external/Qt-Color-Widgets/include/color_wheel.hpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../data/graphics.qrc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../data/icon.rc # windows binary icon resource file
|
||||
${QM_FILES}
|
||||
main.cpp)
|
||||
|
||||
target_include_directories(
|
||||
flameshot
|
||||
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../external/singleapplication/>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../external/Qt-Color-Widgets/include>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../dbus/>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/cli>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/config>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/core>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/arrow>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/pixelate>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/circle>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/circlecount>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/copy>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/exit>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/imgur>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/launcher>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/line>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/marker>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/move>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/pencil>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/pin>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/rectangle>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/redo>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/save>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/selection>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/sizeindicator>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/text>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/tools/undo>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/utils>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/widgets>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/widgets/panel>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/widgets/capture>
|
||||
$<INSTALL_INTERFACE:include/mylib>)
|
||||
|
||||
target_link_libraries(
|
||||
flameshot
|
||||
project_warnings
|
||||
project_options
|
||||
Qt5::Svg
|
||||
Qt5::DBus
|
||||
Qt5::Network
|
||||
Qt5::Widgets)
|
||||
|
||||
target_compile_definitions(flameshot PRIVATE APP_PREFIX="${CMAKE_INSTALL_PREFIX}")
|
||||
target_compile_definitions(flameshot PRIVATE APP_VERSION="v${PROJECT_VERSION}")
|
||||
target_compile_definitions(flameshot PRIVATE IMGUR_CLIENT_ID="313baf0c7b4d3ff")
|
||||
target_compile_definitions(flameshot PRIVATE QAPPLICATION_CLASS=QApplication)
|
||||
|
||||
foreach(FILE ${QM_FILES})
|
||||
get_filename_component(F_NAME ${FILE} NAME)
|
||||
add_custom_command(
|
||||
TARGET flameshot
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/${F_NAME}
|
||||
${CMAKE_CURRENT_BINARY_DIR}/translations/${F_NAME})
|
||||
endforeach()
|
||||
# ######################################################################################################################
|
||||
# Installation instructions
|
||||
|
||||
include(GNUInstallDirs)
|
||||
set(INSTALL_CONFIGDIR ${CMAKE_INSTALL_LIBDIR}/cmake/Flameshot)
|
||||
|
||||
# Install binary
|
||||
install(
|
||||
TARGETS flameshot
|
||||
EXPORT flameshot-targets
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
|
||||
# Install desktop files, completion and dbus files
|
||||
configure_file(${CMAKE_SOURCE_DIR}/docs/desktopEntry/package/flameshot.desktop
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/applications/flameshot.desktop COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/docs/appdata/flameshot.metainfo.xml
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/metainfo/flameshot.metainfo.xml COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/docs/shell-completion/flameshot
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/bash-completion/completions/flameshot COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/docs/shell-completion/flameshot
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/zsh/site-functions/_flameshot COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/data/dbus/org.flameshot.Flameshot.xml
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/dbus-1/interfaces/org.flameshot.Flameshot.xml COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/data/dbus/org.flameshot.Flameshot.service.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/dbus-1/services/org.flameshot.Flameshot.service)
|
||||
|
||||
# Install Icons
|
||||
configure_file(${CMAKE_SOURCE_DIR}/data/img/hicolor/48x48/apps/flameshot.png
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/icons/hicolor/48x48/apps/flameshot.png COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/data/img/hicolor/128x128/apps/flameshot.png
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/icons/hicolor/128x128/apps/flameshot.png COPYONLY)
|
||||
|
||||
configure_file(${CMAKE_SOURCE_DIR}/data/img/hicolor/scalable/apps/flameshot.svg
|
||||
${CMAKE_CURRENT_BINARY_DIR}/share/icons/hicolor/scalable/apps/flameshot.svg COPYONLY)
|
||||
|
||||
# Install assets
|
||||
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/share/ DESTINATION ${CMAKE_INSTALL_DATAROOTDIR})
|
||||
|
||||
# Install Translations
|
||||
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/flameshot/translations)
|
||||
|
||||
|
||||
# windeployqt
|
||||
if(WIN32)
|
||||
if(EXISTS $ENV{QTDIR}/bin/windeployqt.exe)
|
||||
if(CMAKE_BUILD_TYPE MATCHES Release)
|
||||
set(BINARIES_TYPE --release)
|
||||
else()
|
||||
set(BINARIES_TYPE --debug)
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
TARGET flameshot POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E remove_directory ${CMAKE_BINARY_DIR}/windeployqt_stuff
|
||||
COMMAND $ENV{QTDIR}/bin/windeployqt.exe ${BINARIES_TYPE} --no-translations --compiler-runtime --no-system-d3d-compiler --no-angle --no-webkit2 --no-quick-import --dir ${CMAKE_BINARY_DIR}/windeployqt_stuff $<TARGET_FILE:flameshot>
|
||||
# copy translations manually
|
||||
# QM_FILES
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/windeployqt_stuff/translations
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/src/translations ${CMAKE_BINARY_DIR}/windeployqt_stuff/translations
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${CMAKE_BINARY_DIR}/windeployqt_stuff/
|
||||
DESTINATION bin
|
||||
)
|
||||
|
||||
else()
|
||||
message("Unable to find executable QTDIR/bin/windeployqt.")
|
||||
endif()
|
||||
endif()
|
||||
1
src/cli/CMakeLists.txt
Normal file
1
src/cli/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
target_sources(flameshot PRIVATE commandlineparser.cpp commandoption.cpp commandargument.cpp)
|
||||
@@ -61,7 +61,7 @@ QString optionsToString(const QList<CommandOption>& options,
|
||||
// generate the text
|
||||
QString result;
|
||||
if (!dashedOptionList.isEmpty()) {
|
||||
result += QLatin1String("Options:\n");
|
||||
result += QObject::tr("Options") + ":\n";
|
||||
QString linePadding =
|
||||
QStringLiteral(" ").repeated(size + 4).prepend("\n");
|
||||
for (int i = 0; i < options.length(); ++i) {
|
||||
@@ -75,7 +75,7 @@ QString optionsToString(const QList<CommandOption>& options,
|
||||
}
|
||||
}
|
||||
if (!arguments.isEmpty()) {
|
||||
result += QLatin1String("Arguments:\n");
|
||||
result += QObject::tr("Arguments") + ":\n";
|
||||
}
|
||||
for (int i = 0; i < arguments.length(); ++i) {
|
||||
result += QStringLiteral(" %1 %2\n")
|
||||
@@ -327,16 +327,25 @@ void CommandLineParser::printHelp(QStringList args, const Node* node)
|
||||
{
|
||||
args.removeLast(); // remove the help, it's always the last
|
||||
QString helpText;
|
||||
|
||||
// add usage info
|
||||
QString argName = node->argument.name();
|
||||
if (argName.isEmpty()) {
|
||||
argName = qApp->applicationName();
|
||||
}
|
||||
QString argText = node->subNodes.isEmpty() ? "" : "[arguments]";
|
||||
helpText += QStringLiteral("Usage: %1 [%2-options] %3\n\n")
|
||||
QString argText =
|
||||
node->subNodes.isEmpty() ? "" : "[" + QObject::tr("arguments") + "]";
|
||||
helpText += QObject::tr("Usage") + ": %1 [%2-" + QObject::tr("options") +
|
||||
QStringLiteral("] %3\n\n")
|
||||
.arg(args.join(QStringLiteral(" ")))
|
||||
.arg(argName)
|
||||
.arg(argText);
|
||||
|
||||
// short section about default behavior
|
||||
helpText += QObject::tr("Per default runs Flameshot in the background and \
|
||||
adds a tray icon for configuration.");
|
||||
helpText += "\n\n";
|
||||
|
||||
// add command options and subarguments
|
||||
QList<CommandArgument> subArgs;
|
||||
for (const Node& n : node->subNodes)
|
||||
|
||||
11
src/config/CMakeLists.txt
Normal file
11
src/config/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE buttonlistview.cpp
|
||||
clickablelabel.cpp
|
||||
configwindow.cpp
|
||||
extendedslider.cpp
|
||||
filenameeditor.cpp
|
||||
geneneralconf.cpp
|
||||
strftimechooserwidget.cpp
|
||||
uicoloreditor.cpp
|
||||
visualseditor.cpp)
|
||||
@@ -35,9 +35,9 @@ ButtonListView::ButtonListView(QWidget* parent)
|
||||
void ButtonListView::initButtonList()
|
||||
{
|
||||
ToolFactory factory;
|
||||
auto listTypes = CaptureButton::getIterableButtonTypes();
|
||||
auto listTypes = CaptureToolButton::getIterableButtonTypes();
|
||||
|
||||
for (const CaptureButton::ButtonType t : listTypes) {
|
||||
for (const CaptureToolButton::ButtonType t : listTypes) {
|
||||
CaptureTool* tool = factory.CreateTool(t);
|
||||
|
||||
// add element to the local map
|
||||
@@ -63,14 +63,14 @@ void ButtonListView::initButtonList()
|
||||
|
||||
void ButtonListView::updateActiveButtons(QListWidgetItem* item)
|
||||
{
|
||||
CaptureButton::ButtonType bType = m_buttonTypeByName[item->text()];
|
||||
CaptureToolButton::ButtonType bType = m_buttonTypeByName[item->text()];
|
||||
if (item->checkState() == Qt::Checked) {
|
||||
m_listButtons.append(bType);
|
||||
// TODO refactor so we don't need external sorts
|
||||
using bt = CaptureButton::ButtonType;
|
||||
using bt = CaptureToolButton::ButtonType;
|
||||
std::sort(m_listButtons.begin(), m_listButtons.end(), [](bt a, bt b) {
|
||||
return CaptureButton::getPriorityByButton(a) <
|
||||
CaptureButton::getPriorityByButton(b);
|
||||
return CaptureToolButton::getPriorityByButton(a) <
|
||||
CaptureToolButton::getPriorityByButton(b);
|
||||
});
|
||||
} else {
|
||||
m_listButtons.remove(m_listButtons.indexOf(bType));
|
||||
@@ -100,10 +100,10 @@ void ButtonListView::selectAll()
|
||||
void ButtonListView::updateComponents()
|
||||
{
|
||||
m_listButtons = ConfigHandler().getButtons();
|
||||
auto listTypes = CaptureButton::getIterableButtonTypes();
|
||||
auto listTypes = CaptureToolButton::getIterableButtonTypes();
|
||||
for (int i = 0; i < this->count(); ++i) {
|
||||
QListWidgetItem* item = this->item(i);
|
||||
auto elem = static_cast<CaptureButton::ButtonType>(listTypes.at(i));
|
||||
auto elem = static_cast<CaptureToolButton::ButtonType>(listTypes.at(i));
|
||||
if (m_listButtons.contains(elem)) {
|
||||
item->setCheckState(Qt::Checked);
|
||||
} else {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include <QListWidget>
|
||||
|
||||
class ButtonListView : public QListWidget
|
||||
@@ -36,8 +36,8 @@ protected:
|
||||
void initButtonList();
|
||||
|
||||
private:
|
||||
QVector<CaptureButton::ButtonType> m_listButtons;
|
||||
QMap<QString, CaptureButton::ButtonType> m_buttonTypeByName;
|
||||
QVector<CaptureToolButton::ButtonType> m_listButtons;
|
||||
QMap<QString, CaptureToolButton::ButtonType> m_buttonTypeByName;
|
||||
|
||||
void updateActiveButtons(QListWidgetItem*);
|
||||
};
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include "src/utils/confighandler.h"
|
||||
#include "src/utils/globalvalues.h"
|
||||
#include "src/utils/pathinfo.h"
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include <QFileSystemWatcher>
|
||||
#include <QIcon>
|
||||
#include <QKeyEvent>
|
||||
@@ -56,7 +56,7 @@ ConfigWindow::ConfigWindow(QWidget* parent)
|
||||
connect(
|
||||
m_configWatcher, &QFileSystemWatcher::fileChanged, this, changedSlot);
|
||||
|
||||
QColor background = this->palette().background().color();
|
||||
QColor background = this->palette().window().color();
|
||||
bool isDark = ColorUtils::colorIsDark(background);
|
||||
QString modifier =
|
||||
isDark ? PathInfo::whiteIconPath() : PathInfo::blackIconPath();
|
||||
|
||||
@@ -62,7 +62,7 @@ void FileNameEditor::initWidgets()
|
||||
// preview
|
||||
m_outputLabel = new QLineEdit(this);
|
||||
m_outputLabel->setDisabled(true);
|
||||
QString foreground = this->palette().foreground().color().name();
|
||||
QString foreground = this->palette().windowText().color().name();
|
||||
m_outputLabel->setStyleSheet(QStringLiteral("color: %1").arg(foreground));
|
||||
QPalette pal = m_outputLabel->palette();
|
||||
QColor color =
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
#include "geneneralconf.h"
|
||||
#include "filepathconfiguration.h"
|
||||
#include "src/core/controller.h"
|
||||
#include "src/utils/confighandler.h"
|
||||
#include "src/utils/filenamehandler.h"
|
||||
#include "src/tools/storage/imgstorages.h"
|
||||
#include "src/utils/confighandler.h"
|
||||
#include <QCheckBox>
|
||||
@@ -25,24 +27,27 @@
|
||||
#include <QFileDialog>
|
||||
#include <QGroupBox>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLineEdit>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QRadioButton>
|
||||
#include <QStandardPaths>
|
||||
#include <QTextCodec>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
GeneneralConf::GeneneralConf(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
m_layout = new QVBoxLayout(this);
|
||||
m_layout->setAlignment(Qt::AlignTop);
|
||||
initShowHelp();
|
||||
initShowSidePanelButton();
|
||||
initShowDesktopNotification();
|
||||
initShowTrayIcon();
|
||||
initAutostart();
|
||||
initShowStartupLaunchMessage();
|
||||
initCloseAfterCapture();
|
||||
initCopyAndCloseAfterUpload();
|
||||
initSaveAfterCopy();
|
||||
initCopyPathAfterSave();
|
||||
initUploadStorage();
|
||||
initFilePathConfiguration();
|
||||
@@ -56,11 +61,20 @@ void GeneneralConf::updateComponents()
|
||||
{
|
||||
ConfigHandler config;
|
||||
m_helpMessage->setChecked(config.showHelpValue());
|
||||
m_sidePanelButton->setChecked(config.showSidePanelButtonValue());
|
||||
m_sysNotifications->setChecked(config.desktopNotificationValue());
|
||||
m_autostart->setChecked(config.startupLaunchValue());
|
||||
m_closeAfterCapture->setChecked(config.closeAfterScreenshotValue());
|
||||
m_copyAndCloseAfterUpload->setChecked(
|
||||
config.copyAndCloseAfterUploadEnabled());
|
||||
m_saveAfterCopy->setChecked(config.saveAfterCopyValue());
|
||||
|
||||
if (!config.saveAfterCopyPathValue().isEmpty()) {
|
||||
m_savePath->setText(config.saveAfterCopyPathValue());
|
||||
} else {
|
||||
ConfigHandler().setSaveAfterCopyPath(
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation));
|
||||
}
|
||||
m_copyPathAfterSave->setChecked(config.copyPathAfterSaveEnabled());
|
||||
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||
@@ -73,6 +87,11 @@ void GeneneralConf::showHelpChanged(bool checked)
|
||||
ConfigHandler().setShowHelp(checked);
|
||||
}
|
||||
|
||||
void GeneneralConf::showSidePanelButtonChanged(bool checked)
|
||||
{
|
||||
ConfigHandler().setShowSidePanelButton(checked);
|
||||
}
|
||||
|
||||
void GeneneralConf::showDesktopNotificationChanged(bool checked)
|
||||
{
|
||||
ConfigHandler().setDesktopNotification(checked);
|
||||
@@ -176,6 +195,19 @@ void GeneneralConf::initShowHelp()
|
||||
&GeneneralConf::showHelpChanged);
|
||||
}
|
||||
|
||||
void GeneneralConf::initShowSidePanelButton()
|
||||
{
|
||||
m_sidePanelButton = new QCheckBox(tr("Show the side panel button"), this);
|
||||
m_sidePanelButton->setChecked(ConfigHandler().showSidePanelButtonValue());
|
||||
m_sidePanelButton->setToolTip(
|
||||
tr("Show the side panel toggle button in the capture mode."));
|
||||
m_layout->addWidget(m_sidePanelButton);
|
||||
|
||||
connect(m_sidePanelButton,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&GeneneralConf::showSidePanelButtonChanged);
|
||||
}
|
||||
void GeneneralConf::initShowDesktopNotification()
|
||||
{
|
||||
m_sysNotifications = new QCheckBox(tr("Show desktop notifications"), this);
|
||||
@@ -299,6 +331,62 @@ void GeneneralConf::initCopyAndCloseAfterUpload()
|
||||
});
|
||||
}
|
||||
|
||||
void GeneneralConf::initSaveAfterCopy()
|
||||
{
|
||||
m_saveAfterCopy = new QCheckBox(tr("Save image after copy"), this);
|
||||
m_saveAfterCopy->setToolTip(tr("Save image file after copying it"));
|
||||
m_layout->addWidget(m_saveAfterCopy);
|
||||
connect(m_saveAfterCopy,
|
||||
&QCheckBox::clicked,
|
||||
this,
|
||||
&GeneneralConf::saveAfterCopyChanged);
|
||||
|
||||
QHBoxLayout* pathLayout = new QHBoxLayout();
|
||||
m_layout->addStretch();
|
||||
QGroupBox* box = new QGroupBox(tr("Save Path"));
|
||||
box->setFlat(true);
|
||||
box->setLayout(pathLayout);
|
||||
m_layout->addWidget(box);
|
||||
|
||||
m_savePath = new QLineEdit(
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation), this);
|
||||
m_savePath->setDisabled(true);
|
||||
QString foreground = this->palette().foreground().color().name();
|
||||
m_savePath->setStyleSheet(QStringLiteral("color: %1").arg(foreground));
|
||||
pathLayout->addWidget(m_savePath);
|
||||
|
||||
m_changeSaveButton = new QPushButton(tr("Change..."), this);
|
||||
pathLayout->addWidget(m_changeSaveButton);
|
||||
connect(m_changeSaveButton,
|
||||
&QPushButton::clicked,
|
||||
this,
|
||||
&GeneneralConf::changeSavePath);
|
||||
}
|
||||
|
||||
void GeneneralConf::saveAfterCopyChanged(bool checked)
|
||||
{
|
||||
ConfigHandler().setSaveAfterCopy(checked);
|
||||
}
|
||||
|
||||
void GeneneralConf::changeSavePath()
|
||||
{
|
||||
QString path = QFileDialog::getExistingDirectory(
|
||||
this,
|
||||
tr("Choose a Folder"),
|
||||
QStandardPaths::writableLocation(QStandardPaths::PicturesLocation),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
if (path.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!QFileInfo(path).isWritable()) {
|
||||
QMessageBox::about(
|
||||
this, tr("Error"), tr("Unable to write to directory."));
|
||||
return;
|
||||
}
|
||||
m_savePath->setText(path);
|
||||
ConfigHandler().setSaveAfterCopyPath(path);
|
||||
}
|
||||
|
||||
void GeneneralConf::initCopyPathAfterSave()
|
||||
{
|
||||
m_copyPathAfterSave = new QCheckBox(tr("Copy file path after save"), this);
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
class QVBoxLayout;
|
||||
class QCheckBox;
|
||||
class QPushButton;
|
||||
class QLabel;
|
||||
class QLineEdit;
|
||||
class FilePathConfiguration;
|
||||
|
||||
|
||||
class GeneneralConf : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -35,20 +38,24 @@ public slots:
|
||||
|
||||
private slots:
|
||||
void showHelpChanged(bool checked);
|
||||
void showSidePanelButtonChanged(bool checked);
|
||||
void showDesktopNotificationChanged(bool checked);
|
||||
void showTrayIconChanged(bool checked);
|
||||
void autostartChanged(bool checked);
|
||||
void showStartupLaunchMessageChanged(bool checked);
|
||||
void closeAfterCaptureChanged(bool checked);
|
||||
void saveAfterCopyChanged(bool checked);
|
||||
void changeSavePath();
|
||||
void importConfiguration();
|
||||
void exportFileConfiguration();
|
||||
void resetConfiguration();
|
||||
void showStartupLaunchMessageChanged(bool checked);
|
||||
|
||||
private:
|
||||
QVBoxLayout* m_layout;
|
||||
QCheckBox* m_sysNotifications;
|
||||
QCheckBox* m_showTray;
|
||||
QCheckBox* m_helpMessage;
|
||||
QCheckBox* m_sidePanelButton;
|
||||
QCheckBox* m_autostart;
|
||||
QCheckBox* m_showStartupLaunchMessage;
|
||||
QCheckBox* m_closeAfterCapture;
|
||||
@@ -57,9 +64,13 @@ private:
|
||||
QPushButton* m_importButton;
|
||||
QPushButton* m_exportButton;
|
||||
QPushButton* m_resetButton;
|
||||
QCheckBox* m_saveAfterCopy;
|
||||
QLineEdit* m_savePath;
|
||||
QPushButton* m_changeSaveButton;
|
||||
FilePathConfiguration* m_filePathConfiguration;
|
||||
|
||||
void initShowHelp();
|
||||
void initShowSidePanelButton();
|
||||
void initShowDesktopNotification();
|
||||
void initShowTrayIcon();
|
||||
void initConfingButtons();
|
||||
@@ -67,6 +78,7 @@ private:
|
||||
void initShowStartupLaunchMessage();
|
||||
void initCloseAfterCapture();
|
||||
void initCopyAndCloseAfterUpload();
|
||||
void initSaveAfterCopy();
|
||||
void initCopyPathAfterSave();
|
||||
void initUploadStorage();
|
||||
void initFilePathConfiguration();
|
||||
|
||||
@@ -116,7 +116,7 @@ void UIcolorEditor::initButtons()
|
||||
QGroupBox* frame = new QGroupBox();
|
||||
frame->setFixedSize(frameSize, frameSize);
|
||||
|
||||
m_buttonMainColor = new CaptureButton(m_buttonIconType, frame);
|
||||
m_buttonMainColor = new CaptureToolButton(m_buttonIconType, frame);
|
||||
m_buttonMainColor->move(m_buttonMainColor->x() + extraSize / 2,
|
||||
m_buttonMainColor->y() + extraSize / 2);
|
||||
QHBoxLayout* h1 = new QHBoxLayout();
|
||||
@@ -129,7 +129,7 @@ void UIcolorEditor::initButtons()
|
||||
" mode of the main color."));
|
||||
|
||||
QGroupBox* frame2 = new QGroupBox();
|
||||
m_buttonContrast = new CaptureButton(m_buttonIconType, frame2);
|
||||
m_buttonContrast = new CaptureToolButton(m_buttonIconType, frame2);
|
||||
m_buttonContrast->move(m_buttonContrast->x() + extraSize / 2,
|
||||
m_buttonContrast->y() + extraSize / 2);
|
||||
|
||||
@@ -145,11 +145,11 @@ void UIcolorEditor::initButtons()
|
||||
" mode of the contrast color."));
|
||||
|
||||
connect(m_buttonMainColor,
|
||||
&CaptureButton::pressedButton,
|
||||
&CaptureToolButton::pressedButton,
|
||||
this,
|
||||
&UIcolorEditor::changeLastButton);
|
||||
connect(m_buttonContrast,
|
||||
&CaptureButton::pressedButton,
|
||||
&CaptureToolButton::pressedButton,
|
||||
this,
|
||||
&UIcolorEditor::changeLastButton);
|
||||
// clicking the labels changes the button too
|
||||
@@ -163,7 +163,7 @@ void UIcolorEditor::initButtons()
|
||||
}
|
||||
|
||||
// visual update for the selected button
|
||||
void UIcolorEditor::changeLastButton(CaptureButton* b)
|
||||
void UIcolorEditor::changeLastButton(CaptureToolButton* b)
|
||||
{
|
||||
if (m_lastButtonPressed != b) {
|
||||
m_lastButtonPressed = b;
|
||||
|
||||
@@ -18,12 +18,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "color_wheel.hpp"
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include <QGroupBox>
|
||||
|
||||
class QVBoxLayout;
|
||||
class QHBoxLayout;
|
||||
class CaptureButton;
|
||||
class CaptureToolButton;
|
||||
class ClickableLabel;
|
||||
|
||||
class UIcolorEditor : public QGroupBox
|
||||
@@ -38,19 +38,19 @@ public slots:
|
||||
private slots:
|
||||
void updateUIcolor();
|
||||
void updateLocalColor(const QColor);
|
||||
void changeLastButton(CaptureButton*);
|
||||
void changeLastButton(CaptureToolButton*);
|
||||
|
||||
private:
|
||||
QColor m_uiColor, m_contrastColor;
|
||||
CaptureButton* m_buttonMainColor;
|
||||
CaptureToolButton* m_buttonMainColor;
|
||||
ClickableLabel* m_labelMain;
|
||||
CaptureButton* m_buttonContrast;
|
||||
CaptureToolButton* m_buttonContrast;
|
||||
ClickableLabel* m_labelContrast;
|
||||
CaptureButton* m_lastButtonPressed;
|
||||
CaptureToolButton* m_lastButtonPressed;
|
||||
color_widgets::ColorWheel* m_colorWheel;
|
||||
|
||||
static const CaptureButton::ButtonType m_buttonIconType =
|
||||
CaptureButton::TYPE_CIRCLE;
|
||||
static const CaptureToolButton::ButtonType m_buttonIconType =
|
||||
CaptureToolButton::TYPE_CIRCLE;
|
||||
|
||||
QHBoxLayout* m_hLayout;
|
||||
QVBoxLayout* m_vLayout;
|
||||
|
||||
9
src/core/CMakeLists.txt
Normal file
9
src/core/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
|
||||
# Required to generate MOC
|
||||
target_sources(flameshot PRIVATE controller.h flameshotdbusadapter.h)
|
||||
|
||||
target_sources(flameshot PRIVATE capturerequest.cpp controller.cpp flameshotdbusadapter.cpp)
|
||||
|
||||
IF(WIN32)
|
||||
target_sources(flameshot PRIVATE globalshortcutfilter.h globalshortcutfilter.cpp)
|
||||
ENDIF()
|
||||
@@ -87,7 +87,7 @@ void CaptureRequest::exportCapture(const QPixmap& p)
|
||||
if (m_path.isEmpty()) {
|
||||
ScreenshotSaver().saveToFilesystemGUI(p);
|
||||
} else {
|
||||
ScreenshotSaver().saveToFilesystem(p, m_path);
|
||||
ScreenshotSaver().saveToFilesystem(p, m_path, "");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#include "src/utils/history.h"
|
||||
#include "src/utils/screengrabber.h"
|
||||
#include "src/utils/systemnotification.h"
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include "src/widgets/capture/capturewidget.h"
|
||||
#include "src/widgets/capturelauncher.h"
|
||||
#include "src/widgets/historywidget.h"
|
||||
@@ -95,6 +95,8 @@ void Controller::requestCapture(const CaptureRequest& request)
|
||||
this->startFullscreenCapture(id);
|
||||
});
|
||||
break;
|
||||
// TODO: Figure out the code path that gets here so the deprated warning
|
||||
// can be fixed
|
||||
case CaptureRequest::SCREEN_MODE: {
|
||||
int&& number = request.data().toInt();
|
||||
doLater(request.delay(), this, [this, id, number]() {
|
||||
@@ -188,8 +190,10 @@ void Controller::openInfoWindow()
|
||||
|
||||
void Controller::openLauncherWindow()
|
||||
{
|
||||
CaptureLauncher* w = new CaptureLauncher();
|
||||
w->show();
|
||||
if (!m_launcherWindow) {
|
||||
m_launcherWindow = new CaptureLauncher();
|
||||
}
|
||||
m_launcherWindow->show();
|
||||
}
|
||||
|
||||
void Controller::enableTrayIcon()
|
||||
@@ -210,11 +214,10 @@ void Controller::enableTrayIcon()
|
||||
&QAction::triggered,
|
||||
this,
|
||||
&Controller::openLauncherWindow);
|
||||
|
||||
QAction* configAction = new QAction(tr("&Configuration"), this);
|
||||
connect(
|
||||
configAction, &QAction::triggered, this, &Controller::openConfigWindow);
|
||||
QAction* infoAction = new QAction(tr("&Information"), this);
|
||||
QAction* infoAction = new QAction(tr("&About"), this);
|
||||
connect(infoAction, &QAction::triggered, this, &Controller::openInfoWindow);
|
||||
QAction* quitAction = new QAction(tr("&Quit"), this);
|
||||
connect(quitAction, &QAction::triggered, qApp, &QCoreApplication::quit);
|
||||
|
||||
@@ -29,7 +29,7 @@ class CaptureWidget;
|
||||
class ConfigWindow;
|
||||
class InfoWindow;
|
||||
class QSystemTrayIcon;
|
||||
|
||||
class CaptureLauncher;
|
||||
using lambda = std::function<void(void)>;
|
||||
|
||||
class Controller : public QObject
|
||||
@@ -84,6 +84,7 @@ private:
|
||||
QMap<uint, CaptureRequest> m_requestMap;
|
||||
QPointer<CaptureWidget> m_captureWindow;
|
||||
QPointer<InfoWindow> m_infoWindow;
|
||||
QPointer<CaptureLauncher> m_launcherWindow;
|
||||
QPointer<ConfigWindow> m_configWindow;
|
||||
QPointer<QSystemTrayIcon> m_trayIcon;
|
||||
};
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
class FlameshotDBusAdapter : public QDBusAbstractAdaptor
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_CLASSINFO("D-Bus Interface", "org.dharkael.Flameshot")
|
||||
Q_CLASSINFO("D-Bus Interface", "org.flameshot.Flameshot")
|
||||
|
||||
public:
|
||||
explicit FlameshotDBusAdapter(QObject* parent = nullptr);
|
||||
|
||||
86
src/main.cpp
86
src/main.cpp
@@ -71,7 +71,7 @@ int main(int argc, char* argv[])
|
||||
app.installTranslator(&qtTranslator);
|
||||
app.setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
|
||||
app.setApplicationName(QStringLiteral("flameshot"));
|
||||
app.setOrganizationName(QStringLiteral("Dharkael"));
|
||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
||||
|
||||
auto c = Controller::getInstance();
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||
@@ -82,7 +82,7 @@ int main(int argc, char* argv[])
|
||||
QObject::tr("Unable to connect via DBus"));
|
||||
}
|
||||
dbus.registerObject(QStringLiteral("/"), c);
|
||||
dbus.registerService(QStringLiteral("org.dharkael.Flameshot"));
|
||||
dbus.registerService(QStringLiteral("org.flameshot.Flameshot"));
|
||||
#endif
|
||||
// Exporting captures must be connected after the dbus interface
|
||||
// or the dbus signal gets blocked until we end the exports.
|
||||
@@ -96,65 +96,64 @@ int main(int argc, char* argv[])
|
||||
* ------------*/
|
||||
QCoreApplication app(argc, argv);
|
||||
app.setApplicationName(QStringLiteral("flameshot"));
|
||||
app.setOrganizationName(QStringLiteral("Dharkael"));
|
||||
app.setOrganizationName(QStringLiteral("flameshot"));
|
||||
app.setApplicationVersion(qApp->applicationVersion());
|
||||
CommandLineParser parser;
|
||||
// Add description
|
||||
parser.setDescription(
|
||||
QStringLiteral("Powerful yet simple to use screenshot software."));
|
||||
parser.setGeneralErrorMessage(QStringLiteral("See 'flameshot --help'."));
|
||||
QObject::tr("Powerful yet simple to use screenshot software."));
|
||||
parser.setGeneralErrorMessage(QObject::tr("See") + " flameshot --help.");
|
||||
// Arguments
|
||||
CommandArgument fullArgument(QStringLiteral("full"),
|
||||
QStringLiteral("Capture the entire desktop."));
|
||||
CommandArgument launcherArgument(
|
||||
QStringLiteral("launcher"), QStringLiteral("Open the capture launcher."));
|
||||
QObject::tr("Capture the entire desktop."));
|
||||
CommandArgument launcherArgument(QStringLiteral("launcher"),
|
||||
QObject::tr("Open the capture launcher."));
|
||||
CommandArgument guiArgument(
|
||||
QStringLiteral("gui"),
|
||||
QStringLiteral("Start a manual capture in GUI mode."));
|
||||
QObject::tr("Start a manual capture in GUI mode."));
|
||||
CommandArgument configArgument(QStringLiteral("config"),
|
||||
QStringLiteral("Configure flameshot."));
|
||||
QObject::tr("Configure") + " flameshot.");
|
||||
CommandArgument screenArgument(QStringLiteral("screen"),
|
||||
QStringLiteral("Capture a single screen."));
|
||||
QObject::tr("Capture a single screen."));
|
||||
|
||||
// Options
|
||||
CommandOption pathOption(
|
||||
{ "p", "path" },
|
||||
QStringLiteral("Path where the capture will be saved"),
|
||||
QObject::tr("Path where the capture will be saved"),
|
||||
QStringLiteral("path"));
|
||||
CommandOption clipboardOption(
|
||||
{ "c", "clipboard" },
|
||||
QStringLiteral("Save the capture to the clipboard"));
|
||||
{ "c", "clipboard" }, QObject::tr("Save the capture to the clipboard"));
|
||||
CommandOption delayOption({ "d", "delay" },
|
||||
QStringLiteral("Delay time in milliseconds"),
|
||||
QObject::tr("Delay time in milliseconds"),
|
||||
QStringLiteral("milliseconds"));
|
||||
CommandOption filenameOption({ "f", "filename" },
|
||||
QStringLiteral("Set the filename pattern"),
|
||||
QObject::tr("Set the filename pattern"),
|
||||
QStringLiteral("pattern"));
|
||||
CommandOption trayOption({ "t", "trayicon" },
|
||||
QStringLiteral("Enable or disable the trayicon"),
|
||||
QObject::tr("Enable or disable the trayicon"),
|
||||
QStringLiteral("bool"));
|
||||
CommandOption autostartOption(
|
||||
{ "a", "autostart" },
|
||||
QStringLiteral("Enable or disable run at startup"),
|
||||
QObject::tr("Enable or disable run at startup"),
|
||||
QStringLiteral("bool"));
|
||||
CommandOption showHelpOption(
|
||||
{ "s", "showhelp" },
|
||||
QStringLiteral("Show the help message in the capture mode"),
|
||||
QObject::tr("Show the help message in the capture mode"),
|
||||
QStringLiteral("bool"));
|
||||
CommandOption mainColorOption({ "m", "maincolor" },
|
||||
QStringLiteral("Define the main UI color"),
|
||||
QObject::tr("Define the main UI color"),
|
||||
QStringLiteral("color-code"));
|
||||
CommandOption contrastColorOption(
|
||||
{ "k", "contrastcolor" },
|
||||
QStringLiteral("Define the contrast UI color"),
|
||||
QObject::tr("Define the contrast UI color"),
|
||||
QStringLiteral("color-code"));
|
||||
CommandOption rawImageOption({ "r", "raw" },
|
||||
QStringLiteral("Print raw PNG capture"));
|
||||
QObject::tr("Print raw PNG capture"));
|
||||
CommandOption screenNumberOption(
|
||||
{ "n", "number" },
|
||||
QStringLiteral(
|
||||
"Define the screen to capture,\ndefault: screen containing the cursor"),
|
||||
QStringLiteral("Screen number"),
|
||||
QObject::tr("Define the screen to capture") + ",\n" +
|
||||
QObject::tr("default: screen containing the cursor"),
|
||||
QObject::tr("Screen number"),
|
||||
QStringLiteral("-1"));
|
||||
|
||||
// Add checkers
|
||||
@@ -162,25 +161,26 @@ int main(int argc, char* argv[])
|
||||
QColor parsedColor(colorCode);
|
||||
return parsedColor.isValid() && parsedColor.alphaF() == 1.0;
|
||||
};
|
||||
QString colorErr = "Invalid color, "
|
||||
"this flag supports the following formats:\n"
|
||||
"- #RGB (each of R, G, and B is a single hex digit)\n"
|
||||
"- #RRGGBB\n- #RRRGGGBBB\n"
|
||||
"- #RRRRGGGGBBBB\n"
|
||||
"- Named colors like 'blue' or 'red'\n"
|
||||
"You may need to escape the '#' sign as in '\\#FFF'";
|
||||
QString colorErr =
|
||||
QObject::tr("Invalid color, "
|
||||
"this flag supports the following formats:\n"
|
||||
"- #RGB (each of R, G, and B is a single hex digit)\n"
|
||||
"- #RRGGBB\n- #RRRGGGBBB\n"
|
||||
"- #RRRRGGGGBBBB\n"
|
||||
"- Named colors like 'blue' or 'red'\n"
|
||||
"You may need to escape the '#' sign as in '\\#FFF'");
|
||||
|
||||
const QString delayErr =
|
||||
QStringLiteral("Invalid delay, it must be higher than 0");
|
||||
QObject::tr("Invalid delay, it must be higher than 0");
|
||||
const QString numberErr =
|
||||
QStringLiteral("Invalid screen number, it must be non negative");
|
||||
QObject::tr("Invalid screen number, it must be non negative");
|
||||
auto numericChecker = [](const QString& delayValue) -> bool {
|
||||
int value = delayValue.toInt();
|
||||
return value >= 0;
|
||||
};
|
||||
|
||||
const QString pathErr =
|
||||
QStringLiteral("Invalid path, it must be a real path in the system");
|
||||
QObject::tr("Invalid path, it must be a real path in the system");
|
||||
auto pathChecker = [pathErr](const QString& pathValue) -> bool {
|
||||
bool res = QDir(pathValue).exists();
|
||||
if (!res) {
|
||||
@@ -191,7 +191,7 @@ int main(int argc, char* argv[])
|
||||
};
|
||||
|
||||
const QString booleanErr =
|
||||
QStringLiteral("Invalid value, it must be defined as 'true' or 'false'");
|
||||
QObject::tr("Invalid value, it must be defined as 'true' or 'false'");
|
||||
auto booleanChecker = [](const QString& value) -> bool {
|
||||
return value == QLatin1String("true") ||
|
||||
value == QLatin1String("false");
|
||||
@@ -241,7 +241,7 @@ int main(int argc, char* argv[])
|
||||
if (parser.isSet(helpOption) || parser.isSet(versionOption)) {
|
||||
} else if (parser.isSet(launcherArgument)) { // LAUNCHER
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("openLauncher"));
|
||||
@@ -261,7 +261,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("graphicCapture"));
|
||||
@@ -312,7 +312,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("fullScreen"));
|
||||
@@ -368,7 +368,7 @@ int main(int argc, char* argv[])
|
||||
|
||||
// Send message
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("captureScreen"));
|
||||
@@ -400,7 +400,7 @@ int main(int argc, char* argv[])
|
||||
ConfigHandler config;
|
||||
if (autostart) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("autostartEnabled"));
|
||||
@@ -428,7 +428,7 @@ int main(int argc, char* argv[])
|
||||
}
|
||||
if (tray) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("trayIconEnabled"));
|
||||
@@ -465,7 +465,7 @@ int main(int argc, char* argv[])
|
||||
// Open gui when no options
|
||||
if (!someFlagSet) {
|
||||
QDBusMessage m = QDBusMessage::createMethodCall(
|
||||
QStringLiteral("org.dharkael.Flameshot"),
|
||||
QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("openConfig"));
|
||||
|
||||
165
src/third-party/Qt-Color-Widgets/COPYING
vendored
165
src/third-party/Qt-Color-Widgets/COPYING
vendored
@@ -1,165 +0,0 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
||||
This version of the GNU Lesser General Public License incorporates
|
||||
the terms and conditions of version 3 of the GNU General Public
|
||||
License, supplemented by the additional permissions listed below.
|
||||
|
||||
0. Additional Definitions.
|
||||
|
||||
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||
General Public License.
|
||||
|
||||
"The Library" refers to a covered work governed by this License,
|
||||
other than an Application or a Combined Work as defined below.
|
||||
|
||||
An "Application" is any work that makes use of an interface provided
|
||||
by the Library, but which is not otherwise based on the Library.
|
||||
Defining a subclass of a class defined by the Library is deemed a mode
|
||||
of using an interface provided by the Library.
|
||||
|
||||
A "Combined Work" is a work produced by combining or linking an
|
||||
Application with the Library. The particular version of the Library
|
||||
with which the Combined Work was made is also called the "Linked
|
||||
Version".
|
||||
|
||||
The "Minimal Corresponding Source" for a Combined Work means the
|
||||
Corresponding Source for the Combined Work, excluding any source code
|
||||
for portions of the Combined Work that, considered in isolation, are
|
||||
based on the Application, and not on the Linked Version.
|
||||
|
||||
The "Corresponding Application Code" for a Combined Work means the
|
||||
object code and/or source code for the Application, including any data
|
||||
and utility programs needed for reproducing the Combined Work from the
|
||||
Application, but excluding the System Libraries of the Combined Work.
|
||||
|
||||
1. Exception to Section 3 of the GNU GPL.
|
||||
|
||||
You may convey a covered work under sections 3 and 4 of this License
|
||||
without being bound by section 3 of the GNU GPL.
|
||||
|
||||
2. Conveying Modified Versions.
|
||||
|
||||
If you modify a copy of the Library, and, in your modifications, a
|
||||
facility refers to a function or data to be supplied by an Application
|
||||
that uses the facility (other than as an argument passed when the
|
||||
facility is invoked), then you may convey a copy of the modified
|
||||
version:
|
||||
|
||||
a) under this License, provided that you make a good faith effort to
|
||||
ensure that, in the event an Application does not supply the
|
||||
function or data, the facility still operates, and performs
|
||||
whatever part of its purpose remains meaningful, or
|
||||
|
||||
b) under the GNU GPL, with none of the additional permissions of
|
||||
this License applicable to that copy.
|
||||
|
||||
3. Object Code Incorporating Material from Library Header Files.
|
||||
|
||||
The object code form of an Application may incorporate material from
|
||||
a header file that is part of the Library. You may convey such object
|
||||
code under terms of your choice, provided that, if the incorporated
|
||||
material is not limited to numerical parameters, data structure
|
||||
layouts and accessors, or small macros, inline functions and templates
|
||||
(ten or fewer lines in length), you do both of the following:
|
||||
|
||||
a) Give prominent notice with each copy of the object code that the
|
||||
Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
4. Combined Works.
|
||||
|
||||
You may convey a Combined Work under terms of your choice that,
|
||||
taken together, effectively do not restrict modification of the
|
||||
portions of the Library contained in the Combined Work and reverse
|
||||
engineering for debugging such modifications, if you also do each of
|
||||
the following:
|
||||
|
||||
a) Give prominent notice with each copy of the Combined Work that
|
||||
the Library is used in it and that the Library and its use are
|
||||
covered by this License.
|
||||
|
||||
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||
document.
|
||||
|
||||
c) For a Combined Work that displays copyright notices during
|
||||
execution, include the copyright notice for the Library among
|
||||
these notices, as well as a reference directing the user to the
|
||||
copies of the GNU GPL and this license document.
|
||||
|
||||
d) Do one of the following:
|
||||
|
||||
0) Convey the Minimal Corresponding Source under the terms of this
|
||||
License, and the Corresponding Application Code in a form
|
||||
suitable for, and under terms that permit, the user to
|
||||
recombine or relink the Application with a modified version of
|
||||
the Linked Version to produce a modified Combined Work, in the
|
||||
manner specified by section 6 of the GNU GPL for conveying
|
||||
Corresponding Source.
|
||||
|
||||
1) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (a) uses at run time
|
||||
a copy of the Library already present on the user's computer
|
||||
system, and (b) will operate properly with a modified version
|
||||
of the Library that is interface-compatible with the Linked
|
||||
Version.
|
||||
|
||||
e) Provide Installation Information, but only if you would otherwise
|
||||
be required to provide such information under section 6 of the
|
||||
GNU GPL, and only to the extent that such information is
|
||||
necessary to install and execute a modified version of the
|
||||
Combined Work produced by recombining or relinking the
|
||||
Application with a modified version of the Linked Version. (If
|
||||
you use option 4d0, the Installation Information must accompany
|
||||
the Minimal Corresponding Source and Corresponding Application
|
||||
Code. If you use option 4d1, you must provide the Installation
|
||||
Information in the manner specified by section 6 of the GNU GPL
|
||||
for conveying Corresponding Source.)
|
||||
|
||||
5. Combined Libraries.
|
||||
|
||||
You may place library facilities that are a work based on the
|
||||
Library side by side in a single library together with other library
|
||||
facilities that are not Applications and are not covered by this
|
||||
License, and convey such a combined library under terms of your
|
||||
choice, if you do both of the following:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work based
|
||||
on the Library, uncombined with any other library facilities,
|
||||
conveyed under the terms of this License.
|
||||
|
||||
b) Give prominent notice with the combined library that part of it
|
||||
is a work based on the Library, and explaining where to find the
|
||||
accompanying uncombined form of the same work.
|
||||
|
||||
6. Revised Versions of the GNU Lesser General Public License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions
|
||||
of the GNU Lesser 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
|
||||
Library as you received it specifies that a certain numbered version
|
||||
of the GNU Lesser General Public License "or any later version"
|
||||
applies to it, you have the option of following the terms and
|
||||
conditions either of that published version or of any later version
|
||||
published by the Free Software Foundation. If the Library as you
|
||||
received it does not specify a version number of the GNU Lesser
|
||||
General Public License, you may choose any version of the GNU Lesser
|
||||
General Public License ever published by the Free Software Foundation.
|
||||
|
||||
If the Library as you received it specifies that a proxy can decide
|
||||
whether future versions of the GNU Lesser General Public License shall
|
||||
apply, that proxy's public statement of acceptance of any version is
|
||||
permanent authorization for you to choose that version for the
|
||||
Library.
|
||||
@@ -1,14 +0,0 @@
|
||||
Linking this library statically or dynamically with other modules is making a
|
||||
combined work based on this library. Thus, the terms and conditions of the
|
||||
GNU Lesser General Public License version 3 cover the whole combination.
|
||||
|
||||
As a special exception, the copyright holders of this library give you
|
||||
permission to combine this library with independent
|
||||
modules to produce an executable, and to copy and distribute the resulting
|
||||
executable under terms of any of the GNU General Public licenses, as published
|
||||
by the Free Software Foundation, provided that you also meet,
|
||||
for each linked independent module, the terms and conditions of the license of
|
||||
that module. An independent module is a module which is not derived from or
|
||||
based on this library. If you modify this library, you may extend this
|
||||
exception to your version of the library, but you are not obliged to do so.
|
||||
If you do not wish to do so, delete this exception statement from your version.
|
||||
64
src/third-party/Qt-Color-Widgets/README.md
vendored
64
src/third-party/Qt-Color-Widgets/README.md
vendored
@@ -1,64 +0,0 @@
|
||||
Color Widgets
|
||||
=============
|
||||
|
||||
Here is a color dialog that is more user-friendly than the default QColorDialog
|
||||
and several other color-related widgets
|
||||
|
||||
The provided widgets are:
|
||||
|
||||
* ColorWheel, An analog widget used to select a color
|
||||
* ColorPreview, A simple widget that displays a color
|
||||
* GradientSlider, A slider that has a gradient background
|
||||
* HueSlider, A variant of GradientSlider that has a rainbow background
|
||||
* ColorSelector, A ColorPreview that shows a ColorDialog when clicked
|
||||
* ColorDialog, A dialog that uses the above widgets to provide a better user experience than QColorDialog
|
||||
* ColorListWidget, A widget to edit a list of colors
|
||||
* Swatch, A widget to display a color palette
|
||||
* ColorPaletteWidget, A widget to use and manage a list of palettes
|
||||
* Color2DSlider, An analog widget used to select 2 color components
|
||||
* ColorLineEdit, A widget to manipulate a string representing a color
|
||||
|
||||
they are all in the color_widgets namespace.
|
||||
|
||||
See [the gallery](gallery/README.md) for more information and screenshots.
|
||||
|
||||
|
||||
Using it in a project
|
||||
---------------------
|
||||
|
||||
For QMake-based projects, include color_widgets.pri in the QMake project file.
|
||||
For CMake-based projects, add this as subdirectory, it will be compiled as a
|
||||
library and you can link the required targets to ColorWidgets-qt5.
|
||||
All the required files are in ./src and ./include.
|
||||
|
||||
|
||||
Installing as a Qt Designer/Creator Plugin
|
||||
------------------------------------------
|
||||
|
||||
The sources for the designer plugin are in ./color_widgets_designer_plugin
|
||||
|
||||
Compile the library and install in
|
||||
(Qt SDK)/Tools/QtCreator/bin/designer/
|
||||
(Qt SDK)/(Qt Version)/(Toolchain)/plugins/designer
|
||||
|
||||
cd build && cmake .. && make ColorWidgetsPlugin && make install
|
||||
|
||||
|
||||
Latest Version
|
||||
--------------
|
||||
|
||||
The latest version of the sources can be found at the following locations:
|
||||
|
||||
* https://github.com/mbasaglia/Qt-Color-Widgets
|
||||
* git://github.com/mbasaglia/Qt-Color-Widgets.git
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
|
||||
LGPLv3+, See COPYING.
|
||||
As a special exception, this library can be included in any project under the
|
||||
terms of any of the GNU liceses, distributing the whole project under a
|
||||
different GNU license, see LICENSE-EXCEPTION for details.
|
||||
|
||||
Copyright (C) 2013-2017 Mattia Basaglia <mattia.basaglia@gmail.com>
|
||||
@@ -1,31 +0,0 @@
|
||||
# Copyright (C) 2013-2017 Mattia Basaglia
|
||||
#
|
||||
#
|
||||
# This software 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 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This software 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 Color Widgets. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
INCLUDEPATH += $$PWD/src $$PWD/include
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/src/color_wheel.cpp \
|
||||
$$PWD/src/color_utils.cpp
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/include/color_wheel.hpp \
|
||||
$$PWD/src/color_utils.hpp
|
||||
|
||||
RESOURCES += \
|
||||
$$PWD/src/color_widgets.qrc
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2013-2017 Mattia Basaglia
|
||||
#
|
||||
# This program 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 3 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.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
TEMPLATE=lib
|
||||
CONFIG += dll
|
||||
QT += core gui widgets
|
||||
DEFINES += QTCOLORWIDGETS_LIBRARY
|
||||
|
||||
TARGET=ColorWidgets-qt5
|
||||
|
||||
VERSION=1.0.0
|
||||
|
||||
OBJECTS_DIR = out/obj
|
||||
MOC_DIR = out/generated
|
||||
UI_DIR = out/generated
|
||||
RCC_DIR = out/generated
|
||||
|
||||
include(color_widgets.pri)
|
||||
|
||||
build_all:!build_pass {
|
||||
CONFIG -= build_all
|
||||
CONFIG += release
|
||||
}
|
||||
|
||||
unix {
|
||||
LIB_TARGET = lib$${TARGET}.so
|
||||
}
|
||||
win32 {
|
||||
LIB_TARGET = $${TARGET}.dll
|
||||
}
|
||||
|
||||
isEmpty(PREFIX) {
|
||||
PREFIX = /usr/local
|
||||
}
|
||||
target.path = $$PREFIX/lib
|
||||
headers.path = $$PREFIX/include/QtColorWidgets
|
||||
headers.files = $$HEADERS
|
||||
|
||||
INSTALLS += target headers
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
#include "color_wheel.hpp"
|
||||
@@ -1,169 +0,0 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Mattia Basaglia
|
||||
*
|
||||
* \copyright Copyright (C) 2013-2017 Mattia Basaglia
|
||||
*
|
||||
* This program 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 3 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifndef COLOR_WHEEL_HPP
|
||||
#define COLOR_WHEEL_HPP
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace color_widgets {
|
||||
|
||||
/**
|
||||
* \brief Display an analog widget that allows the selection of a HSV color
|
||||
*
|
||||
* It has an outer wheel to select the Hue and an intenal square to select
|
||||
* Saturation and Lightness.
|
||||
*/
|
||||
class ColorWheel : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged DESIGNABLE true STORED false )
|
||||
Q_PROPERTY(qreal hue READ hue WRITE setHue DESIGNABLE false )
|
||||
Q_PROPERTY(qreal saturation READ saturation WRITE setSaturation DESIGNABLE false )
|
||||
Q_PROPERTY(qreal value READ value WRITE setValue DESIGNABLE false )
|
||||
Q_PROPERTY(unsigned wheelWidth READ wheelWidth WRITE setWheelWidth DESIGNABLE true )
|
||||
Q_PROPERTY(DisplayFlags displayFlags READ displayFlags WRITE setDisplayFlags NOTIFY displayFlagsChanged DESIGNABLE true )
|
||||
|
||||
public:
|
||||
enum DisplayEnum
|
||||
{
|
||||
SHAPE_DEFAULT = 0x000, ///< Use the default shape
|
||||
SHAPE_TRIANGLE = 0x001, ///< A triangle
|
||||
SHAPE_SQUARE = 0x002, ///< A square
|
||||
SHAPE_FLAGS = 0x00f, ///< Mask for the shape flags
|
||||
|
||||
ANGLE_DEFAULT = 0x000, ///< Use the default rotation style
|
||||
ANGLE_FIXED = 0x010, ///< The inner part doesn't rotate
|
||||
ANGLE_ROTATING = 0x020, ///< The inner part follows the hue selector
|
||||
ANGLE_FLAGS = 0x0f0, ///< Mask for the angle flags
|
||||
|
||||
COLOR_DEFAULT = 0x000, ///< Use the default colorspace
|
||||
COLOR_HSV = 0x100, ///< Use the HSV color space
|
||||
COLOR_HSL = 0x200, ///< Use the HSL color space
|
||||
COLOR_LCH = 0x400, ///< Use Luma Chroma Hue (Y_601')
|
||||
COLOR_FLAGS = 0xf00, ///< Mask for the color space flags
|
||||
|
||||
FLAGS_DEFAULT = 0x000, ///< Use all defaults
|
||||
FLAGS_ALL = 0xfff ///< Mask matching all flags
|
||||
};
|
||||
Q_DECLARE_FLAGS(DisplayFlags, DisplayEnum)
|
||||
Q_FLAGS(DisplayFlags)
|
||||
|
||||
explicit ColorWheel(QWidget *parent = nullptr);
|
||||
~ColorWheel();
|
||||
|
||||
/// Get current color
|
||||
QColor color() const;
|
||||
|
||||
virtual QSize sizeHint() const Q_DECL_OVERRIDE;
|
||||
|
||||
/// Get current hue in the range [0-1]
|
||||
qreal hue() const;
|
||||
|
||||
/// Get current saturation in the range [0-1]
|
||||
qreal saturation() const;
|
||||
|
||||
/// Get current value in the range [0-1]
|
||||
qreal value() const;
|
||||
|
||||
/// Get the width in pixels of the outer wheel
|
||||
unsigned int wheelWidth() const;
|
||||
|
||||
/// Set the width in pixels of the outer wheel
|
||||
void setWheelWidth(unsigned int w);
|
||||
|
||||
/// Get display flags
|
||||
DisplayFlags displayFlags(DisplayFlags mask = FLAGS_ALL) const;
|
||||
|
||||
/// Set the default display flags
|
||||
static void setDefaultDisplayFlags(DisplayFlags flags);
|
||||
|
||||
/// Get default display flags
|
||||
static DisplayFlags defaultDisplayFlags(DisplayFlags mask = FLAGS_ALL);
|
||||
|
||||
/**
|
||||
* @brief Set a specific display flag
|
||||
* @param flag Flag replacing the mask
|
||||
* @param mask Mask to be cleared
|
||||
*/
|
||||
void setDisplayFlag(DisplayFlags flag, DisplayFlags mask);
|
||||
|
||||
public Q_SLOTS:
|
||||
|
||||
/// Set current color
|
||||
void setColor(QColor c);
|
||||
|
||||
/**
|
||||
* @param h Hue [0-1]
|
||||
*/
|
||||
void setHue(qreal h);
|
||||
|
||||
/**
|
||||
* @param s Saturation [0-1]
|
||||
*/
|
||||
void setSaturation(qreal s);
|
||||
|
||||
/**
|
||||
* @param v Value [0-1]
|
||||
*/
|
||||
void setValue(qreal v);
|
||||
|
||||
/**
|
||||
* @brief Set the display flags
|
||||
* @param flags which will replace the current ones
|
||||
*/
|
||||
void setDisplayFlags(ColorWheel::DisplayFlags flags);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* Emitted when the user selects a color or setColor is called
|
||||
*/
|
||||
void colorChanged(QColor);
|
||||
|
||||
/**
|
||||
* Emitted when the user selects a color
|
||||
*/
|
||||
void colorSelected(QColor);
|
||||
|
||||
void displayFlagsChanged(ColorWheel::DisplayFlags flags);
|
||||
|
||||
void mouseReleaseOnColor(QColor);
|
||||
|
||||
protected:
|
||||
void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
|
||||
void mouseMoveEvent(QMouseEvent *) Q_DECL_OVERRIDE;
|
||||
void mousePressEvent(QMouseEvent *) Q_DECL_OVERRIDE;
|
||||
void resizeEvent(QResizeEvent *) Q_DECL_OVERRIDE;
|
||||
void mouseReleaseEvent(QMouseEvent *) Q_DECL_OVERRIDE;
|
||||
void dragEnterEvent(QDragEnterEvent* event) Q_DECL_OVERRIDE;
|
||||
void dropEvent(QDropEvent* event) Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private * const p;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(ColorWheel::DisplayFlags)
|
||||
|
||||
} // namespace color_widgets
|
||||
|
||||
#endif // COLOR_WHEEL_HPP
|
||||
BIN
src/third-party/Qt-Color-Widgets/src/alphaback.png
vendored
BIN
src/third-party/Qt-Color-Widgets/src/alphaback.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 208 B |
@@ -1,81 +0,0 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Mattia Basaglia
|
||||
*
|
||||
* \copyright Copyright (C) 2013-2017 Mattia Basaglia
|
||||
*
|
||||
* This program 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 3 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "color_utils.hpp"
|
||||
|
||||
namespace color_widgets {
|
||||
namespace detail {
|
||||
|
||||
QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha)
|
||||
{
|
||||
qreal h1 = hue * 6;
|
||||
qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1));
|
||||
QColor col;
|
||||
if (h1 >= 0 && h1 < 1)
|
||||
col = QColor::fromRgbF(chroma, x, 0);
|
||||
else if (h1 < 2)
|
||||
col = QColor::fromRgbF(x, chroma, 0);
|
||||
else if (h1 < 3)
|
||||
col = QColor::fromRgbF(0, chroma, x);
|
||||
else if (h1 < 4)
|
||||
col = QColor::fromRgbF(0, x, chroma);
|
||||
else if (h1 < 5)
|
||||
col = QColor::fromRgbF(x, 0, chroma);
|
||||
else if (h1 < 6)
|
||||
col = QColor::fromRgbF(chroma, 0, x);
|
||||
|
||||
qreal m = luma - color_lumaF(col);
|
||||
|
||||
return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0),
|
||||
qBound(0.0, col.greenF() + m, 1.0),
|
||||
qBound(0.0, col.blueF() + m, 1.0),
|
||||
alpha);
|
||||
}
|
||||
|
||||
QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha)
|
||||
{
|
||||
qreal chroma = (1 - qAbs(2 * lig - 1)) * sat;
|
||||
qreal h1 = hue * 6;
|
||||
qreal x = chroma * (1 - qAbs(std::fmod(h1, 2) - 1));
|
||||
QColor col;
|
||||
if (h1 >= 0 && h1 < 1)
|
||||
col = QColor::fromRgbF(chroma, x, 0);
|
||||
else if (h1 < 2)
|
||||
col = QColor::fromRgbF(x, chroma, 0);
|
||||
else if (h1 < 3)
|
||||
col = QColor::fromRgbF(0, chroma, x);
|
||||
else if (h1 < 4)
|
||||
col = QColor::fromRgbF(0, x, chroma);
|
||||
else if (h1 < 5)
|
||||
col = QColor::fromRgbF(x, 0, chroma);
|
||||
else if (h1 < 6)
|
||||
col = QColor::fromRgbF(chroma, 0, x);
|
||||
|
||||
qreal m = lig - chroma / 2;
|
||||
|
||||
return QColor::fromRgbF(qBound(0.0, col.redF() + m, 1.0),
|
||||
qBound(0.0, col.greenF() + m, 1.0),
|
||||
qBound(0.0, col.blueF() + m, 1.0),
|
||||
alpha);
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace color_widgets
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Mattia Basaglia
|
||||
*
|
||||
* \copyright Copyright (C) 2013-2017 Mattia Basaglia
|
||||
*
|
||||
* This program 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 3 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include <QColor>
|
||||
#include <qmath.h>
|
||||
|
||||
namespace color_widgets {
|
||||
namespace detail {
|
||||
|
||||
|
||||
inline qreal color_chromaF(const QColor& c)
|
||||
{
|
||||
qreal max = qMax(c.redF(), qMax(c.greenF(), c.blueF()));
|
||||
qreal min = qMin(c.redF(), qMin(c.greenF(), c.blueF()));
|
||||
return max - min;
|
||||
}
|
||||
|
||||
inline qreal color_lumaF(const QColor& c)
|
||||
{
|
||||
return 0.30 * c.redF() + 0.59 * c.greenF() + 0.11 * c.blueF();
|
||||
}
|
||||
QColor color_from_lch(qreal hue, qreal chroma, qreal luma, qreal alpha = 1 );
|
||||
|
||||
inline QColor rainbow_lch(qreal hue)
|
||||
{
|
||||
return color_from_lch(hue,1,1);
|
||||
}
|
||||
|
||||
inline QColor rainbow_hsv(qreal hue)
|
||||
{
|
||||
return QColor::fromHsvF(hue,1,1);
|
||||
}
|
||||
|
||||
inline qreal color_lightnessF(const QColor& c)
|
||||
{
|
||||
return ( qMax(c.redF(),qMax(c.greenF(),c.blueF())) +
|
||||
qMin(c.redF(),qMin(c.greenF(),c.blueF())) ) / 2;
|
||||
}
|
||||
|
||||
inline qreal color_HSL_saturationF(const QColor& col)
|
||||
{
|
||||
qreal c = color_chromaF(col);
|
||||
qreal l = color_lightnessF(col);
|
||||
if ( qFuzzyCompare(l+1,1) || qFuzzyCompare(l+1,2) )
|
||||
return 0;
|
||||
return c / (1-qAbs(2*l-1));
|
||||
}
|
||||
|
||||
QColor color_from_hsl(qreal hue, qreal sat, qreal lig, qreal alpha = 1 );
|
||||
|
||||
} // namespace detail
|
||||
} // namespace color_widgets
|
||||
545
src/third-party/Qt-Color-Widgets/src/color_wheel.cpp
vendored
545
src/third-party/Qt-Color-Widgets/src/color_wheel.cpp
vendored
@@ -1,545 +0,0 @@
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \author Mattia Basaglia
|
||||
*
|
||||
* \copyright Copyright (C) 2013-2017 Mattia Basaglia
|
||||
*
|
||||
* This program 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 3 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.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#include "color_wheel.hpp"
|
||||
|
||||
#include "color_utils.hpp"
|
||||
#include <QDragEnterEvent>
|
||||
#include <QLineF>
|
||||
#include <QMimeData>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <cmath>
|
||||
|
||||
namespace color_widgets {
|
||||
|
||||
enum MouseStatus
|
||||
{
|
||||
Nothing,
|
||||
DragCircle,
|
||||
DragSquare
|
||||
};
|
||||
|
||||
static const ColorWheel::DisplayFlags hard_default_flags =
|
||||
ColorWheel::SHAPE_TRIANGLE | ColorWheel::ANGLE_ROTATING |
|
||||
ColorWheel::COLOR_HSV;
|
||||
static ColorWheel::DisplayFlags default_flags = hard_default_flags;
|
||||
static const double selector_radius = 6;
|
||||
|
||||
class ColorWheel::Private
|
||||
{
|
||||
private:
|
||||
ColorWheel* const w;
|
||||
|
||||
public:
|
||||
qreal hue, sat, val;
|
||||
qreal bgBrightness;
|
||||
unsigned int wheel_width;
|
||||
MouseStatus mouse_status;
|
||||
QPixmap hue_ring;
|
||||
QImage inner_selector;
|
||||
DisplayFlags display_flags;
|
||||
QColor (*color_from)(qreal, qreal, qreal, qreal);
|
||||
QColor (*rainbow_from_hue)(qreal);
|
||||
int max_size = 128;
|
||||
|
||||
explicit Private(ColorWheel* widget)
|
||||
: w(widget)
|
||||
, hue(0)
|
||||
, sat(0)
|
||||
, val(0)
|
||||
, wheel_width(20)
|
||||
, mouse_status(Nothing)
|
||||
, display_flags(FLAGS_DEFAULT)
|
||||
, color_from(&QColor::fromHsvF)
|
||||
, rainbow_from_hue(&detail::rainbow_hsv)
|
||||
{
|
||||
QColor bgColor = widget->palette().background().color();
|
||||
bgBrightness = color_widgets::detail::color_lumaF(bgColor);
|
||||
}
|
||||
|
||||
/// Calculate outer wheel radius from idget center
|
||||
qreal outer_radius() const
|
||||
{
|
||||
return qMin(w->geometry().width(), w->geometry().height()) / 2;
|
||||
}
|
||||
|
||||
/// Calculate inner wheel radius from idget center
|
||||
qreal inner_radius() const { return outer_radius() - wheel_width; }
|
||||
|
||||
/// Calculate the edge length of the inner square
|
||||
qreal square_size() const { return inner_radius() * qSqrt(2); }
|
||||
|
||||
/// Calculate the height of the inner triangle
|
||||
qreal triangle_height() const { return inner_radius() * 3 / 2; }
|
||||
|
||||
/// Calculate the side of the inner triangle
|
||||
qreal triangle_side() const { return inner_radius() * qSqrt(3); }
|
||||
|
||||
/// return line from center to given point
|
||||
QLineF line_to_point(const QPoint& p) const
|
||||
{
|
||||
return QLineF(
|
||||
w->geometry().width() / 2, w->geometry().height() / 2, p.x(), p.y());
|
||||
}
|
||||
|
||||
void render_square()
|
||||
{
|
||||
int width = qMin<int>(square_size(), max_size);
|
||||
QSize size(width, width);
|
||||
inner_selector = QImage(size, QImage::Format_RGB32);
|
||||
|
||||
for (int y = 0; y < width; ++y) {
|
||||
for (int x = 0; x < width; ++x) {
|
||||
inner_selector.setPixel(
|
||||
x,
|
||||
y,
|
||||
color_from(hue, double(x) / width, double(y) / width, 1)
|
||||
.rgb());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief renders the selector as a triangle
|
||||
* \note It's the same as a square with the edge with value=0 collapsed to a
|
||||
* single point
|
||||
*/
|
||||
void render_triangle()
|
||||
{
|
||||
QSizeF size = selector_size();
|
||||
if (size.height() > max_size)
|
||||
size *= max_size / size.height();
|
||||
|
||||
qreal ycenter = size.height() / 2;
|
||||
inner_selector = QImage(size.toSize(), QImage::Format_RGB32);
|
||||
|
||||
for (int x = 0; x < inner_selector.width(); x++) {
|
||||
qreal pval = x / size.height();
|
||||
qreal slice_h = size.height() * pval;
|
||||
for (int y = 0; y < inner_selector.height(); y++) {
|
||||
qreal ymin = ycenter - slice_h / 2;
|
||||
qreal psat = qBound(0.0, (y - ymin) / slice_h, 1.0);
|
||||
|
||||
inner_selector.setPixel(
|
||||
x, y, color_from(hue, psat, pval, 1).rgb());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the inner image that displays the saturation-value selector
|
||||
void render_inner_selector()
|
||||
{
|
||||
if (display_flags & ColorWheel::SHAPE_TRIANGLE)
|
||||
render_triangle();
|
||||
else
|
||||
render_square();
|
||||
}
|
||||
|
||||
/// Offset of the selector image
|
||||
QPointF selector_image_offset()
|
||||
{
|
||||
if (display_flags & SHAPE_TRIANGLE)
|
||||
return QPointF(-inner_radius(), -triangle_side() / 2);
|
||||
return QPointF(-square_size() / 2, -square_size() / 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Size of the selector when rendered to the screen
|
||||
*/
|
||||
QSizeF selector_size()
|
||||
{
|
||||
if (display_flags & SHAPE_TRIANGLE)
|
||||
return QSizeF(triangle_height(), triangle_side());
|
||||
return QSizeF(square_size(), square_size());
|
||||
}
|
||||
|
||||
/// Rotation of the selector image
|
||||
qreal selector_image_angle()
|
||||
{
|
||||
if (display_flags & SHAPE_TRIANGLE) {
|
||||
if (display_flags & ANGLE_ROTATING)
|
||||
return -hue * 360 - 60;
|
||||
return -150;
|
||||
} else {
|
||||
if (display_flags & ANGLE_ROTATING)
|
||||
return -hue * 360 - 45;
|
||||
else
|
||||
return 180;
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates the outer ring that displays the hue selector
|
||||
void render_ring()
|
||||
{
|
||||
hue_ring = QPixmap(outer_radius() * 2, outer_radius() * 2);
|
||||
hue_ring.fill(Qt::transparent);
|
||||
QPainter painter(&hue_ring);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
|
||||
const int hue_stops = 24;
|
||||
QConicalGradient gradient_hue(0, 0, 0);
|
||||
if (gradient_hue.stops().size() < hue_stops) {
|
||||
for (double a = 0; a < 1.0; a += 1.0 / (hue_stops - 1)) {
|
||||
gradient_hue.setColorAt(a, rainbow_from_hue(a));
|
||||
}
|
||||
gradient_hue.setColorAt(1, rainbow_from_hue(0));
|
||||
}
|
||||
|
||||
painter.translate(outer_radius(), outer_radius());
|
||||
|
||||
painter.setPen(Qt::NoPen);
|
||||
painter.setBrush(QBrush(gradient_hue));
|
||||
painter.drawEllipse(QPointF(0, 0), outer_radius(), outer_radius());
|
||||
|
||||
painter.setBrush(Qt::transparent); // palette().background());
|
||||
painter.drawEllipse(QPointF(0, 0), inner_radius(), inner_radius());
|
||||
}
|
||||
|
||||
void set_color(const QColor& c)
|
||||
{
|
||||
if (display_flags & ColorWheel::COLOR_HSV) {
|
||||
hue = qMax(0.0, c.hsvHueF());
|
||||
sat = c.hsvSaturationF();
|
||||
val = c.valueF();
|
||||
} else if (display_flags & ColorWheel::COLOR_HSL) {
|
||||
hue = qMax(0.0, c.hueF());
|
||||
sat = detail::color_HSL_saturationF(c);
|
||||
val = detail::color_lightnessF(c);
|
||||
} else if (display_flags & ColorWheel::COLOR_LCH) {
|
||||
hue = qMax(0.0, c.hsvHueF());
|
||||
sat = detail::color_chromaF(c);
|
||||
val = detail::color_lumaF(c);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ColorWheel::ColorWheel(QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, p(new Private(this))
|
||||
{
|
||||
setDisplayFlags(FLAGS_DEFAULT);
|
||||
setAcceptDrops(true);
|
||||
}
|
||||
|
||||
ColorWheel::~ColorWheel()
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
|
||||
QColor ColorWheel::color() const
|
||||
{
|
||||
return p->color_from(p->hue, p->sat, p->val, 1);
|
||||
}
|
||||
|
||||
QSize ColorWheel::sizeHint() const
|
||||
{
|
||||
return QSize(p->wheel_width * 5, p->wheel_width * 5);
|
||||
}
|
||||
|
||||
qreal ColorWheel::hue() const
|
||||
{
|
||||
if ((p->display_flags & COLOR_LCH) && p->sat > 0.01)
|
||||
return color().hueF();
|
||||
return p->hue;
|
||||
}
|
||||
|
||||
qreal ColorWheel::saturation() const
|
||||
{
|
||||
return color().hsvSaturationF();
|
||||
}
|
||||
|
||||
qreal ColorWheel::value() const
|
||||
{
|
||||
return color().valueF();
|
||||
}
|
||||
|
||||
unsigned int ColorWheel::wheelWidth() const
|
||||
{
|
||||
return p->wheel_width;
|
||||
}
|
||||
|
||||
void ColorWheel::setWheelWidth(unsigned int w)
|
||||
{
|
||||
p->wheel_width = w;
|
||||
p->render_inner_selector();
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorWheel::paintEvent(QPaintEvent*)
|
||||
{
|
||||
QPainter painter(this);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
painter.translate(geometry().width() / 2, geometry().height() / 2);
|
||||
|
||||
// hue wheel
|
||||
if (p->hue_ring.isNull())
|
||||
p->render_ring();
|
||||
|
||||
painter.drawPixmap(-p->outer_radius(), -p->outer_radius(), p->hue_ring);
|
||||
|
||||
// hue selector
|
||||
QColor penColor = p->bgBrightness < 0.6 ? Qt::white : Qt::black;
|
||||
painter.setPen(QPen(penColor, 3));
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
QLineF ray(0, 0, p->outer_radius(), 0);
|
||||
ray.setAngle(p->hue * 360);
|
||||
QPointF h1 = ray.p2();
|
||||
ray.setLength(p->inner_radius());
|
||||
QPointF h2 = ray.p2();
|
||||
painter.drawLine(h1, h2);
|
||||
|
||||
// lum-sat square
|
||||
if (p->inner_selector.isNull())
|
||||
p->render_inner_selector();
|
||||
|
||||
painter.rotate(p->selector_image_angle());
|
||||
painter.translate(p->selector_image_offset());
|
||||
|
||||
QPointF selector_position;
|
||||
if (p->display_flags & SHAPE_SQUARE) {
|
||||
qreal side = p->square_size();
|
||||
selector_position = QPointF(p->sat * side, p->val * side);
|
||||
} else if (p->display_flags & SHAPE_TRIANGLE) {
|
||||
qreal side = p->triangle_side();
|
||||
qreal height = p->triangle_height();
|
||||
qreal slice_h = side * p->val;
|
||||
qreal ymin = side / 2 - slice_h / 2;
|
||||
|
||||
selector_position = QPointF(p->val * height, ymin + p->sat * slice_h);
|
||||
QPolygonF triangle;
|
||||
triangle.append(QPointF(0, side / 2));
|
||||
triangle.append(QPointF(height, 0));
|
||||
triangle.append(QPointF(height, side));
|
||||
QPainterPath clip;
|
||||
clip.addPolygon(triangle);
|
||||
painter.setClipPath(clip);
|
||||
}
|
||||
|
||||
painter.drawImage(QRectF(QPointF(0, 0), p->selector_size()),
|
||||
p->inner_selector);
|
||||
painter.setClipping(false);
|
||||
|
||||
// lum-sat selector
|
||||
// we define the color of the selecto based on the background color of the
|
||||
// widget in order to improve the contrast
|
||||
qreal colorBrightness = color_widgets::detail::color_lumaF(color());
|
||||
if (p->bgBrightness < 0.6) // dark theme
|
||||
{
|
||||
bool isWhite = (colorBrightness < 0.7);
|
||||
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
|
||||
} else // light theme
|
||||
{
|
||||
bool isWhite = (colorBrightness < 0.4 && p->val < 0.3);
|
||||
painter.setPen(QPen(isWhite ? Qt::white : Qt::black, 3));
|
||||
}
|
||||
painter.setBrush(Qt::NoBrush);
|
||||
painter.drawEllipse(selector_position, selector_radius, selector_radius);
|
||||
}
|
||||
|
||||
void ColorWheel::mouseMoveEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (p->mouse_status == DragCircle) {
|
||||
p->hue = p->line_to_point(ev->pos()).angle() / 360.0;
|
||||
p->render_inner_selector();
|
||||
|
||||
emit colorSelected(color());
|
||||
emit colorChanged(color());
|
||||
update();
|
||||
} else if (p->mouse_status == DragSquare) {
|
||||
QLineF glob_mouse_ln = p->line_to_point(ev->pos());
|
||||
QLineF center_mouse_ln(QPointF(0, 0),
|
||||
glob_mouse_ln.p2() - glob_mouse_ln.p1());
|
||||
|
||||
center_mouse_ln.setAngle(center_mouse_ln.angle() +
|
||||
p->selector_image_angle());
|
||||
center_mouse_ln.setP2(center_mouse_ln.p2() -
|
||||
p->selector_image_offset());
|
||||
|
||||
if (p->display_flags & SHAPE_SQUARE) {
|
||||
p->sat = qBound(0.0, center_mouse_ln.x2() / p->square_size(), 1.0);
|
||||
p->val = qBound(0.0, center_mouse_ln.y2() / p->square_size(), 1.0);
|
||||
} else if (p->display_flags & SHAPE_TRIANGLE) {
|
||||
QPointF pt = center_mouse_ln.p2();
|
||||
|
||||
qreal side = p->triangle_side();
|
||||
p->val = qBound(0.0, pt.x() / p->triangle_height(), 1.0);
|
||||
qreal slice_h = side * p->val;
|
||||
|
||||
qreal ycenter = side / 2;
|
||||
qreal ymin = ycenter - slice_h / 2;
|
||||
|
||||
if (slice_h > 0)
|
||||
p->sat = qBound(0.0, (pt.y() - ymin) / slice_h, 1.0);
|
||||
}
|
||||
|
||||
emit colorSelected(color());
|
||||
emit colorChanged(color());
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
void ColorWheel::mousePressEvent(QMouseEvent* ev)
|
||||
{
|
||||
if (ev->buttons() & Qt::LeftButton) {
|
||||
setFocus();
|
||||
QLineF ray = p->line_to_point(ev->pos());
|
||||
if (ray.length() <= p->inner_radius())
|
||||
p->mouse_status = DragSquare;
|
||||
else if (ray.length() <= p->outer_radius())
|
||||
p->mouse_status = DragCircle;
|
||||
|
||||
// Update the color
|
||||
mouseMoveEvent(ev);
|
||||
}
|
||||
}
|
||||
|
||||
void ColorWheel::mouseReleaseEvent(QMouseEvent* ev)
|
||||
{
|
||||
mouseMoveEvent(ev);
|
||||
p->mouse_status = Nothing;
|
||||
emit mouseReleaseOnColor(color());
|
||||
}
|
||||
|
||||
void ColorWheel::resizeEvent(QResizeEvent*)
|
||||
{
|
||||
p->render_ring();
|
||||
p->render_inner_selector();
|
||||
}
|
||||
|
||||
void ColorWheel::setColor(QColor c)
|
||||
{
|
||||
qreal oldh = p->hue;
|
||||
p->set_color(c);
|
||||
if (!qFuzzyCompare(oldh + 1, p->hue + 1))
|
||||
p->render_inner_selector();
|
||||
update();
|
||||
emit colorChanged(c);
|
||||
}
|
||||
|
||||
void ColorWheel::setHue(qreal h)
|
||||
{
|
||||
p->hue = qBound(0.0, h, 1.0);
|
||||
p->render_inner_selector();
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorWheel::setSaturation(qreal s)
|
||||
{
|
||||
p->sat = qBound(0.0, s, 1.0);
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorWheel::setValue(qreal v)
|
||||
{
|
||||
p->val = qBound(0.0, v, 1.0);
|
||||
update();
|
||||
}
|
||||
|
||||
void ColorWheel::setDisplayFlags(DisplayFlags flags)
|
||||
{
|
||||
if (!(flags & COLOR_FLAGS))
|
||||
flags |= default_flags & COLOR_FLAGS;
|
||||
if (!(flags & ANGLE_FLAGS))
|
||||
flags |= default_flags & ANGLE_FLAGS;
|
||||
if (!(flags & SHAPE_FLAGS))
|
||||
flags |= default_flags & SHAPE_FLAGS;
|
||||
|
||||
if ((flags & COLOR_FLAGS) != (p->display_flags & COLOR_FLAGS)) {
|
||||
QColor old_col = color();
|
||||
if (flags & ColorWheel::COLOR_HSL) {
|
||||
p->hue = old_col.hueF();
|
||||
p->sat = detail::color_HSL_saturationF(old_col);
|
||||
p->val = detail::color_lightnessF(old_col);
|
||||
p->color_from = &detail::color_from_hsl;
|
||||
p->rainbow_from_hue = &detail::rainbow_hsv;
|
||||
} else if (flags & ColorWheel::COLOR_LCH) {
|
||||
p->hue = old_col.hueF();
|
||||
p->sat = detail::color_chromaF(old_col);
|
||||
p->val = detail::color_lumaF(old_col);
|
||||
p->color_from = &detail::color_from_lch;
|
||||
p->rainbow_from_hue = &detail::rainbow_lch;
|
||||
} else {
|
||||
p->hue = old_col.hsvHueF();
|
||||
p->sat = old_col.hsvSaturationF();
|
||||
p->val = old_col.valueF();
|
||||
p->color_from = &QColor::fromHsvF;
|
||||
p->rainbow_from_hue = &detail::rainbow_hsv;
|
||||
}
|
||||
p->render_ring();
|
||||
}
|
||||
|
||||
p->display_flags = flags;
|
||||
p->render_inner_selector();
|
||||
update();
|
||||
emit displayFlagsChanged(flags);
|
||||
}
|
||||
|
||||
ColorWheel::DisplayFlags ColorWheel::displayFlags(DisplayFlags mask) const
|
||||
{
|
||||
return p->display_flags & mask;
|
||||
}
|
||||
|
||||
void ColorWheel::setDefaultDisplayFlags(DisplayFlags flags)
|
||||
{
|
||||
if (!(flags & COLOR_FLAGS))
|
||||
flags |= hard_default_flags & COLOR_FLAGS;
|
||||
if (!(flags & ANGLE_FLAGS))
|
||||
flags |= hard_default_flags & ANGLE_FLAGS;
|
||||
if (!(flags & SHAPE_FLAGS))
|
||||
flags |= hard_default_flags & SHAPE_FLAGS;
|
||||
default_flags = flags;
|
||||
}
|
||||
|
||||
ColorWheel::DisplayFlags ColorWheel::defaultDisplayFlags(DisplayFlags mask)
|
||||
{
|
||||
return default_flags & mask;
|
||||
}
|
||||
|
||||
void ColorWheel::setDisplayFlag(DisplayFlags flag, DisplayFlags mask)
|
||||
{
|
||||
setDisplayFlags((p->display_flags & ~mask) | flag);
|
||||
}
|
||||
|
||||
void ColorWheel::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
if (event->mimeData()->hasColor() ||
|
||||
(event->mimeData()->hasText() &&
|
||||
QColor(event->mimeData()->text()).isValid()))
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
|
||||
void ColorWheel::dropEvent(QDropEvent* event)
|
||||
{
|
||||
if (event->mimeData()->hasColor()) {
|
||||
setColor(event->mimeData()->colorData().value<QColor>());
|
||||
event->accept();
|
||||
} else if (event->mimeData()->hasText()) {
|
||||
QColor col(event->mimeData()->text());
|
||||
if (col.isValid()) {
|
||||
setColor(col);
|
||||
event->accept();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace color_widgets
|
||||
@@ -1,5 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/color_widgets">
|
||||
<file>alphaback.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
162
src/third-party/singleapplication/CHANGELOG.md
vendored
162
src/third-party/singleapplication/CHANGELOG.md
vendored
@@ -1,162 +0,0 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
__3.0.10__
|
||||
----------
|
||||
|
||||
* Removed C style casts and eliminated all clang warnings. Fixed `instanceId`
|
||||
reading from only one byte in the message deserialization. Cleaned up
|
||||
serialization code using `QDataStream`. Changed connection type to use
|
||||
`quint8 enum` rather than `char`.
|
||||
* Renamed `SingleAppConnectionType` to `ConnectionType`. Added initialization
|
||||
values to all `ConnectionType` enum cases.
|
||||
|
||||
_Jedidiah Buck McCready_
|
||||
|
||||
__3.0.9__
|
||||
---------
|
||||
|
||||
* Added SingleApplicationPrivate::primaryPid() as a solution to allow
|
||||
bringing the primary window of an application to the foreground on
|
||||
Windows.
|
||||
|
||||
_Eelco van Dam from Peacs BV_
|
||||
|
||||
__3.0.8__
|
||||
---------
|
||||
|
||||
* Bug fix - changed QApplication::instance() to QCoreApplication::instance()
|
||||
|
||||
_Evgeniy Bazhenov_
|
||||
|
||||
__3.0.7a__
|
||||
----------
|
||||
|
||||
* Fixed compilation error with Mingw32 in MXE thanks to Vitaly Tonkacheyev.
|
||||
* Removed QMutex used for thread safe behaviour. The implementation now uses
|
||||
QCoreApplication::instance() to get an instance to SingleApplication for
|
||||
memory deallocation.
|
||||
|
||||
__3.0.6a__
|
||||
----------
|
||||
|
||||
* Reverted GetUserName API usage on Windows. Fixed bug with missing library.
|
||||
* Fixed bug in the Calculator example, preventing it's window to be raised
|
||||
on Windows.
|
||||
|
||||
Special thanks to Charles Gunawan.
|
||||
|
||||
__3.0.5a__
|
||||
----------
|
||||
|
||||
* Fixed a memory leak in the SingleApplicationPrivate destructor.
|
||||
|
||||
_Sergei Moiseev_
|
||||
|
||||
__3.0.4a__
|
||||
----------
|
||||
|
||||
* Fixed shadow and uninitialised variable warnings.
|
||||
|
||||
_Paul Walmsley_
|
||||
|
||||
__3.0.3a__
|
||||
----------
|
||||
|
||||
* Removed Microsoft Windows specific code for getting username due to
|
||||
multiple problems and compiler differences on Windows platforms. On
|
||||
Windows the shared memory block in User mode now includes the user's
|
||||
home path (which contains the user's username).
|
||||
|
||||
* Explicitly getting absolute path of the user's home directory as on Unix
|
||||
a relative path (`~`) may be returned.
|
||||
|
||||
__3.0.2a__
|
||||
----------
|
||||
|
||||
* Fixed bug on Windows when username containing wide characters causes the
|
||||
library to crash.
|
||||
|
||||
_Le Liu_
|
||||
|
||||
__3.0.1a__
|
||||
----------
|
||||
|
||||
* Allows the application path and version to be excluded from the server name
|
||||
hash. The following flags were added for this purpose:
|
||||
* `SingleApplication::Mode::ExcludeAppVersion`
|
||||
* `SingleApplication::Mode::ExcludeAppPath`
|
||||
* Allow a non elevated process to connect to a local server created by an
|
||||
elevated process run by the same user on Windows
|
||||
* Fixes a problem with upper case letters in paths on Windows
|
||||
|
||||
_Le Liu_
|
||||
|
||||
__v3.0a__
|
||||
---------
|
||||
|
||||
* Depricated secondary instances count.
|
||||
* Added a sendMessage() method to send a message to the primary instance.
|
||||
* Added a receivedMessage() signal, emitted when a message is received from a
|
||||
secondary instance.
|
||||
* The SingleApplication constructor's third parameter is now a bool
|
||||
specifying if the current instance should be allowed to run as a secondary
|
||||
instance if there is already a primary instance.
|
||||
* The SingleApplication constructor accept a fourth parameter specifying if
|
||||
the SingleApplication block should be User-wide or System-wide.
|
||||
* SingleApplication no longer relies on `applicationName` and
|
||||
`organizationName` to be set. It instead concatenates all of the following
|
||||
data and computes a `SHA256` hash which is used as the key of the
|
||||
`QSharedMemory` block and the `QLocalServer`. Since at least
|
||||
`applicationFilePath` is always present there is no need to explicitly set
|
||||
any of the following prior to initialising `SingleApplication`.
|
||||
* `QCoreApplication::applicationName`
|
||||
* `QCoreApplication::applicationVersion`
|
||||
* `QCoreApplication::applicationFilePath`
|
||||
* `QCoreApplication::organizationName`
|
||||
* `QCoreApplication::organizationDomain`
|
||||
* User name or home directory path if in User mode
|
||||
* The primary instance is no longer notified when a secondary instance had
|
||||
been started by default. A `Mode` flag for this feature exists.
|
||||
* Added `instanceNumber()` which represents a unique identifier for each
|
||||
secondary instance started. When called from the primary instance will
|
||||
return `0`.
|
||||
|
||||
__v2.4__
|
||||
--------
|
||||
|
||||
* Stability improvements
|
||||
* Support for secondary instances.
|
||||
* The library now recovers safely after the primary process has crashed
|
||||
and the shared memory had not been deleted.
|
||||
|
||||
__v2.3__
|
||||
--------
|
||||
|
||||
* Improved pimpl design and inheritance safety.
|
||||
|
||||
_Vladislav Pyatnichenko_
|
||||
|
||||
__v2.2__
|
||||
--------
|
||||
|
||||
* The `QAPPLICATION_CLASS` macro can now be defined in the file including the
|
||||
Single Application header or with a `DEFINES+=` statement in the project file.
|
||||
|
||||
__v2.1__
|
||||
--------
|
||||
|
||||
* A race condition can no longer occur when starting two processes nearly
|
||||
simultaneously.
|
||||
|
||||
Fix issue [#3](https://github.com/itay-grudev/SingleApplication/issues/3)
|
||||
|
||||
__v2.0__
|
||||
--------
|
||||
|
||||
* SingleApplication is now being passed a reference to `argc` instead of a
|
||||
copy.
|
||||
|
||||
Fix issue [#1](https://github.com/itay-grudev/SingleApplication/issues/1)
|
||||
|
||||
* Improved documentation.
|
||||
24
src/third-party/singleapplication/LICENSE
vendored
24
src/third-party/singleapplication/LICENSE
vendored
@@ -1,24 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) Itay Grudev 2015 - 2016
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
Note: Some of the examples include code not distributed under the terms of the
|
||||
MIT License.
|
||||
287
src/third-party/singleapplication/README.md
vendored
287
src/third-party/singleapplication/README.md
vendored
@@ -1,287 +0,0 @@
|
||||
SingleApplication
|
||||
=================
|
||||
|
||||
This is a replacement of the QtSingleApplication for `Qt5`.
|
||||
|
||||
Keeps the Primary Instance of your Application and kills each subsequent
|
||||
instances. It can (if enabled) spawn secondary (non-related to the primary)
|
||||
instances and can send data to the primary instance from secondary instances.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The `SingleApplication` class inherits from whatever `Q[Core|Gui]Application`
|
||||
class you specify via the `QAPPLICATION_CLASS` macro (`QCoreApplication` is the
|
||||
default). Further usage is similar to the use of the `Q[Core|Gui]Application`
|
||||
classes.
|
||||
|
||||
The library sets up a `QLocalServer` and a `QSharedMemory` block. The first
|
||||
instance of your Application is your Primary Instance. It would check if the
|
||||
shared memory block exists and if not it will start a `QLocalServer` and listen
|
||||
for connections. Each subsequent instance of your application would check if the
|
||||
shared memory block exists and if it does, it will connect to the QLocalServer
|
||||
to notify the primary instance that a new instance had been started, after which
|
||||
it would terminate with status code `0`. In the Primary Instance
|
||||
`SingleApplication` would emit the `instanceStarted()` signal upon detecting
|
||||
that a new instance had been started.
|
||||
|
||||
The library uses `stdlib` to terminate the program with the `exit()` function.
|
||||
|
||||
You can use the library as if you use any other `QCoreApplication` derived
|
||||
class:
|
||||
|
||||
```cpp
|
||||
#include <QApplication>
|
||||
#include <SingleApplication.h>
|
||||
|
||||
int main( int argc, char* argv[] )
|
||||
{
|
||||
SingleApplication app( argc, argv );
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
```
|
||||
|
||||
To include the library files I would recommend that you add it as a git
|
||||
submodule to your project and include it's contents with a `.pri` file. Here is
|
||||
how:
|
||||
|
||||
```bash
|
||||
git submodule add git@github.com:itay-grudev/SingleApplication.git singleapplication
|
||||
```
|
||||
|
||||
Then include the `singleapplication.pri` file in your `.pro` project file. Also
|
||||
don't forget to specify which `QCoreApplication` class your app is using if it
|
||||
is not `QCoreApplication`.
|
||||
|
||||
```qmake
|
||||
include(singleapplication/singleapplication.pri)
|
||||
DEFINES += QAPPLICATION_CLASS=QApplication
|
||||
```
|
||||
|
||||
The `Instance Started` signal
|
||||
------------------------
|
||||
|
||||
The SingleApplication class implements a `instanceStarted()` signal. You can
|
||||
bind to that signal to raise your application's window when a new instance had
|
||||
been started, for example.
|
||||
|
||||
```cpp
|
||||
// window is a QWindow instance
|
||||
QObject::connect(
|
||||
&app,
|
||||
&SingleApplication::instanceStarted,
|
||||
&window,
|
||||
&QWindow::raise
|
||||
);
|
||||
```
|
||||
|
||||
Using `SingleApplication::instance()` is a neat way to get the
|
||||
`SingleApplication` instance for binding to it's signals anywhere in your
|
||||
program.
|
||||
|
||||
__Note:__ On Windows the ability to bring the application windows to the
|
||||
foreground is restricted. See [Windows specific implementations](Windows.md)
|
||||
for a workaround and an example implementation.
|
||||
|
||||
|
||||
Secondary Instances
|
||||
-------------------
|
||||
|
||||
If you want to be able to launch additional Secondary Instances (not related to
|
||||
your Primary Instance) you have to enable that with the third parameter of the
|
||||
`SingleApplication` constructor. The default is `false` meaning no Secondary
|
||||
Instances. Here is an example of how you would start a Secondary Instance send
|
||||
a message with the command line arguments to the primary instance and then shut
|
||||
down.
|
||||
|
||||
```cpp
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
SingleApplication app( argc, argv, true );
|
||||
|
||||
if( app.isSecondary() ) {
|
||||
app.sendMessage( app.arguments().join(' ')).toUtf8() );
|
||||
app.exit( 0 );
|
||||
}
|
||||
|
||||
return app.exec();
|
||||
}
|
||||
```
|
||||
|
||||
*__Note:__ A secondary instance won't cause the emission of the
|
||||
`instanceStarted()` signal by default. See `SingleApplication::Mode` for more
|
||||
details.*
|
||||
|
||||
You can check whether your instance is a primary or secondary with the following
|
||||
methods:
|
||||
|
||||
```cpp
|
||||
app.isPrimary();
|
||||
// or
|
||||
app.isSecondary();
|
||||
```
|
||||
|
||||
*__Note:__ If your Primary Instance is terminated a newly launched instance
|
||||
will replace the Primary one even if the Secondary flag has been set.*
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
### Members
|
||||
|
||||
```cpp
|
||||
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 100 )
|
||||
```
|
||||
|
||||
Depending on whether `allowSecondary` is set, this constructor may terminate
|
||||
your app if there is already a primary instance running. Additional `Options`
|
||||
can be specified to set whether the SingleApplication block should work
|
||||
user-wide or system-wide. Additionally the `Mode::SecondaryNotification` may be
|
||||
used to notify the primary instance whenever a secondary instance had been
|
||||
started (disabled by default). `timeout` specifies the maximum time in
|
||||
milliseconds to wait for blocking operations.
|
||||
|
||||
*__Note:__ `argc` and `argv` may be changed as Qt removes arguments that it
|
||||
recognizes.*
|
||||
|
||||
*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
|
||||
and the secondary instance.*
|
||||
|
||||
*__Note:__ Operating system can restrict the shared memory blocks to the same
|
||||
user, in which case the User/System modes will have no effect and the block will
|
||||
be user wide.*
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
bool SingleApplication::sendMessage( QByteArray message, int timeout = 100 )
|
||||
```
|
||||
|
||||
Sends `message` to the Primary Instance. Uses `timeout` as a the maximum timeout
|
||||
in milliseconds for blocking functions
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
bool SingleApplication::isPrimary()
|
||||
```
|
||||
|
||||
Returns if the instance is the primary instance.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
bool SingleApplication::isSecondary()
|
||||
```
|
||||
Returns if the instance is a secondary instance.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
quint32 SingleApplication::instanceId()
|
||||
```
|
||||
|
||||
Returns a unique identifier for the current instance.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
qint64 SingleApplication::primaryPid()
|
||||
```
|
||||
|
||||
Returns the process ID (PID) of the primary instance.
|
||||
|
||||
### Signals
|
||||
|
||||
```cpp
|
||||
void SingleApplication::instanceStarted()
|
||||
```
|
||||
|
||||
Triggered whenever a new instance had been started, except for secondary
|
||||
instances if the `Mode::SecondaryNotification` flag is not specified.
|
||||
|
||||
---
|
||||
|
||||
```cpp
|
||||
void SingleApplication::receivedMessage( quint32 instanceId, QByteArray message )
|
||||
```
|
||||
|
||||
Triggered whenever there is a message received from a secondary instance.
|
||||
|
||||
---
|
||||
|
||||
### Flags
|
||||
|
||||
```cpp
|
||||
enum SingleApplication::Mode
|
||||
```
|
||||
|
||||
* `Mode::User` - The SingleApplication block should apply user wide. This adds
|
||||
user specific data to the key used for the shared memory and server name.
|
||||
This is the default functionality.
|
||||
* `Mode::System` – The SingleApplication block applies system-wide.
|
||||
* `Mode::SecondaryNotification` – Whether to trigger `instanceStarted()` even
|
||||
whenever secondary instances are started.
|
||||
* `Mode::ExcludeAppPath` – Excludes the application path from the server name
|
||||
(and memory block) hash.
|
||||
* `Mode::ExcludeAppVersion` – Excludes the application version from the server
|
||||
name (and memory block) hash.
|
||||
|
||||
*__Note:__ `Mode::SecondaryNotification` only works if set on both the primary
|
||||
and the secondary instance.*
|
||||
|
||||
*__Note:__ Operating system can restrict the shared memory blocks to the same
|
||||
user, in which case the User/System modes will have no effect and the block will
|
||||
be user wide.*
|
||||
|
||||
---
|
||||
|
||||
Versioning
|
||||
----------
|
||||
|
||||
Each major version introduces either very significant changes or is not
|
||||
backwards compatible with the previous version. Minor versions only add
|
||||
additional features, bug fixes or performance improvements and are backwards
|
||||
compatible with the previous release. See [`CHANGELOG.md`](CHANGELOG.md) for
|
||||
more details.
|
||||
|
||||
Implementation
|
||||
--------------
|
||||
|
||||
The library is implemented with a QSharedMemory block which is thread safe and
|
||||
guarantees a race condition will not occur. It also uses a QLocalSocket to
|
||||
notify the main process that a new instance had been spawned and thus invoke the
|
||||
`instanceStarted()` signal.
|
||||
|
||||
To handle an issue on `*nix` systems, where the operating system owns the shared
|
||||
memory block and if the program crashes the memory remains untouched, the
|
||||
library binds to the following signals and closes the program with
|
||||
`error code = 128 + signum` where signum is the number representation of the
|
||||
signal listed below. Handling the signal is required in order to safely delete
|
||||
the `QSharedMemory` block. Each of these signals are potentially lethal and will
|
||||
results in process termination.
|
||||
|
||||
* `SIGHUP` - `1`, Hangup.
|
||||
* `SIGINT` - `2`, Terminal interrupt signal
|
||||
* `SIGQUIT` - `3`, Terminal quit signal.
|
||||
* `SIGILL` - `4`, Illegal instruction.
|
||||
* `SIGABRT` - `6`, Process abort signal.
|
||||
* `SIGBUS` - `7`, Access to an undefined portion of a memory object.
|
||||
* `SIGFPE` - `8`, Erroneous arithmetic operation (such as division by zero).
|
||||
* `SIGSEGV` - `11`, Invalid memory reference.
|
||||
* `SIGSYS` - `12`, Bad system call.
|
||||
* `SIGPIPE` - `13`, Write on a pipe with no one to read it.
|
||||
* `SIGALRM` - `14`, Alarm clock.
|
||||
* `SIGTERM` - `15`, Termination signal.
|
||||
* `SIGXCPU` - `24`, CPU time limit exceeded.
|
||||
* `SIGXFSZ` - `25`, File size limit exceeded.
|
||||
|
||||
Additionally the library can recover from being killed with uncatchable signals
|
||||
and will reset the memory block given that there are no other instances running.
|
||||
|
||||
License
|
||||
-------
|
||||
This library and it's supporting documentation are released under
|
||||
`The MIT License (MIT)` with the exception of some of the examples distributed
|
||||
under the BSD license.
|
||||
46
src/third-party/singleapplication/Windows.md
vendored
46
src/third-party/singleapplication/Windows.md
vendored
@@ -1,46 +0,0 @@
|
||||
Windows Specific Implementations
|
||||
================================
|
||||
|
||||
Setting the foreground window
|
||||
-----------------------------
|
||||
|
||||
In the `instanceStarted()` example in the `README` we demonstrated how an
|
||||
application can bring it's primary instance window whenever a second copy
|
||||
of the application is started.
|
||||
|
||||
On Windows the ability to bring the application windows to the foreground is
|
||||
restricted, see [`AllowSetForegroundWindow()`][AllowSetForegroundWindow] for more
|
||||
details.
|
||||
|
||||
The background process (the primary instance) can bring its windows to the
|
||||
foreground if it is allowed by the current foreground process (the secondary
|
||||
instance). To bypass this `SingleApplication` must be initialized with the
|
||||
`allowSecondary` parameter set to `true` and the `options` parameter must
|
||||
include `Mode::SecondaryNotification`, See `SingleApplication::Mode` for more
|
||||
details.
|
||||
|
||||
Here is an example:
|
||||
|
||||
```cpp
|
||||
if( app.isSecondary() ) {
|
||||
// This API requires LIBS += User32.lib to be added to the project
|
||||
AllowSetForegroundWindow( DWORD( app.getPrimaryPid() ) );
|
||||
}
|
||||
|
||||
if( app.isPrimary() ) {
|
||||
QObject::connect(
|
||||
&app,
|
||||
&SingleApplication::instanceStarted,
|
||||
this,
|
||||
&App::instanceStarted
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
```cpp
|
||||
void App::instanceStarted() {
|
||||
QApplication::setActiveWindow( [window/widget to set to the foreground] );
|
||||
}
|
||||
```
|
||||
|
||||
[AllowSetForegroundWindow]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms632668.aspx
|
||||
@@ -1,508 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) Itay Grudev 2015 - 2016
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <QMessageBox>
|
||||
#include <QTimer>
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QCryptographicHash>
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QProcess>
|
||||
#include <QtCore/QSemaphore>
|
||||
#include <QtCore/QSharedMemory>
|
||||
#include <QtCore/QStandardPaths>
|
||||
#include <QtNetwork/QLocalServer>
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#include <lmcons.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "singleapplication.h"
|
||||
#include "singleapplication_p.h"
|
||||
|
||||
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication* q_ptr)
|
||||
: q_ptr(q_ptr)
|
||||
{
|
||||
server = nullptr;
|
||||
socket = nullptr;
|
||||
}
|
||||
|
||||
SingleApplicationPrivate::~SingleApplicationPrivate()
|
||||
{
|
||||
if (socket != nullptr) {
|
||||
socket->close();
|
||||
delete socket;
|
||||
}
|
||||
|
||||
memory->lock();
|
||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||
if (server != nullptr) {
|
||||
server->close();
|
||||
delete server;
|
||||
inst->primary = false;
|
||||
inst->primaryPid = -1;
|
||||
}
|
||||
memory->unlock();
|
||||
|
||||
delete memory;
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::genBlockServerName(int timeout)
|
||||
{
|
||||
QCryptographicHash appData(QCryptographicHash::Sha256);
|
||||
appData.addData("SingleApplication", 17);
|
||||
appData.addData(SingleApplication::app_t::applicationName().toUtf8());
|
||||
appData.addData(SingleApplication::app_t::organizationName().toUtf8());
|
||||
appData.addData(SingleApplication::app_t::organizationDomain().toUtf8());
|
||||
|
||||
if (!(options & SingleApplication::Mode::ExcludeAppVersion)) {
|
||||
appData.addData(
|
||||
SingleApplication::app_t::applicationVersion().toUtf8());
|
||||
}
|
||||
|
||||
if (!(options & SingleApplication::Mode::ExcludeAppPath)) {
|
||||
#ifdef Q_OS_WIN
|
||||
appData.addData(
|
||||
SingleApplication::app_t::applicationFilePath().toLower().toUtf8());
|
||||
#else
|
||||
appData.addData(
|
||||
SingleApplication::app_t::applicationFilePath().toUtf8());
|
||||
#endif
|
||||
}
|
||||
|
||||
// User level block requires a user specific data in the hash
|
||||
if (options & SingleApplication::Mode::User) {
|
||||
#ifdef Q_OS_WIN
|
||||
Q_UNUSED(timeout);
|
||||
wchar_t username[UNLEN + 1];
|
||||
// Specifies size of the buffer on input
|
||||
DWORD usernameLength = UNLEN + 1;
|
||||
if (GetUserNameW(username, &usernameLength)) {
|
||||
appData.addData(QString::fromWCharArray(username).toUtf8());
|
||||
} else {
|
||||
appData.addData(
|
||||
QStandardPaths::standardLocations(QStandardPaths::HomeLocation)
|
||||
.join("")
|
||||
.toUtf8());
|
||||
}
|
||||
#endif
|
||||
#ifdef Q_OS_UNIX
|
||||
QProcess process;
|
||||
process.start(QStringLiteral("whoami"));
|
||||
if (process.waitForFinished(timeout) &&
|
||||
process.exitCode() == QProcess::NormalExit) {
|
||||
appData.addData(process.readLine());
|
||||
} else {
|
||||
appData.addData(QDir(QStandardPaths::standardLocations(
|
||||
QStandardPaths::HomeLocation)
|
||||
.first())
|
||||
.absolutePath()
|
||||
.toUtf8());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
|
||||
// server naming requirements.
|
||||
blockServerName = appData.result().toBase64().replace("/", "_");
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::startPrimary(bool resetMemory)
|
||||
{
|
||||
Q_Q(SingleApplication);
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
// Handle any further termination signals to ensure the
|
||||
// QSharedMemory block is deleted even if the process crashes
|
||||
crashHandler();
|
||||
#endif
|
||||
// Successful creation means that no main process exists
|
||||
// So we start a QLocalServer to listen for connections
|
||||
QLocalServer::removeServer(blockServerName);
|
||||
server = new QLocalServer();
|
||||
|
||||
// Restrict access to the socket according to the
|
||||
// SingleApplication::Mode::User flag on User level or no restrictions
|
||||
if (options & SingleApplication::Mode::User) {
|
||||
server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||
} else {
|
||||
server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
}
|
||||
|
||||
server->listen(blockServerName);
|
||||
QObject::connect(server,
|
||||
&QLocalServer::newConnection,
|
||||
this,
|
||||
&SingleApplicationPrivate::slotConnectionEstablished);
|
||||
|
||||
// Reset the number of connections
|
||||
memory->lock();
|
||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||
|
||||
if (resetMemory) {
|
||||
inst->secondary = 0;
|
||||
}
|
||||
|
||||
inst->primary = true;
|
||||
inst->primaryPid = q->applicationPid();
|
||||
|
||||
memory->unlock();
|
||||
|
||||
instanceNumber = 0;
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::startSecondary()
|
||||
{
|
||||
#ifdef Q_OS_UNIX
|
||||
// Handle any further termination signals to ensure the
|
||||
// QSharedMemory block is deleted even if the process crashes
|
||||
crashHandler();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::connectToPrimary(int msecs,
|
||||
ConnectionType connectionType)
|
||||
{
|
||||
// Connect to the Local Server of the Primary Instance if not already
|
||||
// connected.
|
||||
if (socket == nullptr) {
|
||||
socket = new QLocalSocket();
|
||||
}
|
||||
|
||||
// If already connected - we are done;
|
||||
if (socket->state() == QLocalSocket::ConnectedState)
|
||||
return;
|
||||
|
||||
// If not connect
|
||||
if (socket->state() == QLocalSocket::UnconnectedState ||
|
||||
socket->state() == QLocalSocket::ClosingState) {
|
||||
socket->connectToServer(blockServerName);
|
||||
}
|
||||
|
||||
// Wait for being connected
|
||||
if (socket->state() == QLocalSocket::ConnectingState) {
|
||||
socket->waitForConnected(msecs);
|
||||
}
|
||||
|
||||
// Initialisation message according to the SingleApplication protocol
|
||||
if (socket->state() == QLocalSocket::ConnectedState) {
|
||||
// Notify the parent that a new instance had been started;
|
||||
QByteArray initMsg;
|
||||
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
||||
writeStream.setVersion(QDataStream::Qt_5_2);
|
||||
writeStream << blockServerName.toLatin1();
|
||||
writeStream << static_cast<quint8>(connectionType);
|
||||
writeStream << instanceNumber;
|
||||
quint16 checksum = qChecksum(initMsg.constData(),
|
||||
static_cast<quint32>(initMsg.length()));
|
||||
writeStream << checksum;
|
||||
|
||||
socket->write(initMsg);
|
||||
socket->flush();
|
||||
socket->waitForBytesWritten(msecs);
|
||||
}
|
||||
}
|
||||
|
||||
qint64 SingleApplicationPrivate::primaryPid()
|
||||
{
|
||||
qint64 pid;
|
||||
|
||||
memory->lock();
|
||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||
pid = inst->primaryPid;
|
||||
memory->unlock();
|
||||
|
||||
return pid;
|
||||
}
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
void SingleApplicationPrivate::crashHandler()
|
||||
{
|
||||
// Handle any further termination signals to ensure the
|
||||
// QSharedMemory block is deleted even if the process crashes
|
||||
signal(SIGHUP, SingleApplicationPrivate::terminate); // 1
|
||||
signal(SIGINT, SingleApplicationPrivate::terminate); // 2
|
||||
signal(SIGQUIT, SingleApplicationPrivate::terminate); // 3
|
||||
signal(SIGILL, SingleApplicationPrivate::terminate); // 4
|
||||
signal(SIGABRT, SingleApplicationPrivate::terminate); // 6
|
||||
signal(SIGFPE, SingleApplicationPrivate::terminate); // 8
|
||||
signal(SIGBUS, SingleApplicationPrivate::terminate); // 10
|
||||
signal(SIGSEGV, SingleApplicationPrivate::terminate); // 11
|
||||
signal(SIGSYS, SingleApplicationPrivate::terminate); // 12
|
||||
signal(SIGPIPE, SingleApplicationPrivate::terminate); // 13
|
||||
signal(SIGALRM, SingleApplicationPrivate::terminate); // 14
|
||||
signal(SIGTERM, SingleApplicationPrivate::terminate); // 15
|
||||
signal(SIGXCPU, SingleApplicationPrivate::terminate); // 24
|
||||
signal(SIGXFSZ, SingleApplicationPrivate::terminate); // 25
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::terminate(int signum)
|
||||
{
|
||||
delete ((SingleApplication*)QCoreApplication::instance())->d_ptr;
|
||||
::exit(128 + signum);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Executed when a connection has been made to the LocalServer
|
||||
*/
|
||||
void SingleApplicationPrivate::slotConnectionEstablished()
|
||||
{
|
||||
Q_Q(SingleApplication);
|
||||
|
||||
QLocalSocket* nextConnSocket = server->nextPendingConnection();
|
||||
|
||||
quint32 instanceId = 0;
|
||||
ConnectionType connectionType = InvalidConnection;
|
||||
if (nextConnSocket->waitForReadyRead(100)) {
|
||||
// read all data from message in same order/format as written
|
||||
QByteArray msgBytes =
|
||||
nextConnSocket->read(nextConnSocket->bytesAvailable() -
|
||||
static_cast<qint64>(sizeof(quint16)));
|
||||
QByteArray checksumBytes = nextConnSocket->read(sizeof(quint16));
|
||||
QDataStream readStream(msgBytes);
|
||||
readStream.setVersion(QDataStream::Qt_5_2);
|
||||
|
||||
// server name
|
||||
QByteArray latin1Name;
|
||||
readStream >> latin1Name;
|
||||
// connectioon type
|
||||
quint8 connType = InvalidConnection;
|
||||
readStream >> connType;
|
||||
connectionType = static_cast<ConnectionType>(connType);
|
||||
// instance id
|
||||
readStream >> instanceId;
|
||||
// checksum
|
||||
quint16 msgChecksum = 0;
|
||||
QDataStream checksumStream(checksumBytes);
|
||||
checksumStream.setVersion(QDataStream::Qt_5_2);
|
||||
checksumStream >> msgChecksum;
|
||||
|
||||
const quint16 actualChecksum = qChecksum(
|
||||
msgBytes.constData(), static_cast<quint32>(msgBytes.length()));
|
||||
|
||||
if (readStream.status() != QDataStream::Ok ||
|
||||
QLatin1String(latin1Name) != blockServerName ||
|
||||
msgChecksum != actualChecksum) {
|
||||
connectionType = InvalidConnection;
|
||||
}
|
||||
}
|
||||
|
||||
if (connectionType == InvalidConnection) {
|
||||
nextConnSocket->close();
|
||||
delete nextConnSocket;
|
||||
return;
|
||||
}
|
||||
|
||||
QObject::connect(nextConnSocket,
|
||||
&QLocalSocket::aboutToClose,
|
||||
this,
|
||||
[nextConnSocket, instanceId, this]() {
|
||||
emit this->slotClientConnectionClosed(nextConnSocket,
|
||||
instanceId);
|
||||
});
|
||||
|
||||
QObject::connect(nextConnSocket,
|
||||
&QLocalSocket::readyRead,
|
||||
this,
|
||||
[nextConnSocket, instanceId, this]() {
|
||||
emit this->slotDataAvailable(nextConnSocket,
|
||||
instanceId);
|
||||
});
|
||||
|
||||
if (connectionType == NewInstance ||
|
||||
(connectionType == SecondaryInstance &&
|
||||
options & SingleApplication::Mode::SecondaryNotification)) {
|
||||
emit q->instanceStarted();
|
||||
}
|
||||
|
||||
if (nextConnSocket->bytesAvailable() > 0) {
|
||||
emit this->slotDataAvailable(nextConnSocket, instanceId);
|
||||
}
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket* dataSocket,
|
||||
quint32 instanceId)
|
||||
{
|
||||
Q_Q(SingleApplication);
|
||||
emit q->receivedMessage(instanceId, dataSocket->readAll());
|
||||
}
|
||||
|
||||
void SingleApplicationPrivate::slotClientConnectionClosed(
|
||||
QLocalSocket* closedSocket,
|
||||
quint32 instanceId)
|
||||
{
|
||||
if (closedSocket->bytesAvailable() > 0)
|
||||
emit slotDataAvailable(closedSocket, instanceId);
|
||||
closedSocket->deleteLater();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Constructor. Checks and fires up LocalServer or closes the program
|
||||
* if another instance already exists
|
||||
* @param argc
|
||||
* @param argv
|
||||
* @param {bool} allowSecondaryInstances
|
||||
*/
|
||||
SingleApplication::SingleApplication(int& argc,
|
||||
char* argv[],
|
||||
bool allowSecondary,
|
||||
Options options,
|
||||
int timeout)
|
||||
: app_t(argc, argv)
|
||||
, d_ptr(new SingleApplicationPrivate(this))
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
|
||||
// Store the current mode of the program
|
||||
d->options = options;
|
||||
|
||||
// Generating an application ID used for identifying the shared memory
|
||||
// block and QLocalServer
|
||||
d->genBlockServerName(timeout);
|
||||
|
||||
// Guarantee thread safe behaviour with a shared memory block. Also by
|
||||
// explicitly attaching it and then deleting it we make sure that the
|
||||
// memory is deleted even if the process had crashed on Unix.
|
||||
#ifdef Q_OS_UNIX
|
||||
d->memory = new QSharedMemory(d->blockServerName);
|
||||
d->memory->attach();
|
||||
delete d->memory;
|
||||
#endif
|
||||
d->memory = new QSharedMemory(d->blockServerName);
|
||||
|
||||
// Create a shared memory block
|
||||
if (d->memory->create(sizeof(InstancesInfo))) {
|
||||
d->startPrimary(true);
|
||||
return;
|
||||
} else {
|
||||
// Attempt to attach to the memory segment
|
||||
if (d->memory->attach()) {
|
||||
d->memory->lock();
|
||||
InstancesInfo* inst =
|
||||
static_cast<InstancesInfo*>(d->memory->data());
|
||||
|
||||
if (!inst->primary) {
|
||||
d->startPrimary(false);
|
||||
d->memory->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if another instance can be started
|
||||
if (allowSecondary) {
|
||||
inst->secondary += 1;
|
||||
d->instanceNumber = inst->secondary;
|
||||
d->startSecondary();
|
||||
if (d->options & Mode::SecondaryNotification) {
|
||||
d->connectToPrimary(
|
||||
timeout, SingleApplicationPrivate::SecondaryInstance);
|
||||
}
|
||||
d->memory->unlock();
|
||||
return;
|
||||
}
|
||||
|
||||
d->memory->unlock();
|
||||
}
|
||||
}
|
||||
|
||||
d->connectToPrimary(timeout, SingleApplicationPrivate::NewInstance);
|
||||
delete d;
|
||||
|
||||
// show message box with inforation that Flameshot is already launched
|
||||
QMessageBox msgBox;
|
||||
msgBox.setText(QObject::tr(
|
||||
"Hi, I'm already running!\nYou can find me in the system tray."));
|
||||
int cnt = 3;
|
||||
QTimer cntDown;
|
||||
QObject::connect(
|
||||
&cntDown, &QTimer::timeout, [&msgBox, &cnt, &cntDown]() -> void {
|
||||
if (--cnt < 0) {
|
||||
cntDown.stop();
|
||||
msgBox.close();
|
||||
} else {
|
||||
msgBox.setWindowTitle(QString("Flameshot (%1)").arg(cnt + 1));
|
||||
}
|
||||
});
|
||||
cntDown.start(1000);
|
||||
msgBox.exec();
|
||||
|
||||
::exit(EXIT_SUCCESS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
SingleApplication::~SingleApplication()
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool SingleApplication::isPrimary()
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
return d->server != nullptr;
|
||||
}
|
||||
|
||||
bool SingleApplication::isSecondary()
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
return d->server == nullptr;
|
||||
}
|
||||
|
||||
quint32 SingleApplication::instanceId()
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
return d->instanceNumber;
|
||||
}
|
||||
|
||||
qint64 SingleApplication::primaryPid()
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
return d->primaryPid();
|
||||
}
|
||||
|
||||
bool SingleApplication::sendMessage(QByteArray message, int timeout)
|
||||
{
|
||||
Q_D(SingleApplication);
|
||||
|
||||
// Nobody to connect to
|
||||
if (isPrimary())
|
||||
return false;
|
||||
|
||||
// Make sure the socket is connected
|
||||
d->connectToPrimary(timeout, SingleApplicationPrivate::Reconnect);
|
||||
|
||||
d->socket->write(message);
|
||||
bool dataWritten = d->socket->flush();
|
||||
d->socket->waitForBytesWritten(timeout);
|
||||
return dataWritten;
|
||||
}
|
||||
@@ -1,140 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) Itay Grudev 2015 - 2016
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#ifndef SINGLE_APPLICATION_H
|
||||
#define SINGLE_APPLICATION_H
|
||||
|
||||
#include <QtCore/QtGlobal>
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
|
||||
#ifndef QAPPLICATION_CLASS
|
||||
#define QAPPLICATION_CLASS QCoreApplication
|
||||
#endif
|
||||
|
||||
#include QT_STRINGIFY(QAPPLICATION_CLASS)
|
||||
|
||||
class SingleApplicationPrivate;
|
||||
|
||||
/**
|
||||
* @brief The SingleApplication class handles multipe instances of the same
|
||||
* Application
|
||||
* @see QCoreApplication
|
||||
*/
|
||||
class SingleApplication : public QAPPLICATION_CLASS
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
typedef QAPPLICATION_CLASS app_t;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Mode of operation of SingleApplication.
|
||||
* Whether the block should be user-wide or system-wide and whether the
|
||||
* primary instance should be notified when a secondary instance had been
|
||||
* started.
|
||||
* @note Operating system can restrict the shared memory blocks to the same
|
||||
* user, in which case the User/System modes will have no effect and the
|
||||
* block will be user wide.
|
||||
* @enum
|
||||
*/
|
||||
enum Mode
|
||||
{
|
||||
User = 1 << 0,
|
||||
System = 1 << 1,
|
||||
SecondaryNotification = 1 << 2,
|
||||
ExcludeAppVersion = 1 << 3,
|
||||
ExcludeAppPath = 1 << 4
|
||||
};
|
||||
Q_DECLARE_FLAGS(Options, Mode)
|
||||
|
||||
/**
|
||||
* @brief Intitializes a SingleApplication instance with argc command line
|
||||
* arguments in argv
|
||||
* @arg {int &} argc - Number of arguments in argv
|
||||
* @arg {const char *[]} argv - Supplied command line arguments
|
||||
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
||||
* if there is already a primary instance.
|
||||
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
|
||||
* User wide or System wide.
|
||||
* @arg {int} timeout - Timeout to wait in miliseconds.
|
||||
* @note argc and argv may be changed as Qt removes arguments that it
|
||||
* recognizes
|
||||
* @note Mode::SecondaryNotification only works if set on both the primary
|
||||
* instance and the secondary instance.
|
||||
* @note The timeout is just a hint for the maximum time of blocking
|
||||
* operations. It does not guarantee that the SingleApplication
|
||||
* initialisation will be completed in given time, though is a good hint.
|
||||
* Usually 4*timeout would be the worst case (fail) scenario.
|
||||
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
||||
*/
|
||||
explicit SingleApplication(int& argc,
|
||||
char* argv[],
|
||||
bool allowSecondary = false,
|
||||
Options options = Mode::User,
|
||||
int timeout = 100);
|
||||
~SingleApplication();
|
||||
|
||||
/**
|
||||
* @brief Returns if the instance is the primary instance
|
||||
* @returns {bool}
|
||||
*/
|
||||
bool isPrimary();
|
||||
|
||||
/**
|
||||
* @brief Returns if the instance is a secondary instance
|
||||
* @returns {bool}
|
||||
*/
|
||||
bool isSecondary();
|
||||
|
||||
/**
|
||||
* @brief Returns a unique identifier for the current instance
|
||||
* @returns {qint32}
|
||||
*/
|
||||
quint32 instanceId();
|
||||
|
||||
/**
|
||||
* @brief Returns the process ID (PID) of the primary instance
|
||||
* @returns {qint64}
|
||||
*/
|
||||
qint64 primaryPid();
|
||||
|
||||
/**
|
||||
* @brief Sends a message to the primary instance. Returns true on success.
|
||||
* @param {int} timeout - Timeout for connecting
|
||||
* @returns {bool}
|
||||
* @note sendMessage() will return false if invoked from the primary
|
||||
* instance.
|
||||
*/
|
||||
bool sendMessage(QByteArray message, int timeout = 100);
|
||||
|
||||
Q_SIGNALS:
|
||||
void instanceStarted();
|
||||
void receivedMessage(quint32 instanceId, QByteArray message);
|
||||
|
||||
private:
|
||||
SingleApplicationPrivate* d_ptr;
|
||||
Q_DECLARE_PRIVATE(SingleApplication)
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
|
||||
|
||||
#endif // SINGLE_APPLICATION_H
|
||||
@@ -1,18 +0,0 @@
|
||||
QT += core network
|
||||
CONFIG += c++11
|
||||
|
||||
HEADERS += $$PWD/singleapplication.h \
|
||||
$$PWD/singleapplication_p.h
|
||||
SOURCES += $$PWD/singleapplication.cpp
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
win32 {
|
||||
msvc:LIBS += Advapi32.lib
|
||||
gcc:LIBS += -lAdvapi32
|
||||
}
|
||||
|
||||
DISTFILES += \
|
||||
$$PWD/README.md \
|
||||
$$PWD/CHANGELOG.md \
|
||||
$$PWD/Windows.md
|
||||
@@ -1,88 +0,0 @@
|
||||
// The MIT License (MIT)
|
||||
//
|
||||
// Copyright (c) Itay Grudev 2015 - 2016
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
//
|
||||
// W A R N I N G !!!
|
||||
// -----------------
|
||||
//
|
||||
// This file is not part of the SingleApplication API. It is used purely as an
|
||||
// implementation detail. This header file may change from version to
|
||||
// version without notice, or may even be removed.
|
||||
//
|
||||
|
||||
#ifndef SINGLEAPPLICATION_P_H
|
||||
#define SINGLEAPPLICATION_P_H
|
||||
|
||||
#include "singleapplication.h"
|
||||
#include <QtCore/QSharedMemory>
|
||||
#include <QtNetwork/QLocalServer>
|
||||
#include <QtNetwork/QLocalSocket>
|
||||
|
||||
struct InstancesInfo
|
||||
{
|
||||
bool primary;
|
||||
quint32 secondary;
|
||||
qint64 primaryPid;
|
||||
};
|
||||
|
||||
class SingleApplicationPrivate : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum ConnectionType : quint8
|
||||
{
|
||||
InvalidConnection = 0,
|
||||
NewInstance = 1,
|
||||
SecondaryInstance = 2,
|
||||
Reconnect = 3
|
||||
};
|
||||
Q_DECLARE_PUBLIC(SingleApplication)
|
||||
|
||||
SingleApplicationPrivate(SingleApplication* q_ptr);
|
||||
~SingleApplicationPrivate();
|
||||
|
||||
void genBlockServerName(int msecs);
|
||||
void startPrimary(bool resetMemory);
|
||||
void startSecondary();
|
||||
void connectToPrimary(int msecs, ConnectionType connectionType);
|
||||
qint64 primaryPid();
|
||||
|
||||
#ifdef Q_OS_UNIX
|
||||
void crashHandler();
|
||||
static void terminate(int signum);
|
||||
#endif
|
||||
|
||||
QSharedMemory* memory;
|
||||
SingleApplication* q_ptr;
|
||||
QLocalSocket* socket;
|
||||
QLocalServer* server;
|
||||
quint32 instanceNumber;
|
||||
QString blockServerName;
|
||||
SingleApplication::Options options;
|
||||
|
||||
public Q_SLOTS:
|
||||
void slotConnectionEstablished();
|
||||
void slotDataAvailable(QLocalSocket*, quint32);
|
||||
void slotClientConnectionClosed(QLocalSocket*, quint32);
|
||||
};
|
||||
|
||||
#endif // SINGLEAPPLICATION_P_H
|
||||
60
src/tools/CMakeLists.txt
Normal file
60
src/tools/CMakeLists.txt
Normal file
@@ -0,0 +1,60 @@
|
||||
target_sources(flameshot PRIVATE arrow/arrowtool.h arrow/arrowtool.cpp)
|
||||
target_sources(flameshot PRIVATE pixelate/pixelatetool.h pixelate/pixelatetool.cpp)
|
||||
target_sources(flameshot PRIVATE circle/circletool.h circle/circletool.cpp)
|
||||
target_sources(flameshot PRIVATE circlecount/circlecounttool.h circlecount/circlecounttool.cpp)
|
||||
target_sources(flameshot PRIVATE copy/copytool.h copy/copytool.cpp)
|
||||
target_sources(flameshot PRIVATE exit/exittool.h exit/exittool.cpp)
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE imgur/imguruploader.h
|
||||
imgur/imguruploadertool.h
|
||||
imgur/imguruploader.cpp
|
||||
imgur/imguruploadertool.cpp)
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE launcher/applaunchertool.h
|
||||
launcher/applauncherwidget.h
|
||||
launcher/launcheritemdelegate.h
|
||||
launcher/terminallauncher.h
|
||||
launcher/applaunchertool.cpp
|
||||
launcher/applauncherwidget.cpp
|
||||
launcher/launcheritemdelegate.cpp
|
||||
launcher/openwithprogram.cpp
|
||||
launcher/terminallauncher.cpp)
|
||||
target_sources(flameshot PRIVATE line/linetool.h line/linetool.cpp)
|
||||
target_sources(flameshot PRIVATE marker/markertool.h marker/markertool.cpp)
|
||||
target_sources(flameshot PRIVATE move/movetool.h move/movetool.cpp)
|
||||
target_sources(flameshot PRIVATE pencil/penciltool.h pencil/penciltool.cpp)
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE pin/pintool.h
|
||||
pin/pinwidget.h
|
||||
pin/pintool.cpp
|
||||
pin/pinwidget.cpp)
|
||||
target_sources(flameshot PRIVATE rectangle/rectangletool.h rectangle/rectangletool.cpp)
|
||||
target_sources(flameshot PRIVATE redo/redotool.h redo/redotool.cpp)
|
||||
target_sources(flameshot PRIVATE save/savetool.h save/savetool.cpp)
|
||||
target_sources(flameshot PRIVATE selection/selectiontool.h selection/selectiontool.cpp)
|
||||
target_sources(flameshot PRIVATE sizeindicator/sizeindicatortool.h sizeindicator/sizeindicatortool.cpp)
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE text/textconfig.h
|
||||
text/texttool.h
|
||||
text/textwidget.h
|
||||
text/textconfig.cpp
|
||||
text/texttool.cpp
|
||||
text/textwidget.cpp)
|
||||
target_sources(flameshot PRIVATE undo/undotool.h undo/undotool.cpp)
|
||||
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE abstractactiontool.cpp
|
||||
abstractpathtool.cpp
|
||||
abstracttwopointtool.cpp
|
||||
capturecontext.cpp
|
||||
toolfactory.cpp
|
||||
abstractactiontool.h
|
||||
abstractpathtool.h
|
||||
abstracttwopointtool.h
|
||||
capturetool.h
|
||||
toolfactory.h)
|
||||
@@ -36,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
virtual ToolType nameID() const = 0;
|
||||
|
||||
public slots:
|
||||
void drawEnd(const QPoint& p) override;
|
||||
void drawMove(const QPoint& p) override;
|
||||
|
||||
@@ -42,6 +42,8 @@ protected:
|
||||
void updateBackup(const QPixmap& pixmap);
|
||||
void addPoint(const QPoint& point);
|
||||
|
||||
virtual ToolType nameID() const = 0;
|
||||
|
||||
QPixmap m_pixmapBackup;
|
||||
QRect m_backupArea;
|
||||
QColor m_color;
|
||||
|
||||
@@ -72,6 +72,9 @@ void AbstractTwoPointTool::undo(QPixmap& pixmap)
|
||||
{
|
||||
QPainter p(&pixmap);
|
||||
p.drawPixmap(backupRect(pixmap.rect()).topLeft(), m_pixmapBackup);
|
||||
if (this->nameID() == ToolType::CIRCLECOUNT) {
|
||||
emit requestAction(REQ_DECREMENT_CIRCLE_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
void AbstractTwoPointTool::drawEnd(const QPoint& p)
|
||||
|
||||
@@ -53,6 +53,8 @@ protected:
|
||||
bool m_supportsOrthogonalAdj = false;
|
||||
bool m_supportsDiagonalAdj = false;
|
||||
|
||||
virtual ToolType nameID() const = 0;
|
||||
|
||||
private:
|
||||
QPoint adjustedVector(QPoint v) const;
|
||||
};
|
||||
|
||||
@@ -88,9 +88,9 @@ QString ArrowTool::name() const
|
||||
return tr("Arrow");
|
||||
}
|
||||
|
||||
QString ArrowTool::nameID()
|
||||
ToolType ArrowTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::ARROW;
|
||||
}
|
||||
|
||||
QString ArrowTool::description() const
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "src/tools/abstracttwopointtool.h"
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
|
||||
class ArrowTool : public AbstractTwoPointTool
|
||||
{
|
||||
@@ -28,7 +29,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -38,6 +38,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
//
|
||||
// This file is part of Flameshot.
|
||||
//
|
||||
// Flameshot 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Flameshot 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 Flameshot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "blurtool.h"
|
||||
#include <QApplication>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QPainter>
|
||||
|
||||
BlurTool::BlurTool(QObject* parent)
|
||||
: AbstractTwoPointTool(parent)
|
||||
{}
|
||||
|
||||
QIcon BlurTool::icon(const QColor& background, bool inEditor) const
|
||||
{
|
||||
Q_UNUSED(inEditor);
|
||||
return QIcon(iconPath(background) + "blur.svg");
|
||||
}
|
||||
QString BlurTool::name() const
|
||||
{
|
||||
return tr("Blur");
|
||||
}
|
||||
|
||||
QString BlurTool::nameID()
|
||||
{
|
||||
return QLatin1String("");
|
||||
}
|
||||
|
||||
QString BlurTool::description() const
|
||||
{
|
||||
return tr("Set Blur as the paint tool");
|
||||
}
|
||||
|
||||
CaptureTool* BlurTool::copy(QObject* parent)
|
||||
{
|
||||
return new BlurTool(parent);
|
||||
}
|
||||
|
||||
void BlurTool::process(QPainter& painter,
|
||||
const QPixmap& pixmap,
|
||||
bool recordUndo)
|
||||
{
|
||||
if (recordUndo) {
|
||||
updateBackup(pixmap);
|
||||
}
|
||||
QPoint& p0 = m_points.first;
|
||||
QPoint& p1 = m_points.second;
|
||||
auto pixelRatio = pixmap.devicePixelRatio();
|
||||
|
||||
QRect selection = QRect(p0, p1).normalized();
|
||||
QRect selectionScaled =
|
||||
QRect(p0 * pixelRatio, p1 * pixelRatio).normalized();
|
||||
|
||||
QGraphicsBlurEffect* blur = new QGraphicsBlurEffect;
|
||||
blur->setBlurRadius(10);
|
||||
QGraphicsPixmapItem* item =
|
||||
new QGraphicsPixmapItem(pixmap.copy(selectionScaled));
|
||||
item->setGraphicsEffect(blur);
|
||||
|
||||
QGraphicsScene scene;
|
||||
scene.addItem(item);
|
||||
|
||||
scene.render(&painter, selection, QRectF());
|
||||
blur->setBlurRadius(12);
|
||||
for (int cnt = 100; cnt > 0; cnt--) {
|
||||
scene.render(&painter, selection, QRectF());
|
||||
}
|
||||
}
|
||||
|
||||
void BlurTool::paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(painter);
|
||||
}
|
||||
|
||||
void BlurTool::drawStart(const CaptureContext& context)
|
||||
{
|
||||
m_thickness = context.thickness;
|
||||
m_points.first = context.mousePos;
|
||||
m_points.second = context.mousePos;
|
||||
}
|
||||
|
||||
void BlurTool::pressed(const CaptureContext& context)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
}
|
||||
@@ -42,6 +42,7 @@ struct CaptureContext
|
||||
QPoint mousePos;
|
||||
// Value of the desired thickness
|
||||
int thickness;
|
||||
int circleCount;
|
||||
// Mode of the capture widget
|
||||
bool fullscreen;
|
||||
|
||||
|
||||
@@ -23,6 +23,30 @@
|
||||
#include <QIcon>
|
||||
#include <QPainter>
|
||||
|
||||
enum class ToolType
|
||||
{
|
||||
ARROW,
|
||||
CIRCLE,
|
||||
CIRCLECOUNT,
|
||||
COPY,
|
||||
EXIT,
|
||||
IMGUR,
|
||||
LAUNCHER,
|
||||
LINE,
|
||||
MARKER,
|
||||
MOVE,
|
||||
PENCIL,
|
||||
PIN,
|
||||
PIXELATE,
|
||||
RECTANGLE,
|
||||
REDO,
|
||||
SAVE,
|
||||
SELECTION,
|
||||
SIZEINDICATOR,
|
||||
TEXT,
|
||||
UNDO
|
||||
};
|
||||
|
||||
class CaptureTool : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -64,6 +88,10 @@ public:
|
||||
REQ_ADD_CHILD_WINDOW,
|
||||
// Instance this->widget()'s widget which handles its own lifetime.
|
||||
REQ_ADD_EXTERNAL_WIDGETS,
|
||||
|
||||
REQ_INCREMENT_CIRCLE_COUNT,
|
||||
|
||||
REQ_DECREMENT_CIRCLE_COUNT,
|
||||
};
|
||||
|
||||
explicit CaptureTool(QObject* parent = nullptr)
|
||||
@@ -91,7 +119,7 @@ public:
|
||||
virtual QString name() const = 0;
|
||||
// Codename for the tool, this hsouldn't change as it is used as ID
|
||||
// for the tool in the internals of Flameshot
|
||||
static QString nameID();
|
||||
virtual ToolType nameID() const = 0;
|
||||
// Short description of the tool.
|
||||
virtual QString description() const = 0;
|
||||
|
||||
|
||||
@@ -38,9 +38,9 @@ QString CircleTool::name() const
|
||||
return tr("Circle");
|
||||
}
|
||||
|
||||
QString CircleTool::nameID()
|
||||
ToolType CircleTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::CIRCLE;
|
||||
}
|
||||
|
||||
QString CircleTool::description() const
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -37,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
134
src/tools/circlecount/circlecounttool.cpp
Normal file
134
src/tools/circlecount/circlecounttool.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
//
|
||||
// This file is part of Flameshot.
|
||||
//
|
||||
// Flameshot 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Flameshot 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 Flameshot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "circlecounttool.h"
|
||||
#include <QPainter>
|
||||
namespace {
|
||||
#define PADDING_VALUE 2
|
||||
}
|
||||
|
||||
CircleCountTool::CircleCountTool(QObject* parent)
|
||||
: AbstractTwoPointTool(parent)
|
||||
{
|
||||
m_count = 0;
|
||||
}
|
||||
|
||||
QIcon CircleCountTool::icon(const QColor& background, bool inEditor) const
|
||||
{
|
||||
Q_UNUSED(inEditor);
|
||||
return QIcon(iconPath(background) + "circlecount-outline.svg");
|
||||
}
|
||||
QString CircleCountTool::name() const
|
||||
{
|
||||
return tr("Circle Counter");
|
||||
}
|
||||
|
||||
ToolType CircleCountTool::nameID() const
|
||||
{
|
||||
return ToolType::CIRCLECOUNT;
|
||||
}
|
||||
|
||||
QString CircleCountTool::description() const
|
||||
{
|
||||
return tr("Add an autoincrementing counter bubble");
|
||||
}
|
||||
|
||||
CaptureTool* CircleCountTool::copy(QObject* parent)
|
||||
{
|
||||
return new CircleCountTool(parent);
|
||||
}
|
||||
|
||||
void CircleCountTool::process(QPainter& painter,
|
||||
const QPixmap& pixmap,
|
||||
bool recordUndo)
|
||||
{
|
||||
if (recordUndo) {
|
||||
updateBackup(pixmap);
|
||||
}
|
||||
painter.setBrush(m_color);
|
||||
|
||||
int bubble_size = m_thickness;
|
||||
// Decrease by 1px so the border is properly ereased when doing undo
|
||||
painter.drawEllipse(m_points.first, bubble_size - 1, bubble_size - 1);
|
||||
QRect textRect = QRect(m_points.first.x() - bubble_size / 2,
|
||||
m_points.first.y() - bubble_size / 2,
|
||||
bubble_size,
|
||||
bubble_size);
|
||||
auto orig_font = painter.font();
|
||||
auto new_font = orig_font;
|
||||
auto fontSize = bubble_size;
|
||||
new_font.setPixelSize(fontSize);
|
||||
painter.setFont(new_font);
|
||||
|
||||
QRect bRect =
|
||||
painter.boundingRect(textRect, Qt::AlignCenter, QString::number(m_count));
|
||||
|
||||
while (bRect.width() > textRect.width()) {
|
||||
fontSize--;
|
||||
if (fontSize == 0) {
|
||||
break;
|
||||
}
|
||||
new_font.setPixelSize(fontSize);
|
||||
painter.setFont(new_font);
|
||||
|
||||
bRect = painter.boundingRect(
|
||||
textRect, Qt::AlignCenter, QString::number(m_count));
|
||||
}
|
||||
|
||||
// Lightness value ranges from 0-255, we split at 75 as this looks best
|
||||
if (m_color.lightness() <= 75) {
|
||||
painter.setPen(Qt::white);
|
||||
} else {
|
||||
painter.setPen(Qt::black);
|
||||
}
|
||||
|
||||
painter.drawText(textRect, Qt::AlignCenter, QString::number(m_count));
|
||||
painter.setFont(orig_font);
|
||||
}
|
||||
|
||||
void CircleCountTool::paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context)
|
||||
{
|
||||
m_thickness = context.thickness + PADDING_VALUE;
|
||||
if (m_thickness < 15) {
|
||||
m_thickness = 15;
|
||||
}
|
||||
|
||||
// Thickness for pen is *2 to range from radius to diameter to match the
|
||||
// ellipse draw function
|
||||
painter.setPen(
|
||||
QPen(context.color, m_thickness * 2, Qt::SolidLine, Qt::RoundCap));
|
||||
painter.drawLine(context.mousePos,
|
||||
{ context.mousePos.x() + 1, context.mousePos.y() + 1 });
|
||||
}
|
||||
|
||||
void CircleCountTool::drawStart(const CaptureContext& context)
|
||||
{
|
||||
m_color = context.color;
|
||||
m_thickness = context.thickness + PADDING_VALUE;
|
||||
if (m_thickness < 15) {
|
||||
m_thickness = 15;
|
||||
}
|
||||
m_points.first = context.mousePos;
|
||||
m_count = context.circleCount;
|
||||
emit requestAction(REQ_INCREMENT_CIRCLE_COUNT);
|
||||
}
|
||||
|
||||
void CircleCountTool::pressed(const CaptureContext& context)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
}
|
||||
47
src/tools/circlecount/circlecounttool.h
Normal file
47
src/tools/circlecount/circlecounttool.h
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
//
|
||||
// This file is part of Flameshot.
|
||||
//
|
||||
// Flameshot 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Flameshot 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 Flameshot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "src/tools/abstracttwopointtool.h"
|
||||
|
||||
class CircleCountTool : public AbstractTwoPointTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit CircleCountTool(QObject* parent = nullptr);
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
void process(QPainter& painter,
|
||||
const QPixmap& pixmap,
|
||||
bool recordUndo = false) override;
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
private:
|
||||
unsigned int m_count;
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
@@ -38,9 +38,9 @@ QString CopyTool::name() const
|
||||
return tr("Copy");
|
||||
}
|
||||
|
||||
QString CopyTool::nameID()
|
||||
ToolType CopyTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::COPY;
|
||||
}
|
||||
|
||||
QString CopyTool::description() const
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
@@ -37,9 +37,9 @@ QString ExitTool::name() const
|
||||
return tr("Exit");
|
||||
}
|
||||
|
||||
QString ExitTool::nameID()
|
||||
ToolType ExitTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::EXIT;
|
||||
}
|
||||
|
||||
QString ExitTool::description() const
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
@@ -37,9 +37,9 @@ QString AppLauncher::name() const
|
||||
return tr("App Launcher");
|
||||
}
|
||||
|
||||
QString AppLauncher::nameID()
|
||||
ToolType AppLauncher::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::LAUNCHER;
|
||||
}
|
||||
|
||||
QString AppLauncher::description() const
|
||||
|
||||
@@ -29,13 +29,15 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
QWidget* widget() override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
|
||||
@@ -112,6 +112,8 @@ void AppLauncherWidget::launch(const QModelIndex& index)
|
||||
QString command = index.data(Qt::UserRole)
|
||||
.toString()
|
||||
.replace(QRegExp("(\\%.)"), '"' + m_tempFile + '"');
|
||||
|
||||
QString app_name = index.data(Qt::UserRole).toString().split(" ").at(0);
|
||||
bool inTerminal =
|
||||
index.data(Qt::UserRole + 1).toBool() || m_terminalCheckbox->isChecked();
|
||||
if (inTerminal) {
|
||||
@@ -121,7 +123,7 @@ void AppLauncherWidget::launch(const QModelIndex& index)
|
||||
this, tr("Error"), tr("Unable to launch in terminal."));
|
||||
}
|
||||
} else {
|
||||
QProcess::startDetached(command);
|
||||
QProcess::startDetached(app_name, { m_tempFile });
|
||||
}
|
||||
if (!m_keepOpen) {
|
||||
close();
|
||||
|
||||
@@ -21,8 +21,12 @@
|
||||
#include "src/utils/filenamehandler.h"
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
#include <Shlobj.h>
|
||||
#include <windows.h>
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x601
|
||||
#endif
|
||||
#include <Shlobj.h>
|
||||
|
||||
#pragma comment(lib, "Shell32.lib")
|
||||
#else
|
||||
|
||||
@@ -59,5 +59,5 @@ bool TerminalLauncher::launchDetached(const QString& command)
|
||||
{
|
||||
TerminalApp app = getPreferedTerminal();
|
||||
QString s = app.name + " " + app.arg + " " + command;
|
||||
return QProcess::startDetached(s);
|
||||
return QProcess::startDetached(app.name, { app.arg, command });
|
||||
}
|
||||
|
||||
@@ -41,9 +41,9 @@ QString LineTool::name() const
|
||||
return tr("Line");
|
||||
}
|
||||
|
||||
QString LineTool::nameID()
|
||||
ToolType LineTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::LINE;
|
||||
}
|
||||
|
||||
QString LineTool::description() const
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -37,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -41,9 +41,9 @@ QString MarkerTool::name() const
|
||||
return tr("Marker");
|
||||
}
|
||||
|
||||
QString MarkerTool::nameID()
|
||||
ToolType MarkerTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::MARKER;
|
||||
}
|
||||
|
||||
QString MarkerTool::description() const
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -37,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -37,9 +37,9 @@ QString MoveTool::name() const
|
||||
return tr("Move");
|
||||
}
|
||||
|
||||
QString MoveTool::nameID()
|
||||
ToolType MoveTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::MOVE;
|
||||
}
|
||||
|
||||
QString MoveTool::description() const
|
||||
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
ToolType nameID() const override;
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
@@ -32,9 +32,9 @@ QString PencilTool::name() const
|
||||
return tr("Pencil");
|
||||
}
|
||||
|
||||
QString PencilTool::nameID()
|
||||
ToolType PencilTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::PENCIL;
|
||||
}
|
||||
|
||||
QString PencilTool::description() const
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -38,6 +37,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -37,9 +37,9 @@ QString PinTool::name() const
|
||||
return tr("Pin Tool");
|
||||
}
|
||||
|
||||
QString PinTool::nameID()
|
||||
ToolType PinTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::PIN;
|
||||
}
|
||||
|
||||
QString PinTool::description() const
|
||||
|
||||
@@ -29,13 +29,15 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
QWidget* widget() override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ int PinWidget::margin() const
|
||||
|
||||
void PinWidget::wheelEvent(QWheelEvent* e)
|
||||
{
|
||||
int val = e->delta() > 0 ? 15 : -15;
|
||||
int val = e->angleDelta().y() > 0 ? 15 : -15;
|
||||
int newWidth = qBound(50, m_label->width() + val, maximumWidth());
|
||||
int newHeight = qBound(50, m_label->height() + val, maximumHeight());
|
||||
|
||||
|
||||
115
src/tools/pixelate/pixelatetool.cpp
Normal file
115
src/tools/pixelate/pixelatetool.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright(c) 2017-2019 Alejandro Sirgo Rica & Contributors
|
||||
//
|
||||
// This file is part of Flameshot.
|
||||
//
|
||||
// Flameshot 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 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Flameshot 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 Flameshot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "pixelatetool.h"
|
||||
#include <QApplication>
|
||||
#include <QGraphicsBlurEffect>
|
||||
#include <QGraphicsPixmapItem>
|
||||
#include <QGraphicsScene>
|
||||
#include <QImage>
|
||||
#include <QPainter>
|
||||
#include <cassert>
|
||||
|
||||
PixelateTool::PixelateTool(QObject* parent)
|
||||
: AbstractTwoPointTool(parent)
|
||||
{}
|
||||
|
||||
QIcon PixelateTool::icon(const QColor& background, bool inEditor) const
|
||||
{
|
||||
Q_UNUSED(inEditor);
|
||||
return QIcon(iconPath(background) + "pixelate.svg");
|
||||
}
|
||||
QString PixelateTool::name() const
|
||||
{
|
||||
return tr("Pixelate");
|
||||
}
|
||||
|
||||
ToolType PixelateTool::nameID() const
|
||||
{
|
||||
return ToolType::PIXELATE;
|
||||
}
|
||||
|
||||
QString PixelateTool::description() const
|
||||
{
|
||||
return tr("Set Pixelate as the paint tool");
|
||||
}
|
||||
|
||||
CaptureTool* PixelateTool::copy(QObject* parent)
|
||||
{
|
||||
return new PixelateTool(parent);
|
||||
}
|
||||
|
||||
void PixelateTool::process(QPainter& painter,
|
||||
const QPixmap& pixmap,
|
||||
bool recordUndo)
|
||||
{
|
||||
|
||||
if (recordUndo) {
|
||||
updateBackup(pixmap);
|
||||
}
|
||||
|
||||
QPoint& p0 = m_points.first;
|
||||
QPoint& p1 = m_points.second;
|
||||
QRect selection = QRect(p0, p1).normalized();
|
||||
|
||||
// If thickness is less than 1, use old blur process
|
||||
if (m_thickness <= 1) {
|
||||
auto pixelRatio = pixmap.devicePixelRatio();
|
||||
|
||||
QRect selectionScaled =
|
||||
QRect(p0 * pixelRatio, p1 * pixelRatio).normalized();
|
||||
|
||||
QGraphicsBlurEffect* blur = new QGraphicsBlurEffect;
|
||||
blur->setBlurRadius(10);
|
||||
QGraphicsPixmapItem* item =
|
||||
new QGraphicsPixmapItem(pixmap.copy(selectionScaled));
|
||||
item->setGraphicsEffect(blur);
|
||||
|
||||
QGraphicsScene scene;
|
||||
scene.addItem(item);
|
||||
|
||||
scene.render(&painter, selection, QRectF());
|
||||
blur->setBlurRadius(12);
|
||||
scene.render(&painter, selection, QRectF());
|
||||
} else {
|
||||
int width = selection.width() * (0.5 / qMax(1, m_thickness));
|
||||
|
||||
QPixmap t = pixmap.copy(selection);
|
||||
t = t.scaledToWidth(qMax(width, 10), Qt::SmoothTransformation);
|
||||
t = t.scaledToWidth(selection.width());
|
||||
painter.drawImage(selection, t.toImage());
|
||||
}
|
||||
}
|
||||
|
||||
void PixelateTool::paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(painter);
|
||||
}
|
||||
|
||||
void PixelateTool::drawStart(const CaptureContext& context)
|
||||
{
|
||||
m_thickness = context.thickness;
|
||||
m_points.first = context.mousePos;
|
||||
m_points.second = context.mousePos;
|
||||
}
|
||||
|
||||
void PixelateTool::pressed(const CaptureContext& context)
|
||||
{
|
||||
Q_UNUSED(context);
|
||||
}
|
||||
@@ -19,15 +19,14 @@
|
||||
|
||||
#include "src/tools/abstracttwopointtool.h"
|
||||
|
||||
class BlurTool : public AbstractTwoPointTool
|
||||
class PixelateTool : public AbstractTwoPointTool
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit BlurTool(QObject* parent = nullptr);
|
||||
explicit PixelateTool(QObject* parent = nullptr);
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -37,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
@@ -38,9 +38,9 @@ QString RectangleTool::name() const
|
||||
return tr("Rectangle");
|
||||
}
|
||||
|
||||
QString RectangleTool::nameID()
|
||||
ToolType RectangleTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::RECTANGLE;
|
||||
}
|
||||
|
||||
QString RectangleTool::description() const
|
||||
|
||||
@@ -27,7 +27,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -37,6 +36,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -37,9 +37,9 @@ QString RedoTool::name() const
|
||||
return tr("Redo");
|
||||
}
|
||||
|
||||
QString RedoTool::nameID()
|
||||
ToolType RedoTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::REDO;
|
||||
}
|
||||
|
||||
QString RedoTool::description() const
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
@@ -38,9 +38,9 @@ QString SaveTool::name() const
|
||||
return tr("Save");
|
||||
}
|
||||
|
||||
QString SaveTool::nameID()
|
||||
ToolType SaveTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::SAVE;
|
||||
}
|
||||
|
||||
QString SaveTool::description() const
|
||||
@@ -64,7 +64,7 @@ void SaveTool::pressed(const CaptureContext& context)
|
||||
}
|
||||
} else {
|
||||
bool ok = ScreenshotSaver().saveToFilesystem(
|
||||
context.selectedScreenshotArea(), context.savePath);
|
||||
context.selectedScreenshotArea(), context.savePath, "");
|
||||
if (ok) {
|
||||
emit requestAction(REQ_CAPTURE_DONE_OK);
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
@@ -43,9 +43,9 @@ QString SelectionTool::name() const
|
||||
return tr("Rectangular Selection");
|
||||
}
|
||||
|
||||
QString SelectionTool::nameID()
|
||||
ToolType SelectionTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::SELECTION;
|
||||
}
|
||||
|
||||
QString SelectionTool::description() const
|
||||
|
||||
@@ -29,7 +29,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
@@ -39,6 +38,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawStart(const CaptureContext& context) override;
|
||||
void pressed(const CaptureContext& context) override;
|
||||
|
||||
@@ -37,9 +37,9 @@ QString SizeIndicatorTool::name() const
|
||||
return tr("Selection Size Indicator");
|
||||
}
|
||||
|
||||
QString SizeIndicatorTool::nameID()
|
||||
ToolType SizeIndicatorTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::SIZEINDICATOR;
|
||||
}
|
||||
|
||||
QString SizeIndicatorTool::description() const
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
@@ -40,10 +40,9 @@ TextConfig::TextConfig(QWidget* parent)
|
||||
int index = fontsCB->findText(font().family());
|
||||
fontsCB->setCurrentIndex(index);
|
||||
|
||||
QColor bgColor(palette().background().color());
|
||||
QString iconPrefix = ColorUtils::colorIsDark(bgColor)
|
||||
? PathInfo::whiteIconPath()
|
||||
: PathInfo::blackIconPath();
|
||||
QString iconPrefix = ColorUtils::colorIsDark(palette().windowText().color())
|
||||
? PathInfo::blackIconPath()
|
||||
: PathInfo::whiteIconPath();
|
||||
|
||||
m_strikeOutButton = new QPushButton(
|
||||
QIcon(iconPrefix + "format_strikethrough.svg"), QLatin1String(""));
|
||||
|
||||
@@ -57,9 +57,9 @@ QString TextTool::name() const
|
||||
return tr("Text");
|
||||
}
|
||||
|
||||
QString TextTool::nameID()
|
||||
ToolType TextTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::TEXT;
|
||||
}
|
||||
|
||||
QString TextTool::description() const
|
||||
|
||||
@@ -36,7 +36,6 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
QWidget* widget() override;
|
||||
@@ -50,6 +49,9 @@ public:
|
||||
void paintMousePreview(QPainter& painter,
|
||||
const CaptureContext& context) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void drawEnd(const QPoint& p) override;
|
||||
void drawMove(const QPoint& p) override;
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
#include "toolfactory.h"
|
||||
#include "arrow/arrowtool.h"
|
||||
#include "blur/blurtool.h"
|
||||
#include "circle/circletool.h"
|
||||
#include "circlecount/circlecounttool.h"
|
||||
#include "copy/copytool.h"
|
||||
#include "exit/exittool.h"
|
||||
#include "launcher/applaunchertool.h"
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "move/movetool.h"
|
||||
#include "pencil/penciltool.h"
|
||||
#include "pin/pintool.h"
|
||||
#include "pixelate/pixelatetool.h"
|
||||
#include "rectangle/rectangletool.h"
|
||||
#include "redo/redotool.h"
|
||||
#include "save/savetool.h"
|
||||
@@ -41,71 +42,74 @@ ToolFactory::ToolFactory(QObject* parent)
|
||||
: QObject(parent)
|
||||
{}
|
||||
|
||||
CaptureTool* ToolFactory::CreateTool(CaptureButton::ButtonType t,
|
||||
CaptureTool* ToolFactory::CreateTool(CaptureToolButton::ButtonType t,
|
||||
QObject* parent)
|
||||
{
|
||||
StorageManager storageManager;
|
||||
|
||||
CaptureTool* tool;
|
||||
CaptureTool *tool;
|
||||
switch (t) {
|
||||
case CaptureButton::TYPE_ARROW:
|
||||
case CaptureToolButton::TYPE_ARROW:
|
||||
tool = new ArrowTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_CIRCLE:
|
||||
case CaptureToolButton::TYPE_CIRCLE:
|
||||
tool = new CircleTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_COPY:
|
||||
case CaptureToolButton::TYPE_COPY:
|
||||
tool = new CopyTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_EXIT:
|
||||
case CaptureToolButton::TYPE_EXIT:
|
||||
tool = new ExitTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_IMAGEUPLOADER:
|
||||
tool = storageManager.imgUploaderTool(
|
||||
ConfigHandler().uploadStorage(), parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_DRAWER:
|
||||
case CaptureToolButton::TYPE_DRAWER:
|
||||
tool = new LineTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_MARKER:
|
||||
case CaptureToolButton::TYPE_MARKER:
|
||||
tool = new MarkerTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_MOVESELECTION:
|
||||
case CaptureToolButton::TYPE_MOVESELECTION:
|
||||
tool = new MoveTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_PENCIL:
|
||||
case CaptureToolButton::TYPE_PENCIL:
|
||||
tool = new PencilTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_RECTANGLE:
|
||||
case CaptureToolButton::TYPE_RECTANGLE:
|
||||
tool = new RectangleTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_SAVE:
|
||||
case CaptureToolButton::TYPE_SAVE:
|
||||
tool = new SaveTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_SELECTION:
|
||||
case CaptureToolButton::TYPE_SELECTION:
|
||||
tool = new SelectionTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_SELECTIONINDICATOR:
|
||||
case CaptureToolButton::TYPE_SELECTIONINDICATOR:
|
||||
tool = new SizeIndicatorTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_UNDO:
|
||||
case CaptureToolButton::TYPE_UNDO:
|
||||
tool = new UndoTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_REDO:
|
||||
case CaptureToolButton::TYPE_REDO:
|
||||
tool = new RedoTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_OPEN_APP:
|
||||
case CaptureToolButton::TYPE_OPEN_APP:
|
||||
tool = new AppLauncher(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_BLUR:
|
||||
tool = new BlurTool(parent);
|
||||
case CaptureToolButton::TYPE_PIXELATE:
|
||||
tool = new PixelateTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_PIN:
|
||||
case CaptureToolButton::TYPE_PIN:
|
||||
tool = new PinTool(parent);
|
||||
break;
|
||||
case CaptureButton::TYPE_TEXT:
|
||||
case CaptureToolButton::TYPE_TEXT:
|
||||
tool = new TextTool(parent);
|
||||
break;
|
||||
case CaptureToolButton::TYPE_CIRCLECOUNT:
|
||||
tool = new CircleCountTool(parent);
|
||||
break;
|
||||
|
||||
default:
|
||||
tool = nullptr;
|
||||
break;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/tools/capturetool.h"
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include <QObject>
|
||||
|
||||
class CaptureTool;
|
||||
@@ -33,6 +33,6 @@ public:
|
||||
ToolFactory(const ToolFactory&) = delete;
|
||||
ToolFactory& operator=(const ToolFactory&) = delete;
|
||||
|
||||
CaptureTool* CreateTool(CaptureButton::ButtonType t,
|
||||
CaptureTool* CreateTool(CaptureToolButton::ButtonType t,
|
||||
QObject* parent = nullptr);
|
||||
};
|
||||
|
||||
@@ -37,9 +37,9 @@ QString UndoTool::name() const
|
||||
return tr("Undo");
|
||||
}
|
||||
|
||||
QString UndoTool::nameID()
|
||||
ToolType UndoTool::nameID() const
|
||||
{
|
||||
return QLatin1String("");
|
||||
return ToolType::UNDO;
|
||||
}
|
||||
|
||||
QString UndoTool::description() const
|
||||
|
||||
@@ -29,11 +29,13 @@ public:
|
||||
|
||||
QIcon icon(const QColor& background, bool inEditor) const override;
|
||||
QString name() const override;
|
||||
static QString nameID();
|
||||
QString description() const override;
|
||||
|
||||
CaptureTool* copy(QObject* parent = nullptr) override;
|
||||
|
||||
protected:
|
||||
ToolType nameID() const override;
|
||||
|
||||
public slots:
|
||||
void pressed(const CaptureContext& context) override;
|
||||
};
|
||||
|
||||
21
src/utils/CMakeLists.txt
Normal file
21
src/utils/CMakeLists.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
# Required to generate MOC
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE dbusutils.h
|
||||
filenamehandler.h
|
||||
screengrabber.h
|
||||
systemnotification.h)
|
||||
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE filenamehandler.cpp
|
||||
screengrabber.cpp
|
||||
confighandler.cpp
|
||||
systemnotification.cpp
|
||||
screenshotsaver.cpp
|
||||
dbusutils.cpp
|
||||
globalvalues.cpp
|
||||
desktopfileparse.cpp
|
||||
desktopinfo.cpp
|
||||
pathinfo.cpp
|
||||
colorutils.cpp)
|
||||
@@ -30,9 +30,9 @@ ConfigHandler::ConfigHandler()
|
||||
m_settings.setDefaultFormat(QSettings::IniFormat);
|
||||
}
|
||||
|
||||
QVector<CaptureButton::ButtonType> ConfigHandler::getButtons()
|
||||
QVector<CaptureToolButton::ButtonType> ConfigHandler::getButtons()
|
||||
{
|
||||
QVector<CaptureButton::ButtonType> buttons;
|
||||
QVector<CaptureToolButton::ButtonType> buttons;
|
||||
if (m_settings.contains(QStringLiteral("buttons"))) {
|
||||
// TODO: remove toList in v1.0
|
||||
QVector<int> buttonsInt = m_settings.value(QStringLiteral("buttons"))
|
||||
@@ -46,31 +46,35 @@ QVector<CaptureButton::ButtonType> ConfigHandler::getButtons()
|
||||
buttons = fromIntToButton(buttonsInt);
|
||||
} else {
|
||||
// Default tools
|
||||
buttons << CaptureButton::TYPE_PENCIL << CaptureButton::TYPE_DRAWER
|
||||
<< CaptureButton::TYPE_ARROW << CaptureButton::TYPE_SELECTION
|
||||
<< CaptureButton::TYPE_RECTANGLE << CaptureButton::TYPE_CIRCLE
|
||||
<< CaptureButton::TYPE_MARKER << CaptureButton::TYPE_BLUR
|
||||
<< CaptureButton::TYPE_SELECTIONINDICATOR
|
||||
<< CaptureButton::TYPE_MOVESELECTION << CaptureButton::TYPE_UNDO
|
||||
<< CaptureButton::TYPE_REDO << CaptureButton::TYPE_COPY
|
||||
<< CaptureButton::TYPE_SAVE << CaptureButton::TYPE_EXIT
|
||||
<< CaptureButton::TYPE_IMAGEUPLOADER
|
||||
#if defined(Q_OS_LINUX) || defined(Q_OS_UNIX)
|
||||
<< CaptureButton::TYPE_OPEN_APP
|
||||
#endif
|
||||
<< CaptureButton::TYPE_PIN << CaptureButton::TYPE_TEXT;
|
||||
buttons << CaptureToolButton::TYPE_PENCIL
|
||||
<< CaptureToolButton::TYPE_DRAWER
|
||||
<< CaptureToolButton::TYPE_ARROW
|
||||
<< CaptureToolButton::TYPE_SELECTION
|
||||
<< CaptureToolButton::TYPE_RECTANGLE
|
||||
<< CaptureToolButton::TYPE_CIRCLE
|
||||
<< CaptureToolButton::TYPE_MARKER
|
||||
<< CaptureToolButton::TYPE_PIXELATE
|
||||
<< CaptureToolButton::TYPE_SELECTIONINDICATOR
|
||||
<< CaptureToolButton::TYPE_MOVESELECTION
|
||||
<< CaptureToolButton::TYPE_UNDO << CaptureToolButton::TYPE_REDO
|
||||
<< CaptureToolButton::TYPE_COPY << CaptureToolButton::TYPE_SAVE
|
||||
<< CaptureToolButton::TYPE_EXIT
|
||||
<< CaptureToolButton::TYPE_IMAGEUPLOADER
|
||||
<< CaptureToolButton::TYPE_OPEN_APP
|
||||
<< CaptureToolButton::TYPE_PIN << CaptureToolButton::TYPE_TEXT
|
||||
<< CaptureToolButton::TYPE_CIRCLECOUNT;
|
||||
}
|
||||
|
||||
using bt = CaptureButton::ButtonType;
|
||||
using bt = CaptureToolButton::ButtonType;
|
||||
std::sort(buttons.begin(), buttons.end(), [](bt a, bt b) {
|
||||
return CaptureButton::getPriorityByButton(a) <
|
||||
CaptureButton::getPriorityByButton(b);
|
||||
return CaptureToolButton::getPriorityByButton(a) <
|
||||
CaptureToolButton::getPriorityByButton(b);
|
||||
});
|
||||
return buttons;
|
||||
}
|
||||
|
||||
void ConfigHandler::setButtons(
|
||||
const QVector<CaptureButton::ButtonType>& buttons)
|
||||
const QVector<CaptureToolButton::ButtonType>& buttons)
|
||||
{
|
||||
QVector<int> l = fromButtonToInt(buttons);
|
||||
normalizeButtons(l);
|
||||
@@ -172,9 +176,9 @@ QColor ConfigHandler::uiContrastColorValue()
|
||||
{
|
||||
QColor res = QColor(39, 0, 50);
|
||||
|
||||
if (m_settings.contains(QStringLiteral("contastUiColor"))) {
|
||||
if (m_settings.contains(QStringLiteral("contrastUiColor"))) {
|
||||
QString hex =
|
||||
m_settings.value(QStringLiteral("contastUiColor")).toString();
|
||||
m_settings.value(QStringLiteral("contrastUiColor")).toString();
|
||||
|
||||
if (QColor::isValidColor(hex)) {
|
||||
res = QColor(hex);
|
||||
@@ -186,7 +190,7 @@ QColor ConfigHandler::uiContrastColorValue()
|
||||
|
||||
void ConfigHandler::setUIContrastColor(const QColor& c)
|
||||
{
|
||||
m_settings.setValue(QStringLiteral("contastUiColor"), c.name());
|
||||
m_settings.setValue(QStringLiteral("contrastUiColor"), c.name());
|
||||
}
|
||||
|
||||
QColor ConfigHandler::drawColorValue()
|
||||
@@ -223,6 +227,18 @@ void ConfigHandler::setShowHelp(const bool showHelp)
|
||||
m_settings.setValue(QStringLiteral("showHelp"), showHelp);
|
||||
}
|
||||
|
||||
bool ConfigHandler::showSidePanelButtonValue()
|
||||
{
|
||||
return m_settings.value(QStringLiteral("showSidePanelButton"), true)
|
||||
.toBool();
|
||||
}
|
||||
|
||||
void ConfigHandler::setShowSidePanelButton(const bool showSidePanelButton)
|
||||
{
|
||||
m_settings.setValue(QStringLiteral("showSidePanelButton"),
|
||||
showSidePanelButton);
|
||||
}
|
||||
|
||||
bool ConfigHandler::desktopNotificationValue()
|
||||
{
|
||||
bool res = true;
|
||||
@@ -425,6 +441,15 @@ void ConfigHandler::setCopyAndCloseAfterUploadEnabled(const bool value)
|
||||
{
|
||||
m_settings.setValue(QStringLiteral("copyAndCloseAfterUpload"), value);
|
||||
}
|
||||
bool ConfigHandler::saveAfterCopyValue()
|
||||
{
|
||||
return m_settings.value(QStringLiteral("saveAfterCopy")).toBool();
|
||||
}
|
||||
|
||||
void ConfigHandler::setSaveAfterCopy(const bool save)
|
||||
{
|
||||
m_settings.setValue(QStringLiteral("saveAfterCopy"), save);
|
||||
}
|
||||
|
||||
bool ConfigHandler::copyPathAfterSaveEnabled()
|
||||
{
|
||||
@@ -455,6 +480,16 @@ const QString& ConfigHandler::uploadStorage()
|
||||
return m_strRes;
|
||||
}
|
||||
|
||||
QString ConfigHandler::saveAfterCopyPathValue()
|
||||
{
|
||||
return m_settings.value(QStringLiteral("saveAfterCopyPath")).toString();
|
||||
}
|
||||
|
||||
void ConfigHandler::setSaveAfterCopyPath(const QString& path)
|
||||
{
|
||||
m_settings.setValue(QStringLiteral("saveAfterCopyPath"), path);
|
||||
}
|
||||
|
||||
void ConfigHandler::setDefaults()
|
||||
{
|
||||
m_settings.clear();
|
||||
@@ -463,8 +498,8 @@ void ConfigHandler::setDefaults()
|
||||
void ConfigHandler::setAllTheButtons()
|
||||
{
|
||||
QVector<int> buttons;
|
||||
auto listTypes = CaptureButton::getIterableButtonTypes();
|
||||
for (const CaptureButton::ButtonType t : listTypes) {
|
||||
auto listTypes = CaptureToolButton::getIterableButtonTypes();
|
||||
for (const CaptureToolButton::ButtonType t : listTypes) {
|
||||
buttons << static_cast<int>(t);
|
||||
}
|
||||
// TODO: remove toList in v1.0
|
||||
@@ -479,7 +514,7 @@ QString ConfigHandler::configFilePath() const
|
||||
|
||||
bool ConfigHandler::normalizeButtons(QVector<int>& buttons)
|
||||
{
|
||||
auto listTypes = CaptureButton::getIterableButtonTypes();
|
||||
auto listTypes = CaptureToolButton::getIterableButtonTypes();
|
||||
QVector<int> listTypesInt;
|
||||
for (auto i : listTypes)
|
||||
listTypesInt << static_cast<int>(i);
|
||||
@@ -494,17 +529,17 @@ bool ConfigHandler::normalizeButtons(QVector<int>& buttons)
|
||||
return hasChanged;
|
||||
}
|
||||
|
||||
QVector<CaptureButton::ButtonType> ConfigHandler::fromIntToButton(
|
||||
QVector<CaptureToolButton::ButtonType> ConfigHandler::fromIntToButton(
|
||||
const QVector<int>& l)
|
||||
{
|
||||
QVector<CaptureButton::ButtonType> buttons;
|
||||
QVector<CaptureToolButton::ButtonType> buttons;
|
||||
for (auto const i : l)
|
||||
buttons << static_cast<CaptureButton::ButtonType>(i);
|
||||
buttons << static_cast<CaptureToolButton::ButtonType>(i);
|
||||
return buttons;
|
||||
}
|
||||
|
||||
QVector<int> ConfigHandler::fromButtonToInt(
|
||||
const QVector<CaptureButton::ButtonType>& l)
|
||||
const QVector<CaptureToolButton::ButtonType>& l)
|
||||
{
|
||||
QVector<int> buttons;
|
||||
for (auto const i : l)
|
||||
|
||||
@@ -17,19 +17,18 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "src/widgets/capture/capturebutton.h"
|
||||
#include "src/widgets/capture/capturetoolbutton.h"
|
||||
#include <QSettings>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
class ConfigHandler : public QObject
|
||||
class ConfigHandler
|
||||
{
|
||||
|
||||
public:
|
||||
explicit ConfigHandler();
|
||||
|
||||
QVector<CaptureButton::ButtonType> getButtons();
|
||||
void setButtons(const QVector<CaptureButton::ButtonType>&);
|
||||
QVector<CaptureToolButton::ButtonType> getButtons();
|
||||
void setButtons(const QVector<CaptureToolButton::ButtonType>&);
|
||||
|
||||
QVector<QColor> getUserColors();
|
||||
void setUserColors(const QVector<QColor>&);
|
||||
@@ -51,6 +50,9 @@ public:
|
||||
bool showHelpValue();
|
||||
void setShowHelp(const bool);
|
||||
|
||||
bool showSidePanelButtonValue();
|
||||
void setShowSidePanelButton(const bool);
|
||||
|
||||
bool desktopNotificationValue();
|
||||
void setDesktopNotification(const bool);
|
||||
|
||||
@@ -81,6 +83,11 @@ public:
|
||||
|
||||
bool copyAndCloseAfterUploadEnabled();
|
||||
void setCopyAndCloseAfterUploadEnabled(const bool);
|
||||
bool saveAfterCopyValue();
|
||||
void setSaveAfterCopy(const bool);
|
||||
|
||||
QString saveAfterCopyPathValue();
|
||||
void setSaveAfterCopyPath(const QString&);
|
||||
|
||||
bool copyPathAfterSaveEnabled();
|
||||
void setCopyPathAfterSaveEnabled(const bool);
|
||||
@@ -105,6 +112,8 @@ private:
|
||||
|
||||
bool normalizeButtons(QVector<int>&);
|
||||
|
||||
QVector<CaptureButton::ButtonType> fromIntToButton(const QVector<int>& l);
|
||||
QVector<int> fromButtonToInt(const QVector<CaptureButton::ButtonType>& l);
|
||||
QVector<CaptureToolButton::ButtonType> fromIntToButton(
|
||||
const QVector<int>& l);
|
||||
QVector<int> fromButtonToInt(
|
||||
const QVector<CaptureToolButton::ButtonType>& l);
|
||||
};
|
||||
|
||||
@@ -29,14 +29,14 @@ void DBusUtils::connectPrintCapture(QDBusConnection& session, uint id)
|
||||
{
|
||||
m_id = id;
|
||||
// captureTaken
|
||||
session.connect(QStringLiteral("org.dharkael.Flameshot"),
|
||||
session.connect(QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("captureTaken"),
|
||||
this,
|
||||
SLOT(captureTaken(uint, QByteArray)));
|
||||
// captureFailed
|
||||
session.connect(QStringLiteral("org.dharkael.Flameshot"),
|
||||
session.connect(QStringLiteral("org.flameshot.Flameshot"),
|
||||
QStringLiteral("/"),
|
||||
QLatin1String(""),
|
||||
QStringLiteral("captureFailed"),
|
||||
|
||||
@@ -27,14 +27,31 @@
|
||||
|
||||
ScreenshotSaver::ScreenshotSaver() {}
|
||||
|
||||
// TODO: If data is saved to the clipboard before the notification is sent via
|
||||
// dbus, the application freezes.
|
||||
void ScreenshotSaver::saveToClipboard(const QPixmap& capture)
|
||||
{
|
||||
SystemNotification().sendMessage(QObject::tr("Capture saved to clipboard"));
|
||||
QApplication::clipboard()->setPixmap(capture);
|
||||
|
||||
// If we are able to properly save the file, save the file and copy to
|
||||
// clipboard.
|
||||
if ((ConfigHandler().saveAfterCopyValue()) &&
|
||||
(!ConfigHandler().saveAfterCopyPathValue().isEmpty())) {
|
||||
saveToFilesystem(capture,
|
||||
ConfigHandler().saveAfterCopyPathValue(),
|
||||
QObject::tr("Capture saved to clipboard."));
|
||||
QApplication::clipboard()->setPixmap(capture);
|
||||
}
|
||||
// Otherwise only save to clipboard
|
||||
else {
|
||||
SystemNotification().sendMessage(
|
||||
QObject::tr("Capture saved to clipboard"));
|
||||
QApplication::clipboard()->setPixmap(capture);
|
||||
}
|
||||
}
|
||||
|
||||
bool ScreenshotSaver::saveToFilesystem(const QPixmap& capture,
|
||||
const QString& path)
|
||||
const QString& path,
|
||||
const QString& messagePrefix)
|
||||
{
|
||||
QString completePath = FileNameHandler().generateAbsolutePath(path);
|
||||
completePath += QLatin1String(".png");
|
||||
@@ -44,9 +61,11 @@ bool ScreenshotSaver::saveToFilesystem(const QPixmap& capture,
|
||||
|
||||
if (ok) {
|
||||
ConfigHandler().setSavePath(path);
|
||||
saveMessage = QObject::tr("Capture saved as ") + completePath;
|
||||
saveMessage =
|
||||
messagePrefix + QObject::tr("Capture saved as ") + completePath;
|
||||
} else {
|
||||
saveMessage = QObject::tr("Error trying to save as ") + completePath;
|
||||
saveMessage = messagePrefix + QObject::tr("Error trying to save as ") +
|
||||
completePath;
|
||||
notificationPath = "";
|
||||
}
|
||||
|
||||
@@ -83,10 +102,9 @@ bool ScreenshotSaver::saveToFilesystemGUI(const QPixmap& capture)
|
||||
ok = capture.save(savePath);
|
||||
|
||||
if (ok) {
|
||||
ConfigHandler config;
|
||||
QString pathNoFile =
|
||||
savePath.left(savePath.lastIndexOf(QLatin1String("/")));
|
||||
config.setSavePath(pathNoFile);
|
||||
ConfigHandler().setSavePath(pathNoFile);
|
||||
QString msg = QObject::tr("Capture saved as ") + savePath;
|
||||
if (config.copyPathAfterSaveEnabled()) {
|
||||
QApplication::clipboard()->setText(savePath);
|
||||
|
||||
@@ -26,6 +26,8 @@ public:
|
||||
ScreenshotSaver();
|
||||
|
||||
void saveToClipboard(const QPixmap& capture);
|
||||
bool saveToFilesystem(const QPixmap& capture, const QString& path);
|
||||
bool saveToFilesystem(const QPixmap& capture,
|
||||
const QString& path,
|
||||
const QString& messagePrefix);
|
||||
bool saveToFilesystemGUI(const QPixmap& capture);
|
||||
};
|
||||
|
||||
23
src/widgets/CMakeLists.txt
Normal file
23
src/widgets/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
add_subdirectory(panel)
|
||||
add_subdirectory(capture)
|
||||
|
||||
# Required to generate MOC
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE capturelauncher.h
|
||||
draggablewidgetmaker.h
|
||||
imagelabel.h
|
||||
infowindow.h
|
||||
loadspinner.h
|
||||
notificationwidget.h
|
||||
orientablepushbutton.h)
|
||||
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE capturelauncher.cpp
|
||||
draggablewidgetmaker.cpp
|
||||
imagelabel.cpp
|
||||
infowindow.cpp
|
||||
loadspinner.cpp
|
||||
notificationwidget.cpp
|
||||
orientablepushbutton.cpp)
|
||||
23
src/widgets/capture/CMakeLists.txt
Normal file
23
src/widgets/capture/CMakeLists.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
# Required to generate MOC
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE buttonhandler.h
|
||||
capturebutton.h
|
||||
capturetoolbutton.h
|
||||
capturewidget.h
|
||||
colorpicker.h
|
||||
hovereventfilter.h
|
||||
selectionwidget.h
|
||||
notifierbox.h)
|
||||
|
||||
target_sources(
|
||||
flameshot
|
||||
PRIVATE buttonhandler.cpp
|
||||
capturebutton.cpp
|
||||
capturetoolbutton.cpp
|
||||
capturewidget.cpp
|
||||
colorpicker.cpp
|
||||
hovereventfilter.cpp
|
||||
modificationcommand.cpp
|
||||
notifierbox.cpp
|
||||
selectionwidget.cpp)
|
||||
@@ -24,7 +24,8 @@
|
||||
// ButtonHandler is a habdler for every active button. It makes easier to
|
||||
// manipulate the buttons as a unit.
|
||||
|
||||
ButtonHandler::ButtonHandler(const QVector<CaptureButton*>& v, QObject* parent)
|
||||
ButtonHandler::ButtonHandler(const QVector<CaptureToolButton*>& v,
|
||||
QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
setButtons(v);
|
||||
@@ -39,7 +40,7 @@ ButtonHandler::ButtonHandler(QObject* parent)
|
||||
|
||||
void ButtonHandler::hide()
|
||||
{
|
||||
for (CaptureButton* b : m_vectorButtons)
|
||||
for (CaptureToolButton* b : m_vectorButtons)
|
||||
b->hide();
|
||||
}
|
||||
|
||||
@@ -48,14 +49,14 @@ void ButtonHandler::show()
|
||||
if (m_vectorButtons.isEmpty() || m_vectorButtons.first()->isVisible()) {
|
||||
return;
|
||||
}
|
||||
for (CaptureButton* b : m_vectorButtons)
|
||||
for (CaptureToolButton* b : m_vectorButtons)
|
||||
b->animatedShow();
|
||||
}
|
||||
|
||||
bool ButtonHandler::isVisible() const
|
||||
{
|
||||
bool ret = true;
|
||||
for (const CaptureButton* b : m_vectorButtons) {
|
||||
for (const CaptureToolButton* b : m_vectorButtons) {
|
||||
if (!b->isVisible()) {
|
||||
ret = false;
|
||||
break;
|
||||
@@ -239,7 +240,7 @@ QVector<QPoint> ButtonHandler::verticalPoints(const QPoint& center,
|
||||
QRect ButtonHandler::intersectWithAreas(const QRect& rect)
|
||||
{
|
||||
QRect res;
|
||||
for (const QRect& r : m_screenRegions.rects()) {
|
||||
for (const QRect& r : m_screenRegions) {
|
||||
QRect temp = rect.intersected(r);
|
||||
if (temp.height() * temp.width() > res.height() * res.width()) {
|
||||
res = temp;
|
||||
@@ -361,12 +362,12 @@ void ButtonHandler::adjustHorizontalCenter(QPoint& center)
|
||||
}
|
||||
|
||||
// setButtons redefines the buttons of the button handler
|
||||
void ButtonHandler::setButtons(const QVector<CaptureButton*> v)
|
||||
void ButtonHandler::setButtons(const QVector<CaptureToolButton*> v)
|
||||
{
|
||||
if (v.isEmpty())
|
||||
return;
|
||||
|
||||
for (CaptureButton* b : m_vectorButtons)
|
||||
for (CaptureToolButton* b : m_vectorButtons)
|
||||
delete (b);
|
||||
m_vectorButtons = v;
|
||||
m_buttonBaseSize = GlobalValues::buttonBaseSize();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user