Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ jobs:
qmake fuzzy_clock.pro "CONFIG+=release"
nmake release

- name: Тесты
run: |
New-Item -ItemType Directory tests-build | Out-Null
Set-Location tests-build
qmake ..\tests\tests.pro "CONFIG+=release"
nmake release
.\release\fuzzy_clock_tests.exe
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }

- name: Развёртывание
run: |
New-Item -ItemType Directory deploy | Out-Null
Expand Down
Binary file added FuzzyClock_from KDE (original C source).cab
Binary file not shown.
2 changes: 2 additions & 0 deletions fuzzy_clock.pro
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ win32: RC_FILE = resource.rc

HEADERS += \
fuzzy_clock.h \
fuzzy_dock.h \
fuzzy_helper.h \
fuzzy_clock_window.h

SOURCES += \
fuzzy_clock.cpp \
fuzzy_dock.cpp \
fuzzy_helper.cpp \
fuzzy_clock_window.cpp \
main.cpp
Expand Down
52 changes: 48 additions & 4 deletions fuzzy_clock_window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <iterator>

#include "fuzzy_clock_window.h"
#include "fuzzy_dock.h"
#include "fuzzy_helper.h"

namespace {
Expand Down Expand Up @@ -42,6 +43,9 @@ const Opacity Opacities[] = { { "10%", 0.1 }, { "50%", 0.5 }, { "100%", 1.0 } };

const char *const FuzzinessNames[] = { "Четверть пятого", "Вечер", "Середина недели" };

// на каком расстоянии от края экрана окно к нему притягивается
constexpr int SnapDistance = 15;

QString autostartCommand()
{
return "\"" + QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + "\"";
Expand Down Expand Up @@ -104,6 +108,15 @@ fuzzyClockWindow::fuzzyClockWindow()
restorePosition();
setWindowOpacity(m_Settings.value("Opacity", 1.0).toDouble());

// панель задач переместилась, сменилось разрешение - окно остаётся у своих краёв
const auto watchScreen = [this](QScreen *screen) {
connect(screen, &QScreen::availableGeometryChanged, this, &fuzzyClockWindow::applyDock);
};
for (QScreen *screen : QGuiApplication::screens())
watchScreen(screen);
connect(qApp, &QGuiApplication::screenAdded, this, watchScreen);
connect(qApp, &QGuiApplication::screenRemoved, this, &fuzzyClockWindow::applyDock, Qt::QueuedConnection);

/* Context menu */
createMenu();

Expand Down Expand Up @@ -133,6 +146,7 @@ void fuzzyClockWindow::updateTime()
setToolTip(QLocale(QLocale::Russian).toString(now, "HH:mm, dddd, d MMMM"));
m_label->adjustSize(); // учитывает шрифт из CSS (вызывает ensurePolished)
setFixedSize(m_label->size() + QSize(10, 10));
applyDock(); // при прилипании справа или снизу окно растёт внутрь экрана

// следующее обновление - в начале следующей минуты
m_timer.start(60000 - now.time().msecsSinceStartOfDay() % 60000);
Expand Down Expand Up @@ -190,17 +204,45 @@ void fuzzyClockWindow::mousePressEvent(QMouseEvent *event)
mpos = event->pos();
}

// Drag window without title
// Drag window without title; Shift отключает прилипание к краям
void fuzzyClockWindow::mouseMoveEvent(QMouseEvent *event)
{
if (event->buttons() & Qt::LeftButton)
move(pos() + event->pos() - mpos);
if (!(event->buttons() & Qt::LeftButton))
return;
const QPoint p = pos() + event->pos() - mpos;
if (event->modifiers() & Qt::ShiftModifier)
move(p);
else
move(fuzzyDock::snapped(QRect(p, size()), dockArea(p), SnapDistance));
}

void fuzzyClockWindow::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
if (event->button() == Qt::LeftButton) {
m_dock = fuzzyDock::edges(geometry(), dockArea(pos()));
savePosition(); // перетаскивание закончено
}
}

QRect fuzzyClockWindow::dockArea(const QPoint &topLeft) const
{
const QScreen *screen = QGuiApplication::screenAt(QRect(topLeft, size()).center());
if (!screen)
screen = QGuiApplication::screenAt(pos());
if (!screen)
screen = QGuiApplication::primaryScreen();
return screen->availableGeometry(); // без панели задач
}

