diff --git a/docs/backup.rst b/docs/backup.rst index 3c161427c4..6ad4d624df 100644 --- a/docs/backup.rst +++ b/docs/backup.rst @@ -1,3 +1,5 @@ +.. _backup: + Backup ====== @@ -17,15 +19,22 @@ Back Up Manually ---------------- To back up all the data, **exit the application** first and **copy -the configuration directory**. +the configuration directory** and **the data directory**. -Path to configuration is usually: +Path to the configuration is usually: - Windows: ``%APPDATA%\copyq`` - Portable version for Windows: ``config`` sub-folder in unzipped application directory - Linux: ``~/.config/copyq`` +Path to the data is usually: + +- Windows: ``%APPDATA%\copyq\items`` +- Portable version for Windows: ``items`` sub-folder in unzipped + application directory +- Linux: ``~/.local/share/copyq/copyq/items`` + To copy the configuration path to clipboard from CopyQ: 1. Open Action dialog (``F5`` shortcut). @@ -39,6 +48,8 @@ To copy the configuration path to clipboard from CopyQ: 3. Click OK dialog button. +To copy the data path, change ``'config'`` to ``'data'``. + To restore the backup, exit the application and replace the configuration directory. diff --git a/docs/faq.rst b/docs/faq.rst index 5fc659ab3c..a39ce635a1 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -97,6 +97,8 @@ then choose what to import back. Importing tabs and commands won't override existing tabs, and will create new ones. +See also: :ref:`backup` + .. _faq-disable-notifications: How to enable or disable displaying notification when clipboard changes? diff --git a/docs/sessions.rst b/docs/sessions.rst index 8c3d421f80..e9d806738f 100644 --- a/docs/sessions.rst +++ b/docs/sessions.rst @@ -71,6 +71,40 @@ outside the application. $ COPYQ_SETTINGS_PATH=$HOME/copyq-settings copyq tab &clipboard +Item Data Path +-------------- + +Item data path can be overridden with ``COPYQ_ITEM_DATA_PATH`` +environment variable. + +:: + + $ copyq info data + /home/user/.local/share/copyq/copyq + + $ COPYQ_ITEM_DATA_PATH=$HOME/copyq-data copyq info data + /home/user/copyq-data/copyq/copyq.conf + +The directory contains data for items that exceeds 4096 bytes. The default +threshold can be overridden with ``item_data_threshold`` option. + +:: + + $ copyq config item_data_threshold + 4096 + +To disable using the data directory and store everything into tab data files, +set the threshold to a negative value. The tab data file will be updated only +after the items in the tab change. + +:: + + $ copyq config item_data_threshold -1 + -1 + +Note: Using data directory ensure that the application is fast even if there +are a lot of large items in tabs. + Icon Color ---------- diff --git a/src/app/app.cpp b/src/app/app.cpp index 84bef750c9..836169e0d7 100644 --- a/src/app/app.cpp +++ b/src/app/app.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #include @@ -149,6 +150,24 @@ App::App(QCoreApplication *application, QCoreApplication::setOrganizationName(session); QCoreApplication::setApplicationName(session); + if ( qEnvironmentVariableIsEmpty("COPYQ_ITEM_DATA_PATH") ) { + if ( !m_app->property("CopyQ_item_data_path").isValid() ) { + m_app->setProperty( + "CopyQ_item_data_path", + QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + + QLatin1String("/items")); + } + } else { + m_app->setProperty( + "CopyQ_item_data_path", +#if QT_VERSION >= QT_VERSION_CHECK(5,10,0) + qEnvironmentVariable("COPYQ_ITEM_DATA_PATH") +#else + QString::fromLocal8bit(qgetenv("COPYQ_ITEM_DATA_PATH")) +#endif + ); + } + #ifdef HAS_TESTS initTests(); #endif diff --git a/src/gui/notificationnative/notificationnative.cpp b/src/gui/notificationnative/notificationnative.cpp index a2647ed31e..1234b9df04 100644 --- a/src/gui/notificationnative/notificationnative.cpp +++ b/src/gui/notificationnative/notificationnative.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include diff --git a/src/item/itemstore.cpp b/src/item/itemstore.cpp index 740c0fa921..4d62a66542 100644 --- a/src/item/itemstore.cpp +++ b/src/item/itemstore.cpp @@ -13,7 +13,6 @@ #include #include #include -#include namespace { @@ -178,8 +177,8 @@ bool moveItems(const QString &oldId, const QString &newId) void cleanDataFiles(const QStringList &tabNames) { - QDir dir( QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) ); - if ( !dir.cd(QStringLiteral("items")) ) + QDir dir(itemDataPath()); + if ( !dir.exists() ) return; QStringList files; diff --git a/src/item/serialize.cpp b/src/item/serialize.cpp index 88c2bc9b28..eb78762cfa 100644 --- a/src/item/serialize.cpp +++ b/src/item/serialize.cpp @@ -7,6 +7,7 @@ #include "common/mimetypes.h" #include +#include #include #include #include @@ -15,7 +16,6 @@ #include #include #include -#include #include #include @@ -185,12 +185,12 @@ bool deserializeDataV2(QDataStream *out, QVariantMap *data) QString dataFilePath(const QByteArray &bytes, bool create = false) { - QDir dir( QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) ); + QDir dir(itemDataPath()); QCryptographicHash hash(QCryptographicHash::Sha256); hash.addData(QByteArrayLiteral("copyq_salt")); hash.addData(bytes); const QString sha = QString::fromUtf8( hash.result().toHex() ); - const QString subpath = QStringLiteral("items/%1/%2/%3").arg( + const QString subpath = QStringLiteral("%1/%2/%3").arg( sha.mid(0, 16), sha.mid(16, 16), sha.mid(32, 16) @@ -432,3 +432,8 @@ bool itemDataFiles(QIODevice *file, QStringList *files) return out.status() == QDataStream::Ok; } + +QString itemDataPath() +{ + return qApp->property("CopyQ_item_data_path").toString(); +} diff --git a/src/item/serialize.h b/src/item/serialize.h index 15e1977270..04fb5c1791 100644 --- a/src/item/serialize.h +++ b/src/item/serialize.h @@ -25,6 +25,7 @@ bool deserializeData(QAbstractItemModel *model, QDataStream *stream, int maxItem bool serializeData(const QAbstractItemModel &model, QIODevice *file, int itemDataThreshold = -1); bool deserializeData(QAbstractItemModel *model, QIODevice *file, int maxItems); +QString itemDataPath(); bool itemDataFiles(QIODevice *file, QStringList *files); #endif // SERIALIZE_H diff --git a/src/platform/win/winplatform.cpp b/src/platform/win/winplatform.cpp index 5ff98e575e..c935170a01 100644 --- a/src/platform/win/winplatform.cpp +++ b/src/platform/win/winplatform.cpp @@ -125,6 +125,7 @@ Application *createApplication(int &argc, char **argv) if ( !portableFolder.isEmpty() ) { QSettings::setPath(QSettings::IniFormat, QSettings::UserScope, portableFolder); qputenv("COPYQ_LOG_FILE", portableFolder.toUtf8() + "/copyq.log"); + app->setProperty("CopyQ_item_data_path", portableFolder + QLatin1String("/items")); } return app; diff --git a/src/scriptable/scriptable.cpp b/src/scriptable/scriptable.cpp index 1ad338f395..e0c78369d7 100644 --- a/src/scriptable/scriptable.cpp +++ b/src/scriptable/scriptable.cpp @@ -47,7 +47,6 @@ #include #include #include -#include #include #include @@ -1741,7 +1740,7 @@ QJSValue Scriptable::info() info.insert("config", QSettings().fileName()); info.insert("exe", QCoreApplication::applicationFilePath()); info.insert("log", logFileName()); - info.insert("data", QStandardPaths::writableLocation(QStandardPaths::AppDataLocation)); + info.insert("data", itemDataPath()); info.insert("plugins", #ifdef COPYQ_PLUGIN_PREFIX diff --git a/src/tests/tests.cpp b/src/tests/tests.cpp index c0a1833bc3..644840f30d 100644 --- a/src/tests/tests.cpp +++ b/src/tests/tests.cpp @@ -3419,6 +3419,20 @@ void Tests::configPathEnvVariable() QCOMPARE( out.left(expectedOut.size()), expectedOut ); } +void Tests::itemDataPathEnvVariable() +{ + const auto path = QDir::home().absoluteFilePath("copyq-data"); + const auto environment = QStringList("COPYQ_ITEM_DATA_PATH=" + path); + + QByteArray out; + QByteArray err; + run(Args() << "info" << "data", &out, &err, QByteArray(), environment); + QVERIFY2( testStderr(err), err ); + + const auto expectedOut = path.toUtf8(); + QCOMPARE( out.left(expectedOut.size()), expectedOut ); +} + void Tests::configTabs() { const QString sep = QStringLiteral("\n"); diff --git a/src/tests/tests.h b/src/tests/tests.h index 215de2ee58..41b98a2a9b 100644 --- a/src/tests/tests.h +++ b/src/tests/tests.h @@ -216,6 +216,7 @@ private slots: void configAutostart(); void configPathEnvVariable(); + void itemDataPathEnvVariable(); void configTabs();