Skip to content

Commit 3baf3a7

Browse files
committed
Слежение заметок за своими папками - при изменении извне файлов настроек,
содержимого заметок происходит перезагрузка этих файлов. При изменении папки прикрепленных файлов - обновление списка файлов. Рефакторинг. Signed-off-by: gil9red <gil9red@gmail.com>
1 parent f6dd2d6 commit 3baf3a7

File tree

5 files changed

+164
-59
lines changed

5 files changed

+164
-59
lines changed

Note/RichTextNote.cpp

Lines changed: 143 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -115,16 +115,50 @@ QString RichTextNote::settingsFilePath()
115115
void RichTextNote::setFileName( const QString & dirName )
116116
{
117117
noteFileName = dirName;
118-
119118
// Если уже существует, то выходим
120119
if ( QDir( noteFileName ).exists() )
120+
{
121+
// Настройка слежения за папкой заметки
122+
{
123+
// Прекращаем слежение за предыдущими файлами
124+
const QStringList & directories = fileSystemWatcher.directories();
125+
if ( !directories.isEmpty() )
126+
fileSystemWatcher.removePaths( directories );
127+
128+
const QStringList & files = fileSystemWatcher.files();
129+
if ( !files.isEmpty() )
130+
fileSystemWatcher.removePaths( files );
131+
132+
// Устанавливаем слежение за новыми
133+
fileSystemWatcher.addPath( attachDirPath() ); // Папка с прикрепленными файлами
134+
fileSystemWatcher.addPath( contentFilePath() ); // Файл, описывающий содержимое заметки (html)
135+
fileSystemWatcher.addPath( settingsFilePath() ); // Файл, описывающий заметку - название, положение, размер, цвет и т.п.
136+
137+
// Так как папка у нас одна - папка с прикрепленными файлами, то обновляем только ее, а по хорошему нужно создать отдельный слот-обработчик.
138+
QObject::connect( &fileSystemWatcher, SIGNAL(directoryChanged(QString)), SLOT(directoryChanged(QString)) );
139+
QObject::connect( &fileSystemWatcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)) );
140+
}
141+
121142
return;
143+
}
122144

123145
// Создадим папку заметки с нужными папками и файлами
124146
QDir().mkdir( noteFileName );
125147
QDir().mkdir( attachDirPath() );
126148
QFile( contentFilePath() ).open( QIODevice::WriteOnly );
127149
QFile( settingsFilePath() ).open( QIODevice::WriteOnly );
150+
151+
// Настройка слежения за папкой заметки
152+
{
153+
// Устанавливаем слежение за новыми
154+
fileSystemWatcher.addPath( attachDirPath() ); // Папка с прикрепленными файлами
155+
fileSystemWatcher.addPath( contentFilePath() ); // Файл, описывающий содержимое заметки (html)
156+
fileSystemWatcher.addPath( settingsFilePath() ); // Файл, описывающий заметку - название, положение, размер, цвет и т.п.
157+
158+
// Так как папка у нас одна - папка с прикрепленными файлами, то обновляем только ее, а по хорошему нужно создать отдельный слот-обработчик.
159+
QObject::connect( &fileSystemWatcher, SIGNAL(directoryChanged(QString)), SLOT(directoryChanged(QString)) );
160+
QObject::connect( &fileSystemWatcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged(QString)) );
161+
}
128162
}
129163

130164
void RichTextNote::setDefaultSettingsFromMap(const QVariantMap & data )
@@ -341,20 +375,7 @@ void RichTextNote::setupGUI()
341375

