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:
Yuriy Puchkov
2020-09-24 18:52:49 +03:00
351 changed files with 23741 additions and 14935 deletions

208
src/CMakeLists.txt Normal file
View 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
View File

@@ -0,0 +1 @@
target_sources(flameshot PRIVATE commandlineparser.cpp commandoption.cpp commandargument.cpp)

View File

@@ -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
View 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)

View File

@@ -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 {

View File

@@ -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*);
};

View File

@@ -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();

View File

@@ -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 =

View File

@@ -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);

View File

@@ -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();

View File

@@ -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;

View File

@@ -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
View 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()

View File

@@ -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, "");
}
}

View File

@@ -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);

View File

@@ -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;
};

View File

@@ -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);

View File

@@ -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"));

View File

@@ -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.

View File

@@ -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.

View File

@@ -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>

View File

@@ -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

View File

@@ -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

View File

@@ -1 +0,0 @@
#include "color_wheel.hpp"

View File

@@ -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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 B

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,5 +0,0 @@
<RCC>
<qresource prefix="/color_widgets">
<file>alphaback.png</file>
</qresource>
</RCC>

View File

@@ -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.

View File

@@ -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.

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
View 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)

View File

@@ -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;

View File

@@ -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;

View File

@@ -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)

View File

@@ -53,6 +53,8 @@ protected:
bool m_supportsOrthogonalAdj = false;
bool m_supportsDiagonalAdj = false;
virtual ToolType nameID() const = 0;
private:
QPoint adjustedVector(QPoint v) const;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -42,6 +42,7 @@ struct CaptureContext
QPoint mousePos;
// Value of the desired thickness
int thickness;
int circleCount;
// Mode of the capture widget
bool fullscreen;

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View 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);
}

View 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;
};

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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();

View File

@@ -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

View File

@@ -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 });
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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());

View 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);
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View File

@@ -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;
};

View File

@@ -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(""));

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
};

View File

@@ -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

View File

@@ -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
View 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)

View File

@@ -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)

View File

@@ -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);
};

View File

@@ -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"),

View File

@@ -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);

View File

@@ -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);
};

View 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)

View 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)

View File

@@ -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