void fuzzyClockWindow::applyDock()
{
if (!m_dock)
return;
const QPoint p = fuzzyDock::docked(geometry(), dockArea(pos()), m_dock);
if (p != pos()) {
move(p);
savePosition();
}
}

void fuzzyClockWindow::closeEvent(QCloseEvent *event)
Expand All @@ -226,6 +268,7 @@ void fuzzyClockWindow::savePosition()
m_Settings.setValue("currentPath", QDir::currentPath());
m_Settings.setValue("Top", pos().y());
m_Settings.setValue("Left", pos().x());
m_Settings.setValue("Dock", m_dock);
}

void fuzzyClockWindow::restorePosition()
Expand All @@ -235,6 +278,7 @@ void fuzzyClockWindow::restorePosition()
if (!QGuiApplication::screenAt(p))
p = QGuiApplication::primaryScreen()->availableGeometry().center();
move(p);
m_dock = m_Settings.value("Dock", 0).toInt(); // применяется после первого расчёта размера в updateTime()
}

void fuzzyClockWindow::createMenu()
Expand Down
5 changes: 5 additions & 0 deletions fuzzy_clock_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,18 @@ private slots:
void restorePosition();
void savePosition();

// Прилипание к краям экрана (расчёты - в fuzzy_dock.h)
QRect dockArea(const QPoint &topLeft) const; // рабочая область экрана, на котором окажется окно
void applyDock(); // удержать прижатые края при смене размера окна или экрана

fuzzyClock::Fuzziness fuzziness() const;

fuzzyClock m_clock;
QLabel *m_label;
QTimer m_timer;
QSettings m_Settings;
QPoint mpos;
int m_dock = 0; // сочетание fuzzyDock::Edge

QMenu *m_menu;
QAction *m_autostartAct;
Expand Down
52 changes: 52 additions & 0 deletions fuzzy_dock.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <QtGlobal>

#include "fuzzy_dock.h"

namespace fuzzyDock {

QPoint snapped(const QRect &window, const QRect &area, int distance)
{
QPoint p = window.topLeft();

if (qAbs(window.left() - area.left()) <= distance)
p.setX(area.left());
else if (qAbs(window.right() - area.right()) <= distance)
p.setX(area.right() - window.width() + 1);

if (qAbs(window.top() - area.top()) <= distance)
p.setY(area.top());
else if (qAbs(window.bottom() - area.bottom()) <= distance)
p.setY(area.bottom() - window.height() + 1);

return p;
}

int edges(const QRect &window, const QRect &area)
{
int result = 0;
if (window.left() == area.left())
result |= Left;
else if (window.right() == area.right())
result |= Right;
if (window.top() == area.top())
result |= Top;
else if (window.bottom() == area.bottom())
result |= Bottom;
return result;
}

QPoint docked(const QRect &window, const QRect &area, int edges)
{
QPoint p = window.topLeft();
if (edges & Left)
p.setX(area.left());
else if (edges & Right)
p.setX(area.right() - window.width() + 1);
if (edges & Top)
p.setY(area.top());
else if (edges & Bottom)
p.setY(area.bottom() - window.height() + 1);
return p;
}

}
23 changes: 23 additions & 0 deletions fuzzy_dock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#ifndef FUZZY_DOCK_H
#define FUZZY_DOCK_H

#include <QPoint>
#include <QRect>

// Прилипание окна к краям рабочей области экрана
namespace fuzzyDock {

enum Edge { Left = 1, Right = 2, Top = 4, Bottom = 8 };

// позиция окна с притяжением к краям area, если до края не больше distance пикселей
QPoint snapped(const QRect &window, const QRect &area, int distance);

// края area, к которым окно прижато (сочетание Edge)
int edges(const QRect &window, const QRect &area);

// позиция, при которой окно остаётся прижатым к краям edges
QPoint docked(const QRect &window, const QRect &area, int edges);

}

#endif // FUZZY_DOCK_H
18 changes: 18 additions & 0 deletions tests/tests.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Тесты логики часов: фразы из fuzzy.conf и прилипание к краям экрана
QT = core testlib
CONFIG += console testcase
TARGET = fuzzy_clock_tests

INCLUDEPATH += ..
DEFINES += SOURCE_DIR=\\\"$$PWD/..\\\"

HEADERS += \
../fuzzy_clock.h \
../fuzzy_dock.h \
../fuzzy_helper.h

SOURCES += \
tst_fuzzy_clock.cpp \
../fuzzy_clock.cpp \
../fuzzy_dock.cpp \
../fuzzy_helper.cpp
Loading