342376
void RichTextNote::save()
343377
{
344-
mapSettings[ "Top" ] = isTop();
345-
mapSettings[ "ColorTitle" ] = titleColor().name();
346-
mapSettings[ "ColorBody" ] = bodyColor().name();
347-
mapSettings[ "Opacity" ] = opacity();
348-
mapSettings[ "Visible" ] = isVisible();
349-
mapSettings[ "Title" ] = title();
350-
mapSettings[ "FontTitle" ] = titleFont().toString();
351-
mapSettings[ "Position" ] = pos();
352-
mapSettings[ "Size" ] = size();
353-
354-
QSettings ini( settingsFilePath(), QSettings::IniFormat );
355-
ini.setIniCodec( "utf8" );
356-
ini.setValue( "Settings", mapSettings );
357-
378+
saveSettings();
358379
saveContent();
359380
statusBar()->showMessage( tr( "Save completed" ), 5000 );
360381
emit changed( EventsNote::SaveEnded );
@@ -363,20 +384,9 @@ void RichTextNote::load()
363384
{
364385
QSettings ini( settingsFilePath(), QSettings::IniFormat );
365386
ini.setIniCodec( "utf8" );
366-
mapSettings = ini.value( "Settings" ).toMap();
367-
368-
QString _title;
369-
QFont _fontTitle;
370-
QSize _size;
371-
QPoint _position;
372-
QColor _titleColor;
373-
QColor _bodyColor;
374-
bool _top;
375-
qreal _opacity;
376-
bool _visible;
377387

378388
// Если пуст, значит эта заметка новая -> берем параметры из дэфолтных настроек
379-
if ( mapSettings.isEmpty() )
389+
if ( ini.value( "Settings" ).toMap().isEmpty() )
380390
{
381391
const QDateTime & currentDateTime = QDateTime::currentDateTime();
382392
const QRect & desktop = QDesktopWidget().geometry();
@@ -386,16 +396,21 @@ void RichTextNote::load()
386396
mapSettings[ "Created" ] = currentDateTime;
387397
mapSettings[ "Modified" ] = currentDateTime;
388398

389-
_title = TextTemplateParser::get( defaultMapSettings[ "Title" ].toString() );
399+
QString _title = TextTemplateParser::get( defaultMapSettings[ "Title" ].toString() );
400+
QFont _fontTitle;
401+
QSize _size = defaultMapSettings[ "Size" ].toSize();
402+
QPoint _position;
403+
390404
_fontTitle.fromString( defaultMapSettings[ "FontTitle" ].toString() );
391-
_size = defaultMapSettings[ "Size" ].toSize();
392405

393406
// TODO: доработать с учетом размера заметок, т.к. новые заметки может разместить за экран
394407
if ( randomPosition )
395408
_position = QPoint( qrand() % desktop.width(), qrand() % desktop.height() );
396409
else
397410
_position = defaultMapSettings[ "Position" ].toPoint();
398411

412+
QColor _titleColor;
413+
QColor _bodyColor;
399414
if ( randomColor )
400415
{
401416
_titleColor.setRgb( qrand() % 0xff, qrand() % 0xff, qrand() % 0xff );
@@ -406,45 +421,79 @@ void RichTextNote::load()
406421
_bodyColor = QColor( defaultMapSettings[ "ColorBody" ].toString() );
407422
}
408423

409-
_top = defaultMapSettings[ "Top" ].toBool();
410-
_opacity = defaultMapSettings.value( "Opacity" ).toDouble();
411-
_visible = defaultMapSettings.value( "Visible" ).toBool();
424+
bool _top = defaultMapSettings[ "Top" ].toBool();
425+
qreal _opacity = defaultMapSettings.value( "Opacity" ).toDouble();
426+
bool _visible = defaultMapSettings.value( "Visible" ).toBool();
412427

413428
setText( TextTemplateParser::get( defaultMapSettings[ "Text" ].toString() ) );
414429

430+
setTitle( _title );
431+
setTitleFont( _fontTitle );
432+
resize( _size );
433+
move( _position );
434+
setTitleColor( _titleColor );
435+
setBodyColor( _bodyColor );
436+
setTop( _top );
437+
setOpacity( _opacity );
438+
setVisible( _visible );
415439
} else
416440
{
417-
_fontTitle.fromString( mapSettings[ "FontTitle" ].toString() );
418-
_title = mapSettings[ "Title" ].toString();
419-
_size = mapSettings[ "Size" ].toSize();
420-
_position = mapSettings[ "Position" ].toPoint();
421-
_titleColor = QColor( mapSettings[ "ColorTitle" ].toString() );
422-
_bodyColor = QColor( mapSettings[ "ColorBody" ].toString() );
423-
_top = mapSettings[ "Top" ].toBool();
424-
_opacity = mapSettings[ "Opacity" ].toDouble();
425-
_visible = mapSettings.value( "Visible" ).toBool();
426-
441+
loadSettings();
427442
loadContent();
428443
}
429444

430-
setTitle( _title );
431-
setTitleFont( _fontTitle );
432-
resize( _size );
433-
move( _position );
434-
setTitleColor( _titleColor );
435-
setBodyColor( _bodyColor );
436-
setTop( _top );
437-
setOpacity( _opacity );
438-
setVisible( _visible );
439-
440445
setActivateTimerAutosave( defaultMapSettings[ "Autosave" ].toBool() );
441446
setIntervalAutosave( defaultMapSettings[ "AutosaveInterval" ].toInt() );
442447

443448
updateStates();
444449
emit changed( EventsNote::LoadEnded );
445450
}
451+
void RichTextNote::loadSettings()
452+
{
453+
QSettings ini( settingsFilePath(), QSettings::IniFormat );
454+
ini.setIniCodec( "utf8" );
455+
mapSettings = ini.value( "Settings" ).toMap();
456+
457+
setTitle( mapSettings[ "Title" ].toString() );
458+
setTitleFont( mapSettings[ "FontTitle" ].toString() );
459+
resize( mapSettings[ "Size" ].toSize() );
460+
move( mapSettings[ "Position" ].toPoint() );
461+
setTitleColor( QColor( mapSettings[ "ColorTitle" ].toString() ) );
462+
setBodyColor( QColor( mapSettings[ "ColorBody" ].toString() ) );
463+
setTop( mapSettings[ "Top" ].toBool() );
464+
setOpacity( mapSettings[ "Opacity" ].toDouble() );
465+
setVisible( mapSettings.value( "Visible" ).toBool() );
466+
467+
updateStates();
468+
emit changed( EventsNote::LoadEnded );
469+
}
470+
void RichTextNote::saveSettings()
471+
{
472+
// Не нужно реагировать на изменение при сохранении
473+
fileSystemWatcher.blockSignals( true );
474+
475+
mapSettings[ "Top" ] = isTop();
476+
mapSettings[ "ColorTitle" ] = titleColor().name();
477+
mapSettings[ "ColorBody" ] = bodyColor().name();
478+
mapSettings[ "Opacity" ] = opacity();
479+
mapSettings[ "Visible" ] = isVisible();
480+
mapSettings[ "Title" ] = title();
481+
mapSettings[ "FontTitle" ] = titleFont().toString();
482+
mapSettings[ "Position" ] = pos();
483+
mapSettings[ "Size" ] = size();
484+
485+
QSettings ini( settingsFilePath(), QSettings::IniFormat );
486+
ini.setIniCodec( "utf8" );
487+
ini.setValue( "Settings", mapSettings );
488+
ini.sync();
489+
490+
fileSystemWatcher.blockSignals( false );
491+
}
446492
void RichTextNote::saveContent()
447493
{
494+
// Не нужно реагировать на изменение при сохранении
495+
fileSystemWatcher.blockSignals( true );
496+
448497
QFile content( contentFilePath() );
449498
if ( !content.open( QIODevice::Truncate | QIODevice::WriteOnly ) )
450499
{
@@ -457,11 +506,22 @@ void RichTextNote::saveContent()
457506
in << text();
458507
content.close();
459508

509+
fileSystemWatcher.blockSignals( false );
510+
460511
updateStates();
461512
}
462513
void RichTextNote::loadContent()
463514
{
464-
editor.setSource( QUrl::fromLocalFile( contentFilePath() ) );
515+
// editor.setSource( QUrl::fromLocalFile( contentFilePath() ) );
516+
517+
QFile file( contentFilePath() );
518+
if ( !file.open( QIODevice::ReadOnly ) )
519+
return;
520+
521+
QTextStream in( &file );
522+
in.setCodec( QTextCodec::codecForName( codec ) );
523+
524+
editor.setHtml( in.readAll() );
465525
}
466526
void RichTextNote::setText( const QString & str )
467527
{
@@ -476,8 +536,17 @@ QString RichTextNote::text()
476536
}
477537
void RichTextNote::removeDir()
478538
{
539+
// Прекращаем слежение за файлами и папками
540+
const QStringList & directories = fileSystemWatcher.directories();
541+
if ( !directories.isEmpty() )
542+
fileSystemWatcher.removePaths( directories );
543+
544+
const QStringList & files = fileSystemWatcher.files();
545+
if ( !files.isEmpty() )
546+
fileSystemWatcher.removePaths( files );
547+
479548
if ( !removePath( fileName() ) )
480-
QMessageBox::warning( this, tr( "Warning" ), tr( "I can not delete" ) );
549+
QMessageBox::warning( this, tr( "Warning" ), tr( "I can not delete" ) );
481550
}
482551
void RichTextNote::remove()
483552
{
@@ -705,10 +774,15 @@ void RichTextNote::insertImage( const QPixmap & pixmap )
705774

706775
QString RichTextNote::attach( const QString & fileName )
707776
{
777+
fileSystemWatcher.blockSignals( true );
778+
708779
QString newFileName = attachDirPath() + QDir::separator() + QFileInfo( fileName ).fileName();
709780
QFile::copy( fileName, newFileName );
710781

711782
attachModel.appendRow( new QStandardItem( QFileInfo( fileName ).fileName() ) );
783+
784+
fileSystemWatcher.blockSignals( false );
785+
712786
emit changed( EventsNote::ChangeAttach );
713787
return newFileName;
714788
}
@@ -807,6 +881,21 @@ void RichTextNote::doubleClickingOnTitle()
807881
}
808882
}
809883

884+
void RichTextNote::directoryChanged( const QString & name )
885+
{
886+
// Если это была папка с прикрепленными файлами
887+
if ( name == attachDirPath() )
888+
updateAttachList();
889+
}
890+
void RichTextNote::fileChanged( const QString & name )
891+
{
892+
if ( name == contentFilePath() )
893+
loadContent();
894+
895+
else if ( name == settingsFilePath() )
896+
loadSettings();
897+
}
898+
810899
void RichTextNote::enterEvent( QEvent * )
811900
{
812901
QPropertyAnimation * animation = new QPropertyAnimation( this, "windowOpacity" );

Note/RichTextNote.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,11 @@
44
#include "abstractnote.h"
55
#include "texteditor.h"
66
#include "AttachPanel.h"
7-
87
#include <QApplication>
98
#include <QDateTime>
109
#include <QDir>
1110
#include <QEvent>
12-
11+
#include <QFileSystemWatcher>
1312
#include "quickfind.h"
1413
#include "findandreplace.h"
1514
#include "utils/func.h"
@@ -59,6 +58,8 @@ class RichTextNote: public AbstractNote
5958
public slots:
6059
void save(); //!< Сохранение заметки.
6160
void load(); //!< Загрузка заметки.
61+
void loadSettings();
62+
void saveSettings();
6263
void saveContent(); //!< Сохранение только содержимого заметки.
6364
void loadContent(); //!< Загрузка только содержимого заметки.
6465

@@ -155,6 +156,9 @@ private slots:
155156
//! Срабатывает, когда происходит двойной клик на заголовок
156157
void doubleClickingOnTitle();
157158

159+
void directoryChanged( const QString & name );
160+
void fileChanged( const QString & name );
161+
158162
public:
159163
QAction * actionSetTopBottom;
160164
QAction * actionVisibleToolBar;
@@ -172,6 +176,7 @@ private slots:
172176
static QVariantMap defaultMapSettings; //!< Массив с дэфолтными настройками для заметок.
173177

174178
private:
179+
QFileSystemWatcher fileSystemWatcher; //!< Будет следить за папкой заметки.
175180
QTimer timerAutosave; //!< Таймер автосохранений
176181
QString noteFileName; //! Путь до папки заметки
177182
TextEditor editor; //! Редактор заметки

history_ru

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
#### Версия 0.0.2:
2+
Слежение заметок за своими папками - при изменении извне файлов настроек,
3+
содержимого заметок происходит перезагрузка этих файлов. При изменении папки прикрепленных файлов - обновление списка файлов.
4+
5+
Рефакторинг.
6+
--
27
Автоматическое сохранение дерева и позиции вкладок, при изменении текущей вкладки редактора менеджера.
38
--
49
К запрещенным в именах файлов windows символам добавлен символ \.

main.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
#include <QDebug>
1515
#include <QDateTime>
1616

17-
static const char codec[] = "utf8";
18-
1917
#include "Manager/Manager.h"
2018
#include "utils/func.h"
2119
#include "utils/mysplashscreen.h"
@@ -78,9 +76,15 @@ static QScriptValue importExtension( QScriptContext *context, QScriptEngine * en
7876
/// TODO: при создании заметки от буфера обмена, можно заголовок ее брать от части текста (например, первые 10 символов)
7977
/// TODO: добавить возможность выбора иконок для иерархического дерева
8078
/// TODO: при добавлении заметки от буфера обмена, пропадают символы перехода на следующую строку.
79+
///
80+
/// EventsNote::LoadEnded разделить на окончание загрузки контента и параметров, тоже самое и для сохранения
81+
/// Пропали иконки кнопок прикрепленных файлов
82+
/// Пора редактор "понизить" до QTextEdit - функции QTextBrowser явно не нужны, а обработку гиперссылок реализовать вручную (см qNotesManager)
83+
/// Пусть QSystemFileWatcher также будет создан для слежения папок с заметками - если происходит удаление папки заметки, удаляем и ее из менеджера, и наоборот
84+
/// В пункт меню Окно добавить поверх всех окон - пусть менеджер умеет это делать
8185

8286
QString nm_Note::style = "";
83-
#include <windows.h>
87+
8488
int main( int argc, char * argv[] )
8589
{
8690
qsrand( QTime( 0, 0, 0 ).secsTo( QTime::currentTime() ) );

utils/func.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#define CRITICAL( msg ) qCritical( OUT_MESSAGE, msg, __FUNCTION__, __FILE__, __LINE__ );
1212
#define FATAL( msg ) qFatal( OUT_MESSAGE, msg, __FUNCTION__, __FILE__, __LINE__ );
1313

14+
static const char codec[] = "utf8";
15+
1416
//! Содержит классы, облегчающие создание объектов, имеющих множество свойств (параметров).
1517
namespace Create
1618
{

0 commit comments

Comments
 (0)