Compare commits

...

297 Commits

Author SHA1 Message Date
Jonathan White
e19559fe81 Merge pull request #29 from Manko10/develop
Update link to new upstream repository for pull requests
2016-10-05 18:51:34 -04:00
Janek Bevendorff
7dd30d4db1 Update link to new upstream repository for pull requests 2016-10-05 18:21:26 +02:00
Jonathan White
9b8b7b490a Merge branch 'keepassx_203' into develop 2016-10-02 21:51:08 -04:00
Felix Geyer
5ec9d0685d Finalize changelog. 2016-10-02 21:50:15 -04:00
Felix Geyer
004c412501 Update translations. 2016-10-02 21:50:15 -04:00
Felix Geyer
f05caf7623 Prepare for 2.0.3 release. 2016-10-02 21:50:15 -04:00
Jonathan White
7d165f133a Merge branch 'keepassx_master' into develop 2016-10-02 21:49:24 -04:00
Felix Geyer
fff9e7ac46 Convert Q_FOREACH loops to C++11 for loops.
Q_FOREACH will de deprecated soon.
2016-10-02 21:45:55 -04:00
Felix Geyer
ad834f0f58 Merge branch '2.0' 2016-10-02 21:45:55 -04:00
Felix Geyer
8a50ee8b22 Close database without asking when unmodified.
Don't ask for confirmation when closing/locking a database and
- it's in edit entry mode
- there haven't been any modifications

Refs #511
2016-10-02 21:45:54 -04:00
Felix Geyer
cf8186312a Refactor parts of EditEntryWidget::saveEntry() into updateEntryData(). 2016-10-02 21:45:54 -04:00
Felix Geyer
8f87b5cfd4 Split EditWidgetIcons::save() into state() and reset(). 2016-10-02 21:45:54 -04:00
Felix Geyer
61ce733c6f Make Entry::endUpdate() return whether the entry has been modified. 2016-10-02 21:45:54 -04:00
Felix Geyer
c78822f6e6 Merge branch '2.0' 2016-10-02 21:45:54 -04:00
Felix Geyer
a10a30f390 Fix name of Qt translation file.
In Qt5 it's qtbase_<lang> instead of qt_<lang>
2016-10-02 21:44:33 -04:00
Felix Geyer
7c7014d951 Drop obsolete GCRYPT_HAS_SALSA20 ifdef. 2016-10-02 21:44:33 -04:00
Jonathan White
dee331d52d Fixed Travis CI build process 2016-10-02 21:30:17 -04:00
Jonathan
2146392a2f Merge pull request #8 from daniellandau/save-with-ctrl-return
Save entry with ctrl+return keyboard shortcut
2016-10-02 10:10:33 -04:00
Jonathan White
e011a6eb25 Fixed typo from merge 2016-10-02 10:02:54 -04:00
Jonathan White
5eadd10612 Merge remote-tracking branch 'origin/keepassx_merge' 2016-09-29 22:37:45 -04:00
Felix Geyer
c2a80ce570 Remember auto-type window size.
Resize columns once when the entry list is set.

Based on https://github.com/keepassx/keepassx/pull/158

Closes #478
2016-09-29 22:08:37 -04:00
Felix Geyer
3415073051 Display an error message when opening the database fails.
Closes #462
2016-09-29 22:08:29 -04:00
Felix Geyer
ba68e0a4a1 Show proper error message when key is wrong for .kdb files. 2016-09-29 22:08:20 -04:00
Felix Geyer
8a7e98820a Fix typo.
# Conflicts:
#	src/format/KeePass2Reader.cpp
2016-09-29 22:08:10 -04:00
Felix Geyer
d61e4d69b5 Update optional dependencies in the README.
# Conflicts:
#	README.md
2016-09-29 22:05:32 -04:00
Felix Geyer
9b8912c483 Print libXtst instead of libXtest in the feature summary.
The protocol is called XTEST but the library libxtst.

Closes #440

# Conflicts:
#	src/autotype/CMakeLists.txt
2016-09-29 21:58:56 -04:00
Felix Geyer
878995366a Ask the user before moving an entry to the recycle bin.
Closes #447
2016-09-02 12:00:12 +02:00
Felix Geyer
1635a5211f Pass entryFlags to clone() when recursing into sub-groups.
Based on https://github.com/keepassx/keepassx/pull/178 by Mois Moshev <mois@monomon.me>

Closes #525
2016-09-02 11:47:22 +02:00
Felix Geyer
595b1011dd Refresh fileInfo after creating the file.
Fixes canonicalFilePath() returning an empty string.
2016-09-02 11:35:39 +02:00
Felix Geyer
9bb291235d Fix monospace font on Windows.
Closes #424
2016-09-02 11:35:39 +02:00
Felix Geyer
7d4ef0b8d0 Generate new password whenever the generator widget is opened.
Closes #414
2016-09-02 11:35:39 +02:00
Florian Geyer
8d16522d39 Repair UUID of inconsistent history items.
Closes #130
2016-08-03 23:48:40 +02:00
Felix Geyer
cd1192b409 Allow deleting the recycle bin.
Closes #46
2016-08-03 23:45:04 +02:00
Felix Geyer
bf2fd63131 Fix crash when deleting parent group of recycle bin.
In these cases delete the group instead of trying to move it to the recycle bin.

Closes #520
2016-08-03 23:27:02 +02:00
Daniel Landau
029da87346 Save and exit entry editing with Ctrl+Return
When the cursor is on most fields, you can use Return to end editing and
save, but on the Notes field Return just changes the line. This commit
adds a shortcut to the whole widget to save with Ctrl+Return, so that
saving and exiting is quick even when editing notes.
2016-08-02 16:10:54 +03:00
Felix Geyer
9532bedd7d Update min. length for password generator.
Update the minimum length for the password generator depending on the chosen
options.

Closes #420
2016-07-31 22:07:47 +02:00
Felix Geyer
e9c8363b70 Save to canonical file path so we don't overwrite symlinks.
When saving a database we previously replaced symlinks with a regular file.

Closes #442
2016-07-31 18:29:43 +02:00
Felix Geyer
fb57ed2bcd Add proper error handling when QSaveFile::open() fails.
Based on pull request by Valeriy <jazzvoid@gmail.com>

Closes #450
2016-07-31 17:07:31 +02:00
Felix Geyer
57ec558396 Detect image format solely on content.
Otherwise reading fails if the file extension is wrong.

Closes #512
2016-07-31 15:36:29 +02:00
Felix Geyer
6e2de1cd79 Display proper error message when reading an icon fails.
Refs #512
2016-07-31 14:44:45 +02:00
Felix Geyer
8ace3ab7f2 Don't consider windows with WithdrawnState as top level windows.
Fixes many bogus windows in auto-type window list when using gnome-shell.
2016-07-31 14:44:45 +02:00
Felix Geyer
18e4dca6c9 Explicitly include QFile in TestKeePass2Writer.
Closes #452
2016-07-31 14:44:45 +02:00
Jonathan White
99bb5d33f2 Incorporated fix for IPV6 remote server 2016-07-07 19:32:31 -04:00
Felix Geyer
d4ed4f9325 Remember auto-type window size.
Resize columns once when the entry list is set.

Based on https://github.com/keepassx/keepassx/pull/158

Closes #478
2016-05-25 16:55:06 +02:00
Jonathan White
bb2e1ee8da Revert "Fix IPv6 support and warn when binding fails"
Yikes this fix doesn't compile.
2016-05-24 02:21:17 -04:00
Jonathan White
51bfbc964e Fix IPv6 support and warn when binding fails
Thanks to @eugenesan
2016-05-24 02:12:33 -04:00
Felix Geyer
48eca3e11f Display an error message when opening the database fails.
Closes #462
2016-05-20 16:49:32 +02:00
Felix Geyer
57c1a0f4b6 Show proper error message when key is wrong for .kdb files. 2016-04-09 16:09:53 +02:00
Felix Geyer
bde4d63fdb Fix typo. 2016-04-09 16:02:49 +02:00
Jonathan White
cbb1269b39 Merge from eugenesan/keepassx to implement 1.8.4.1 improvements 2016-04-03 10:49:00 -04:00
Jonathan White
175167b311 Temporary fix for new keepasshttp version
Updates internal version number to prevent warnings on browser plugins. Does not implement host change protocol added in this version.
2016-03-26 09:09:35 -04:00
Jonathan White
029052fa18 Updated readme 2016-03-14 21:19:34 -04:00
Jonathan White
a454469949 Fixed test cases not building 2016-03-14 21:17:18 -04:00
Jonathan
0562ed720b Merge pull request #1 from liangwang/master
update header file for Qt5
2016-03-14 21:12:48 -04:00
Liang Wang
cbe8a9649c update header file for Qt5 2016-03-14 11:34:21 -04:00
Jonathan White
f48fdc1d71 Updated Readme 2016-02-28 11:00:05 -05:00
Jonathan White
7f7753a004 Fixed various Qt5 changes in the http code 2016-02-28 10:52:02 -05:00
Jonathan White
aba4fa94be Merge remote-tracking branch 'keepassx/master'
# Conflicts:
#	README.md
#	share/translations/keepassx_de.ts
#	src/CMakeLists.txt
#	src/gui/MainWindow.h
2016-02-27 19:11:09 -05:00
Felix Geyer
4eea7c8297 Remove KEEPASSX_EXPORT attribute from Tools::binaryFind().
It's an inline function. Declaring it as KEEPASSX_EXPORT breaks
building on Windows.

Closes #373
2016-02-13 11:54:54 +01:00
Felix Geyer
4867d26f7d Update optional dependencies in the README. 2016-02-13 11:24:11 +01:00
Felix Geyer
9bd3ab717e Print libXtst instead of libXtest in the feature summary.
The protocol is called XTEST but the library libxtst.

Closes #440
2016-02-13 11:13:15 +01:00
Felix Geyer
d6d92ce90a Merge branch '2.0' 2016-02-08 18:13:29 +01:00
Felix Geyer
3679b21701 Fix typo in changelog. 2016-02-02 01:22:48 +01:00
Felix Geyer
49f58b4ed8 Prepare 2.0.2 release. 2016-02-02 01:21:39 +01:00
Felix Geyer
235361faf4 Explicitly cast char constant to QChar. 2016-02-02 00:57:28 +01:00
Felix Geyer
208b803fbe Fix KeePass2Repair to retain multi-byte UTF-8 chars.
Since char is (often) unsigned the ch < 0x20 check matched all
multi-byte encoded UTF-8 chars.
2016-02-02 00:41:16 +01:00
Felix Geyer
8a92cec03f Keep valid surrogate pairs in stripInvalidXml10Chars(). 2016-02-02 00:38:58 +01:00
Felix Geyer
00f068b93e Fix typo in changelog. 2016-01-31 20:00:44 +01:00
Felix Geyer
654353e26b Update translations. 2016-01-31 19:03:25 +01:00
Felix Geyer
d670ef2638 Prepare for 2.0.1 release. 2016-01-31 18:49:35 +01:00
Felix Geyer
aff935b3c7 Properly handle a missing key filename. 2016-01-31 17:08:50 +01:00
Felix Geyer
107c0673c7 Make sure we don't write negative icon ids into the database. 2016-01-31 17:06:51 +01:00
Felix Geyer
c14d04b3e8 Fix crash when icon id is larger than INT_MAX.
In these cases icon id was interpreted as a negative number.
The QList access with a negative index resulted in a crash.
2016-01-31 16:44:34 +01:00
Felix Geyer
7a017041bf Allow opening databases that have no password and keyfile.
Closes #391
2016-01-31 16:17:24 +01:00
Felix Geyer
bfae81ec70 Use C++11 keyword directly in new methods. 2016-01-29 17:25:32 +01:00
Felix Geyer
71d4cb781d Merge branch '2.0' 2016-01-29 17:22:37 +01:00
Felix Geyer
eb56bd8973 Add repair functionality to strip invalid XML chars.
Refs #392
2016-01-28 23:07:04 +01:00
Felix Geyer
93585aded7 Always display scaled custom icons.
Closes #322
2016-01-26 22:44:38 +01:00
Felix Geyer
38245aa2a9 Add iconScaledPixmap() convenience functions. 2016-01-24 20:12:33 +01:00
Felix Geyer
1f33e6f044 Add Metadata::customIconScaledPixmap(). 2016-01-24 20:12:33 +01:00
Felix Geyer
4752adf9d3 Move pixmap caching to Metadata. 2016-01-24 20:12:21 +01:00
Felix Geyer
2d741afe3e Strip invalid XML chars when writing databases.
These characters are unprintable or just plain invalid.
QXmlStreamReader throws and error when reading XML documents with such chars.

Closes #392
2016-01-24 17:20:16 +01:00
Florian Geyer
5e6b17aba4 Disable password generator button when showing entry in history mode.
Closes #422
2016-01-22 22:55:28 +01:00
Florian Geyer
c51098e2cf Flush temporary file before opening attachment.
Closes #390
2015-12-16 21:38:20 +01:00
Felix Geyer
ecfbf72a57 Merge branch '2.0' 2015-12-15 21:05:00 +01:00
Felix Geyer
24275d8dc4 Bump version. 2015-12-06 22:19:05 +01:00
Felix Geyer
94d82948f6 Update translations. 2015-12-06 21:06:06 +01:00
Felix Geyer
54fb1abb96 Update changelog. 2015-12-06 21:03:00 +01:00
Felix Geyer
a3b936fcd0 Coding style fixes. 2015-12-06 20:27:09 +01:00
Felix Geyer
efc4cd5969 Merge remote-tracking branch 'github/pr/74' 2015-12-06 19:21:38 +01:00
Felix Geyer
17ab438c5a Make sure Windows doesn't load DLLs from the current working directory. 2015-12-06 14:32:06 +01:00
Felix Geyer
77b4bfb14e Cleanup string argument numbers. 2015-12-06 14:31:23 +01:00
Felix Geyer
7839280cb3 Check if the tray icon is visible before minimizing to it. 2015-11-01 23:32:37 +01:00
Felix Geyer
9e1ea264e2 Use availableGeometry() to calculate the dialog position.
availableGeometry() excludes ares where windows can't be placed (e.g. panels).
2015-11-01 23:26:40 +01:00
Felix Geyer
b02ec98ec6 Show AutoTypeSelectDialog on the active desktop.
This wasn't always the case on X11 with virtual desktops.

Closes #359
2015-11-01 23:23:01 +01:00
Felix Geyer
2fa531745f Check XML key file for valid base64 before using it.
QByteArray::fromBase64() doesn't validate the input.

Closes #366
2015-11-01 18:32:15 +01:00
Felix Geyer
0c36c40a5d Make TestGui work with offscreen QPA.
For some reason hasFocus() returns true here.
Use isVisible() instead as it's a stronger check anyway.
2015-11-01 13:37:03 +01:00
Felix Geyer
6337e673f9 travis-ci: Restore accidentally removed cmake args. 2015-10-15 20:58:00 +02:00
Felix Geyer
e800892cc1 travis-ci: Install xvfb package to run the gui tests. 2015-10-15 20:56:39 +02:00
Felix Geyer
a21e893749 travis-ci: Switch to the Ubuntu trusty image. 2015-10-15 20:28:50 +02:00
Felix Geyer
dff3fc0572 Coding style fixes. 2015-10-15 18:02:31 +02:00
Felix Geyer
5de0ec94e0 Stop using deprecated methods from QtAlgorithms. 2015-10-13 22:52:07 +02:00
Felix Geyer
a408b01111 Add WITH_DEV_BUILD mode.
It disables/warns about deprecated methods.
2015-10-13 22:51:31 +02:00
Felix Geyer
6e45cf0dab Use C++11 keywords directly. 2015-10-11 10:47:30 +02:00
Felix Geyer
dc7b6623a9 Merge branch '2.0' 2015-10-11 10:44:30 +02:00
Felix Geyer
820941fd40 Auto-Type: Only require a substring match for regex.
This matches the behavior of KeePass.

Refs #357
2015-10-10 17:36:08 +02:00
Felix Geyer
862941abf6 TestAutoType: Restore AutoTypeEntryTitleMatch before every test. 2015-10-10 17:23:57 +02:00
Felix Geyer
e98c30f633 Disable systray on OS X.
It's not useful on that platform.

Refs #326
2015-10-10 17:10:29 +02:00
Felix Geyer
316a7e6fb7 Expose version of used libraries in the About dialog. 2015-10-10 17:10:29 +02:00
Felix Geyer
58ed99d562 OS X: Restore main window when clicking on the docker icon.
Apparently this worked previously. Maybe a regression in Qt?

Refs #326
2015-10-10 17:10:27 +02:00
Felix Geyer
840642394f Cope with focusWidget/activeWindow returning windows that are minimized. 2015-10-10 12:07:28 +02:00
Frank Nießen
9484af5329 Minimize-On-Startup: call configuredMinimizeWindow() function of MainWindow to hide it after database is unlocked 2015-10-08 20:30:03 +02:00
Frank Nießen
3cf1a16398 Minimize-On-Startup: add function to minimize mainwindow if all four tray settings are true 2015-10-08 19:25:42 +02:00
Frank Nießen
0f0af12353 Minimize-On-Startup: get and set new setting from/to config object 2015-10-08 19:09:58 +02:00
Frank Nießen
7cb9a4ee4a Minimize-On-Startup: translation (de) for new checkbox in ui 2015-10-08 19:09:58 +02:00
Frank Nießen
28a1eb86da Minimize-On-Startup: new checkbox in ui 2015-10-08 19:09:41 +02:00
Frank Nießen
86f12d9e83 cleaner handling of TrayIconEnabled 2015-10-08 16:27:29 +02:00
Frank Nießen
539f86fd0b respect setting of parent checkboxes for minimizeToTray 2015-10-08 15:13:22 +02:00
Frank Nießen
c93b12ff05 better handling and display for systray checkbox buttons 2015-10-06 21:12:59 +02:00
Frank Nießen
319edca870 add translation for new checkbox button 2015-10-06 21:11:51 +02:00
Florian Geyer
ebeedba072 Reset visibility state of password field on unlocking.
Closes #354
2015-09-28 22:30:29 +02:00
Felix Geyer
568dfde074 Fix minimum size of AboutDialog.
Also make the dialog non-resizeable.

Closes #352
2015-09-28 22:08:33 +02:00
Felix Geyer
5a59287927 Revert "travis-ci: Restore some sanity."
This reverts commit 20726ae75c.

The packages fail to install, probably conflict with some other
installed packages.
I can't be bothered to debug this. Let's hope Travis CI updates
the build environment to something more usable soon.
2015-09-27 23:20:27 +02:00
Felix Geyer
b8c1829857 Improve tray icon behavior on OS X.
Previously the main window had issues on restore:
- was sometimes hidden again.
- window was unresponsive, all actions disabled.
2015-09-27 23:16:18 +02:00
Felix Geyer
4f2d56a55f Fix another small memory leak. 2015-09-26 12:41:53 +02:00
Felix Geyer
6b49f8f26b Free input device list.
Fixes a memory leak.
2015-09-26 12:41:53 +02:00
Felix Geyer
fc8cb7cd14 Check if XListInputDevices returns an error.
Refs #351
2015-09-26 12:41:52 +02:00
Felix Geyer
727094abc6 Unload auto-type plugins if they run in an unsupported environment.
Refs #351
2015-09-26 12:41:47 +02:00
Felix Geyer
20726ae75c travis-ci: Restore some sanity. 2015-09-26 11:48:31 +02:00
Felix Geyer
3b2a39fd38 Merge branch '2.0' 2015-09-26 11:44:27 +02:00
Felix Geyer
bcb54bc38a Avoid dereferencing QLists. 2015-09-25 21:34:56 +02:00
Felix Geyer
14aac09318 Avoid implicit casts from bool to int. 2015-09-25 21:34:56 +02:00
Felix Geyer
9d42db9849 Mark more methods as override. 2015-09-25 21:34:56 +02:00
Felix Geyer
ee81c7c00e Remove WITH_LTO option.
It's broken and probably not worth the potential again.

Refs #353
2015-09-25 21:34:51 +02:00
Felix Geyer
2edf414aa4 Fix compiler warning on OS X and Windows. 2015-09-24 18:45:23 +02:00
Felix Geyer
54f44f5267 Show a better message when trying to open an old database format.
Refs #338
2015-09-23 23:16:49 +02:00
Felix Geyer
6ab54bc95a Check if libXi is installed and explicitly link against it. 2015-09-23 22:26:49 +02:00
Felix Geyer
c8ae31a248 Remove backported Qt5 test macros. 2015-09-23 22:21:21 +02:00
Florian Geyer
66a01e4fef Better output of translation file paths in cmake message. 2015-09-23 20:15:09 +02:00
Felix Geyer
d559db4fb1 Merge branch '2.0' 2015-09-21 23:23:51 +02:00
Felix Geyer
673dff2268 Auto-Type: Raise target window after showing the select dialog.
kwin >= 5.4 (since commit cfa1d61) prefers to focus the main window
instead of following the focus chain.

We ask the window manager nicely to focus the window we want to
type into. kwin seems to follow that (in the default configuration).
2015-09-21 23:12:10 +02:00
Felix Geyer
6f5871434d Update required version of build-dependencies.
Refs #350
2015-09-19 11:28:03 +02:00
Felix Geyer
685f249fd0 Merge remote-tracking branch 'github/pr/128'
https://github.com/keepassx/keepassx/pull/128
2015-09-19 11:22:17 +02:00
Nairolf21
26ccd577b5 Update dependencies to build KeepassX 2015-09-18 01:13:53 -07:00
Felix Geyer
bb38be40f6 Enable Ctrl+M shortcut to minimize window on all platforms.
Closes #329
2015-09-13 22:33:07 +02:00
Felix Geyer
f236c32063 Clear clipboard when locking databases.
Closes #342
2015-09-13 12:38:19 +02:00
Felix Geyer
236edae60b travis-ci: Backport OS X improvements from master. 2015-09-12 23:35:59 +02:00
Felix Geyer
5a13402b51 Activate window in TestGui.
It doesn't seem to get the focus automatically when run inside Xvfb.
QTRY_VERIFY(searchEdit->hasFocus()) failed as a result of this.
2015-09-12 23:12:17 +02:00
Felix Geyer
82aa02a980 travis-ci: Switch to Qt 5.4.2 ppa. 2015-09-12 21:46:15 +02:00
Felix Geyer
3dd98deecc Use QStandardPaths::DataLocation instead of AppDataLocation.
AppDataLocation is only available in Qt >= 5.4.
2015-09-12 18:41:48 +02:00
Felix Geyer
2e23fb203a Pass -std=c++11 to the C++ compiler unconditionally.
All supported compiler should understand it.
2015-09-12 16:16:18 +02:00
Felix Geyer
625e9a2547 Make TestGui agnostic to added "&" in tab title.
Fixes tests on OS X / Qt 5.5.0.
2015-09-12 15:48:38 +02:00
Felix Geyer
aab2b7df1c travis-ci: Remove conflicting libgcrypt11-dev package. 2015-09-12 15:43:18 +02:00
Felix Geyer
31bd44bec5 travis-ci: Output test failures on OS X. 2015-09-12 15:39:21 +02:00
Felix Geyer
11532b603a travis-ci: Use more force. 2015-09-12 15:38:48 +02:00
Felix Geyer
523c88b80d travis-ci: Install libgcrypt from Ubuntu 14.04.
This is getting really ugly but we need libgcrypt >= 1.6.
2015-09-12 15:31:24 +02:00
Felix Geyer
7cf1bb7e38 travis-ci: Pass Qt5 installation path to cmake. 2015-09-12 15:26:45 +02:00
Felix Geyer
eb9fdb43c1 travis-ci: install and use gcc 4.7.
gcc 4.6 doesn't support all C++11 feature we need.
2015-09-12 15:24:42 +02:00
Felix Geyer
0362f45547 Don't try to install homebrew packages that are already there.
brew install <existing package> returns an error code.
2015-09-12 14:43:37 +02:00
Felix Geyer
31f55fdb26 Install cmake binaries provided by upstream.
cmake 2.8.7 in Ubuntu 12.04 is too old.
2015-09-12 14:34:59 +02:00
Felix Geyer
26928a63e8 Try to work around travis providing an ancient build environment. 2015-09-12 14:12:27 +02:00
Paultergeist
abacec5787 Fixed compile error on Mac 2015-09-12 14:00:53 +02:00
Benjamin Robin
d84af2def0 Fix the open recent database menu.
With at least Qt 5.5 the action text is automatically modified from
/home/ben/db.kdbx to /&home/ben/db.kdbx

So add the path of the database to the action using setData

Signed-off-by: Benjamin Robin <dev@benjarobin.fr>
2015-09-12 14:00:03 +02:00
Felix Geyer
7fa0eddc5f Make C++11 mandatory. 2015-09-12 13:55:50 +02:00
Felix Geyer
0e85c98d02 Remove backported definitions from Global.h. 2015-09-12 13:51:49 +02:00
Felix Geyer
ae2b27d400 Connect rowsAboutToBeMoved() and rowsMoved() again.
Accidentally removed in 4fcce6f98f3d481514825ebdffc024c36bd5389c
2015-09-12 13:51:49 +02:00
Felix Geyer
7c424e1b85 Merge updated modeltest from Qt 5. 2015-09-12 13:51:49 +02:00
Felix Geyer
ba1ca4ec08 Rename x11 auto-type plugin to xcb.
This matches what QGuiApplication::platformName() returns.
2015-09-12 13:51:49 +02:00
Felix Geyer
20b13a4a2e Ger rid of last Qt 4 version check. 2015-09-12 13:51:49 +02:00
Felix Geyer
460b23b1eb Use QElapsedTimer everywhere. 2015-09-12 13:51:49 +02:00
Felix Geyer
9882f16614 Remove Tools::currentDateTimeUtc(). 2015-09-12 13:51:49 +02:00
Felix Geyer
60daa2b41b Require libgcrypt >= 1.6.0.
Remove our own Salsa20 implementation as libgcrypt ships one
with that version.
2015-09-12 13:51:49 +02:00
Felix Geyer
d81565df55 qttools5-dev-tools is also required for building on Debian. 2015-09-12 13:51:49 +02:00
Felix Geyer
e2ac176d3c Remove second argument of QSKIP call.
Has been removed in Qt 5.
2015-09-12 13:51:49 +02:00
Felix Geyer
ec8c0bb3e7 Setup new build dependencies. 2015-09-12 13:51:49 +02:00
Felix Geyer
b904fe5acd Adapt X11 auto-type plugin to handle xcb instead of xlib events. 2015-09-12 13:51:49 +02:00
Felix Geyer
3b07098731 Port native event filter to Qt 5. 2015-09-12 13:51:49 +02:00
Felix Geyer
03a330a4dd Port Tools::platform() to Qt 5.
The Q_WS_* definitions are gone.
2015-09-12 13:51:49 +02:00
Felix Geyer
6502da549b Fix build failure in AutoTypePlatformX11::SendEvent(). 2015-09-12 13:51:49 +02:00
Felix Geyer
a71e25a8ba Fix GUI tests. 2015-09-12 13:51:49 +02:00
Felix Geyer
9e05f41747 Port to Qt 5 plugin system. 2015-09-12 13:51:49 +02:00
Felix Geyer
208b0f39e6 Adapt to QtConcurrent being a separate module now. 2015-09-12 13:51:49 +02:00
Felix Geyer
5ad9edc3fd QDesktopServices::storageLocation() calls to QStandardPaths. 2015-09-12 13:51:49 +02:00
Felix Geyer
c714fc89f1 Add missing include statements. 2015-09-12 13:51:49 +02:00
Felix Geyer
e3cde7b55e Adapt to setSupportedDragActions() begin removed.
Models have a virtual supportedDragActions() now.
2015-09-12 13:51:49 +02:00
Felix Geyer
5a745da07b Remove QCOmmandLineParser.
It is part of Qt >= 5.2.
2015-09-12 13:51:49 +02:00
Felix Geyer
531018e58d Remove QSaveFile and QLockFile.
They are part of Qt >= 5.1.
2015-09-12 13:51:49 +02:00
Felix Geyer
813c64a055 Port cmake files to Qt 5. 2015-09-12 13:51:49 +02:00
Felix Geyer
a954e9a4d8 Update translations. 2015-09-06 23:41:29 +02:00
Felix Geyer
95c449481e Prepare beta 2 release. 2015-09-06 23:39:54 +02:00
Felix Geyer
0b43607aa1 Make sure we use the native file dialog on Windows and OS X. 2015-09-06 13:32:12 +02:00
Felix Geyer
e75efb8bfb Improve setting the default file extension in FileDialog.
Largely from PR #105 by Charles Brunet <charles@cbrunet.net>
2015-09-05 19:10:26 +02:00
Felix Geyer
d83fee89bd Fix building WITH_CXX11 on OS X. 2015-09-05 19:03:24 +02:00
Akinori MUSHA
b773dbe645 Test if hitting the Down key moves the focus to the entry view. 2015-08-05 19:02:17 +09:00
Akinori MUSHA
5c7c7f54fa Improve UI of the search edit.
- The copy action (Control+C) when no text is selected copies the
  password of the current entry.  This should be reasonable when
  Control+B copies the username.

- Down at EOL moves the focus to the entry view.  Enter and Tab should
  do that, but it would be handy for user to be able to get to the third
  entry by hitting Down three times.
2015-08-05 19:02:17 +09:00
Felix Geyer
98417d6465 Set default extension when selected filename doesn't have one.
Closes #79
2015-07-25 18:16:33 +02:00
Felix Geyer
0ea64afe92 Fix type of default value for options. 2015-07-25 18:13:57 +02:00
Felix Geyer
a862f62fe8 Set a default filename when saving a new database.
Closes #308
2015-07-25 17:47:45 +02:00
Felix Geyer
5bd525a6dd Use correct keycode when unregistering global shortcuts.
charToKeySym() is already correctly used in registerGlobalShortcut().
2015-07-22 20:38:03 +02:00
Felix Geyer
af3d896bdf Make setNativeLocks() non-fatal on OS X. 2015-07-21 23:12:20 +02:00
Felix Geyer
ceeb72a277 Pull QLockFile updates from the qtbase repository. 2015-07-21 23:11:02 +02:00
Felix Geyer
2c17fdcff0 Correct link order of testhashedblockstream.
Fixes FTBFS on Windows.
2015-07-21 23:08:12 +02:00
Florian Geyer
41a7c96968 Close search before locking database and add additional check on current group.
Closes #309.
2015-07-20 22:45:57 +02:00
Felix Geyer
98d9dae087 Test if reset() and close() write only one final block. 2015-07-20 21:51:32 +02:00
Felix Geyer
2033174d95 Test if we correctly detect errors when writing. 2015-07-20 21:35:48 +02:00
Felix Geyer
606e36acf3 Detect and display more errors when writing databases. 2015-07-20 21:35:48 +02:00
Felix Geyer
0422943d52 Explicitly close/reset streams so we can detect errors. 2015-07-20 21:35:48 +02:00
Felix Geyer
0024f2e30f Signal errors in QXmlStreamWriter upstream.
Unfortunately the method is only avaiable in Qt >= 4.8.
Not much we can do about that.
2015-07-20 21:35:43 +02:00
Felix Geyer
abe5e8ecea Don't write final block(s) if we already have. 2015-07-20 21:33:51 +02:00
Felix Geyer
61503a8047 SymmetricCipherStream: Add error handling when reading from the device. 2015-07-20 19:54:18 +02:00
Felix Geyer
fcb5deff0a SymmetricCipherStream: Fix error string when detecting an error while writing. 2015-07-20 19:53:17 +02:00
Felix Geyer
fdec16c3a0 Fix copyright file match for username-copy.png. 2015-07-19 21:16:22 +02:00
Felix Geyer
84ee8b993f Explicity hide the tray icon before deleting it.
In some conditions the tray icon stayed visible until the application
was closed.
Tested on Kubuntu 15.04 (KDE Plasma 5.2).
2015-07-19 21:14:08 +02:00
Felix Geyer
3d1c27ceb7 Copy the database in TestGui before opening it.
We don't want to create lock files in the source tree.
2015-07-19 19:33:47 +02:00
denk-mal
0390c67c4d allow multiple databeses on command line 2015-06-23 11:40:54 +02:00
denk-mal
1f6161132e makr filename parameter as optinal 2015-06-23 11:22:15 +02:00
denk-mal
fc74e16097 add optionsfield to set http port 2015-06-22 14:11:15 +02:00
Frank Nießen
b03f54ffcd remove duplicate 'using namespace KeepassHttpProtocol' 2015-06-21 21:45:18 +02:00
Frank Nießen
26f33a1c12 add fake workaround for the nasty bahvior of QJSON 2015-06-21 21:43:20 +02:00
Frank Nießen
6e8aeea76d set error to response if list is empty (avoid ChromeIPass hanging) (reverted from commit c736ba7059) 2015-06-21 20:46:09 +02:00
denk-mal
c736ba7059 set error to response if list is empty (avoid ChromeIPass hanging) 2015-06-19 13:19:30 +02:00
denk-mal
3eb4b3b208 Sort switch statement to real order (easier code reading ;-) ) 2015-06-19 13:17:28 +02:00
denk-mal
5982763bed implement a (nonperfect) hide-to-tray on win close 2015-06-18 15:23:41 +02:00
denk-mal
6b7f7bb777 disable calls to missing m_cipher.isValid() 2015-06-18 15:22:25 +02:00
denk-mal
5b9338e40e set actual version of keepasshttp (1.8.4.0) 2015-06-18 13:13:50 +02:00
denk-mal
eab4861383 Call Init for request and response object to avoid crashes on first plugin contact 2015-06-18 12:58:28 +02:00
Ivan
4008e6ab58 Fixed compile issue with latest merged changes from upstream 2015-05-22 21:23:21 -07:00
Ivan
a115bbdc6f Merge branch 'master' of https://github.com/keepassx/keepassx 2015-05-22 21:06:32 -07:00
Ivan
33ed4fd7cf Merge branch 'master' of https://github.com/keepassx/keepassx 2015-05-12 11:03:48 -07:00
Ivan
d70ee509b4 Merge branch 'master' of https://github.com/keepassx/keepassx 2015-04-11 15:41:25 -07:00
Ivan
e20968bdfe Merge branch 'master' of https://github.com/keepassx/keepassx 2015-04-04 23:31:12 -07:00
IvanF
9e124e4a75 Removed unused qhttpserver code
Updated README.md
2015-01-30 00:58:52 -08:00
IvanF
db37b7b933 Updated README.md 2015-01-30 00:42:45 -08:00
IvanF
2e94066e50 Fixes to get code to compile with latest upstream. 2015-01-30 00:35:38 -08:00
IvanF
61c6962bf2 Deleted unused and unrelated files
Merged lots of changes from upstream that were missed or ignored
2015-01-30 00:29:01 -08:00
IvanF
9cbdd58af5 Fixed HTTP settings and service start-up 2015-01-30 00:04:27 -08:00
IvanF
eea9d7db97 Added http service start to MainWindow
Added http settings pane to SettingsWidget
Settings are probably broken still
2015-01-29 01:19:15 -08:00
IvanF
235baa3dcc Merge branch 'master' of https://github.com/keepassx/keepassx
Conflicts:
	README.md
	src/core/Config.cpp
	src/gui/DatabaseTabWidget.cpp
	src/gui/DatabaseTabWidget.h
	src/gui/DatabaseWidget.cpp
	src/gui/DatabaseWidget.h
	src/gui/MainWindow.cpp
	src/gui/MainWindow.h
	src/gui/MainWindow.ui
	src/gui/SearchWidget.ui
	src/gui/SettingsWidget.cpp
	src/gui/SettingsWidgetGeneral.ui
2015-01-29 00:17:39 -08:00
IvanF
f04f4302a2 Deleted local qjson, now using system qjson
Modified CmakeLists to require qjson
Replaced non-standard qjson calls with standard ones
2015-01-28 22:42:02 -08:00
Jascha Dachtera
65eb71e645 Merge branch 'master' of https://github.com/keepassx/keepassx 2014-05-02 21:29:12 +02:00
Jascha Dachtera
47e885ddbf Merge branch 'master' of https://github.com/jdachtera/keepassx 2014-04-18 13:59:58 +02:00
Jascha Dachtera
65626f0da2 Merge branch 'master' of https://github.com/keepassx/keepassx
Use SymmetricCipherGcrypt directly in Protocol.cpp to make it work with the latest master
revision.
2014-04-18 13:59:24 +02:00
Jascha Dachtera
8584901f9e Merge branch 'master' of https://github.com/keithbennett/keepassx
Use SymmetricCipherGcrypt directly in Protocol.cpp to make it work with the latest master
revision.
2014-04-18 13:51:45 +02:00
Keith Bennett
e2d446e446 Added back missing copyright notices. 2014-03-24 19:29:11 +00:00
Keith Bennett
54306473f3 Added README.md 2014-03-23 19:25:15 +00:00
Keith Bennett
c7158234dc Removed assert test for indexFromEntry.
When no row is selected, row equals -1. Some operations call
indexFromEntry when there is no row selected and these should
be allowed to succeed.
2014-03-23 19:09:49 +00:00
Keith Bennett
b28cb19ae3 Added keybinding for copy URL 2014-03-23 19:09:48 +00:00
Keith Bennett
86a01b6984 Ensure that external DB changes are always detected.
QFileSystemWatcher seems to reset itself occasionally. This patch
works around the issue by re-applying the QFileSystemWatcher
whenever a change is handled.
2014-03-23 19:09:48 +00:00
Keith Bennett
b432103b82 Return password quality to keepasshttp client. 2014-03-23 19:09:45 +00:00
Keith Bennett
75564c8fb5 Fixed password generation for keepasshttp 2014-03-23 19:09:43 +00:00
Keith Bennett
b87097a7ab Added global autotype support for OSX. 2014-03-23 17:25:40 +00:00
Keith Bennett
6ef5f34070 Split the new association message across multiple lines. 2014-03-23 17:25:40 +00:00
Keith Bennett
b953ea9042 Tidied up layout of the search field. 2014-03-23 17:25:40 +00:00
Keith Bennett
61ada66e3a Updated keepasshttp version number. 2014-03-23 17:25:39 +00:00
Keith Bennett
a9a724714f Stop qsearchfield from swallowing keypresses. 2014-03-23 17:25:39 +00:00
Keith Bennett
612ef0ef9b Fixed a typo. 2014-03-23 17:25:39 +00:00
Keith Bennett
a627870bbb Added a new DatabaseWidget modal state.
Commit d8857bf4 attempted to fix currentMode() while the DB had not
yet been opened. However, the fix meant that the title bar always
displayed the state as being "locked". This change works around the
issue by introducing a new modal state for when the DB is not yet
open.
2014-03-23 17:25:39 +00:00
Keith Bennett
fae4f69b8c Quieten compilation warnings. 2014-03-23 17:25:39 +00:00
Keith Bennett
b27ba03d42 Replaced qhttpserver with libmicrohttp.
The qhttpserver seems to be riddled with memory leaks and was
continuously crashing. I don't know Qt well enough to fix it so
I have replaced it with libmicrohttp. This is not nearly as
elegant but it is much more stable.
2014-03-23 17:25:39 +00:00
Keith Bennett
2cd6787141 Fixed compilation using qjson subtree. 2014-03-22 17:06:08 +00:00
Francois Ferrand
21204971ff re-apply: Cleaner qobject2qvariant(). 2014-03-22 17:06:08 +00:00
Keith Bennett
c570a13a1f Merge commit '5c71260c12798afe3c331d08477bb241acdb78ca' as 'src/http/qjson' 2014-03-22 17:05:45 +00:00
Keith Bennett
5c71260c12 Squashed 'src/http/qjson/' content from commit c6d92ba
git-subtree-dir: src/http/qjson
git-subtree-split: c6d92bada76be2c46dcf6f585f03b2fba47f9da3
2014-03-22 17:05:45 +00:00
Keith Bennett
e105970945 Removed qjson so we can replace it with a subtree. 2014-03-22 17:04:59 +00:00
Keith Bennett
0c33019f93 Fixed building of qocoa subtree. 2014-03-22 17:04:59 +00:00
Keith Bennett
16598a8386 Merge commit 'f52f6e2d44bc3a08a5b2fa281459af8baac68f0d' as 'src/gui/qocoa' 2014-03-22 17:02:43 +00:00
Keith Bennett
f52f6e2d44 Squashed 'src/gui/qocoa/' content from commit ffe23cb
git-subtree-dir: src/gui/qocoa
git-subtree-split: ffe23cbb2f221bc9eacd1de2134c2947fed71c12
2014-03-22 17:02:43 +00:00
Keith Bennett
304cebefe4 Removed qocoa so we can replace it with a subtree. 2014-03-22 17:01:53 +00:00
Keith Bennett
d7a8a43024 Temporary fixup for the password generator. 2014-03-22 17:01:52 +00:00
Keith Bennett
73f91db939 Merged keepassx-http. 2014-03-22 14:49:32 +00:00
Francois Ferrand
41be9e8178 Implement option to search all open databases. 2013-05-02 13:58:01 +02:00
Francois Ferrand
be24872bba Notifications pseudo-code. 2013-05-02 13:58:01 +02:00
Francois Ferrand
db56546871 Filter GetAllLogins entries, to return only entries with an URL. 2013-05-02 13:58:01 +02:00
Francois Ferrand
53b30e267c Fix entry partial matching rules. 2013-05-02 13:58:01 +02:00
Francois Ferrand
8f33c5235b Fix StringField copy. 2013-05-02 13:58:00 +02:00
Francois Ferrand
d8857bf42d Fix currentMode() while DB is not yet open. 2013-05-02 13:58:00 +02:00
Francois Ferrand
a85ac07576 Qocoa compilation fix for MacOS. 2013-05-02 13:58:00 +02:00
Francois Ferrand
d2ab008aa0 Auto-reload settings. 2013-04-30 17:31:08 +02:00
Francois Ferrand
f4ff8b17f7 Use search field for search.
Search options are presented in a context menu on the search field, as well as
links in search header.
2013-04-29 18:05:08 +02:00
Francois Ferrand
d5c8787451 Detect background changes to database file.
This gives the option to reload the database.

TODO:
 - Settings for reloadBehavior (ask, reloadUnchanged, ignore)
 - Improve notification, by using a header instead of dialog: nicer, less
intrusive, gives more options to user, and works better when multiple databases
are open.
 - Keep tab order on reload.
2013-04-29 09:11:26 +02:00
Francois Ferrand
850c7c7ecf Option to automatically reopen databases which were last opened. 2013-04-24 13:30:30 +02:00
Francois Ferrand
7ff475977e Favicon download button. 2013-04-22 11:25:01 +02:00
Francois Ferrand
478d30b529 Fix typo. 2013-04-19 17:20:26 +02:00
Francois Ferrand
d6597400de Support IPv6 as well as IPv4. 2013-04-19 11:30:11 +02:00
Francois Ferrand
af394ff65c Settings UI integration. 2013-04-19 11:29:46 +02:00
Francois Ferrand
f6fa6d6563 KeyPassX/Http settings. 2013-04-19 11:29:46 +02:00
Francois Ferrand
fd7a49f4a6 Sort entries. 2013-04-18 17:57:00 +02:00
Francois Ferrand
47d7598e99 Fix confirmation allowing access to all entries. 2013-04-18 17:57:00 +02:00
Francois Ferrand
e2ba754f91 Default icon. 2013-04-18 17:57:00 +02:00
Francois Ferrand
c98aad698a Cleanup reference/pointer declarations. 2013-04-18 17:57:00 +02:00
Francois Ferrand
75f0d132e5 Add removeSharedEncryptionKeys() and removeStoredPermissions() 2013-04-18 17:57:00 +02:00
Francois Ferrand
f82725139a Support "KPH: " extra fields. 2013-04-18 17:57:00 +02:00
Francois Ferrand
b9e58c77af Use splitter in 'Additional attributes'. 2013-04-12 15:18:10 +02:00
Francois Ferrand
ad67eac257 Confirmation dialog to list entries. 2013-04-12 15:17:56 +02:00
Francois Ferrand
eef51f26f0 Cleaner qobject2qvariant(). 2013-04-12 15:17:19 +02:00
Francois Ferrand
ea992bc3e6 Support KeyPassHttp protocol.
Allows using passIfox (firefox) and Chromeipass (chrome).
2013-04-12 15:16:56 +02:00
Francois Ferrand
20f3f23576 Customizable toolbar icon size. 2013-04-11 12:11:33 +02:00
263 changed files with 18786 additions and 7249 deletions

View File

@@ -1,19 +1,33 @@
language: cpp
sudo: required
dist: trusty
os:
- linux
- osx
# - osx
compiler:
- gcc
- clang
language: cpp
install:
# - clang
git:
depth: 3
before_install:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq update; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libqt4-dev libgcrypt11-dev zlib1g-dev libxtst-dev; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get -qq install cmake libmicrohttpd10 libmicrohttpd-dev libxi-dev qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev libxtst-dev xvfb; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew install cmake qt libgcrypt; fi
before_script: mkdir build && pushd build
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq cmake || brew install cmake; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq qt5 || brew install qt5; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew ls | grep -wq libgcrypt || brew install libgcrypt; fi
before_script:
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then CMAKE_ARGS="-DCMAKE_PREFIX_PATH=/usr/local/opt/qt5"; fi
- mkdir build && pushd build
script:
- cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_GUI_TESTS=ON ..
- cmake -DCMAKE_BUILD_TYPE=Release -DWITH_GUI_TESTS=ON $CMAKE_ARGS ..
- make
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then make test ARGS+="-E testgui --output-on-failure"; fi
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then xvfb-run -a --server-args="-screen 0 800x600x24" make test ARGS+="-R testgui --output-on-failure"; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test; fi
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then make test ARGS+="--output-on-failure"; fi

View File

@@ -1,3 +1,54 @@
2.0.3 (2016-09-04)
=========================
- Improved error reporting when reading / writing databases fails. [#450, #462]
- Display an error message when opening a custom icon fails.
- Detect custom icon format based on contents instead of the filename. [#512]
- Keep symlink intact when saving databases. [#442].
- Fix a crash when deleting parent group of recycle bin. [#520]
- Display a confirm dialog before moving an entry to the recycle bin. [#447]
- Repair UUIDs of inconsistent history items. [#130]
- Only include top-level windows in auto-type window list when using gnome-shell.
- Update translations.
2.0.2 (2016-02-02)
=========================
- Fix regression in database writer that caused it to strip certain special
characters (characters from Unicode plane > 0).
- Fix bug in repair function that caused it to strip non-ASCII characters.
2.0.1 (2016-01-31)
=========================
- Flush temporary file before opening attachment. [#390]
- Disable password generator when showing entry in history mode. [#422]
- Strip invalid XML chars when writing databases. [#392]
- Add repair function to fix databases with invalid XML chars. [#392]
- Display custom icons scaled. [#322]
- Allow opening databases that have no password and keyfile. [#391]
- Fix crash when importing .kdb files with invalid icon ids. [#425]
- Update translations.
2.0 (2015-12-06)
=========================
- Improve UI of the search edit.
- Clear clipboard when locking databases. [#342]
- Enable Ctrl+M shortcut to minimize the window on all platforms. [#329]
- Show a better message when trying to open an old database format. [#338]
- Fix global auto-type behavior with some window managers.
- Show global auto-type window on the active desktop. [#359]
- Disable systray on OS X. [#326]
- Restore main window when clicking on the OS X docker icon. [#326]
2.0 Beta 2 (2015-09-06)
=========================
- Fix crash when locking with search UI open [#309]
- Fix file locking on Mac OS X [#327]
- Set default extension when saving a database [#79, #308]
2.0 Beta 1 (2015-07-18)
=========================

View File

@@ -21,7 +21,7 @@ endif()
project(KeePassX)
cmake_minimum_required(VERSION 2.6.4)
cmake_minimum_required(VERSION 2.8.12)
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
@@ -31,11 +31,10 @@ include(CheckCXXSourceCompiles)
option(WITH_TESTS "Enable building of unit tests" ON)
option(WITH_GUI_TESTS "Enable building of GUI tests" OFF)
option(WITH_LTO "Enable Link Time Optimization (LTO)" OFF)
option(WITH_CXX11 "Build with the C++ 11 standard" ON)
option(WITH_DEV_BUILD "Use only for development. Disables/warns about deprecated methods." OFF)
set(KEEPASSX_VERSION "2.0 beta 1")
set(KEEPASSX_VERSION_NUM "1.9.91")
set(KEEPASSX_VERSION "2.0.3")
set(KEEPASSX_VERSION_NUM "2.0.3")
if("${CMAKE_C_COMPILER}" MATCHES "clang$" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_COMPILER_IS_CLANG 1)
@@ -62,7 +61,7 @@ macro(add_gcc_compiler_flags FLAGS)
add_gcc_compiler_cflags("${FLAGS}")
endmacro(add_gcc_compiler_flags)
add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_NO_STL -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
add_definitions(-DQT_NO_KEYWORDS -DQT_NO_EXCEPTIONS -DQT_STRICT_ITERATORS -DQT_NO_CAST_TO_ASCII)
add_gcc_compiler_flags("-fno-common -fstack-protector --param=ssp-buffer-size=4")
add_gcc_compiler_flags("-Wall -Wextra -Wundef -Wpointer-arith -Wno-long-long")
@@ -101,25 +100,16 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,relro")
endif()
if(WITH_LTO)
if(CMAKE_COMPILER_IS_GNUCC AND CMAKE_COMPILER_IS_GNUCXX)
check_cxx_compiler_flag("-flto -fuse-linker-plugin" LTO_AVAILABLE)
add_gcc_compiler_cxxflags("-std=c++11")
if(LTO_AVAILABLE)
add_gcc_compiler_flags("-flto -fuse-linker-plugin")
else()
message(FATAL_ERROR "This version of gcc doesn't support LTO")
endif(LTO_AVAILABLE)
else()
message(FATAL_ERROR "LTO is only supported with gcc")
endif()
if(APPLE)
add_gcc_compiler_cxxflags("-stdlib=libc++")
endif()
if (WITH_CXX11)
add_gcc_compiler_cxxflags("-std=c++0x")
add_gcc_compiler_cflags("-ansi")
else()
add_gcc_compiler_flags("-ansi")
add_gcc_compiler_cflags("-ansi")
if(WITH_DEV_BUILD)
add_definitions(-DQT_DEPRECATED_WARNINGS -DGCRYPT_NO_DEPRECATED)
endif()
if(MINGW)
@@ -158,19 +148,21 @@ if(WITH_TESTS)
enable_testing()
endif(WITH_TESTS)
set(QT_REQUIRED_MODULES QtCore QtGui QtTest)
find_package(Qt5Core 5.2 REQUIRED)
find_package(Qt5Concurrent 5.2 REQUIRED)
find_package(Qt5Widgets 5.2 REQUIRED)
find_package(Qt5Test 5.2 REQUIRED)
find_package(Qt5LinguistTools 5.2 REQUIRED)
find_package(Qt5Network 5.2 REQUIRED)
set(CMAKE_AUTOMOC ON)
find_package(Qt4 4.6.0 REQUIRED ${QT_REQUIRED_MODULES})
include(${QT_USE_FILE})
# Debian sets the the build type to None for package builds.
# Make sure we don't enable asserts there.
set_property(DIRECTORY APPEND PROPERTY COMPILE_DEFINITIONS_NONE QT_NO_DEBUG)
find_package(Gcrypt REQUIRED)
if(NOT (${GCRYPT_VERSION_STRING} VERSION_LESS "1.6.0"))
message(STATUS "Gcrypt ${GCRYPT_VERSION_STRING} supports the SALSA20 cipher")
set(GCRYPT_HAS_SALSA20 1)
endif()
find_package(Gcrypt 1.6.0 REQUIRED)
find_package(LibMicroHTTPD REQUIRED)
find_package(ZLIB REQUIRED)
@@ -211,10 +203,7 @@ endif()
include_directories(SYSTEM ${GCRYPT_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR})
if(NOT (${CMAKE_VERSION} VERSION_LESS 2.8.3))
set(PRINT_SUMMARY ON)
include(FeatureSummary)
endif()
include(FeatureSummary)
add_subdirectory(src)
add_subdirectory(share)

View File

@@ -139,10 +139,10 @@ Files: share/icons/application/*/actions/application-exit.png
share/icons/application/*/actions/password-copy.png
share/icons/application/*/actions/password-show-*.png
share/icons/application/*/actions/system-search.png
share/icons/application/*/actions/username-copy.png
share/icons/application/*/status/dialog-error.png
share/icons/application/*/status/dialog-information.png
share/icons/application/*/status/dialog-warning.png
share/icons/application/*/status/username-copy.png
share/icons/svg/*.svgz
Copyright: 2007, Nuno Pinheiro <nuno@oxygen-icons.org>
2007, David Vignoni <david@icon-king.com>

View File

@@ -1,68 +1,35 @@
# KeePassX
# KeePassX v2.0.2 + keepasshttp
![alt text](https://travis-ci.org/keepassxreboot/keepassx.svg?branch=master "Travis-CI Badge")
## About
KeePassX is an application for people with extremely high demands on secure personal data management.
It has a light interface, is cross platform and published under the terms of the GNU General Public License.
Fork of [KeePassX](https://www.keepassx.org/) with keepasshttp support for use with [PassIFox](https://addons.mozilla.org/en-us/firefox/addon/passifox/) for Mozilla Firefox and [chromeIPass](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) for Google Chrome.
KeePassX saves many different information e.g. user names, passwords, urls, attachments and comments in one single database.
For a better management user-defined titles and icons can be specified for each single entry.
Furthermore the entries are sorted in groups, which are customizable as well. The integrated search function allows to search in a single group or the complete database.
KeePassX offers a little utility for secure password generation. The password generator is very customizable, fast and easy to use.
Especially someone who generates passwords frequently will appreciate this feature.
KeePassHttp implementation has been forked from jdachtera's repository, which in turn was based on code from code with Francois Ferrand's [keepassx-http](https://gitorious.org/keepassx/keepassx-http/source/master:) repository.
The complete database is always encrypted with the AES (aka Rijndael) encryption algorithm using a 256 bit key.
Therefore the saved information can be considered as quite safe. KeePassX uses a database format that is compatible with [KeePass Password Safe](http://keepass.info/).
This makes the use of that application even more favorable.
## Install
KeePassX can be downloaded and installed using an assortment of installers available on the main [KeePassX website](http://www.keepassx.org).
KeePassX can also be installed from the official repositories of many Linux repositories.
If you wish to build KeePassX from source, rather than rely on the pre-compiled binaries, you may wish to read up on the _From Source_ section.
### Debian
To install KeePassX from the Debian repository:
```bash
sudo apt-get install keepassx
```
### Red Hat
Install KeePassX from the Red Hat (or CentOS) repository:
```bash
sudo yum install keepassx
```
### Windows / Mac OS X
Download the installer from the KeePassX [download](https://www.keepassx.org/downloads) page.
Once downloaded, double click on the file to execute the installer.
### From Source
This is a rebuild from [denk-mal's keepasshttp](https://github.com/denk-mal/keepassx.git) that brings it forward to Qt5 and KeePassX v2.0.2.
#### Build Dependencies
The following tools must exist within your PATH:
* make
* cmake (>= 2.6.4)
* g++ or clang++
* cmake (>= 2.8.12)
* g++ (>= 4.7) or clang++ (>= 3.0)
The following libraries are required:
* Qt 4 (>= 4.6)
* libgcrypt
* Qt 5 (>= 5.2): qtbase and qttools5
* libgcrypt (>= 1.6)
* zlib
* libxtst (optional for auto-type on X11)
* libmicrohttpd
* libxi, libxtst, qtx11extras (optional for auto-type on X11)
On Debian you can install them with:
```bash
sudo apt-get install build-essential cmake libqt4-dev libgcrypt11-dev zlib1g-dev
sudo apt-get install build-essential cmake libmicrohttpd-dev libxi-dev qtbase5-dev libqt5x11extras5-dev qttools5-dev qttools5-dev-tools libgcrypt20-dev zlib1g-dev
```
#### Build Steps
@@ -72,7 +39,7 @@ To compile from source:
```bash
mkdir build
cd build
cmake ..
cmake -DWITH_TESTS=OFF ..
make [-jX]
```
@@ -121,7 +88,7 @@ Our software isn't always perfect, but we strive to always improve our work. You
Along with our desire to hear your feedback and suggestions, we're also interested in accepting direct assistance in the form of code.
Issue merge requests against our [GitHub repository](https://github.com/keepassx/keepassx).
Issue merge requests against our [GitHub repository](https://github.com/keepassxreboot/keepassx).
### Translations

View File

@@ -0,0 +1,9 @@
find_path(MHD_INCLUDE_DIR microhttpd.h)
find_library(MHD_LIBRARIES microhttpd)
mark_as_advanced(MHD_LIBRARIES MHD_INCLUDE_DIR)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LibMicroHTTPD DEFAULT_MSG MHD_LIBRARIES MHD_INCLUDE_DIR)

View File

@@ -17,9 +17,9 @@ file(GLOB TRANSLATION_FILES *.ts)
get_filename_component(TRANSLATION_EN_ABS keepassx_en.ts ABSOLUTE)
list(REMOVE_ITEM TRANSLATION_FILES keepassx_en.ts)
list(REMOVE_ITEM TRANSLATION_FILES ${TRANSLATION_EN_ABS})
message(STATUS ${TRANSLATION_FILES})
message(STATUS "${TRANSLATION_FILES}")
qt4_add_translation(QM_FILES ${TRANSLATION_FILES})
qt5_add_translation(QM_FILES ${TRANSLATION_FILES})
install(FILES ${QM_FILES} DESTINATION ${DATA_INSTALL_DIR}/translations)
add_custom_target(translations DEPENDS ${QM_FILES})

View File

@@ -3,22 +3,30 @@
<name>AboutDialog</name>
<message>
<source>About KeePassX</source>
<translation>O aplikaci KeePassX</translation>
<translation>O KeePassX</translation>
</message>
<message>
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX je šířeno za podmínek licence GNU General Public License (GPL) verze 2 a (případně) 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Revize</translation>
</message>
<message>
<source>Using:</source>
<translation>S použitím:</translation>
</message>
</context>
<context>
<name>AutoType</name>
<message>
<source>Auto-Type - KeePassX</source>
<translation>Samočinné vyplňování KeePassX</translation>
<translation>Automatické vyplňování KeePassX</translation>
</message>
<message>
<source>Couldn&apos;t find an entry that matches the window title:</source>
<translation>Nelze nalézt položku, která by se shodovala s titulkem okna:</translation>
<translation>Nedaří se nalézt položku, která by se shodovala s titulkem okna:</translation>
</message>
</context>
<context>
@@ -40,11 +48,11 @@
<name>AutoTypeSelectDialog</name>
<message>
<source>Auto-Type - KeePassX</source>
<translation>Samočinné vyplňování KeePassX</translation>
<translation>Automatické vyplňování KeePassX</translation>
</message>
<message>
<source>Select entry to Auto-Type:</source>
<translation>Vyberte položku pro samočinné vyplňování:</translation>
<translation>Vyberte položku, kterou se bude automaticky vyplňovat:</translation>
</message>
</context>
<context>
@@ -91,7 +99,7 @@
</message>
<message>
<source>Unable to create Key File : </source>
<translation>Nelze vytvořit soubor s klíčem :</translation>
<translation>Nedaří se vytvořit soubor s klíčem:</translation>
</message>
<message>
<source>Select a key file</source>
@@ -99,15 +107,25 @@
</message>
<message>
<source>Question</source>
<translation>Otázka</translation>
<translation>Dotaz</translation>
</message>
<message>
<source>Do you really want to use an empty string as password?</source>
<translation>Opravdu chcete heslo ponechat nevyplněné?</translation>
<translation>Opravdu chcete ponechat bez hesla, tedy nechráněné?</translation>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Zadání hesla nejsou shodná.</translation>
<translation>Nepodařilo se vám zadat heslo do obou kolonek stejně.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Nezdařilo se nastavit soubor s klíčem</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Nezdařilo se nastavit %1 jako soubor s klíčem:
%2</translation>
</message>
</context>
<context>
@@ -134,11 +152,11 @@
</message>
<message>
<source>Unable to open the database.</source>
<translation>Databázi nebylo možné otevřít.</translation>
<translation>Databázi se nedaří otevřít.</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Soubor s klíčem nelze otevřít.</translation>
<translation>Soubor s klíčem se nedaří otevřít</translation>
</message>
<message>
<source>All files</source>
@@ -153,6 +171,43 @@
<translation>Vyberte soubor s klíčem</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Opravit databázi</translation>
</message>
<message>
<source>Error</source>
<translation>Chyba</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Nedaří se otevřít soubor s klíčem</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Databáze je v pořádku otevřená. Není třeba žádného zásahu.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Nedaří se otevřít databázi.</translation>
</message>
<message>
<source>Success</source>
<translation>Úspěch</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Databáze je úspěšně opravená
Nyní můžete uložit.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Databázi se nedaří opravit.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -165,7 +220,7 @@
</message>
<message>
<source>Transform rounds:</source>
<translation>Počet průchodů:</translation>
<translation>Počet průchodů šifrovacího algoritmu:</translation>
</message>
<message>
<source>Default username:</source>
@@ -173,11 +228,11 @@
</message>
<message>
<source>Use recycle bin:</source>
<translation>Použít Koš:</translation>
<translation>Namísto mazání přesouvat do Koše:</translation>
</message>
<message>
<source> MiB</source>
<translation type="unfinished"/>
<translation> MiB</translation>
</message>
<message>
<source>Benchmark</source>
@@ -185,11 +240,11 @@
</message>
<message>
<source>Max. history items:</source>
<translation>Nejvyšší umožněný položek historie:</translation>
<translation>Omezit počet uchovávaných předchozích verzí položky na:</translation>
</message>
<message>
<source>Max. history size:</source>
<translation>Nejvyšší umožněná velikost historie:</translation>
<translation>Omezit datový objem předchozích verzí položek na:</translation>
</message>
</context>
<context>
@@ -200,7 +255,7 @@
</message>
<message>
<source>KeePass 2 Database</source>
<translation>Databáze aplikace KeePass 2</translation>
<translation>Databáze ve formátu KeePass verze 2</translation>
</message>
<message>
<source>All files</source>
@@ -220,11 +275,11 @@
</message>
<message>
<source>Open KeePass 1 database</source>
<translation>Otevřít databázi aplikace KeePass 1</translation>
<translation>Otevřít databázi ve formátu KeePass verze 1</translation>
</message>
<message>
<source>KeePass 1 database</source>
<translation>Databáze aplikace KeePass 1</translation>
<translation>Databáze ve formátu KeePass verze 1</translation>
</message>
<message>
<source>All files (*)</source>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>Zavřít?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>%1 je upravováno.
Přesto zavřít?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Uložit změny?</translation>
@@ -247,7 +296,7 @@ Přesto zavřít?</translation>
<message>
<source>&quot;%1&quot; was modified.
Save changes?</source>
<translation>%1 bylo změněno.
<translation>%1 bylo změněno.
Uložit změny?</translation>
</message>
<message>
@@ -270,6 +319,64 @@ Uložit změny?</translation>
<source>locked</source>
<translation>zamčeno</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Pro databázi, kterou se pokoušíte otevřít, existuje zámek úprav (stejnojmenný
.lock soubor). To znamená, že je nejspíš otevřená v jiném okně KeePassX
(v případě sdíleného úložiště, třeba i na jiném počítači). Pokud tomu tak není,
je zámek nejspíš pozůstatkem předchozího neočekávaného ukončení aplikace
a je možné ho smazat. V každém případě, dotčenou databázi je možné otevřít
i tak, ale pouze pro čtení. Chcete?</translation>
</message>
<message>
<source>Lock database</source>
<translation>Uzamknout databázi</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Nelze uzamknout databázi, protože ji v tuto chvíli upravujete.
Pokud chcete změny dokončit, klikněte na Zrušit. V opačném případě změny zahodíte.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Tato databáze doposud ještě nebyla uložena.
Buď ji můžete uložit, nebo neuzamknout.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Tato databáze byla upravena.
Chcete ji před uzamčením uložit?
Pokud ne, provedené změny budou ztraceny.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>„%1“ je právě upravováno.
Přesto zavřít a zahodit změny?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Exportovat databázi do CSV souboru</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV soubor</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Zápis do CSV souboru se nezdařil.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Databáze, kterou se pokoušíte uložit, je uzamčena jinou instancí KeePassX.
Přesto uložit?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -283,7 +390,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Do you really want to delete the entry &quot;%1&quot; for good?</source>
<translation>Opravdu chcete smazat položku %1?</translation>
<translation>Opravdu chcete nenávratně smazat položku „%1“?</translation>
</message>
<message>
<source>Delete entries?</source>
@@ -291,7 +398,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Do you really want to delete %1 entries for good?</source>
<translation>Opravdu chcete smazat %1 položek?</translation>
<translation>Opravdu chcete nenávratně smazat %1 položek?</translation>
</message>
<message>
<source>Move entries to recycle bin?</source>
@@ -299,7 +406,7 @@ Uložit změny?</translation>
</message>
<message numerus="yes">
<source>Do you really want to move %n entry(s) to the recycle bin?</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Opravdu chcete přesunout %n položku do Koše?</numerusform><numerusform>Opravdu chcete přesunout %n položky do Koše?</numerusform><numerusform>Opravdu chcete přesunout %n položek do Koše?</numerusform></translation>
</message>
<message>
<source>Delete group?</source>
@@ -307,12 +414,20 @@ Uložit změny?</translation>
</message>
<message>
<source>Do you really want to delete the group &quot;%1&quot; for good?</source>
<translation>Opravdu chcete smazat skupinu %1?</translation>
<translation>Opravdu chcete nenávratně smazat skupinu „%1“?</translation>
</message>
<message>
<source>Current group</source>
<translation>Stávající skupina</translation>
</message>
<message>
<source>Error</source>
<translation>Chyba</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Nedaří se spočítat hlavní klíč</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -330,7 +445,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Auto-Type</source>
<translation>Samočinné vyplňování</translation>
<translation>Automatické vyplňování</translation>
</message>
<message>
<source>Properties</source>
@@ -370,7 +485,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Unable to open file</source>
<translation>Soubor nelze otevřít</translation>
<translation>Soubor se nedaří otevřít</translation>
</message>
<message>
<source>Save attachment</source>
@@ -379,7 +494,7 @@ Uložit změny?</translation>
<message>
<source>Unable to save the attachment:
</source>
<translation>Přílohu nelze uložit:
<translation>Přílohu se nedaří uložit:
</translation>
</message>
<message>
@@ -388,11 +503,11 @@ Uložit změny?</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>%n týden</numerusform><numerusform>%n týdny</numerusform><numerusform>%n týdnů</numerusform></translation>
</message>
<message numerus="yes">
<source>%n month(s)</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>%n měsíc</numerusform><numerusform>%n měsíce</numerusform><numerusform>%n měsíců</numerusform></translation>
</message>
<message>
<source>1 year</source>
@@ -425,28 +540,32 @@ Uložit změny?</translation>
<source>Save</source>
<translation>Uložit</translation>
</message>
<message>
<source>Open</source>
<translation>Otevřít</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
<message>
<source>Enable Auto-Type for this entry</source>
<translation>Zapnout samočinné vyplňování u této položky</translation>
<translation>Zapnout automatické vyplňování této položky</translation>
</message>
<message>
<source>Inherit default Auto-Type sequence from the group</source>
<translation>Převzít výchozí posloupnost samočinného vyplňování ze skupiny</translation>
<translation>Převzít výchozí posloupnost automatického vyplňování od skupiny</translation>
</message>
<message>
<source>Use custom Auto-Type sequence:</source>
<translation>Použít vlastní posloupnost samočinného vyplňování:</translation>
<translation>Použít vlastní posloupnost automatického vyplňování:</translation>
</message>
<message>
<source>+</source>
<translation type="unfinished"/>
<translation>+</translation>
</message>
<message>
<source>-</source>
<translation type="unfinished"/>
<translation>-</translation>
</message>
<message>
<source>Window title:</source>
@@ -496,11 +615,11 @@ Uložit změny?</translation>
</message>
<message>
<source>Repeat:</source>
<translation>Zopakovat:</translation>
<translation>Zopakování hesla:</translation>
</message>
<message>
<source>Gen.</source>
<translation>Obec.</translation>
<translation>Tvoř</translation>
</message>
<message>
<source>URL:</source>
@@ -512,7 +631,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Presets</source>
<translation>Přednastavené</translation>
<translation>Předpřipravené</translation>
</message>
<message>
<source>Notes:</source>
@@ -551,7 +670,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Inherit from parent group (%1)</source>
<translation>Převzít z nadřazené skupiny (%1)</translation>
<translation>Převzít od nadřazené skupiny (%1)</translation>
</message>
</context>
<context>
@@ -574,7 +693,15 @@ Uložit změny?</translation>
</message>
<message>
<source>Auto-type</source>
<translation>Samočinné vyplňování</translation>
<translation>Automatické vyplňování</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Použít výchozí posloupnost automatického vyplňování z nadřazené skupiny</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Nastavit výchozí posloupnost automatického vyplňování</translation>
</message>
</context>
<context>
@@ -585,15 +712,15 @@ Uložit změny?</translation>
</message>
<message>
<source>Use custom icon</source>
<translation>Použít vlastní ikonu</translation>
<translation>Použít svou vlastní ikonu</translation>
</message>
<message>
<source>Add custom icon</source>
<translation>Přidat vlastní ikonu</translation>
<translation>Přidat svou vlastní ikonu</translation>
</message>
<message>
<source>Delete custom icon</source>
<translation>Smazat vlastní ikonu</translation>
<translation>Smazat svou vlastní ikonu</translation>
</message>
<message>
<source>Images</source>
@@ -613,26 +740,26 @@ Uložit změny?</translation>
</message>
<message numerus="yes">
<source>Can&apos;t delete icon. Still used by %n item(s).</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Ikonu není možné smazat. Je používána %n položkou.</numerusform><numerusform>Ikonu není možné smazat. Je používána %n položkami.</numerusform><numerusform>Ikonu není možné smazat. Ještě jí používá %n položek.</numerusform></translation>
</message>
</context>
<context>
<name>EditWidgetProperties</name>
<message>
<source>Created:</source>
<translation>Vytvořeno:</translation>
<translation>Okamžik vytvoření:</translation>
</message>
<message>
<source>Modified:</source>
<translation>Čas poslední změny:</translation>
<translation>Okamžik minulé úpravy:</translation>
</message>
<message>
<source>Accessed:</source>
<translation>Čas posledního přístupu:</translation>
<translation>Okamžik minulého přístupu:</translation>
</message>
<message>
<source>Uuid:</source>
<translation>Uuid identifikátor:</translation>
<translation>Univerzálně jedinečný identifikátor:</translation>
</message>
</context>
<context>
@@ -646,7 +773,7 @@ Uložit změny?</translation>
<name>EntryHistoryModel</name>
<message>
<source>Last modified</source>
<translation>Čas poslední změny</translation>
<translation>Okamžik minulé změny</translation>
</message>
<message>
<source>Title</source>
@@ -691,7 +818,7 @@ Uložit změny?</translation>
<name>KeePass1OpenWidget</name>
<message>
<source>Import KeePass1 database</source>
<translation>Importovat databázi aplikace KeePass 1</translation>
<translation>Importovat databázi ve formátu KeePass verze 1</translation>
</message>
<message>
<source>Error</source>
@@ -699,14 +826,14 @@ Uložit změny?</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Databázi nelze otevřít.</translation>
<translation>Databázi se nedaří otevřít.</translation>
</message>
</context>
<context>
<name>KeePass1Reader</name>
<message>
<source>Unable to read keyfile.</source>
<translation>Soubor s klíčem nebylo možné načíst.</translation>
<translation>Nedaří se načíst soubor s klíčem.</translation>
</message>
<message>
<source>Not a KeePass database.</source>
@@ -724,6 +851,10 @@ Uložit změny?</translation>
<source>Root</source>
<translation>Kořen</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Nedaří se spočítat hlavní klíč</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -739,12 +870,26 @@ Uložit změny?</translation>
<source>Wrong key or database file is corrupt.</source>
<translation>Chybný klíč nebo je databáze poškozená.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Nedaří se spočítat hlavní klíč</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Zvolený soubor je databáze ve starém formátu KeePass 1 (.kdb).
Můžete ho importovat pomocí Databáze Importovat databázi KeePass 1.
Jedná se o jednosměrný převod. Databázi, vzniklou z importu, nepůjde otevřít ve staré verzi KeePassX 0.4.</translation>
</message>
</context>
<context>
<name>Main</name>
<message>
<source>Fatal error while testing the cryptographic functions.</source>
<translation>Při testování šifrovacích funkcí došlo k fatální chybě.</translation>
<translation>Při ověřování šifrovacích funkcí byl zjištěn fatální nedostatek.</translation>
</message>
<message>
<source>KeePassX - Error</source>
@@ -777,17 +922,13 @@ Uložit změny?</translation>
<source>Groups</source>
<translation>Skupiny</translation>
</message>
<message>
<source>Extras</source>
<translation>Doplňující</translation>
</message>
<message>
<source>View</source>
<translation>Zobrazit</translation>
</message>
<message>
<source>Quit</source>
<translation>Ukončit</translation>
<translation>Ukončit aplikaci</translation>
</message>
<message>
<source>About</source>
@@ -847,7 +988,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Import KeePass 1 database</source>
<translation>Importovat databázi aplikace KeePass 1</translation>
<translation>Importovat databázi aplikace KeePass verze 1</translation>
</message>
<message>
<source>Clone entry</source>
@@ -857,18 +998,10 @@ Uložit změny?</translation>
<source>Find</source>
<translation>Najít</translation>
</message>
<message>
<source>Username</source>
<translation>Uživatelské jméno</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Zkopírovat uživatelské jméno do schránky</translation>
</message>
<message>
<source>Password</source>
<translation>Heslo</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Zkopírovat heslo do schránky</translation>
@@ -879,7 +1012,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Perform Auto-Type</source>
<translation>Provést samočinné vyplnění</translation>
<translation>Provést automatické vyplnění</translation>
</message>
<message>
<source>Open URL</source>
@@ -911,7 +1044,47 @@ Uložit změny?</translation>
</message>
<message>
<source>Toggle window</source>
<translation>Přepnout okno</translation>
<translation>Zobrazit/skrýt okno</translation>
</message>
<message>
<source>Tools</source>
<translation>Nástroje</translation>
</message>
<message>
<source>Copy username</source>
<translation>Zkopírovat uživatelské jméno</translation>
</message>
<message>
<source>Copy password</source>
<translation>Zkopírovat heslo</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Exportovat do CSV souboru</translation>
</message>
<message>
<source>Repair database</source>
<translation>Opravit databázi</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>Databáze ve formátu KeePass 2</translation>
</message>
<message>
<source>All files</source>
<translation>Všechny soubory</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Uložit opravenou databázi</translation>
</message>
<message>
<source>Error</source>
<translation>Chyba</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Zápis do databáze se nezdařil.</translation>
</message>
</context>
<context>
@@ -938,19 +1111,19 @@ Uložit změny?</translation>
</message>
<message>
<source>Numbers</source>
<translation>Čísla</translation>
<translation>Číslice</translation>
</message>
<message>
<source>Special Characters</source>
<translation>Speciál znaky</translation>
<translation>Zvlášt znaky</translation>
</message>
<message>
<source>Exclude look-alike characters</source>
<translation>Vynechat podobně vypadající znaky</translation>
<translation>Vynechat podobně vypadající znaky (předejití záměně)</translation>
</message>
<message>
<source>Ensure that the password contains characters from every group</source>
<translation>Zajistit, aby heslo obsahovalo znaky ze všech zvolených skupin</translation>
<translation>Zajistit, aby heslo obsahovalo znaky ze všech zvolených skupin znaků</translation>
</message>
<message>
<source>Accept</source>
@@ -969,11 +1142,11 @@ Uložit změny?</translation>
</message>
<message>
<source>Unknown option &apos;%1&apos;.</source>
<translation>Neznámá volba %1.</translation>
<translation>Neznámá předvolba %1.</translation>
</message>
<message>
<source>Unknown options: %1.</source>
<translation>Neznámé volby: %1.</translation>
<translation>Neznámé předvolby: %1.</translation>
</message>
<message>
<source>Missing value after &apos;%1&apos;.</source>
@@ -985,7 +1158,7 @@ Uložit změny?</translation>
</message>
<message>
<source>[options]</source>
<translation>[volby]</translation>
<translation>[předvolby]</translation>
</message>
<message>
<source>Usage: %1</source>
@@ -993,7 +1166,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Options:</source>
<translation>Volby:</translation>
<translation>Předvolby:</translation>
</message>
<message>
<source>Arguments:</source>
@@ -1004,7 +1177,7 @@ Uložit změny?</translation>
<name>QSaveFile</name>
<message>
<source>Existing file %1 is not writable</source>
<translation>Existující soubor %1 ne zapisovatelný</translation>
<translation>Do stávajícího souboru %1 nelze zapisovat</translation>
</message>
<message>
<source>Writing canceled by application</source>
@@ -1012,7 +1185,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Partial write. Partition full?</source>
<translation>Zápis nebylo možné dokončit zcela. Nedostatek volného místa?</translation>
<translation>Zápis nebylo možné zcela dokončit. Nedostatek volného místa?</translation>
</message>
</context>
<context>
@@ -1023,15 +1196,15 @@ Uložit změny?</translation>
</message>
<message>
<source>Error writing to underlying device: </source>
<translation>Chyba při zápisu na zařízení:</translation>
<translation>Došlo k chybě při zápisu na zařízení, na kterém se nachází:</translation>
</message>
<message>
<source>Error opening underlying device: </source>
<translation>Chyba při otevírání zařízení:</translation>
<translation>Došlo k chybě při otevírání zařízení, na kterém se nachází:</translation>
</message>
<message>
<source>Error reading data from underlying device: </source>
<translation>Chyba při čtení dat ze zařízení:</translation>
<translation>Došlo k chybě při čtení dat ze zařízení, na kterém se nachází:</translation>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
@@ -1042,7 +1215,7 @@ Uložit změny?</translation>
<name>QtIOCompressor::open</name>
<message>
<source>The gzip format not supported in this version of zlib.</source>
<translation>Formát tohoto gzip archivu není podporován touto verzí knihovny zlib.</translation>
<translation>Použitý formát gzip komprese není podporován verzí knihovny zlib, která je právě používána na tomto systému.</translation>
</message>
<message>
<source>Internal zlib error: </source>
@@ -1057,7 +1230,7 @@ Uložit změny?</translation>
</message>
<message>
<source>Case sensitive</source>
<translation>Rozlišovat velikost písmen</translation>
<translation>Rozlišovat malá/velká písmena</translation>
</message>
<message>
<source>Current group</source>
@@ -1087,39 +1260,35 @@ Uložit změny?</translation>
<name>SettingsWidgetGeneral</name>
<message>
<source>Remember last databases</source>
<translation>Pamatovat si nedávno otevíra databáze</translation>
<translation>Pamatovat si nedávno otevře databáze</translation>
</message>
<message>
<source>Open previous databases on startup</source>
<translation>Při startu otevřít minule otevřenou databázi</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation>Při změnách rozšířeného stavu označit jako změněné</translation>
<translation>Při spuštění aplikace otevřít minule otevřené databáze</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>i ukončová samočinně uložit</translation>
<translation>ed ukončem aplikace automaticky uložit případné změny</translation>
</message>
<message>
<source>Automatically save after every change</source>
<translation>Po každé změně okamžitě samočinně uložit</translation>
<translation>Po každé změně hned automaticky uložit</translation>
</message>
<message>
<source>Minimize when copying to clipboard</source>
<translation>Po zkopírování do schránky samočinně zminimalizovat aplikaci</translation>
<translation>Po zkopírování údaje do schránky automaticky minimalizovat okno KeePassX (do popředí se tak dostane okno, do kterého se zkopírovaný údaj bude vkládat)</translation>
</message>
<message>
<source>Use group icon on entry creation</source>
<translation>Při vytváření položky použít ikonu skupiny</translation>
<translation>Pro vytvářenou položku použít ikonu skupiny, do které spadá</translation>
</message>
<message>
<source>Global Auto-Type shortcut</source>
<translation>Všeobecná klávesová zkratka pro samočinné vyplňování</translation>
<translation>Klávesová zkratka pro všeobecné automatické vyplňování</translation>
</message>
<message>
<source>Use entry title to match windows for global auto-type</source>
<translation>Použít titulek položky pro porovnání s okny pro všeobecné samočinné vyplňování</translation>
<translation>Všeobecné automatické vyplňování provádět na základě shody titulku položky s titulkem okna.</translation>
</message>
<message>
<source>Language</source>
@@ -1127,22 +1296,26 @@ Uložit změny?</translation>
</message>
<message>
<source>Show a system tray icon</source>
<translation>Zobrazit ikonu v oznamovací oblasti</translation>
<translation>Zobrazovat ikonu v oznamovací oblasti systémového panelu</translation>
</message>
<message>
<source>Hide window to system tray when minimized</source>
<translation>Minimalizovat do oznamovací oblasti</translation>
<translation>Minimalizovat okno aplikace do oznamovací oblasti systémového panelu</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Pamatovat si nedávno otevřené soubory s klíči</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
<message>
<source>Clear clipboard after</source>
<translation>Vyčistit schránku po uplynutí</translation>
<translation>Vymazat obsah schránky po uplynutí</translation>
</message>
<message>
<source> sec</source>
<translation>sek</translation>
<translation>sek.</translation>
</message>
<message>
<source>Lock databases after inactivity of</source>
@@ -1150,11 +1323,11 @@ Uložit změny?</translation>
</message>
<message>
<source>Show passwords in cleartext by default</source>
<translation>Vždy zobrazovat hesla</translation>
<translation>Hesla vždy viditelná (nezakrývat hvězdičkami)</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
<translation>Před provedením samočinného vyplnění se vždy dotázat</translation>
<translation>Před provedením automatického vyplnění se vždy dotázat</translation>
</message>
</context>
<context>
@@ -1163,14 +1336,6 @@ Uložit změny?</translation>
<source>Unlock database</source>
<translation>Odemknout databázi</translation>
</message>
<message>
<source>Error</source>
<translation>Chyba</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Chybný klíč.</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1183,20 +1348,16 @@ Uložit změny?</translation>
<name>main</name>
<message>
<source>KeePassX - cross-platform password manager</source>
<translation>KeePassX multiplatformní správce hesel</translation>
<translation>KeePassX správce hesel, fungující napříč rozličnými operačními systémy</translation>
</message>
<message>
<source>filename of the password database to open (*.kdbx)</source>
<translation>Soubor s databází hesel (*.kdbx), který otevřít</translation>
<translation>který soubor s databází hesel (*.kdbx) otevřít</translation>
</message>
<message>
<source>path to a custom config file</source>
<translation>umístění souboru s vlastními nastaveními</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>heslo databáze (NEBEZPEČNÉ!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>soubor s klíčem k databázi</translation>

View File

@@ -9,12 +9,20 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX distribueres under betingelserne i GNU General Public License (GPL) version 2 eller (efter eget valg) version 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Revision</translation>
</message>
<message>
<source>Using:</source>
<translation>Bruger:</translation>
</message>
</context>
<context>
<name>AutoType</name>
<message>
<source>Auto-Type - KeePassX</source>
<translation type="unfinished"/>
<translation>Auto-indsæt - KeePassX</translation>
</message>
<message>
<source>Couldn&apos;t find an entry that matches the window title:</source>
@@ -40,26 +48,26 @@
<name>AutoTypeSelectDialog</name>
<message>
<source>Auto-Type - KeePassX</source>
<translation type="unfinished"/>
<translation>Auto-indsæt - KeePassX</translation>
</message>
<message>
<source>Select entry to Auto-Type:</source>
<translation type="unfinished"/>
<translation>Vælg post til Auto-Indsæt:</translation>
</message>
</context>
<context>
<name>ChangeMasterKeyWidget</name>
<message>
<source>Password</source>
<translation>Adgangskode</translation>
<translation>Kodeord</translation>
</message>
<message>
<source>Enter password:</source>
<translation>Indtast adgangskode</translation>
<translation>Indtast kodeord</translation>
</message>
<message>
<source>Repeat password:</source>
<translation>Gentag adgangskode</translation>
<translation>Gentag kodeord</translation>
</message>
<message>
<source>Key file</source>
@@ -103,18 +111,28 @@
</message>
<message>
<source>Do you really want to use an empty string as password?</source>
<translation>Vil du virkelig bruge en tom streng som adgangskode?</translation>
<translation>Vil du virkelig bruge en tom streng som kodeord?</translation>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Andre adgangskoder leveret.</translation>
<translation>Andre kodeord leveret.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Kan ikke sætte nøglefil</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Kunne ikke sætte %1 som Nøglefil:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
<message>
<source>Enter master key</source>
<translation>Indtast primærnøgle</translation>
<translation>Indtast hovednøgle</translation>
</message>
<message>
<source>Key File:</source>
@@ -122,7 +140,7 @@
</message>
<message>
<source>Password:</source>
<translation>Adgangskode:</translation>
<translation>Kodeord:</translation>
</message>
<message>
<source>Browse</source>
@@ -153,6 +171,43 @@
<translation>Vælg nøglefil</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Reparer database</translation>
</message>
<message>
<source>Error</source>
<translation>Fejl</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Kan ikke åbne nøglefil</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Databasen åbnede fint. Intet at gøre.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Kan ikke åbne databasen.</translation>
</message>
<message>
<source>Success</source>
<translation>Succes</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Databasen er blevet succesfuldt repareret
Du kan gemme den nu.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Kan ikke reparere databasen.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -165,7 +220,7 @@
</message>
<message>
<source>Transform rounds:</source>
<translation type="unfinished"/>
<translation>Transformationsrunder:</translation>
</message>
<message>
<source>Default username:</source>
@@ -185,18 +240,18 @@
</message>
<message>
<source>Max. history items:</source>
<translation type="unfinished"/>
<translation>Maks. posthistorik:</translation>
</message>
<message>
<source>Max. history size:</source>
<translation type="unfinished"/>
<translation>Maks. historikstørrelse:</translation>
</message>
</context>
<context>
<name>DatabaseTabWidget</name>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Rod</translation>
</message>
<message>
<source>KeePass 2 Database</source>
@@ -234,11 +289,6 @@
<source>Close?</source>
<translation>Luk?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation type="unfinished"/>
</message>
<message>
<source>Save changes?</source>
<translation>Gem ændringer?</translation>
@@ -246,7 +296,8 @@ Close anyway?</source>
<message>
<source>&quot;%1&quot; was modified.
Save changes?</source>
<translation type="unfinished"/>
<translation>&quot;%1&quot; blev ændret.
Gem disse ændringer?</translation>
</message>
<message>
<source>Error</source>
@@ -268,12 +319,66 @@ Save changes?</source>
<source>locked</source>
<translation>låst</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Den database, du prøver at åbne er låst af en anden forekomst af KeePassX.
Vil du åbne den alligevel? Alternativt åbnes databasen skrivebeskyttet.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Lås database</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Kan ikke låse databasen, mens du redigerer i den.
Tryk på Afbryd for at afslutte dine ændringer eller kassere dem.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Denne database er aldrig blevet gemt.
Du kan gemme databasen eller stop låsning.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Denne database er blevet ændret.
Vil du gemme databasen før låsning?
Ellers mister du dine ændringer.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; er i redigeringstilstand.
Kassér ændringer og luk alligevel?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Eksportér databasen til CSV-fil</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV-fil</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Kan ikke skrive til CSV-fil.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Databasen som du prøver at gemme er låst af en anden instans af KeePassX.
Vil du alligevel gemme?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
<message>
<source>Change master key</source>
<translation>Skift primærnøgle</translation>
<translation>Skift hovednøgle</translation>
</message>
<message>
<source>Delete entry?</source>
@@ -281,7 +386,7 @@ Save changes?</source>
</message>
<message>
<source>Do you really want to delete the entry &quot;%1&quot; for good?</source>
<translation type="unfinished"/>
<translation>Vil du virkelig slette posten &quot;%1&quot; permanent?</translation>
</message>
<message>
<source>Delete entries?</source>
@@ -289,7 +394,7 @@ Save changes?</source>
</message>
<message>
<source>Do you really want to delete %1 entries for good?</source>
<translation type="unfinished"/>
<translation>Vil du virkelig slette %1 poster permanent?</translation>
</message>
<message>
<source>Move entries to recycle bin?</source>
@@ -297,7 +402,7 @@ Save changes?</source>
</message>
<message numerus="yes">
<source>Do you really want to move %n entry(s) to the recycle bin?</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Ønsker du virkelig at flytte %n post over i papirkurven?</numerusform><numerusform>Ønsker du virkelig at flytte %n poster over i papirkurven?</numerusform></translation>
</message>
<message>
<source>Delete group?</source>
@@ -305,12 +410,20 @@ Save changes?</source>
</message>
<message>
<source>Do you really want to delete the group &quot;%1&quot; for good?</source>
<translation type="unfinished"/>
<translation>Ønsker du at slette gruppen &quot;%1&quot; permanent?</translation>
</message>
<message>
<source>Current group</source>
<translation>Nuværende gruppe</translation>
</message>
<message>
<source>Error</source>
<translation>Fejl</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kan ikke beregne hovednøgle</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -328,7 +441,7 @@ Save changes?</source>
</message>
<message>
<source>Auto-Type</source>
<translation type="unfinished"/>
<translation>Auto-Indsæt</translation>
</message>
<message>
<source>Properties</source>
@@ -340,7 +453,7 @@ Save changes?</source>
</message>
<message>
<source>Entry history</source>
<translation type="unfinished"/>
<translation>Indtastningshistorik</translation>
</message>
<message>
<source>Add entry</source>
@@ -356,7 +469,7 @@ Save changes?</source>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Andre adgangskoder leveret.</translation>
<translation>Andre kodeord leveret.</translation>
</message>
<message>
<source>New attribute</source>
@@ -377,7 +490,7 @@ Save changes?</source>
<message>
<source>Unable to save the attachment:
</source>
<translation type="unfinished"/>
<translation>Kan ikke gemme vedhæftningen:</translation>
</message>
<message>
<source>Tomorrow</source>
@@ -422,20 +535,24 @@ Save changes?</source>
<source>Save</source>
<translation>Gem</translation>
</message>
<message>
<source>Open</source>
<translation>Åben</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
<message>
<source>Enable Auto-Type for this entry</source>
<translation type="unfinished"/>
<translation>Aktivér Auto-Indsæt for denne post</translation>
</message>
<message>
<source>Inherit default Auto-Type sequence from the group</source>
<translation type="unfinished"/>
<translation>Nedarv standard Auto-Indsæt sekvens fra gruppe</translation>
</message>
<message>
<source>Use custom Auto-Type sequence:</source>
<translation type="unfinished"/>
<translation>Brug brugerdefineret Auto-indsæt sekvens:</translation>
</message>
<message>
<source>+</source>
@@ -451,11 +568,11 @@ Save changes?</source>
</message>
<message>
<source>Use default sequence</source>
<translation type="unfinished"/>
<translation>Brug standardsekvens</translation>
</message>
<message>
<source>Set custom sequence:</source>
<translation type="unfinished"/>
<translation>Definér brugervalgt sekvens:</translation>
</message>
</context>
<context>
@@ -489,7 +606,7 @@ Save changes?</source>
</message>
<message>
<source>Password:</source>
<translation>Adgangskode:</translation>
<translation>Kodeord:</translation>
</message>
<message>
<source>Repeat:</source>
@@ -497,7 +614,7 @@ Save changes?</source>
</message>
<message>
<source>Gen.</source>
<translation type="unfinished"/>
<translation>Generer</translation>
</message>
<message>
<source>URL:</source>
@@ -509,7 +626,7 @@ Save changes?</source>
</message>
<message>
<source>Presets</source>
<translation type="unfinished"/>
<translation>Predefinerede</translation>
</message>
<message>
<source>Notes:</source>
@@ -571,7 +688,15 @@ Save changes?</source>
</message>
<message>
<source>Auto-type</source>
<translation type="unfinished"/>
<translation>Auto-indsæt</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Brug standard Auto-Indsæt sekvens fra forældregruppe</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Definér standard auto-indsæt sekvens</translation>
</message>
</context>
<context>
@@ -610,7 +735,7 @@ Save changes?</source>
</message>
<message numerus="yes">
<source>Can&apos;t delete icon. Still used by %n item(s).</source>
<translation type="unfinished"><numerusform></numerusform><numerusform></numerusform></translation>
<translation><numerusform>Kan ikke slette ikonet. Det anvendes stadig af %n element.</numerusform><numerusform>Kan ikke slette ikonet. Det anvendes stadig af %n elementer.</numerusform></translation>
</message>
</context>
<context>
@@ -719,14 +844,18 @@ Save changes?</source>
</message>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Rod</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kan ikke beregne hovednøgle</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
<message>
<source>Not a KeePass database.</source>
<translation>Det er ikke en KeePass database.</translation>
<translation>Dette er ikke en KeePass database.</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
@@ -736,6 +865,20 @@ Save changes?</source>
<source>Wrong key or database file is corrupt.</source>
<translation>Forkert nøgle eller databasefil er korrupt.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kan ikke beregne hovednøgle</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Den valgte fil er en gammel KeePass 1 databasefil (.kdb).
Du kan importere den ved at klikke Database &gt; &apos;Importér KeePass 1 database&apos;.
Dette er en envejs konvertering. Du vil ikke være i stand til at åbne den importerede database med den gamle KeePassX 0.4 version.</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -774,10 +917,6 @@ Save changes?</source>
<source>Groups</source>
<translation>Grupper</translation>
</message>
<message>
<source>Extras</source>
<translation type="unfinished"/>
</message>
<message>
<source>View</source>
<translation>Vis</translation>
@@ -836,7 +975,7 @@ Save changes?</source>
</message>
<message>
<source>Change master key</source>
<translation>Skift primærnøgle</translation>
<translation>Skift hovednøgle</translation>
</message>
<message>
<source>Database settings</source>
@@ -854,21 +993,13 @@ Save changes?</source>
<source>Find</source>
<translation>Find</translation>
</message>
<message>
<source>Username</source>
<translation>Brugernavn</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Kopiér brugernavn til udklipsholder</translation>
</message>
<message>
<source>Password</source>
<translation>Adgangskode</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Kopiér adgangskode til udklipsholder</translation>
<translation>Kopiér kodeord til udklipsholder</translation>
</message>
<message>
<source>Settings</source>
@@ -876,7 +1007,7 @@ Save changes?</source>
</message>
<message>
<source>Perform Auto-Type</source>
<translation type="unfinished"/>
<translation>Udfør Auto-indsæt</translation>
</message>
<message>
<source>Open URL</source>
@@ -910,12 +1041,52 @@ Save changes?</source>
<source>Toggle window</source>
<translation>Skift vindue</translation>
</message>
<message>
<source>Tools</source>
<translation>Værktøj</translation>
</message>
<message>
<source>Copy username</source>
<translation>Kopiér brugernavn</translation>
</message>
<message>
<source>Copy password</source>
<translation>Kopiér kodeord</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Eksportér til CSV-fil</translation>
</message>
<message>
<source>Repair database</source>
<translation>Reparer database</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 Database</translation>
</message>
<message>
<source>All files</source>
<translation>Alle filer</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Gem repareret database</translation>
</message>
<message>
<source>Error</source>
<translation>Fejl</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Skrivning til database fejler.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
<message>
<source>Password:</source>
<translation>Adgangskode:</translation>
<translation>Kodeord:</translation>
</message>
<message>
<source>Length:</source>
@@ -923,7 +1094,7 @@ Save changes?</source>
</message>
<message>
<source>Character Types</source>
<translation type="unfinished"/>
<translation>Tegntyper</translation>
</message>
<message>
<source>Upper Case Letters</source>
@@ -931,7 +1102,7 @@ Save changes?</source>
</message>
<message>
<source>Lower Case Letters</source>
<translation type="unfinished"/>
<translation>Små Bogstaver</translation>
</message>
<message>
<source>Numbers</source>
@@ -939,15 +1110,15 @@ Save changes?</source>
</message>
<message>
<source>Special Characters</source>
<translation type="unfinished"/>
<translation>Specialtegn</translation>
</message>
<message>
<source>Exclude look-alike characters</source>
<translation type="unfinished"/>
<translation>Udeluk lool-alike tegn</translation>
</message>
<message>
<source>Ensure that the password contains characters from every group</source>
<translation type="unfinished"/>
<translation>Vær sikker at dit kodeord indeholder tegn fra alle grupper</translation>
</message>
<message>
<source>Accept</source>
@@ -1020,11 +1191,11 @@ Save changes?</source>
</message>
<message>
<source>Error writing to underlying device: </source>
<translation type="unfinished"/>
<translation>Fejl ved skrivning til enhed:</translation>
</message>
<message>
<source>Error opening underlying device: </source>
<translation type="unfinished"/>
<translation>Fejl ved åbning fra enhed:</translation>
</message>
<message>
<source>Error reading data from underlying device: </source>
@@ -1032,7 +1203,7 @@ Save changes?</source>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
<translation type="unfinished"/>
<translation>Intern zlib-fejl ved dekomprimering:</translation>
</message>
</context>
<context>
@@ -1054,7 +1225,7 @@ Save changes?</source>
</message>
<message>
<source>Case sensitive</source>
<translation type="unfinished"/>
<translation>Versalfølsom</translation>
</message>
<message>
<source>Current group</source>
@@ -1062,7 +1233,7 @@ Save changes?</source>
</message>
<message>
<source>Root group</source>
<translation type="unfinished"/>
<translation>Rodgruppe</translation>
</message>
</context>
<context>
@@ -1073,7 +1244,7 @@ Save changes?</source>
</message>
<message>
<source>General</source>
<translation type="unfinished"/>
<translation>Generelt</translation>
</message>
<message>
<source>Security</source>
@@ -1084,15 +1255,11 @@ Save changes?</source>
<name>SettingsWidgetGeneral</name>
<message>
<source>Remember last databases</source>
<translation type="unfinished"/>
<translation>Husk seneste databaser</translation>
</message>
<message>
<source>Open previous databases on startup</source>
<translation type="unfinished"/>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation type="unfinished"/>
<translation>Åben foregående databaser ved opstart</translation>
</message>
<message>
<source>Automatically save on exit</source>
@@ -1108,15 +1275,15 @@ Save changes?</source>
</message>
<message>
<source>Use group icon on entry creation</source>
<translation type="unfinished"/>
<translation>Brug gruppeikon ved oprettelse af post</translation>
</message>
<message>
<source>Global Auto-Type shortcut</source>
<translation type="unfinished"/>
<translation>Global Auto-Indsæt genvej</translation>
</message>
<message>
<source>Use entry title to match windows for global auto-type</source>
<translation type="unfinished"/>
<translation>Brug titel post til at matche global aito-indsæt</translation>
</message>
<message>
<source>Language</source>
@@ -1130,6 +1297,10 @@ Save changes?</source>
<source>Hide window to system tray when minimized</source>
<translation>Skjul vindue i systembakken når det er minimeret</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Husk de sidste nøglefiler</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1143,15 +1314,15 @@ Save changes?</source>
</message>
<message>
<source>Lock databases after inactivity of</source>
<translation type="unfinished"/>
<translation>Lås databaserne efter inaktivitet i</translation>
</message>
<message>
<source>Show passwords in cleartext by default</source>
<translation type="unfinished"/>
<translation>Vis kodeord i klartekst som standard</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
<translation type="unfinished"/>
<translation>Spørg altid før auto-indsæt</translation>
</message>
</context>
<context>
@@ -1160,14 +1331,6 @@ Save changes?</source>
<source>Unlock database</source>
<translation>Lås database op</translation>
</message>
<message>
<source>Error</source>
<translation>Fejl</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Forkert nøgle.</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1180,7 +1343,7 @@ Save changes?</source>
<name>main</name>
<message>
<source>KeePassX - cross-platform password manager</source>
<translation type="unfinished"/>
<translation>KeePassX - cross-platform password manager</translation>
</message>
<message>
<source>filename of the password database to open (*.kdbx)</source>
@@ -1188,11 +1351,7 @@ Save changes?</source>
</message>
<message>
<source>path to a custom config file</source>
<translation type="unfinished"/>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>adgangskode til databasen (FAARLIGT!)</translation>
<translation>sti til brugerdefineret indstillingsfil</translation>
</message>
<message>
<source>key file of the database</source>

View File

@@ -7,7 +7,15 @@
</message>
<message>
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX ist unter der GNU General Public License (GPL) version 2 (version 3) veröffentlicht.</translation>
<translation>KeePassX steht unter der GNU General Public License (GPL) version 2 (version 3).</translation>
</message>
<message>
<source>Revision</source>
<translation>Überarbeitung</translation>
</message>
<message>
<source>Using:</source>
<translation>In Benutzung:</translation>
</message>
</context>
<context>
@@ -109,6 +117,15 @@
<source>Different passwords supplied.</source>
<translation>Unterschiedliche Passwörter eingegeben.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Festlegen der Schlüsseldatei nicht möglich.</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Festlegen von %1 als Schlüsseldatei nicht möglich: %2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -153,6 +170,43 @@
<translation>Schlüsseldatei auswählen</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Datenbank reparieren</translation>
</message>
<message>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Schlüsseldatei kann nicht geöffnet werden</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Datenbank wurde ordnungsgemäß geöffnet. Es gibt nichts zu tun.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Öffnen der Datenbank nicht möglich.</translation>
</message>
<message>
<source>Success</source>
<translation>Erfolg</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Datenbank erfolgreich repariert
sie kann nun gespeichert werden.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Reparieren der Datenbank nicht möglich.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -234,12 +288,6 @@
<source>Close?</source>
<translation>Schließen?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; wird bearbeitet.
Trotzdem schließen?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Änderungen speichern?</translation>
@@ -270,6 +318,59 @@ Save changes?</source>
<source>locked</source>
<translation>gesperrt</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Die Datenbank, die geöffnet werden soll, ist aktuell von einer anderen Instanz von KeePassX blockiert. Soll sie dennoch geöffnet werden? Andererseits wird die Datenbank schreibgeschützt geöffnet.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Datenbank sperren</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Datenbank kann nicht gesperrt werden, da sie gerade bearbeitet wird.
Wählen sie &quot;cancel&quot;, um die Änderungen zu speichern oder sie zurückzunehmen.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Diese Datenbank wurde noch nicht gespeichert.
Sie können sie speichern oder Sperre freigeben.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Dieses Datenbank wurde geändert.
Soll sie gespeichert werden bevor sie gesperrt wirt?
Anderenfalls gehen Ihre Änderungen verloren.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; wird bearbeitet.
Änderungen verwerfen und trotzdem schließen?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Datenbank als CSV Datei exportieren.</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV Datei</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Die CSV Datei konnte nicht gespeichert werden.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Die Datenbank, die gespeichert werden soll, ist von einer anderen Instanz von KeePassX blockiert.
Soll sie dennoch gespeichert werden? </translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -313,6 +414,14 @@ Save changes?</source>
<source>Current group</source>
<translation>Aktuelle Gruppe</translation>
</message>
<message>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Berechnung des &quot;master keys&quot; gescheitert</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -424,6 +533,10 @@ Save changes?</source>
<source>Save</source>
<translation>Speichern</translation>
</message>
<message>
<source>Open</source>
<translation>Offen</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -575,6 +688,14 @@ Save changes?</source>
<source>Auto-type</source>
<translation>Auto-type</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Auto-Type-Sequenz der übergeordneten Gruppe anwenden.</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Standard Auto-Type-Sequenz setzen</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -723,6 +844,10 @@ Save changes?</source>
<source>Root</source>
<translation>Root</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Berechnung des &quot;master keys&quot; gescheitert</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -738,6 +863,20 @@ Save changes?</source>
<source>Wrong key or database file is corrupt.</source>
<translation>Falscher Schlüssel oder die Datei ist beschädigt.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Berechnung des &quot;master keys&quot; gescheitert</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Die ausgewählte Datei ist eine alte KeePass 1 Datenbank (.kdb).
Zum Importieren gehen Sie auf Datenbank &gt; &apos;KeePass 1 Datenbank importieren&apos;.
Dieser Vorgang ist nur in eine Richtung möglich. Die importierte Datenbank kann später nicht mehr mit der alten KeePassX Version 0.4 geöffnet werden.</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -776,10 +915,6 @@ Save changes?</source>
<source>Groups</source>
<translation>Gruppen</translation>
</message>
<message>
<source>Extras</source>
<translation>Extras</translation>
</message>
<message>
<source>View</source>
<translation>Ansicht</translation>
@@ -856,18 +991,10 @@ Save changes?</source>
<source>Find</source>
<translation>Suchen</translation>
</message>
<message>
<source>Username</source>
<translation>Benutzername</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Benutzername in die Zwischenablage kopieren</translation>
</message>
<message>
<source>Password</source>
<translation>Passwort</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Passwort in die Zwischenablage kopieren</translation>
@@ -912,6 +1039,46 @@ Save changes?</source>
<source>Toggle window</source>
<translation>Fenster zeigen/verstecken</translation>
</message>
<message>
<source>Tools</source>
<translation>Tools</translation>
</message>
<message>
<source>Copy username</source>
<translation>Benutzername kopieren</translation>
</message>
<message>
<source>Copy password</source>
<translation>Passwort kopieren</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Als CSV Datei exportieren</translation>
</message>
<message>
<source>Repair database</source>
<translation>Datenbank reparieren</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 Datenbank</translation>
</message>
<message>
<source>All files</source>
<translation>Alle Dateien</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Reparierte Datenbank speichern</translation>
</message>
<message>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Schreiben der Datenbank fehlgeschlagen.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1092,10 +1259,6 @@ Save changes?</source>
<source>Open previous databases on startup</source>
<translation>Letzte Datenbank beim Starten öffnen</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation>Als erweiterte Zustandsänderungen makieren</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Automatisch speichern beim Schließen</translation>
@@ -1132,6 +1295,18 @@ Save changes?</source>
<source>Hide window to system tray when minimized</source>
<translation>Fenster verstecken wenn minimiert</translation>
</message>
<message>
<source>Hide window to system tray instead of App Exit</source>
<translation>Fenster zu Taskleistensymbol minimieren statt Programm beenden</translation>
</message>
<message>
<source>Hide window to system tray on App start</source>
<translation>Fenster zu Taskleistensymbol minimieren wenn Programm started</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Letzte Schlüsseldateien merken</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1149,7 +1324,7 @@ Save changes?</source>
</message>
<message>
<source>Show passwords in cleartext by default</source>
<translation>Passwort standartmäßig in Klartext anzeigen</translation>
<translation>Passwörter standardmäßig in Klartext anzeigen</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
@@ -1162,14 +1337,6 @@ Save changes?</source>
<source>Unlock database</source>
<translation>Datenbank entsperren</translation>
</message>
<message>
<source>Error</source>
<translation>Fehler</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Falscher Schlüssel.</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1192,10 +1359,6 @@ Save changes?</source>
<source>path to a custom config file</source>
<translation>Pfad zu einer benutzerdefinierten Konfigurationsdatei</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>Passwort der Datenbank (GEFÄHRLICH!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>Schlüsseldatei der Datenbank</translation>

File diff suppressed because it is too large Load Diff

View File

@@ -11,6 +11,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Revision</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Using:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -164,6 +172,42 @@
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Success</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -316,6 +360,15 @@ Discard changes and close anyway?</source>
<source>Writing the CSV file failed.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -370,6 +423,14 @@ Discard changes and close anyway?</source>
<source>Unable to calculate master key</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Move entry to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Do you really want to move entry &quot;%1&quot; to the recycle bin?</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -692,6 +753,14 @@ Discard changes and close anyway?</source>
<numerusform></numerusform>
</translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Can&apos;t read icon:</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>EditWidgetProperties</name>
@@ -805,6 +874,10 @@ Discard changes and close anyway?</source>
<source>Unable to calculate master key</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Wrong key or database file is corrupt.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -824,6 +897,13 @@ Discard changes and close anyway?</source>
<source>Unable to calculate master key</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; &apos;Import KeePass 1 database&apos;.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>Main</name>
@@ -1002,6 +1082,30 @@ Discard changes and close anyway?</source>
<source>Export to CSV file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Repair database</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>All files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Save repaired database</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Error</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1222,6 +1326,14 @@ Discard changes and close anyway?</source>
<source>Remember last key files</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide window to system tray instead of App Exit</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Hide window to system tray on App start</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1274,10 +1386,6 @@ Discard changes and close anyway?</source>
<source>path to a custom config file</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>key file of the database</source>
<translation type="unfinished"></translation>

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX es distribuido bajo los términos de la versión 2 de la Licencia Pública GNU (GPL) o por la versión 3 (si así lo prefiere).</translation>
</message>
<message>
<source>Revision</source>
<translation>Revisión</translation>
</message>
<message>
<source>Using:</source>
<translation>Usando:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -75,7 +83,7 @@
</message>
<message>
<source>Key files</source>
<translation>Archivos de llaves</translation>
<translation>Archivos llave</translation>
</message>
<message>
<source>All files</source>
@@ -109,6 +117,16 @@
<source>Different passwords supplied.</source>
<translation>Las contraseñas ingresadas son distintas.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>No se pudo establecer el archivo llave</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>No se pudo establecer %1 como el Archivo llave:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -118,7 +136,7 @@
</message>
<message>
<source>Key File:</source>
<translation>Archivo clave:</translation>
<translation>Archivo llave:</translation>
</message>
<message>
<source>Password:</source>
@@ -153,6 +171,43 @@
<translation>Seleccionar archivo llave</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Reparar base de datos</translation>
</message>
<message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>No se puede abrir el archivo llave</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Base de datos abierta correctamente. Nada que hacer.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>No se pudo abrir la base de datos.</translation>
</message>
<message>
<source>Success</source>
<translation>Éxito</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>La base de datos ha sido reparada correctamente
Ahora puede guardarla.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>No se pudo reparar la base de datos.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -196,7 +251,7 @@
<name>DatabaseTabWidget</name>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Raíz</translation>
</message>
<message>
<source>KeePass 2 Database</source>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>¿Cerrar?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; está en modo de edición.
¿Cerrar de todas formas?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>¿Guardar cambios?</translation>
@@ -270,12 +319,66 @@ Save changes?</source>
<source>locked</source>
<translation>bloqueado</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>La base de datos que está intentando abrir está bloqueada por otra instancia de KeePassX.
¿Quiere abrirla de todos modos? Alternativamente, la base de datos se abre como sólo lectura.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Bloquear base de datos</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>No se puede bloquear la base de datos porque actualmente está editándola.
Por favor, pulse cancelar para terminar sus cambios o descartarlos.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Esta base de datos nunca ha sido guardada.
Puede guardar la base de datos o dejar de bloquearla.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Esta base de datos ha sido modificada.
¿Desea guardar la base de datos antes de bloquearla?
De lo contrario se perderán los cambios.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;% 1&quot; está en el modo de edición.
¿Descartar cambios y cerrar de todos modos?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Exportar base de datos a un archivo CSV</translation>
</message>
<message>
<source>CSV file</source>
<translation>Archivo CSV</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>La escritura del archivo CSV falló.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>La base de datos que está tratando de guardar está bloqueda por otra instancia de KeePassX.
̉¿Desea guardarla de cualquier manera?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
<message>
<source>Change master key</source>
<translation>Cambiar la llave maestra</translation>
<translation>Cambiar la clave maestra</translation>
</message>
<message>
<source>Delete entry?</source>
@@ -313,6 +416,14 @@ Save changes?</source>
<source>Current group</source>
<translation>Grupo actual</translation>
</message>
<message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>No se puede calcular la llave maestra</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -425,6 +536,10 @@ Save changes?</source>
<source>Save</source>
<translation>Guardar</translation>
</message>
<message>
<source>Open</source>
<translation>Abrir</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -576,6 +691,14 @@ Save changes?</source>
<source>Auto-type</source>
<translation>Auto-escritura</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Usar escritura automática por defecto del grupo padre</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Establecer escritura automática por defecto</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -722,7 +845,11 @@ Save changes?</source>
</message>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Raíz</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>No se puede calcular la clave maestra</translation>
</message>
</context>
<context>
@@ -739,6 +866,20 @@ Save changes?</source>
<source>Wrong key or database file is corrupt.</source>
<translation>La contraseña es incorrecta o el archivo está dañado</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>No se puede calcular la clave maestra</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>El archivo seleccionado es una vieja base de datos de KeePass 1 (.kdb).
Puede importarla haciendo click en &apos;Base de datos&apos; &gt; &apos;Importar base de datos de Keepass 1&apos;.
Esta migración es en un único sentido. No podrá abrir la base importada con la vieja versión 0.4 de KeePassX. </translation>
</message>
</context>
<context>
<name>Main</name>
@@ -777,10 +918,6 @@ Save changes?</source>
<source>Groups</source>
<translation>Grupos</translation>
</message>
<message>
<source>Extras</source>
<translation>Extras</translation>
</message>
<message>
<source>View</source>
<translation>Ver</translation>
@@ -839,7 +976,7 @@ Save changes?</source>
</message>
<message>
<source>Change master key</source>
<translation>Cambiar la llave maestra</translation>
<translation>Cambiar la clave maestra</translation>
</message>
<message>
<source>Database settings</source>
@@ -857,18 +994,10 @@ Save changes?</source>
<source>Find</source>
<translation>Buscar</translation>
</message>
<message>
<source>Username</source>
<translation>Usuario</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Copiar nombre de usuario al portapapeles</translation>
</message>
<message>
<source>Password</source>
<translation>Contraseña</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Copiar contraseña al portapapeles</translation>
@@ -913,6 +1042,46 @@ Save changes?</source>
<source>Toggle window</source>
<translation>Cambiar a ventana</translation>
</message>
<message>
<source>Tools</source>
<translation>Herramientas</translation>
</message>
<message>
<source>Copy username</source>
<translation>Copiar nombre de usuario</translation>
</message>
<message>
<source>Copy password</source>
<translation>Copiar contraseña</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Exportar a un archivo CSV</translation>
</message>
<message>
<source>Repair database</source>
<translation>Reparar la base de datos</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>Base de datos de KeePass 2</translation>
</message>
<message>
<source>All files</source>
<translation>Todos los archivos</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Guardar base de datos reparada</translation>
</message>
<message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Fallo al escribir la base de datos.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1065,7 +1234,7 @@ Save changes?</source>
</message>
<message>
<source>Root group</source>
<translation type="unfinished"/>
<translation>Grupo raíz</translation>
</message>
</context>
<context>
@@ -1093,10 +1262,6 @@ Save changes?</source>
<source>Open previous databases on startup</source>
<translation>Abrir base de datos anterior al inicio</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation>Marcar como modificado en los cambios de estado ampliados</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Guardar automáticamente al salir</translation>
@@ -1133,6 +1298,10 @@ Save changes?</source>
<source>Hide window to system tray when minimized</source>
<translation>Ocultar la ventana a la bandeja del sistema cuando se minimiza</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Recordar últimos archivos clave</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1163,14 +1332,6 @@ Save changes?</source>
<source>Unlock database</source>
<translation>Desbloquear base de datos</translation>
</message>
<message>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Clave incorrecta.</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1193,10 +1354,6 @@ Save changes?</source>
<source>path to a custom config file</source>
<translation>ruta a un archivo de configuración personalizado</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>contraseña de la base de datos (¡PELIGROSO!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>archivo llave de la base de datos</translation>

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX est distribué selon les conditions de la GNU General Public License (GPL) version 2 ou (à votre choix) version 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Version</translation>
</message>
<message>
<source>Using:</source>
<translation>Utilise :</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -25,7 +33,7 @@
<name>AutoTypeAssociationsModel</name>
<message>
<source>Window</source>
<translation>Fenêtre </translation>
<translation>Fenêtre</translation>
</message>
<message>
<source>Sequence</source>
@@ -63,7 +71,7 @@
</message>
<message>
<source>Key file</source>
<translation>Fichier de clé</translation>
<translation>Fichier-clé</translation>
</message>
<message>
<source>Browse</source>
@@ -75,7 +83,7 @@
</message>
<message>
<source>Key files</source>
<translation>Fichiers de clé</translation>
<translation>Fichiers-clés</translation>
</message>
<message>
<source>All files</source>
@@ -83,7 +91,7 @@
</message>
<message>
<source>Create Key File...</source>
<translation>Créer un fichier de clé...</translation>
<translation>Créer un fichier-clé...</translation>
</message>
<message>
<source>Error</source>
@@ -91,11 +99,11 @@
</message>
<message>
<source>Unable to create Key File : </source>
<translation>Incapable de créer un fichier de clé :</translation>
<translation>Impossible de créer un fichier-clé :</translation>
</message>
<message>
<source>Select a key file</source>
<translation>Choisir un fichier de clé</translation>
<translation>Choisir un fichier-clé</translation>
</message>
<message>
<source>Question</source>
@@ -109,16 +117,26 @@
<source>Different passwords supplied.</source>
<translation>Les mots de passe ne sont pas identiques.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Échec de définition du fichier-clé</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Impossible de définir %1 comme fichier-clé :
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
<message>
<source>Enter master key</source>
<translation>Entrez la clé maîtresse</translation>
<translation>Entrez la clé maître</translation>
</message>
<message>
<source>Key File:</source>
<translation>Fichier de clé :</translation>
<translation>Fichier-clé :</translation>
</message>
<message>
<source>Password:</source>
@@ -138,7 +156,7 @@
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Impossible d&apos;ouvrir le fichier de clé</translation>
<translation>Impossible d&apos;ouvrir le fichier-clé</translation>
</message>
<message>
<source>All files</source>
@@ -146,11 +164,48 @@
</message>
<message>
<source>Key files</source>
<translation>Fichiers de clé</translation>
<translation>Fichiers-clés</translation>
</message>
<message>
<source>Select key file</source>
<translation>Choisissez un fichier de clé</translation>
<translation>Choisissez un fichier-clé</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Réparer la base de données</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Impossible d&apos;ouvrir le fichier-clé</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>La base de données s&apos;est bien ouverte. Aucune action à effectuer.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Impossible d&apos;ouvrir la base de données.</translation>
</message>
<message>
<source>Success</source>
<translation>Succès</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>La base de données a correctement é réparée.
Vous pouvez maintenant la sauvegarder.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Impossible de réparer la base de données.</translation>
</message>
</context>
<context>
@@ -177,7 +232,7 @@
</message>
<message>
<source> MiB</source>
<translation>MiB</translation>
<translation> MiB</translation>
</message>
<message>
<source>Benchmark</source>
@@ -208,7 +263,7 @@
</message>
<message>
<source>Open database</source>
<translation>Ovrire la base de données</translation>
<translation>Ouvrir la base de données</translation>
</message>
<message>
<source>Warning</source>
@@ -216,7 +271,7 @@
</message>
<message>
<source>File not found!</source>
<translation>Fichier introuvable!</translation>
<translation>Fichier introuvable !</translation>
</message>
<message>
<source>Open KeePass 1 database</source>
@@ -232,13 +287,7 @@
</message>
<message>
<source>Close?</source>
<translation>Fermer?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; est en cours de modification.
Fermer quand même ?</translation>
<translation>Fermer ?</translation>
</message>
<message>
<source>Save changes?</source>
@@ -256,7 +305,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Une erreur s&apos;est produite lors de l&apos;écriture de la base de données. </translation>
<translation>Une erreur s&apos;est produite lors de l&apos;écriture de la base de données.</translation>
</message>
<message>
<source>Save database as</source>
@@ -270,12 +319,66 @@ Enregistrer les modifications ?</translation>
<source>locked</source>
<translation>verrouillée</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>La base de données que vous essayez d&apos;ouvrir est verrouillée par une autre instance de KeePassX.
Voulez-vous quand même l&apos;ouvrir ? Dans ce cas, elle sera ouverte en lecture seule.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Verrouiller la base de données</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Impossible de verrouiller la base de données lors de modifications.
Cliquez sur Annuler pour finir vos modifications ou abandonnez-les.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Cette base de données n&apos;a pas encore été sauvegardée.
Vous devez la sauvegarder ou annuler son verrouillage.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>La base de données a été modifiée.
Voulez-vous l&apos;enregistrer avant de la verrouiller ?
Autrement, vos modifications seront perdues.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; est en mode édition.
Ignorer les changements et fermer ?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Exporter la base de données au format CSV</translation>
</message>
<message>
<source>CSV file</source>
<translation>Fichier CSV</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Échec de l&apos;écriture du fichier CSV.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>La base de données que vous essayez de sauvegarder a été verrouillée par une autre instance de KeePassX.
Voulez-vous quand même la sauvegarder ?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
<message>
<source>Change master key</source>
<translation>Changer la clé maîtresse</translation>
<translation>Changer la clé maître</translation>
</message>
<message>
<source>Delete entry?</source>
@@ -311,7 +414,15 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Current group</source>
<translation>Group actif</translation>
<translation>Groupe actif</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Impossible de calculer la clé maître</translation>
</message>
</context>
<context>
@@ -322,7 +433,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Advanced</source>
<translation>Avancées</translation>
<translation>Avancé</translation>
</message>
<message>
<source>Icon</source>
@@ -330,11 +441,11 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Auto-Type</source>
<translation>Auto-Type</translation>
<translation>Remplissage automatique</translation>
</message>
<message>
<source>Properties</source>
<translation>Propriétés </translation>
<translation>Propriétés</translation>
</message>
<message>
<source>History</source>
@@ -379,7 +490,7 @@ Enregistrer les modifications ?</translation>
<message>
<source>Unable to save the attachment:
</source>
<translation>Impossible de enregistrer le fichier attaché:
<translation>Impossible d&apos;enregistrer le fichier attaché :
</translation>
</message>
<message>
@@ -396,14 +507,14 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>1 year</source>
<translation>Une année</translation>
<translation>1 an</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAdvanced</name>
<message>
<source>Additional attributes</source>
<translation>Attributs additionnel </translation>
<translation>Attributs supplémentaires</translation>
</message>
<message>
<source>Add</source>
@@ -423,22 +534,26 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Save</source>
<translation>Enregistrer le fichier </translation>
<translation>Enregistrer le fichier</translation>
</message>
<message>
<source>Open</source>
<translation>Ouvrir</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
<message>
<source>Enable Auto-Type for this entry</source>
<translation>Activer l&apos;Auto-Type pour cette entrée</translation>
<translation>Activer le remplissage automatique pour cette entrée</translation>
</message>
<message>
<source>Inherit default Auto-Type sequence from the group</source>
<translation type="unfinished"/>
<translation>Utiliser la séquence de remplissage automatique par défaut du groupe</translation>
</message>
<message>
<source>Use custom Auto-Type sequence:</source>
<translation>Utiliser une séquence d&apos;Auto-Type personnalisée :</translation>
<translation>Utiliser une séquence de remplissage automatique personnalisée :</translation>
</message>
<message>
<source>+</source>
@@ -450,7 +565,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Window title:</source>
<translation>Titre de la fenêtre:</translation>
<translation>Titre de la fenêtre :</translation>
</message>
<message>
<source>Use default sequence</source>
@@ -458,14 +573,14 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Set custom sequence:</source>
<translation type="unfinished"/>
<translation>Définir une séquence personnalisée :</translation>
</message>
</context>
<context>
<name>EditEntryWidgetHistory</name>
<message>
<source>Show</source>
<translation>Exposer</translation>
<translation>Afficher</translation>
</message>
<message>
<source>Restore</source>
@@ -484,19 +599,19 @@ Enregistrer les modifications ?</translation>
<name>EditEntryWidgetMain</name>
<message>
<source>Title:</source>
<translation>Titre:</translation>
<translation>Titre :</translation>
</message>
<message>
<source>Username:</source>
<translation>Non d&apos;utilisateur:</translation>
<translation>Nom d&apos;utilisateur :</translation>
</message>
<message>
<source>Password:</source>
<translation>Mot de passe:</translation>
<translation>Mot de passe :</translation>
</message>
<message>
<source>Repeat:</source>
<translation>Confirme: </translation>
<translation>Confirmation :</translation>
</message>
<message>
<source>Gen.</source>
@@ -504,7 +619,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>URL:</source>
<translation>URL:</translation>
<translation>URL :</translation>
</message>
<message>
<source>Expires</source>
@@ -516,7 +631,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Notes:</source>
<translation>Notes:</translation>
<translation>Notes :</translation>
</message>
</context>
<context>
@@ -531,15 +646,15 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Properties</source>
<translation>Propriétés </translation>
<translation>Propriétés</translation>
</message>
<message>
<source>Add group</source>
<translation>Ajouter un groupe. </translation>
<translation>Ajouter un groupe</translation>
</message>
<message>
<source>Edit group</source>
<translation>Modifie le groupe</translation>
<translation>Modifier le groupe</translation>
</message>
<message>
<source>Enable</source>
@@ -566,7 +681,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Expires</source>
<translation>Expires</translation>
<translation>Expiration</translation>
</message>
<message>
<source>Search</source>
@@ -574,7 +689,15 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Auto-type</source>
<translation>Auto-type</translation>
<translation>Remplissage automatique</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Utiliser la séquence de remplissage automatique par défaut du groupe parent</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Définir une séquence de remplissage automatique par défaut</translation>
</message>
</context>
<context>
@@ -605,7 +728,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Select Image</source>
<translation>Choisis un image. </translation>
<translation>Choisir une image</translation>
</message>
<message>
<source>Can&apos;t delete icon!</source>
@@ -632,7 +755,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Uuid:</source>
<translation>Uuid:</translation>
<translation>Uuid :</translation>
</message>
</context>
<context>
@@ -673,7 +796,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Username</source>
<translation>Non d&apos;utilisateur</translation>
<translation>Nom d&apos;utilisateur</translation>
</message>
<message>
<source>URL</source>
@@ -684,14 +807,14 @@ Enregistrer les modifications ?</translation>
<name>Group</name>
<message>
<source>Recycle Bin</source>
<translation>Bac de Recyclage</translation>
<translation>Corbeille</translation>
</message>
</context>
<context>
<name>KeePass1OpenWidget</name>
<message>
<source>Import KeePass1 database</source>
<translation>Importe un KeePass1 bas de données</translation>
<translation>Importer une base de données au format KeePass1</translation>
</message>
<message>
<source>Error</source>
@@ -699,18 +822,18 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Impossible d&apos;ouvrir la bas de données.</translation>
<translation>Impossible d&apos;ouvrir la base de données.</translation>
</message>
</context>
<context>
<name>KeePass1Reader</name>
<message>
<source>Unable to read keyfile.</source>
<translation>Impossible de lire le fichier de clé.</translation>
<translation>Impossible de lire le fichier-clé.</translation>
</message>
<message>
<source>Not a KeePass database.</source>
<translation>Ce n&apos;est pas une base de donnée KeePass.</translation>
<translation>Ce n&apos;est pas une base de données KeePass.</translation>
</message>
<message>
<source>Unsupported encryption algorithm.</source>
@@ -718,26 +841,44 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
<translation>Version de base de donnée KeePass non supportée.</translation>
<translation>Version de base de données KeePass non supportée.</translation>
</message>
<message>
<source>Root</source>
<translation>Racine</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Impossible de calculer la clé maître</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
<message>
<source>Not a KeePass database.</source>
<translation>Ce n&apos;est pas une base de donnée KeePass.</translation>
<translation>Ce n&apos;est pas une base de données KeePass.</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
<translation>Version de base de donnée KeePass non supportée.</translation>
<translation>Version de base de données KeePass non supportée.</translation>
</message>
<message>
<source>Wrong key or database file is corrupt.</source>
<translation>Mauvaise clé ou fichier de base de donnée corrompu.</translation>
<translation>Mauvaise clé ou fichier de base de données corrompu.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Impossible de calculer la clé maître</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Le fichier sélectionné est une ancienne base de données pour KeePass 1 (.kdb).
Vous pouvez l&apos;importer en cliquant sur &quot;Base de données&quot; &gt; &quot;Importer une base de données KeePass 1&quot;.
Ceci est une migration à sens unique. Vous ne serez plus en mesure d&apos;ouvrir la base de données importée avec l&apos;ancienne version KeePassX version 0.4.</translation>
</message>
</context>
<context>
@@ -771,16 +912,12 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Copy attribute to clipboard</source>
<translation>Copier l&apos;attribut dans le presse-papiers</translation>
<translation>Copier l&apos;attribut dans le presse-papier</translation>
</message>
<message>
<source>Groups</source>
<translation>Groupes</translation>
</message>
<message>
<source>Extras</source>
<translation>Extras</translation>
</message>
<message>
<source>View</source>
<translation>Vue</translation>
@@ -795,19 +932,19 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Open database</source>
<translation>Ouvrir une base de donnée</translation>
<translation>Ouvrir une base de données</translation>
</message>
<message>
<source>Save database</source>
<translation>Enregistrer la base de donnée</translation>
<translation>Enregistrer la base de données</translation>
</message>
<message>
<source>Close database</source>
<translation>Fermer la base de donnée</translation>
<translation>Fermer la base de données</translation>
</message>
<message>
<source>New database</source>
<translation>Nouvelle base de donnée</translation>
<translation>Nouvelle base de données</translation>
</message>
<message>
<source>Add new entry</source>
@@ -835,7 +972,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Save database as</source>
<translation>Enregistrer la base de donnée sous</translation>
<translation>Enregistrer la base de données sous</translation>
</message>
<message>
<source>Change master key</source>
@@ -843,11 +980,11 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Database settings</source>
<translation>Paramètre de la base de donnée</translation>
<translation>Paramètres de la base de données</translation>
</message>
<message>
<source>Import KeePass 1 database</source>
<translation>Importer une base de donnée KeePass 1</translation>
<translation>Importer une base de données KeePass 1</translation>
</message>
<message>
<source>Clone entry</source>
@@ -857,21 +994,13 @@ Enregistrer les modifications ?</translation>
<source>Find</source>
<translation>Chercher</translation>
</message>
<message>
<source>Username</source>
<translation>Nom d&apos;utilisateur</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Copier le nom d&apos;utilisateur dans le presse-papiers</translation>
</message>
<message>
<source>Password</source>
<translation>Mot de passe</translation>
<translation>Copier le nom d&apos;utilisateur dans le presse-papier</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Copier le mot de passe dans le presse-papiers</translation>
<translation>Copier le mot de passe dans le presse-papier</translation>
</message>
<message>
<source>Settings</source>
@@ -879,7 +1008,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Perform Auto-Type</source>
<translation>Effectuer un Auto-Type</translation>
<translation>Effectuer un remplissage automatique</translation>
</message>
<message>
<source>Open URL</source>
@@ -913,12 +1042,52 @@ Enregistrer les modifications ?</translation>
<source>Toggle window</source>
<translation>Basculer de fenêtre</translation>
</message>
<message>
<source>Tools</source>
<translation>Outils</translation>
</message>
<message>
<source>Copy username</source>
<translation>Copier le nom d&apos;utilisateur</translation>
</message>
<message>
<source>Copy password</source>
<translation>Copier le mot de passe</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Exporter au format CSV</translation>
</message>
<message>
<source>Repair database</source>
<translation>Réparer la base de données</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>Base de données KeePass 2</translation>
</message>
<message>
<source>All files</source>
<translation>Tous les fichiers</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Sauvegarder la base de données réparée</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Une erreur s&apos;est produite lors de l&apos;écriture de la base de données.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
<message>
<source>Password:</source>
<translation>Mot de passe:</translation>
<translation>Mot de passe :</translation>
</message>
<message>
<source>Length:</source>
@@ -926,7 +1095,7 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Character Types</source>
<translation>Types de caractère</translation>
<translation>Types de caractères</translation>
</message>
<message>
<source>Upper Case Letters</source>
@@ -961,7 +1130,7 @@ Enregistrer les modifications ?</translation>
<name>QCommandLineParser</name>
<message>
<source>Displays version information.</source>
<translation>Afficher les informations de version</translation>
<translation>Afficher les informations de version.</translation>
</message>
<message>
<source>Displays this help.</source>
@@ -1023,15 +1192,15 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Error writing to underlying device: </source>
<translation type="unfinished"/>
<translation>Erreur d&apos;écriture sur le périphérique concerné :</translation>
</message>
<message>
<source>Error opening underlying device: </source>
<translation type="unfinished"/>
<translation>Erreur d&apos;ouverture du périphérique concerné :</translation>
</message>
<message>
<source>Error reading data from underlying device: </source>
<translation type="unfinished"/>
<translation>Erreur de lecture sur le périphérique concerné :</translation>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
@@ -1072,7 +1241,7 @@ Enregistrer les modifications ?</translation>
<name>SettingsWidget</name>
<message>
<source>Application Settings</source>
<translation>Paramètre de l&apos;application</translation>
<translation>Paramètres de l&apos;application</translation>
</message>
<message>
<source>General</source>
@@ -1091,23 +1260,19 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Open previous databases on startup</source>
<translation>Ouvrir les base de données précédentes au démarrage</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation type="unfinished"/>
<translation>Ouvrir les bases de données précédentes au démarrage</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Sauvegarde automatiquement à la sortie</translation>
<translation>Sauvegarder automatiquement à la sortie</translation>
</message>
<message>
<source>Automatically save after every change</source>
<translation>Sauvegarde automatiquement après chaque modification</translation>
<translation>Sauvegarder automatiquement après chaque modification</translation>
</message>
<message>
<source>Minimize when copying to clipboard</source>
<translation type="unfinished"/>
<translation>Réduire lors de la copie dans le presse-papier</translation>
</message>
<message>
<source>Use group icon on entry creation</source>
@@ -1115,11 +1280,11 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Global Auto-Type shortcut</source>
<translation>Raccourci d&apos;Auto-Type global</translation>
<translation>Raccourci de remplissage automatique global</translation>
</message>
<message>
<source>Use entry title to match windows for global auto-type</source>
<translation>Utiliser la correspondance entre le titre de l&apos;entrée et de la fenêtre pour l&apos;Auto-Type global</translation>
<translation>Utiliser la correspondance entre le titre de l&apos;entrée et de la fenêtre pour le remplissage automatique global</translation>
</message>
<message>
<source>Language</source>
@@ -1127,26 +1292,30 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Show a system tray icon</source>
<translation type="unfinished"/>
<translation>Afficher une icône dans la zone de notification</translation>
</message>
<message>
<source>Hide window to system tray when minimized</source>
<translation type="unfinished"/>
<translation>Réduire la fenêtre vers la zone de notification lors de sa réduction</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Se rappeler les derniers fichiers-clés ouverts</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
<message>
<source>Clear clipboard after</source>
<translation>Vider le presse-papiers après</translation>
<translation>Vider le presse-papier après</translation>
</message>
<message>
<source> sec</source>
<translation>s</translation>
<translation> s</translation>
</message>
<message>
<source>Lock databases after inactivity of</source>
<translation>Verrouiller les bases de donnée après une inactivité de</translation>
<translation>Verrouiller les bases de données après une inactivité de</translation>
</message>
<message>
<source>Show passwords in cleartext by default</source>
@@ -1154,22 +1323,14 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
<translation>Toujours demander avant d&apos;effectuer un auto-type</translation>
<translation>Toujours demander avant d&apos;effectuer un remplissage automatique</translation>
</message>
</context>
<context>
<name>UnlockDatabaseWidget</name>
<message>
<source>Unlock database</source>
<translation>Déverrouiller la base de donnée</translation>
</message>
<message>
<source>Error</source>
<translation>Erreur</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Mauvaise clé.</translation>
<translation>Déverrouiller la base de données</translation>
</message>
</context>
<context>
@@ -1187,19 +1348,15 @@ Enregistrer les modifications ?</translation>
</message>
<message>
<source>filename of the password database to open (*.kdbx)</source>
<translation>Nom de fichier de la base de donnée de mot de pass à ouvrir (*.kdbx)</translation>
<translation>Nom de fichier de la base de données de mot de passe à ouvrir (*.kdbx)</translation>
</message>
<message>
<source>path to a custom config file</source>
<translation>Chemin vers un fichier de configuration personnalisé</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>Mot de passe de la base de donnée (DANGEREUX !)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>Fichier de clé de la base de donnée</translation>
<translation>Fichier-clé de la base de données</translation>
</message>
</context>
</TS>

View File

@@ -7,7 +7,15 @@
</message>
<message>
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation type="unfinished"/>
<translation>KeePassX disebarluaskan dibawah ketentuan dari Lisensi Publik Umum GNU (GPL) versi 2 atau (sesuai pilihan Anda) versi 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Revisi</translation>
</message>
<message>
<source>Using:</source>
<translation>Menggunakan:</translation>
</message>
</context>
<context>
@@ -18,7 +26,7 @@
</message>
<message>
<source>Couldn&apos;t find an entry that matches the window title:</source>
<translation>Tidak dapat menemukan entri yang cocok dengan judul jendela</translation>
<translation>Tidak bisa menemukan entri yang cocok dengan judul jendela:</translation>
</message>
</context>
<context>
@@ -51,15 +59,15 @@
<name>ChangeMasterKeyWidget</name>
<message>
<source>Password</source>
<translation>Kata Sandi</translation>
<translation>Sandi</translation>
</message>
<message>
<source>Enter password:</source>
<translation>Masukan kata sandi:</translation>
<translation>Masukkan sandi:</translation>
</message>
<message>
<source>Repeat password:</source>
<translation>Ulangi kata sandi:</translation>
<translation>Ulangi sandi:</translation>
</message>
<message>
<source>Key file</source>
@@ -75,7 +83,7 @@
</message>
<message>
<source>Key files</source>
<translation>Berkas Kunci</translation>
<translation>Berkas kunci</translation>
</message>
<message>
<source>All files</source>
@@ -91,11 +99,11 @@
</message>
<message>
<source>Unable to create Key File : </source>
<translation>Tidak dapat membuat Berkas Kunci :</translation>
<translation>Tidak bisa membuat Berkas Kunci :</translation>
</message>
<message>
<source>Select a key file</source>
<translation>Pilih sebuah berkas kunci</translation>
<translation>Pilih berkas kunci</translation>
</message>
<message>
<source>Question</source>
@@ -103,18 +111,28 @@
</message>
<message>
<source>Do you really want to use an empty string as password?</source>
<translation>Apakah anda ingin menggunakan string kosong sebagai kata sandi?</translation>
<translation>Apakah Anda benar-benar ingin menggunakan lema kosong sebagai sandi?</translation>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Kata sandi yang berbeda diberikan.</translation>
<translation>Sandi berbeda.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Gagal menetapkan berkas kunci</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Gagal menetapkan %1 sebagai berkas Kunci:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
<message>
<source>Enter master key</source>
<translation>Masukan kunci utama</translation>
<translation>Masukkan kunci utama</translation>
</message>
<message>
<source>Key File:</source>
@@ -122,7 +140,7 @@
</message>
<message>
<source>Password:</source>
<translation>Kata sandi:</translation>
<translation>Sandi:</translation>
</message>
<message>
<source>Browse</source>
@@ -134,11 +152,11 @@
</message>
<message>
<source>Unable to open the database.</source>
<translation>Tidak dapat membuka basis data</translation>
<translation>Tidak bisa membuka basis data.</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Tidak dapat membuka berkas kunci</translation>
<translation>Tidak bisa membuka berkas kunci</translation>
</message>
<message>
<source>All files</source>
@@ -153,6 +171,43 @@
<translation>Pilih berkas kunci</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Perbaiki basis data</translation>
</message>
<message>
<source>Error</source>
<translation>Galat</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Tidak bisa membuka berkas kunci</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Basis data terbuka dengan baik. Tidak perlu melakukan apa-apa.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Tidak bisa membuka basis data.</translation>
</message>
<message>
<source>Success</source>
<translation>Sukses</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Basis data berhasil diperbaiki
Anda bisa menyimpannya sekarang.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Tidak bisa memperbaiki basis data.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -173,7 +228,7 @@
</message>
<message>
<source>Use recycle bin:</source>
<translation type="unfinished"/>
<translation>Gunakan tong sampah:</translation>
</message>
<message>
<source> MiB</source>
@@ -196,7 +251,7 @@
<name>DatabaseTabWidget</name>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Root</translation>
</message>
<message>
<source>KeePass 2 Database</source>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>Tutup?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; dalam berada mode sunting.
Tetap tutup?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Simpan perubahan?</translation>
@@ -256,7 +305,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Menulis basis data gagal.</translation>
<translation>Gagal membuat basis data.</translation>
</message>
<message>
<source>Save database as</source>
@@ -270,6 +319,60 @@ Simpan perubahan?</translation>
<source>locked</source>
<translation>terkunci</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan.
Apakah Anda tetap ingin membukanya? Alternatif lain buka basis data baca-saja.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Kunci basis data</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Tidak bisa mengunci basis data karena Anda sedang menyuntingnya.
Harap tekan batal untuk menyelesaikan ubahan Anda atau membuangnya.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Basis data ini belum pernah disimpan.
Anda bisa menyimpan basis data atau berhenti menguncinya.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Basis data ini telah dimodifikasi.
Apakah Anda ingin menyimpan basis data sebelum menguncinya?
Kalau tidak, ubahan Anda akan hilang.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; dalam mode penyuntingan.
Tetap buang ubahan dan tutup?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Ekspor basis data ke berkas CSV</translation>
</message>
<message>
<source>CSV file</source>
<translation>Berkas CSV</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Gagal membuat berkas CSV.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Basis data yang Anda coba buka terkunci oleh KeePassX lain yang sedang berjalan.
Apakah Anda tetap ingin menyimpannya?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -283,7 +386,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Do you really want to delete the entry &quot;%1&quot; for good?</source>
<translation>Apakah anda ingin menghapus entri &quot;%1&quot; untuk selamanya?</translation>
<translation>Apakah Anda benar-benar ingin menghapus entri &quot;%1&quot; untuk selamanya?</translation>
</message>
<message>
<source>Delete entries?</source>
@@ -291,15 +394,15 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Do you really want to delete %1 entries for good?</source>
<translation>Apakah anda ingin menghapus entri %1 untuk selamanya?</translation>
<translation>Apakah Anda benar-benar ingin menghapus entri %1 untuk selamanya?</translation>
</message>
<message>
<source>Move entries to recycle bin?</source>
<translation type="unfinished"/>
<translation>Pindah entri ke tong sampah?</translation>
</message>
<message numerus="yes">
<source>Do you really want to move %n entry(s) to the recycle bin?</source>
<translation type="unfinished"><numerusform></numerusform></translation>
<translation><numerusform>Apakah Anda benar-benar ingin memindahkan %n entri ke tong sampah?</numerusform></translation>
</message>
<message>
<source>Delete group?</source>
@@ -307,12 +410,20 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Do you really want to delete the group &quot;%1&quot; for good?</source>
<translation>Apakah anda ingin menghapus grup &quot;%1&quot; untuk selamanya?</translation>
<translation>Apakah Anda benar-benar ingin menghapus grup &quot;%1&quot; untuk selamanya?</translation>
</message>
<message>
<source>Current group</source>
<translation>Grup saat ini</translation>
</message>
<message>
<source>Error</source>
<translation>Galat</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Tidak bisa mengkalkulasi kunci utama</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -342,7 +453,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Entry history</source>
<translation>Entri riwayat</translation>
<translation>Riwayat entri</translation>
</message>
<message>
<source>Add entry</source>
@@ -358,7 +469,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Kata sandi yang berbeda diberikan.</translation>
<translation>Sandi berbeda.</translation>
</message>
<message>
<source>New attribute</source>
@@ -370,7 +481,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Unable to open file</source>
<translation>Tidak dapat membuka berkas</translation>
<translation>Tidak bisa membuka berkas</translation>
</message>
<message>
<source>Save attachment</source>
@@ -379,7 +490,7 @@ Simpan perubahan?</translation>
<message>
<source>Unable to save the attachment:
</source>
<translation>Tidak dapat menyimpan lampiran:
<translation>Tidak bisa menyimpan lampiran:
</translation>
</message>
<message>
@@ -388,11 +499,11 @@ Simpan perubahan?</translation>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation><numerusform>%n minggu(s)</numerusform></translation>
<translation><numerusform>%n minggu</numerusform></translation>
</message>
<message numerus="yes">
<source>%n month(s)</source>
<translation><numerusform>%n bulan(s)</numerusform></translation>
<translation><numerusform>%n bulan</numerusform></translation>
</message>
<message>
<source>1 year</source>
@@ -415,7 +526,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Remove</source>
<translation>Hapus</translation>
<translation>Buang</translation>
</message>
<message>
<source>Attachments</source>
@@ -425,6 +536,10 @@ Simpan perubahan?</translation>
<source>Save</source>
<translation>Simpan</translation>
</message>
<message>
<source>Open</source>
<translation>Buka</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -434,11 +549,11 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Inherit default Auto-Type sequence from the group</source>
<translation type="unfinished"/>
<translation>Mengikuti urutan Ketik-Otomatis baku grup</translation>
</message>
<message>
<source>Use custom Auto-Type sequence:</source>
<translation type="unfinished"/>
<translation>Gunakan urutan Ketik-Otomatis ubahsuai:</translation>
</message>
<message>
<source>+</source>
@@ -458,7 +573,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Set custom sequence:</source>
<translation>Tetapkan urutan kustom:</translation>
<translation>Tetapkan urutan ubahsuai:</translation>
</message>
</context>
<context>
@@ -492,7 +607,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Password:</source>
<translation>Kata sandi:</translation>
<translation>Sandi:</translation>
</message>
<message>
<source>Repeat:</source>
@@ -508,11 +623,11 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Expires</source>
<translation>Kadaluarsa</translation>
<translation>Kedaluwarsa</translation>
</message>
<message>
<source>Presets</source>
<translation type="unfinished"/>
<translation>Prasetel</translation>
</message>
<message>
<source>Notes:</source>
@@ -551,7 +666,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Inherit from parent group (%1)</source>
<translation type="unfinished"/>
<translation>Mengikuti grup induk (%1)</translation>
</message>
</context>
<context>
@@ -566,7 +681,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Expires</source>
<translation>Kadaluarsa</translation>
<translation>Kedaluwarsa</translation>
</message>
<message>
<source>Search</source>
@@ -576,6 +691,14 @@ Simpan perubahan?</translation>
<source>Auto-type</source>
<translation>Ketik-otomatis</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Gunakan urutan ketik-otomatis baku grup induk</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Tetapkan urutan ketik-otomatis baku</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -585,15 +708,15 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Use custom icon</source>
<translation>Gunakan ikon kustom</translation>
<translation>Gunakan ikon ubahsuai</translation>
</message>
<message>
<source>Add custom icon</source>
<translation>Tambah ikon kustom</translation>
<translation>Tambah ikon ubahsuai</translation>
</message>
<message>
<source>Delete custom icon</source>
<translation>Hapus ikon kustom</translation>
<translation>Hapus ikon ubahsuai</translation>
</message>
<message>
<source>Images</source>
@@ -609,11 +732,11 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Can&apos;t delete icon!</source>
<translation>Tidak dapat menghapus ikon!</translation>
<translation>Tidak bisa menghapus ikon!</translation>
</message>
<message numerus="yes">
<source>Can&apos;t delete icon. Still used by %n item(s).</source>
<translation><numerusform>Can&apos;t delete icon. Still used by %n item(s).</numerusform></translation>
<translation><numerusform>Tidak bisa menghapus ikon. Masih digunakan oleh %n item.</numerusform></translation>
</message>
</context>
<context>
@@ -684,7 +807,7 @@ Simpan perubahan?</translation>
<name>Group</name>
<message>
<source>Recycle Bin</source>
<translation type="unfinished"/>
<translation>Tong Sampah</translation>
</message>
</context>
<context>
@@ -699,52 +822,70 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Tidak dapat membuka basis data</translation>
<translation>Tidak bisa membuka basis data.</translation>
</message>
</context>
<context>
<name>KeePass1Reader</name>
<message>
<source>Unable to read keyfile.</source>
<translation>Tidak dapat membaca berkas kunci.</translation>
<translation>Tidak bisa membaca berkas kunci.</translation>
</message>
<message>
<source>Not a KeePass database.</source>
<translation>Bukan basis data KeePass</translation>
<translation>Bukan basis data KeePass.</translation>
</message>
<message>
<source>Unsupported encryption algorithm.</source>
<translation>Algoritma enkripsi tidak didukung</translation>
<translation>Algoritma enkripsi tidak didukung.</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
<translation>Versi Basis data KeePass tidak didukung</translation>
<translation>Versi basis data KeePass tidak didukung.</translation>
</message>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation>Root</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Tidak bisa mengkalkulasi kunci utama</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
<message>
<source>Not a KeePass database.</source>
<translation>Bukan basis data KeePass</translation>
<translation>Bukan basis data KeePass.</translation>
</message>
<message>
<source>Unsupported KeePass database version.</source>
<translation>Versi basis data KeePass tidak didukung</translation>
<translation>Versi basis data KeePass tidak didukung.</translation>
</message>
<message>
<source>Wrong key or database file is corrupt.</source>
<translation>Kunci salah atau berkas basis data korup.</translation>
<translation>Kunci salah atau berkas basis data rusak.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Tidak bisa mengkalkulasi kunci utama</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Berkas yang dipilih adalah basis data KeePass 1 yang lama (.kdb).
Anda bisa mengimpornya dengan mengklik Basis Data &gt; &apos;Impor basis data KeePass 1&apos;.
Ini adalah migrasi satu arah. Anda tidak akan bisa lagi membuka basis data yang diimpor dengan versi lama KeePassX 0.4.</translation>
</message>
</context>
<context>
<name>Main</name>
<message>
<source>Fatal error while testing the cryptographic functions.</source>
<translation type="unfinished"/>
<translation>Galat saat menguji fungsi kriptografi.</translation>
</message>
<message>
<source>KeePassX - Error</source>
@@ -759,7 +900,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Recent databases</source>
<translation type="unfinished"/>
<translation>Basis data baru-baru ini</translation>
</message>
<message>
<source>Help</source>
@@ -777,13 +918,9 @@ Simpan perubahan?</translation>
<source>Groups</source>
<translation>Grup</translation>
</message>
<message>
<source>Extras</source>
<translation>Ekstra</translation>
</message>
<message>
<source>View</source>
<translation type="unfinished"/>
<translation>Lihat</translation>
</message>
<message>
<source>Quit</source>
@@ -815,7 +952,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>View/Edit entry</source>
<translation>Tampil/Sunting entri</translation>
<translation>Lihat/Sunting entri</translation>
</message>
<message>
<source>Delete entry</source>
@@ -851,27 +988,19 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Clone entry</source>
<translation type="unfinished"/>
<translation>Duplikat entri</translation>
</message>
<message>
<source>Find</source>
<translation>Temukan</translation>
</message>
<message>
<source>Username</source>
<translation>Nama pengguna</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Salin nama pengguna ke papan klip</translation>
</message>
<message>
<source>Password</source>
<translation>Kata sandi</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Salin kata sandi ke papan klip</translation>
<translation>Salin sandi ke papan klip</translation>
</message>
<message>
<source>Settings</source>
@@ -879,7 +1008,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Perform Auto-Type</source>
<translation>Melakukan Ketik-Otomatis</translation>
<translation>Lakukan Ketik-Otomatis</translation>
</message>
<message>
<source>Open URL</source>
@@ -907,18 +1036,58 @@ Simpan perubahan?</translation>
</message>
<message>
<source>read-only</source>
<translation>hanya-baca</translation>
<translation>baca-saja</translation>
</message>
<message>
<source>Toggle window</source>
<translation type="unfinished"/>
<translation>Jungkit jendela</translation>
</message>
<message>
<source>Tools</source>
<translation>Perkakas</translation>
</message>
<message>
<source>Copy username</source>
<translation>Salin nama pengguna</translation>
</message>
<message>
<source>Copy password</source>
<translation>Salin sandi</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Ekspor ke berkas CSV</translation>
</message>
<message>
<source>Repair database</source>
<translation>Perbaiki basis data</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>Basis Data KeePass 2</translation>
</message>
<message>
<source>All files</source>
<translation>Semua Berkas</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Simpan basis data yang sudah diperbaiki</translation>
</message>
<message>
<source>Error</source>
<translation>Galat</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Gagal menyimpan basis data.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
<message>
<source>Password:</source>
<translation>Kata sandi:</translation>
<translation>Sandi:</translation>
</message>
<message>
<source>Length:</source>
@@ -926,15 +1095,15 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Character Types</source>
<translation>Tipe karakter</translation>
<translation>Tipe Karakter</translation>
</message>
<message>
<source>Upper Case Letters</source>
<translation type="unfinished"/>
<translation>Huruf Besar</translation>
</message>
<message>
<source>Lower Case Letters</source>
<translation type="unfinished"/>
<translation>Huruf Kecil</translation>
</message>
<message>
<source>Numbers</source>
@@ -946,11 +1115,11 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Exclude look-alike characters</source>
<translation type="unfinished"/>
<translation>Kecualikan karakter mirip</translation>
</message>
<message>
<source>Ensure that the password contains characters from every group</source>
<translation>Pastikan kata sandi berisi karakter dari setiap grup</translation>
<translation>Pastikan sandi berisi karakter dari setiap grup</translation>
</message>
<message>
<source>Accept</source>
@@ -961,11 +1130,11 @@ Simpan perubahan?</translation>
<name>QCommandLineParser</name>
<message>
<source>Displays version information.</source>
<translation>Tampilkan informasi versi</translation>
<translation>Tampilkan informasi versi.</translation>
</message>
<message>
<source>Displays this help.</source>
<translation>Tampilkan bantuan ini</translation>
<translation>Tampilkan bantuan ini.</translation>
</message>
<message>
<source>Unknown option &apos;%1&apos;.</source>
@@ -997,45 +1166,45 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Arguments:</source>
<translation>Argumen</translation>
<translation>Argumen:</translation>
</message>
</context>
<context>
<name>QSaveFile</name>
<message>
<source>Existing file %1 is not writable</source>
<translation>Berkas yang ada %1 tidak dapat ditulis</translation>
<translation>Berkas yang ada %1 tidak bisa ditulis</translation>
</message>
<message>
<source>Writing canceled by application</source>
<translation>Menulis dibatalkan oleh aplikasi</translation>
<translation>Penulisan dibatalkan oleh aplikasi</translation>
</message>
<message>
<source>Partial write. Partition full?</source>
<translation type="unfinished"/>
<translation>Penulisan parsial. Partisi penuh?</translation>
</message>
</context>
<context>
<name>QtIOCompressor</name>
<message>
<source>Internal zlib error when compressing: </source>
<translation>Galat zlib internal ketika mengkompress: </translation>
<translation>Galat zlib internal ketika memampatkan:</translation>
</message>
<message>
<source>Error writing to underlying device: </source>
<translation type="unfinished"/>
<translation>Terjadi kesalahan saat menyimpan ke perangkat:</translation>
</message>
<message>
<source>Error opening underlying device: </source>
<translation type="unfinished"/>
<translation>Terjadi kesalahan saat membuka perangkat:</translation>
</message>
<message>
<source>Error reading data from underlying device: </source>
<translation type="unfinished"/>
<translation>Terjadi kesalahan saat membaca data dari perangkat:</translation>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
<translation>Galat zlib internal ketika dekompress</translation>
<translation>Galat zlib internal ketika dekompres:</translation>
</message>
</context>
<context>
@@ -1057,15 +1226,15 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Case sensitive</source>
<translation type="unfinished"/>
<translation>Sensitif besar kecil huruf</translation>
</message>
<message>
<source>Current group</source>
<translation type="unfinished"/>
<translation>Grup saat ini</translation>
</message>
<message>
<source>Root group</source>
<translation type="unfinished"/>
<translation>Grup root</translation>
</message>
</context>
<context>
@@ -1093,10 +1262,6 @@ Simpan perubahan?</translation>
<source>Open previous databases on startup</source>
<translation>Buka basis data sebelumnya saat mulai</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation type="unfinished"/>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Otomatis simpan ketika keluar</translation>
@@ -1107,7 +1272,7 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Minimize when copying to clipboard</source>
<translation>Kecilkan ketika menyalin ke papan klip</translation>
<translation>Minimalkan ketika menyalin ke papan klip</translation>
</message>
<message>
<source>Use group icon on entry creation</source>
@@ -1115,11 +1280,11 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Global Auto-Type shortcut</source>
<translation>Jalan pintas global Ketik-Otomatis</translation>
<translation>Pintasan global Ketik-Otomatis</translation>
</message>
<message>
<source>Use entry title to match windows for global auto-type</source>
<translation type="unfinished"/>
<translation>Gunakan judul entri untuk mencocokkan jendela untuk ketik-otomatis global</translation>
</message>
<message>
<source>Language</source>
@@ -1127,18 +1292,22 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Show a system tray icon</source>
<translation>Tampilkan sebuah ikon baki sistem</translation>
<translation>Tampilkan ikon baki sistem</translation>
</message>
<message>
<source>Hide window to system tray when minimized</source>
<translation>Sembunyikan jendela ke baki sistem ketika dikecilkan</translation>
<translation>Sembunyikan jendela ke baki sistem ketika diminimalkan</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Ingat berkas kunci terakhir</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
<message>
<source>Clear clipboard after</source>
<translation>Bersihkan papan klip setelaj</translation>
<translation>Kosongkan papan klip setelah</translation>
</message>
<message>
<source> sec</source>
@@ -1146,56 +1315,44 @@ Simpan perubahan?</translation>
</message>
<message>
<source>Lock databases after inactivity of</source>
<translation type="unfinished"/>
<translation>Kunci basis data setelah tidak aktif selama</translation>
</message>
<message>
<source>Show passwords in cleartext by default</source>
<translation type="unfinished"/>
<translation>Tampilkan teks sandi secara baku</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
<translation type="unfinished"/>
<translation>Selalu tanya sebelum melakukan ketik-otomatis</translation>
</message>
</context>
<context>
<name>UnlockDatabaseWidget</name>
<message>
<source>Unlock database</source>
<translation type="unfinished"/>
</message>
<message>
<source>Error</source>
<translation>Galat</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Kunci salah.</translation>
<translation>Buka kunci basis data</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
<message>
<source>Welcome!</source>
<translation>Selamat Datang.</translation>
<translation>Selamat datang!</translation>
</message>
</context>
<context>
<name>main</name>
<message>
<source>KeePassX - cross-platform password manager</source>
<translation>KeePassX - manajer kata sandi cross-platform</translation>
<translation>KeePassX - pengelola sandi lintas platform</translation>
</message>
<message>
<source>filename of the password database to open (*.kdbx)</source>
<translation>nama berkasi dari basis data kata sandi untuk dibuka (*.kdbx)</translation>
<translation>nama berkas dari basis data sandi untuk dibuka (*.kdbx)</translation>
</message>
<message>
<source>path to a custom config file</source>
<translation type="unfinished"/>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>kata sandi dari basis data (BERBAHAYA!)</translation>
<translation>jalur ke berkas konfig ubahsuai</translation>
</message>
<message>
<source>key file of the database</source>

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassXはGNU General Public License (GPL) version 2 version 3 ()</translation>
</message>
<message>
<source>Revision</source>
<translation></translation>
</message>
<message>
<source>Using:</source>
<translation>:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -18,7 +26,7 @@
</message>
<message>
<source>Couldn&apos;t find an entry that matches the window title:</source>
<translation type="unfinished"/>
<translation>:</translation>
</message>
</context>
<context>
@@ -29,11 +37,11 @@
</message>
<message>
<source>Sequence</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Default sequence</source>
<translation type="unfinished"/>
<translation></translation>
</message>
</context>
<context>
@@ -44,7 +52,7 @@
</message>
<message>
<source>Select entry to Auto-Type:</source>
<translation type="unfinished"/>
<translation>:</translation>
</message>
</context>
<context>
@@ -107,16 +115,17 @@
</message>
<message>
<source>Different passwords supplied.</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Failed to set key file</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation type="unfinished"/>
<translation>%1 :
%2</translation>
</message>
</context>
<context>
@@ -147,7 +156,7 @@
</message>
<message>
<source>Can&apos;t open key file</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>All files</source>
@@ -162,6 +171,43 @@
<translation></translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation></translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation></translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation></translation>
</message>
<message>
<source>Success</source>
<translation></translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>
</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation></translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -205,7 +251,7 @@
<name>DatabaseTabWidget</name>
<message>
<source>Root</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>KeePass 2 Database</source>
@@ -243,12 +289,6 @@
<source>Close?</source>
<translation>?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot;
?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>?</translation>
@@ -292,18 +332,46 @@ Do you want to open it anyway? Alternatively the database is opened read-only.</
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation type="unfinished"/>
<translation>現在編集中のため、データベースをロックすることができませんでした。
キャンセルボタンを押し、変更を完了させるか破棄してください。</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation type="unfinished"/>
<translation>このデータベースは一度も保存されていません。
データベースを保存してロックを解除してください。</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation type="unfinished"/>
<translation>このデータベースは変更されました。
ロックを行う前にデータベースを保存しますか?
保存しない場合には変更点は失われます。</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; は現在編集モードです。
変更を破棄して閉じてしまってもよろしいですか?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>データベースをCSVファイルにエクスポートする</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSVファイル</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>CSVファイルの書き込みに失敗しました。</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>保存しようとしたデータベースは別のKeePassXプログラムからロックされています。
とにかく保存しますか?</translation>
</message>
</context>
<context>
@@ -318,7 +386,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Do you really want to delete the entry &quot;%1&quot; for good?</source>
<translation type="unfinished"/>
<translation>本当にエントリー &quot;%1&quot; を永遠に消去しますか?</translation>
</message>
<message>
<source>Delete entries?</source>
@@ -326,7 +394,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Do you really want to delete %1 entries for good?</source>
<translation type="unfinished"/>
<translation>本当に %1 個のエントリーを永遠に消去しますか?</translation>
</message>
<message>
<source>Move entries to recycle bin?</source>
@@ -401,7 +469,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Different passwords supplied.</source>
<translation type="unfinished"/>
<translation>異なるパスワードが入力されました。</translation>
</message>
<message>
<source>New attribute</source>
@@ -431,11 +499,11 @@ Otherwise your changes are lost.</source>
</message>
<message numerus="yes">
<source>%n week(s)</source>
<translation><numerusform>%s週間()</numerusform></translation>
<translation><numerusform>%n週間</numerusform></translation>
</message>
<message numerus="yes">
<source>%n month(s)</source>
<translation><numerusform>%nヶ月()</numerusform></translation>
<translation><numerusform>%nヶ月</numerusform></translation>
</message>
<message>
<source>1 year</source>
@@ -485,7 +553,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Use custom Auto-Type sequence:</source>
<translation>使</translation>
<translation>カスタムの自動入力手順を使う:</translation>
</message>
<message>
<source>+</source>
@@ -535,7 +603,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Username:</source>
<translation></translation>
<translation>ユーザ名:</translation>
</message>
<message>
<source>Password:</source>
@@ -668,7 +736,7 @@ Otherwise your changes are lost.</source>
</message>
<message numerus="yes">
<source>Can&apos;t delete icon. Still used by %n item(s).</source>
<translation><numerusform>%s個のアイテム()使</numerusform></translation>
<translation><numerusform>%n個のアイテムから使われているので、アイコンを削除できません。</numerusform></translation>
</message>
</context>
<context>
@@ -694,7 +762,7 @@ Otherwise your changes are lost.</source>
<name>EntryAttributesModel</name>
<message>
<source>Name</source>
<translation type="unfinished"/>
<translation>名前</translation>
</message>
</context>
<context>
@@ -802,6 +870,16 @@ Otherwise your changes are lost.</source>
<source>Unable to calculate master key</source>
<translation>マスターキーを計算できません</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation> KeePass 1 (.kdb)
&gt; &apos;KeePass 1 &apos;
KeePassX 0.4 </translation>
</message>
</context>
<context>
<name>Main</name>
@@ -916,18 +994,10 @@ Otherwise your changes are lost.</source>
<source>Find</source>
<translation></translation>
</message>
<message>
<source>Username</source>
<translation></translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation></translation>
</message>
<message>
<source>Password</source>
<translation></translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation></translation>
@@ -970,12 +1040,48 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Toggle window</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Tools</source>
<translation></translation>
</message>
<message>
<source>Copy username</source>
<translation></translation>
</message>
<message>
<source>Copy password</source>
<translation></translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>CSVファイルへエクスポート</translation>
</message>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 </translation>
</message>
<message>
<source>All files</source>
<translation></translation>
</message>
<message>
<source>Save repaired database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation></translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1024,11 +1130,11 @@ Otherwise your changes are lost.</source>
<name>QCommandLineParser</name>
<message>
<source>Displays version information.</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Displays this help.</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Unknown option &apos;%1&apos;.</source>
@@ -1067,7 +1173,7 @@ Otherwise your changes are lost.</source>
<name>QSaveFile</name>
<message>
<source>Existing file %1 is not writable</source>
<translation> %1 </translation>
<translation> %1 </translation>
</message>
<message>
<source>Writing canceled by application</source>
@@ -1075,14 +1181,14 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Partial write. Partition full?</source>
<translation type="unfinished"/>
<translation></translation>
</message>
</context>
<context>
<name>QtIOCompressor</name>
<message>
<source>Internal zlib error when compressing: </source>
<translation>zlibエラーが発生しました</translation>
<translation>zlibエラーが発生しました: </translation>
</message>
<message>
<source>Error writing to underlying device: </source>
@@ -1098,7 +1204,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
<translation>zlibエラーが発生しました</translation>
<translation>zlibエラーが発生しました: </translation>
</message>
</context>
<context>
@@ -1178,7 +1284,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Use entry title to match windows for global auto-type</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Language</source>
@@ -1190,7 +1296,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>Hide window to system tray when minimized</source>
<translation type="unfinished"/>
<translation></translation>
</message>
<message>
<source>Remember last key files</source>
@@ -1246,11 +1352,7 @@ Otherwise your changes are lost.</source>
</message>
<message>
<source>path to a custom config file</source>
<translation type="unfinished"/>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation> (!)</translation>
<translation></translation>
</message>
<message>
<source>key file of the database</source>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX wordt verspreid onder de bepalingen van de GNU General Public License (GPL) versie 2 of (als u wenst) versie 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Revisie</translation>
</message>
<message>
<source>Using:</source>
<translation>Maakt gebruik van:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -109,6 +117,16 @@
<source>Different passwords supplied.</source>
<translation>Verschillende wachtwoorden opgegeven.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Niet gelukt het sleutelbestand in te stellen</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Niet gelukt %1 als sleutelbestand in te stellen:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -153,6 +171,43 @@
<translation>Kies sleutelbestand</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Database repareren</translation>
</message>
<message>
<source>Error</source>
<translation>Fout</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Niet mogelijk om het sleutelbestand te openen</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Database werd zonder problemen geopend. Niets te doen.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Niet mogelijk om de database te openen.</translation>
</message>
<message>
<source>Success</source>
<translation>Gelukt</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>De database is met succes gerepareerd
U kunt deze nu opslaan.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Niet mogelijk om de database te repareren.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>Sluiten?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; is in bewerkmodus.
Toch sluiten?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Wijzigingen opslaan?</translation>
@@ -270,6 +319,60 @@ Opslaan?</translation>
<source>locked</source>
<translation>vergrendeld</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>De database die u probeert te openen is vergrendeld door een andere instantie van KeePassX.
Wilt u toch doorgaan met openen? U kunt de database ook alleen-lezen openen.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Database vergrendelen</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Kan de database niet vergrendelen omdat u deze momenteel aan het bewerken bent.
Druk op annuleren om uw wijzigingen aan te passen of gooi de wijzigingen weg.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Deze database is nog niet opgeslagen.
U kunt de database opslaan of het vergrendelen annuleren.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Deze database is gewijzigd.
Wilt u de database opslaan voordat u deze vergrendelt?
Zo nee, dan gaan de wijzigingen verloren.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; is gewijzigd.
Wijzigingen ongedaan maken en doorgaan met sluiten?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Database exporteren naar CSV-bestand</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV-bestand</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Schrijven van het CSV-bestand mislukt.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>De database die u op probeert te slaan is vergrendeld door een andere instantie van KeePassX.
Wilt u toch doorgaan met opslaan?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -313,6 +416,14 @@ Opslaan?</translation>
<source>Current group</source>
<translation>Huidige groep</translation>
</message>
<message>
<source>Error</source>
<translation>Fout</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Niet mogelijk om hoofdsleutel te berekenen</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -425,6 +536,10 @@ Opslaan?</translation>
<source>Save</source>
<translation>Opslaan</translation>
</message>
<message>
<source>Open</source>
<translation>Open</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -576,6 +691,14 @@ Opslaan?</translation>
<source>Auto-type</source>
<translation>Auto-typen</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Gebruik standaard auto-typevolgorde van bovenliggende groep</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Stel standaard auto-typevolgorde in</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -724,6 +847,10 @@ Opslaan?</translation>
<source>Root</source>
<translation>Alles</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Niet mogelijk om hoofdsleutel te berekenen</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -739,6 +866,20 @@ Opslaan?</translation>
<source>Wrong key or database file is corrupt.</source>
<translation>Verkeerde sleutel of corrupte database.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Niet mogelijk om hoofdsleutel te berekenen</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Het gekozen bestand is een oude KeePass 1 database (.kdb).
U kunt het importeren door te klikken op Database &gt; &apos;KeePass 1 database importeren&apos;.
Deze actie is niet omkeerbaar. U kunt de geimporteerde database niet meer openen met KeePassX 0.4.</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -777,10 +918,6 @@ Opslaan?</translation>
<source>Groups</source>
<translation>Groepen</translation>
</message>
<message>
<source>Extras</source>
<translation>Extra&apos;s</translation>
</message>
<message>
<source>View</source>
<translation>Beeld</translation>
@@ -857,18 +994,10 @@ Opslaan?</translation>
<source>Find</source>
<translation>Vind</translation>
</message>
<message>
<source>Username</source>
<translation>Gebruikersnaam</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Kopieer gebruikersnaam naar klembord</translation>
</message>
<message>
<source>Password</source>
<translation>Wachtwoord</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Kopieer wachtwoord naar klembord</translation>
@@ -913,6 +1042,46 @@ Opslaan?</translation>
<source>Toggle window</source>
<translation>Wissel venster</translation>
</message>
<message>
<source>Tools</source>
<translation>Hulpmiddelen</translation>
</message>
<message>
<source>Copy username</source>
<translation>Gebruikersnaam kopieren</translation>
</message>
<message>
<source>Copy password</source>
<translation>Wachtwoord kopiëren</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Naar CSV-bestand exporteren</translation>
</message>
<message>
<source>Repair database</source>
<translation>Database repareren</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 Database</translation>
</message>
<message>
<source>All files</source>
<translation>Alle bestanden</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Gerepareerde database opslaan</translation>
</message>
<message>
<source>Error</source>
<translation>Fout</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Opslaan van de database is mislukt.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1093,10 +1262,6 @@ Opslaan?</translation>
<source>Open previous databases on startup</source>
<translation>Open vorige databases bij starten</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation>Markeer database als gewijzigd bij wijzigen van de status</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Automatisch opslaan bij afsluiten</translation>
@@ -1107,7 +1272,7 @@ Opslaan?</translation>
</message>
<message>
<source>Minimize when copying to clipboard</source>
<translation>Minimaliseer bij kopieeren naar klembord</translation>
<translation>Minimaliseer bij kopiëren naar klembord</translation>
</message>
<message>
<source>Use group icon on entry creation</source>
@@ -1133,6 +1298,10 @@ Opslaan?</translation>
<source>Hide window to system tray when minimized</source>
<translation>Bij minimaliseren enkel icoon in systray tonen</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Onthoud laatste sleutelbestanden</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1163,14 +1332,6 @@ Opslaan?</translation>
<source>Unlock database</source>
<translation>Database ontgrendelen</translation>
</message>
<message>
<source>Error</source>
<translation>Fout</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Verkeerd wachtwoord</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1193,10 +1354,6 @@ Opslaan?</translation>
<source>path to a custom config file</source>
<translation>pad naar een configuratiebestand</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>wachtwoord van de database (GEVAARLIJK!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>sleutelbestand van de database</translation>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX é distribuído sob os termos GNU de licença pública geral (GPL) versão 2 ou (á sua escolha) versão 3.</translation>
</message>
<message>
<source>Revision</source>
<translation type="unfinished"/>
</message>
<message>
<source>Using:</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>AutoType</name>
@@ -163,6 +171,42 @@
<translation>Seleccionar o ficheiro chave</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation type="unfinished"/>
</message>
<message>
<source>Error</source>
<translation type="unfinished"/>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation type="unfinished"/>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation type="unfinished"/>
</message>
<message>
<source>Unable to open the database.</source>
<translation type="unfinished"/>
</message>
<message>
<source>Success</source>
<translation type="unfinished"/>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation type="unfinished"/>
</message>
<message>
<source>Unable to repair the database.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -244,12 +288,6 @@
<source>Close?</source>
<translation>Fechar ?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; em modo de edição.
Fechar na mesma ?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Guardar alterações ?</translation>
@@ -310,6 +348,29 @@ Otherwise your changes are lost.</source>
Pretende guardar a base de dados antes de a trancar ?
Caso contrário as alterações serão perdidas.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>%1 está em modo de edição.
Fechar e Ignorar alterações ?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Exportar base de dados para ficheiro CSV</translation>
</message>
<message>
<source>CSV file</source>
<translation>Ficheiro CSV</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Falha na escrita do ficheiro CSV</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -806,6 +867,13 @@ Caso contrário as alterações serão perdidas.</translation>
<source>Unable to calculate master key</source>
<translation>Impossível calcular chave mestra:</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>Main</name>
@@ -920,18 +988,10 @@ Caso contrário as alterações serão perdidas.</translation>
<source>Find</source>
<translation>Encontrar</translation>
</message>
<message>
<source>Username</source>
<translation>Nome de utilizador</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Copiar nome de utilizador para inserção</translation>
</message>
<message>
<source>Password</source>
<translation>Senha</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Copiar senha para inserção</translation>
@@ -980,6 +1040,42 @@ Caso contrário as alterações serão perdidas.</translation>
<source>Tools</source>
<translation>Ferramentas</translation>
</message>
<message>
<source>Copy username</source>
<translation>Copiar nome de utilizador</translation>
</message>
<message>
<source>Copy password</source>
<translation>Copiar senha</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Exportar para ficheiro CSV</translation>
</message>
<message>
<source>Repair database</source>
<translation type="unfinished"/>
</message>
<message>
<source>KeePass 2 Database</source>
<translation type="unfinished"/>
</message>
<message>
<source>All files</source>
<translation type="unfinished"/>
</message>
<message>
<source>Save repaired database</source>
<translation type="unfinished"/>
</message>
<message>
<source>Error</source>
<translation type="unfinished"/>
</message>
<message>
<source>Writing the database failed.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1252,10 +1348,6 @@ Caso contrário as alterações serão perdidas.</translation>
<source>path to a custom config file</source>
<translation>caminho para um ficheiro de configuração personalizado</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>senha da base de dados (PERIGOSO !)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>ficheiro chave da base de dados</translation>

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX распространяется на условиях Стандартной общественной лицензии GNU (GPL) версии 2 или (на ваше усмотрение) версии 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Ревизия</translation>
</message>
<message>
<source>Using:</source>
<translation>С помощью:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -44,7 +52,7 @@
</message>
<message>
<source>Select entry to Auto-Type:</source>
<translation>Выберете запись для автоввода:</translation>
<translation>Выберите запись для автоввода:</translation>
</message>
</context>
<context>
@@ -103,12 +111,22 @@
</message>
<message>
<source>Do you really want to use an empty string as password?</source>
<translation>Вы действительно хотите использовать пустую строку как пароль?</translation>
<translation>Вы действительно хотите использовать в качестве пароля пустую строку?</translation>
</message>
<message>
<source>Different passwords supplied.</source>
<translation>Пароли не совпадают.</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Не удалось установить файл-ключ</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Не удалось установить %1 как файл-ключ:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -150,7 +168,44 @@
</message>
<message>
<source>Select key file</source>
<translation>Выберете файл-ключ</translation>
<translation>Выберите файл-ключ</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Восстановление хранилища</translation>
</message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Не могу открыть файл-ключ</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation type="unfinished"/>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Невозможно открыть хранилище.</translation>
</message>
<message>
<source>Success</source>
<translation>Успешно</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Хранилище было восстановлено.
Теперь Вы можете сохранить его.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Невозможно восстановить хранилище.</translation>
</message>
</context>
<context>
@@ -169,7 +224,7 @@
</message>
<message>
<source>Default username:</source>
<translation>Имя пользователя по-умолчанию:</translation>
<translation>Имя пользователя по умолчанию:</translation>
</message>
<message>
<source>Use recycle bin:</source>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>Закрыть?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>«%1» в режиме редактирования.
Всё равно закрыть?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Сохранить изменения?</translation>
@@ -268,14 +317,67 @@ Save changes?</source>
</message>
<message>
<source>locked</source>
<translation>заблокированно</translation>
<translation>заблокировано</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Хранилище, которое Вы хотите открыть, заблокировано другой запущенной копией KeePassX. Всё равно открыть? В качестве альтернативы хранилище будет открыто в режиме для чтения.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Заблокировать хранилище</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Невозможно заблокировать базу данных, так как вы в настоящее время редактируете её.
Пожалуйста нажмите Отмена, чтобы завершить свои изменения или отклонить их.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Эта база данных никогда не была сохранена.
Вы можете сохранить базу данных или остановить её заблокированной.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Хранилище было изменено.
Вы хотите сохранить его перед тем, как заблокировать?
В противном случае все изменения будут потеряны.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; в режиме редактирования.
Отменить изменения и всё равно закрыть?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Экспортировать хранилище в файл CSV</translation>
</message>
<message>
<source>CSV file</source>
<translation>Файл CSV</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Не удалось записать CSV файл.</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Данное хранилище заблокировано другой запущенной копией KeePassX.
Вы уверены, что хотите продолжить сохранение?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
<message>
<source>Change master key</source>
<translation>Сменить мастер-пароль</translation>
<translation>Изменить мастер-пароль</translation>
</message>
<message>
<source>Delete entry?</source>
@@ -313,6 +415,14 @@ Save changes?</source>
<source>Current group</source>
<translation>Текущая группа</translation>
</message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Невозможно вычислить мастер-пароль</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -326,7 +436,7 @@ Save changes?</source>
</message>
<message>
<source>Icon</source>
<translation>Иконка</translation>
<translation>Значок</translation>
</message>
<message>
<source>Auto-Type</source>
@@ -425,6 +535,10 @@ Save changes?</source>
<source>Save</source>
<translation>Сохранить</translation>
</message>
<message>
<source>Open</source>
<translation>Открыть</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -500,7 +614,7 @@ Save changes?</source>
</message>
<message>
<source>Gen.</source>
<translation type="unfinished"/>
<translation>Генеральный.</translation>
</message>
<message>
<source>URL:</source>
@@ -527,7 +641,7 @@ Save changes?</source>
</message>
<message>
<source>Icon</source>
<translation>Иконка</translation>
<translation>Значок</translation>
</message>
<message>
<source>Properties</source>
@@ -574,26 +688,34 @@ Save changes?</source>
</message>
<message>
<source>Auto-type</source>
<translation>автоввод</translation>
<translation>Автоввод</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Используйте стандартный автоввод из последовательности родительской группы</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Последовательность автоввода указать по умолчанию</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
<message>
<source>Use default icon</source>
<translation>Использовать стандартную иконку</translation>
<translation>Использовать стандартный значок</translation>
</message>
<message>
<source>Use custom icon</source>
<translation>Использовать свою иконку</translation>
<translation>Использовать свой значок</translation>
</message>
<message>
<source>Add custom icon</source>
<translation>Добавить свою иконку</translation>
<translation>Добавить свой значок</translation>
</message>
<message>
<source>Delete custom icon</source>
<translation>Удалить свою иконку</translation>
<translation>Удалить свой значок</translation>
</message>
<message>
<source>Images</source>
@@ -609,11 +731,11 @@ Save changes?</source>
</message>
<message>
<source>Can&apos;t delete icon!</source>
<translation>Не могу удалить иконку!</translation>
<translation>Не могу удалить значок!</translation>
</message>
<message numerus="yes">
<source>Can&apos;t delete icon. Still used by %n item(s).</source>
<translation><numerusform>Не могу удалить иконку, %n запись всё ещё использует её.</numerusform><numerusform>Не могу удалить иконку, %n записи всё ещё использует её.</numerusform><numerusform>Не могу удалить иконку, %n записей всё ещё использует её.</numerusform><numerusform>Не могу удалить иконку, %n записей всё ещё использует её.</numerusform></translation>
<translation><numerusform>Не могу удалить иконку, %n запись всё ещё использует её.</numerusform><numerusform>Не могу удалить иконку, %n записи всё ещё использует её.</numerusform><numerusform>Не могу удалить иконку, %n записей всё ещё использует её.</numerusform><numerusform>Не могу удалить значок, %n записей всё ещё использует его.</numerusform></translation>
</message>
</context>
<context>
@@ -724,6 +846,10 @@ Save changes?</source>
<source>Root</source>
<translation>Корень</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Невозможно вычислить мастер-пароль</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -739,6 +865,20 @@ Save changes?</source>
<source>Wrong key or database file is corrupt.</source>
<translation>Неверный ключ или файл хранилища повреждён.</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Невозможно вычислить мастер-пароль</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Выбранный файл от старой KeePass 1 базы данных (.kdb).
Вы можете импортировать его, нажав на База Данных &gt; &apos;Импорт KeePass 1 базы данных&apos;.
Это одностороннее перемещение. Вы не сможете открыть импортированный базу данных на старой версии KeePassX 0,4.</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -777,10 +917,6 @@ Save changes?</source>
<source>Groups</source>
<translation>Группы</translation>
</message>
<message>
<source>Extras</source>
<translation>Дополнительно</translation>
</message>
<message>
<source>View</source>
<translation>Вид</translation>
@@ -857,18 +993,10 @@ Save changes?</source>
<source>Find</source>
<translation>Найти</translation>
</message>
<message>
<source>Username</source>
<translation>Имя пользователя</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Скопировать имя пользователя в буфер обмена</translation>
</message>
<message>
<source>Password</source>
<translation>Пароль</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Скопировать пароль в буфер обмена</translation>
@@ -913,6 +1041,46 @@ Save changes?</source>
<source>Toggle window</source>
<translation>Переключить окно</translation>
</message>
<message>
<source>Tools</source>
<translation>Инструменты</translation>
</message>
<message>
<source>Copy username</source>
<translation>Скопировать имя пользователя</translation>
</message>
<message>
<source>Copy password</source>
<translation>Скопировать пароль</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Экспортировать в файл CSV</translation>
</message>
<message>
<source>Repair database</source>
<translation>Восстановление хранилища</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation type="unfinished"/>
</message>
<message>
<source>All files</source>
<translation>Все файлы</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Сохранить восстановленное хранилище</translation>
</message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation type="unfinished"/>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -950,7 +1118,7 @@ Save changes?</source>
</message>
<message>
<source>Ensure that the password contains characters from every group</source>
<translation>Пожалуйста, пусть пароль будет содержать символы всех видов</translation>
<translation>Убедитесь, что пароль содержит символы всех видов</translation>
</message>
<message>
<source>Accept</source>
@@ -1023,19 +1191,19 @@ Save changes?</source>
</message>
<message>
<source>Error writing to underlying device: </source>
<translation>Ошибка записи на нижлежащее устройство:</translation>
<translation>Ошибка записи на низлежащее устройство:</translation>
</message>
<message>
<source>Error opening underlying device: </source>
<translation>Ошибка открытия нижлежащего устройства:</translation>
<translation>Ошибка открытия низлежащего устройства:</translation>
</message>
<message>
<source>Error reading data from underlying device: </source>
<translation>Ошибка чтения с нижлежащего устройства:</translation>
<translation>Ошибка чтения с низлежащего устройства:</translation>
</message>
<message>
<source>Internal zlib error when decompressing: </source>
<translation>Внутренняя ошибка zlib при расжатии:</translation>
<translation>Внутренняя ошибка zlib при распаковке:</translation>
</message>
</context>
<context>
@@ -1093,10 +1261,6 @@ Save changes?</source>
<source>Open previous databases on startup</source>
<translation>Открывать предыдущее хранилище при запуске</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation type="unfinished"/>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Автоматически сохранять при выходе</translation>
@@ -1133,12 +1297,16 @@ Save changes?</source>
<source>Hide window to system tray when minimized</source>
<translation>При сворачивании прятать окно в область системных уведомлений</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Запоминать последние файл-ключи</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
<message>
<source>Clear clipboard after</source>
<translation>Потом почтистить буфер обмена</translation>
<translation>Очищать буфер обмена через</translation>
</message>
<message>
<source> sec</source>
@@ -1150,7 +1318,7 @@ Save changes?</source>
</message>
<message>
<source>Show passwords in cleartext by default</source>
<translation>Показывать пароль в открытую по-умолчанию</translation>
<translation>По умолчанию показывать пароль в открытую</translation>
</message>
<message>
<source>Always ask before performing auto-type</source>
@@ -1163,14 +1331,6 @@ Save changes?</source>
<source>Unlock database</source>
<translation>Разблокировать хранилище</translation>
</message>
<message>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Неверный ключ.</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1193,10 +1353,6 @@ Save changes?</source>
<source>path to a custom config file</source>
<translation>путь к своему файлу настроек</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>пароль от хранилища (ОПАСНО!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>файл-ключ хранилища</translation>

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>Keepassx distribueras enligt villkoren i GNU General Public License (GPL) version 2 eller (om du vill) version 3.</translation>
</message>
<message>
<source>Revision</source>
<translation>Revision</translation>
</message>
<message>
<source>Using:</source>
<translation>Använder:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -109,6 +117,16 @@
<source>Different passwords supplied.</source>
<translation>Olika lösenord angivna</translation>
</message>
<message>
<source>Failed to set key file</source>
<translation>Kunde inte sätta nyckel-fil</translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation>Kunde inte sätta %1 som nyckel-fil:
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -153,6 +171,43 @@
<translation>Välj nyckel-fil</translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation>Laga databasen</translation>
</message>
<message>
<source>Error</source>
<translation>Fel</translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation>Kan inte öppna nyckelfilen</translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation>Databas öppnades fint. Inget att göra.</translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation>Misslyckades att öppna databasen.</translation>
</message>
<message>
<source>Success</source>
<translation>Succé</translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>Databasens reparation har varit lyckad.
Du kan nu spara den.</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation>Misslyckades med att laga databasen.</translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -234,12 +289,6 @@
<source>Close?</source>
<translation>Stäng?</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; är i redigerar-läge.
Stäng ändå?</translation>
</message>
<message>
<source>Save changes?</source>
<translation>Spara ändringar?</translation>
@@ -270,6 +319,60 @@ Spara ändringarna?</translation>
<source>locked</source>
<translation>låst</translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation>Databasen som du försöker öppna är låst av en annan instans av KeePassX.
Vill du öppna den ändå? Databasen kommer att öppnas skrivskyddad.</translation>
</message>
<message>
<source>Lock database</source>
<translation>Lås databasen</translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>Kan inte låsa databasen eftersom du håller på att redigera den.
Tryck avbryt för att ansluta dina ändringar alternativt kasta dem.</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>Databasen has aldrig sparats.
Spara databasen eller sluta lås den.</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>Databasen har ändrats.
Vill du spara databasen innen du låser den?
I annat fall försvinner ändringarna.</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; är i redigeringsläge.
Kasta ändringarna och stäng endå?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>Exportera databasen till en CSV-fil</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV-fil</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>Kunde inte skriva till CSV-filen</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>Databasen du försöker spara som är låst av en annan instans av KeePassX.
Vill du spara endå?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -313,6 +416,14 @@ Spara ändringarna?</translation>
<source>Current group</source>
<translation>Nuvarande grupp</translation>
</message>
<message>
<source>Error</source>
<translation>Fel</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kunde inte räkna nu master-nyckeln</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -425,6 +536,10 @@ Spara ändringarna?</translation>
<source>Save</source>
<translation>Spara</translation>
</message>
<message>
<source>Open</source>
<translation>Öppna</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -576,6 +691,14 @@ Spara ändringarna?</translation>
<source>Auto-type</source>
<translation>Auto-skriv</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>Använd standard auto-skriv sekvensen från föräldergruppen</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>Ange standard auto-skriv sekvens</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -724,6 +847,10 @@ Spara ändringarna?</translation>
<source>Root</source>
<translation>Root</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kunde inte räkna nu master-nyckeln</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -739,6 +866,20 @@ Spara ändringarna?</translation>
<source>Wrong key or database file is corrupt.</source>
<translation>Fel lösenord eller korrupt databas-fil</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>Kunde inte räkna nu master-nyckeln</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation>Den valda filen är en gammal KeePass 1 databas (.kdb)
Du kan importera den genom att klicka Databas &gt; Importera KeePass 1 databas.
Detta är en envägsmigration. Du kan inte spara en databas som KeePass1 databas. Det som används i KeePassX 0.4.</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -759,7 +900,7 @@ Spara ändringarna?</translation>
</message>
<message>
<source>Recent databases</source>
<translation>Senast använda databser</translation>
<translation>Senast använda databaser</translation>
</message>
<message>
<source>Help</source>
@@ -777,10 +918,6 @@ Spara ändringarna?</translation>
<source>Groups</source>
<translation>Grupper</translation>
</message>
<message>
<source>Extras</source>
<translation>Extra</translation>
</message>
<message>
<source>View</source>
<translation>Vy</translation>
@@ -857,18 +994,10 @@ Spara ändringarna?</translation>
<source>Find</source>
<translation>Sök</translation>
</message>
<message>
<source>Username</source>
<translation>Användarnamn</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>Kopiera användarnamn</translation>
</message>
<message>
<source>Password</source>
<translation>Lösenord</translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>Kopiera lösenord</translation>
@@ -913,6 +1042,46 @@ Spara ändringarna?</translation>
<source>Toggle window</source>
<translation>Visa/dölj fönster</translation>
</message>
<message>
<source>Tools</source>
<translation>Verktyg</translation>
</message>
<message>
<source>Copy username</source>
<translation>Kopiera användarnamn</translation>
</message>
<message>
<source>Copy password</source>
<translation>Kopiera lösenord</translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>Exportera till CSV-fil</translation>
</message>
<message>
<source>Repair database</source>
<translation>Laga databasen</translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 databas</translation>
</message>
<message>
<source>All files</source>
<translation>Alla filer</translation>
</message>
<message>
<source>Save repaired database</source>
<translation>Spara lagad databas</translation>
</message>
<message>
<source>Error</source>
<translation>Fel</translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation>Misslyckades med att skriva till databasen.</translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1091,15 +1260,11 @@ Spara ändringarna?</translation>
</message>
<message>
<source>Open previous databases on startup</source>
<translation>Öppna senaste databasen är programmet startar</translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation>Markera som ändrad när utökat läge ändras</translation>
<translation>Öppna senaste databasen r programmet startar</translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation>Spara automatiskt är applikationen anslutas</translation>
<translation>Spara automatiskt r applikationen anslutas</translation>
</message>
<message>
<source>Automatically save after every change</source>
@@ -1133,6 +1298,10 @@ Spara ändringarna?</translation>
<source>Hide window to system tray when minimized</source>
<translation>Vid minimering, minimera fönstret till systemfältet</translation>
</message>
<message>
<source>Remember last key files</source>
<translation>Komihåg senaste nyckel-filen</translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1163,14 +1332,6 @@ Spara ändringarna?</translation>
<source>Unlock database</source>
<translation>Lås upp databas</translation>
</message>
<message>
<source>Error</source>
<translation>Fel</translation>
</message>
<message>
<source>Wrong key.</source>
<translation>Fel lösenord</translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1193,10 +1354,6 @@ Spara ändringarna?</translation>
<source>path to a custom config file</source>
<translation>Sökväg till egen konfigurations-fil</translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>lösenord för databasen (FARLIGT!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation>nyckel-fil för databas</translation>

File diff suppressed because it is too large Load Diff

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX 使 2 GNU (GPL)( 3 ).</translation>
</message>
<message>
<source>Revision</source>
<translation></translation>
</message>
<message>
<source>Using:</source>
<translation>使:</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -163,6 +171,43 @@
<translation></translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation></translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation></translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation></translation>
</message>
<message>
<source>Success</source>
<translation></translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>
</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation></translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -244,12 +289,6 @@
<source>Close?</source>
<translation></translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation> &quot;%1&quot;
</translation>
</message>
<message>
<source>Save changes?</source>
<translation></translation>
@@ -310,6 +349,30 @@ Otherwise your changes are lost.</source>
你想在锁住它以前保存修改吗?
否则修改将会丢失。</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>正在编辑 &quot;%1&quot; 。
仍然要放弃修改并且关闭吗?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>把数据库导出为CSV格式文件</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV格式文件</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>写入CSV格式文件失败</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>你要保存的数据库已被另一个KeePassX锁住。
你仍然要保存吗?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -751,7 +814,7 @@ Otherwise your changes are lost.</source>
<name>KeePass1OpenWidget</name>
<message>
<source>Import KeePass1 database</source>
<translation>KeePass 1 </translation>
<translation>导入 KeePass 1 数据库</translation>
</message>
<message>
<source>Error</source>
@@ -807,6 +870,15 @@ Otherwise your changes are lost.</source>
<source>Unable to calculate master key</source>
<translation>无法计算主密码</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation> KeePass 1 .kdb
&gt; &apos;KeePass 1
KeePassX 0.4</translation>
</message>
</context>
<context>
<name>Main</name>
@@ -921,18 +993,10 @@ Otherwise your changes are lost.</source>
<source>Find</source>
<translation></translation>
</message>
<message>
<source>Username</source>
<translation></translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation></translation>
</message>
<message>
<source>Password</source>
<translation></translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation></translation>
@@ -981,6 +1045,42 @@ Otherwise your changes are lost.</source>
<source>Tools</source>
<translation></translation>
</message>
<message>
<source>Copy username</source>
<translation></translation>
</message>
<message>
<source>Copy password</source>
<translation></translation>
</message>
<message>
<source>Export to CSV file</source>
<translation>CSV格式文件</translation>
</message>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 </translation>
</message>
<message>
<source>All files</source>
<translation></translation>
</message>
<message>
<source>Save repaired database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation></translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1253,10 +1353,6 @@ Otherwise your changes are lost.</source>
<source>path to a custom config file</source>
<translation></translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>(!)</translation>
</message>
<message>
<source>key file of the database</source>
<translation></translation>

View File

@@ -9,6 +9,14 @@
<source>KeePassX is distributed under the term of the GNU General Public License (GPL) version 2 or (at your option) version 3.</source>
<translation>KeePassX 使 2 GNU ( 3 )</translation>
</message>
<message>
<source>Revision</source>
<translation></translation>
</message>
<message>
<source>Using:</source>
<translation>使</translation>
</message>
</context>
<context>
<name>AutoType</name>
@@ -109,6 +117,16 @@
<source>Different passwords supplied.</source>
<translation></translation>
</message>
<message>
<source>Failed to set key file</source>
<translation></translation>
</message>
<message>
<source>Failed to set %1 as the Key file:
%2</source>
<translation> %1
%2</translation>
</message>
</context>
<context>
<name>DatabaseOpenWidget</name>
@@ -153,6 +171,43 @@
<translation></translation>
</message>
</context>
<context>
<name>DatabaseRepairWidget</name>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Can&apos;t open key file</source>
<translation></translation>
</message>
<message>
<source>Database opened fine. Nothing to do.</source>
<translation></translation>
</message>
<message>
<source>Unable to open the database.</source>
<translation></translation>
</message>
<message>
<source>Success</source>
<translation></translation>
</message>
<message>
<source>The database has been successfully repaired
You can now save it.</source>
<translation>
</translation>
</message>
<message>
<source>Unable to repair the database.</source>
<translation></translation>
</message>
</context>
<context>
<name>DatabaseSettingsWidget</name>
<message>
@@ -234,11 +289,6 @@
<source>Close?</source>
<translation></translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Close anyway?</source>
<translation>&quot;%1&quot; </translation>
</message>
<message>
<source>Save changes?</source>
<translation></translation>
@@ -268,6 +318,60 @@ Save changes?</source>
<source>locked</source>
<translation></translation>
</message>
<message>
<source>The database you are trying to open is locked by another instance of KeePassX.
Do you want to open it anyway? Alternatively the database is opened read-only.</source>
<translation> KeePassX
</translation>
</message>
<message>
<source>Lock database</source>
<translation></translation>
</message>
<message>
<source>Can't lock the database as you are currently editing it.
Please press cancel to finish your changes or discard them.</source>
<translation>無法鎖定資料庫,因為目前你正在編輯它
請按下取消完成修改或放棄</translation>
</message>
<message>
<source>This database has never been saved.
You can save the database or stop locking it.</source>
<translation>這個資料庫尚未被儲存
你能儲存資料庫或不再鎖定它</translation>
</message>
<message>
<source>This database has been modified.
Do you want to save the database before locking it?
Otherwise your changes are lost.</source>
<translation>這個資料庫已經被修改
想要在鎖定之前,儲存資料庫嗎?
否則,這次修改將會遺失</translation>
</message>
<message>
<source>&quot;%1&quot; is in edit mode.
Discard changes and close anyway?</source>
<translation>&quot;%1&quot; 正在編輯模式。
是否要放棄編輯及關閉?</translation>
</message>
<message>
<source>Export database to CSV file</source>
<translation>將資料庫輸出成 CSV 檔案</translation>
</message>
<message>
<source>CSV file</source>
<translation>CSV 檔案</translation>
</message>
<message>
<source>Writing the CSV file failed.</source>
<translation>寫入 CSV 檔案失敗</translation>
</message>
<message>
<source>The database you are trying to save as is locked by another instance of KeePassX.
Do you want to save it anyway?</source>
<translation>你嘗試要打開的資料庫已經被另一個正在執行的 KeePassX 鎖定
還要儲存嗎?</translation>
</message>
</context>
<context>
<name>DatabaseWidget</name>
@@ -311,6 +415,14 @@ Save changes?</source>
<source>Current group</source>
<translation>目前的群組</translation>
</message>
<message>
<source>Error</source>
<translation>錯誤</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>無法計算主金鑰</translation>
</message>
</context>
<context>
<name>EditEntryWidget</name>
@@ -423,6 +535,10 @@ Save changes?</source>
<source>Save</source>
<translation>儲存</translation>
</message>
<message>
<source>Open</source>
<translation>打開</translation>
</message>
</context>
<context>
<name>EditEntryWidgetAutoType</name>
@@ -574,6 +690,14 @@ Save changes?</source>
<source>Auto-type</source>
<translation>自動輸入</translation>
</message>
<message>
<source>Use default auto-type sequence of parent group</source>
<translation>使用預設的父群組自動輸入序列</translation>
</message>
<message>
<source>Set default auto-type sequence</source>
<translation>設定預設自動輸入序列</translation>
</message>
</context>
<context>
<name>EditWidgetIcons</name>
@@ -722,6 +846,10 @@ Save changes?</source>
<source>Root</source>
<translation>根</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>無法計算主金鑰</translation>
</message>
</context>
<context>
<name>KeePass2Reader</name>
@@ -737,6 +865,21 @@ Save changes?</source>
<source>Wrong key or database file is corrupt.</source>
<translation>無法的金鑰或資料庫損壞</translation>
</message>
<message>
<source>Unable to calculate master key</source>
<translation>無法計算主金鑰</translation>
</message>
<message>
<source>The selected file is an old KeePass 1 database (.kdb).
You can import it by clicking on Database &gt; 'Import KeePass 1 database'.
This is a one-way migration. You won&apos;t be able to open the imported database with the old KeePassX 0.4 version.</source>
<translation> KeePass 1 (.kdb)
&gt; KeePass 1
KeePassX 0.4 </translation>
</message>
</context>
<context>
<name>Main</name>
@@ -775,10 +918,6 @@ Save changes?</source>
<source>Groups</source>
<translation></translation>
</message>
<message>
<source>Extras</source>
<translation></translation>
</message>
<message>
<source>View</source>
<translation></translation>
@@ -855,18 +994,10 @@ Save changes?</source>
<source>Find</source>
<translation></translation>
</message>
<message>
<source>Username</source>
<translation>使</translation>
</message>
<message>
<source>Copy username to clipboard</source>
<translation>使簿</translation>
</message>
<message>
<source>Password</source>
<translation></translation>
</message>
<message>
<source>Copy password to clipboard</source>
<translation>簿</translation>
@@ -911,6 +1042,46 @@ Save changes?</source>
<source>Toggle window</source>
<translation></translation>
</message>
<message>
<source>Tools</source>
<translation></translation>
</message>
<message>
<source>Copy username</source>
<translation>使</translation>
</message>
<message>
<source>Copy password</source>
<translation></translation>
</message>
<message>
<source>Export to CSV file</source>
<translation> CSV </translation>
</message>
<message>
<source>Repair database</source>
<translation></translation>
</message>
<message>
<source>KeePass 2 Database</source>
<translation>KeePass 2 </translation>
</message>
<message>
<source>All files</source>
<translation></translation>
</message>
<message>
<source>Save repaired database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Writing the database failed.</source>
<translation></translation>
</message>
</context>
<context>
<name>PasswordGeneratorWidget</name>
@@ -1091,10 +1262,6 @@ Save changes?</source>
<source>Open previous databases on startup</source>
<translation></translation>
</message>
<message>
<source>Mark as modified on expanded state changes</source>
<translation></translation>
</message>
<message>
<source>Automatically save on exit</source>
<translation></translation>
@@ -1131,6 +1298,10 @@ Save changes?</source>
<source>Hide window to system tray when minimized</source>
<translation> </translation>
</message>
<message>
<source>Remember last key files</source>
<translation></translation>
</message>
</context>
<context>
<name>SettingsWidgetSecurity</name>
@@ -1161,14 +1332,6 @@ Save changes?</source>
<source>Unlock database</source>
<translation></translation>
</message>
<message>
<source>Error</source>
<translation></translation>
</message>
<message>
<source>Wrong key.</source>
<translation></translation>
</message>
</context>
<context>
<name>WelcomeWidget</name>
@@ -1191,10 +1354,6 @@ Save changes?</source>
<source>path to a custom config file</source>
<translation></translation>
</message>
<message>
<source>password of the database (DANGEROUS!)</source>
<translation>()</translation>
</message>
<message>
<source>key file of the database</source>
<translation></translation>

View File

@@ -54,9 +54,6 @@ set(keepassx_SOURCES
core/ListDeleter.h
core/Metadata.cpp
core/PasswordGenerator.cpp
core/qlockfile.cpp
core/qsavefile.cpp
core/qsavefile_p.h
core/SignalMultiplexer.cpp
core/TimeDelta.cpp
core/TimeInfo.cpp
@@ -64,8 +61,6 @@ set(keepassx_SOURCES
core/Tools.cpp
core/Translator.cpp
core/Uuid.cpp
core/qcommandlineoption.cpp
core/qcommandlineparser.cpp
crypto/Crypto.cpp
crypto/CryptoHash.cpp
crypto/Random.cpp
@@ -78,6 +73,7 @@ set(keepassx_SOURCES
format/KeePass2.h
format/KeePass2RandomStream.cpp
format/KeePass2Reader.cpp
format/KeePass2Repair.cpp
format/KeePass2Writer.cpp
format/KeePass2XmlReader.cpp
format/KeePass2XmlWriter.cpp
@@ -86,6 +82,7 @@ set(keepassx_SOURCES
gui/ChangeMasterKeyWidget.cpp
gui/Clipboard.cpp
gui/DatabaseOpenWidget.cpp
gui/DatabaseRepairWidget.cpp
gui/DatabaseSettingsWidget.cpp
gui/DatabaseTabWidget.cpp
gui/DatabaseWidget.cpp
@@ -119,6 +116,14 @@ set(keepassx_SOURCES
gui/group/EditGroupWidget.cpp
gui/group/GroupModel.cpp
gui/group/GroupView.cpp
http/AccessControlDialog.cpp
http/EntryConfig.cpp
http/HttpPasswordGeneratorWidget.cpp
http/HttpSettings.cpp
http/OptionDialog.cpp
http/Protocol.cpp
http/Server.cpp
http/Service.cpp
keys/CompositeKey.cpp
keys/CompositeKey_p.h
keys/FileKey.cpp
@@ -131,93 +136,10 @@ set(keepassx_SOURCES
streams/SymmetricCipherStream.cpp
)
if(NOT GCRYPT_HAS_SALSA20)
set(keepassx_SOURCES
${keepassx_SOURCES}
crypto/salsa20/ecrypt-config.h
crypto/salsa20/ecrypt-machine.h
crypto/salsa20/ecrypt-portable.h
crypto/salsa20/ecrypt-sync.h
crypto/salsa20/salsa20.c
crypto/SymmetricCipherSalsa20.cpp
)
endif()
if(UNIX)
set(keepassx_SOURCES
${keepassx_SOURCES}
core/qlockfile_unix.cpp
)
elseif(MINGW)
set(keepassx_SOURCES
${keepassx_SOURCES}
core/qlockfile_win.cpp
)
endif()
set(keepassx_SOURCES_MAINEXE
main.cpp
)
set(keepassx_MOC
autotype/AutoType.h
autotype/AutoTypeSelectDialog.h
autotype/AutoTypeSelectView.h
autotype/ShortcutWidget.h
autotype/WindowSelectComboBox.h
core/AutoTypeAssociations.h
core/Config.h
core/Database.h
core/Entry.h
core/EntryAttachments.h
core/EntryAttributes.h
core/Group.h
core/InactivityTimer.h
core/Metadata.h
core/qsavefile.h
gui/AboutDialog.h
gui/Application.h
gui/ChangeMasterKeyWidget.h
gui/Clipboard.h
gui/DatabaseOpenWidget.h
gui/DatabaseSettingsWidget.h
gui/DatabaseTabWidget.h
gui/DatabaseWidget.h
gui/DatabaseWidgetStateSync.h
gui/DialogyWidget.h
gui/DragTabBar.h
gui/EditWidget.h
gui/EditWidgetIcons.h
gui/EditWidgetProperties.h
gui/IconModels.h
gui/KeePass1OpenWidget.h
gui/LineEdit.h
gui/MainWindow.h
gui/PasswordEdit.h
gui/PasswordGeneratorWidget.h
gui/PasswordComboBox.h
gui/SettingsWidget.h
gui/SortFilterHideProxyModel.h
gui/UnlockDatabaseWidget.h
gui/WelcomeWidget.h
gui/entry/AutoTypeAssociationsModel.h
gui/entry/EditEntryWidget.h
gui/entry/EntryAttachmentsModel.h
gui/entry/EntryAttributesModel.h
gui/entry/EntryHistoryModel.h
gui/entry/EntryModel.h
gui/entry/EntryView.h
gui/group/EditGroupWidget.h
gui/group/GroupModel.h
gui/group/GroupView.h
keys/CompositeKey_p.h
streams/HashedBlockStream.h
streams/LayeredStream.h
streams/qtiocompressor.h
streams/StoreDataStream.h
streams/SymmetricCipherStream.h
)
set(keepassx_FORMS
gui/AboutDialog.ui
gui/ChangeMasterKeyWidget.ui
@@ -237,6 +159,9 @@ set(keepassx_FORMS
gui/entry/EditEntryWidgetHistory.ui
gui/entry/EditEntryWidgetMain.ui
gui/group/EditGroupWidgetMain.ui
http/AccessControlDialog.ui
http/HttpPasswordGeneratorWidget.ui
http/OptionDialog.ui
)
if(MINGW)
@@ -245,17 +170,20 @@ if(MINGW)
${CMAKE_SOURCE_DIR}/share/windows/icon.rc)
endif()
qt4_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
qt4_wrap_cpp(keepassx_SOURCES ${keepassx_MOC})
qt5_wrap_ui(keepassx_SOURCES ${keepassx_FORMS})
add_library(keepassx_core STATIC ${keepassx_SOURCES})
set_target_properties(keepassx_core PROPERTIES COMPILE_DEFINITIONS KEEPASSX_BUILDING_CORE)
target_link_libraries(keepassx_core Qt5::Core Qt5::Concurrent Qt5::Widgets Qt5::Network)
add_executable(${PROGNAME} WIN32 MACOSX_BUNDLE ${keepassx_SOURCES_MAINEXE})
target_link_libraries(${PROGNAME}
keepassx_core
${QT_QTCORE_LIBRARY}
${QT_QTGUI_LIBRARY}
${MHD_LIBRARIES}
Qt5::Core
Qt5::Concurrent
Qt5::Widgets
Qt5::Network
${GCRYPT_LIBRARIES}
${ZLIB_LIBRARIES})
@@ -273,7 +201,7 @@ install(TARGETS ${PROGNAME}
add_subdirectory(autotype)
if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
if(APPLE)
if(QT_MAC_USE_COCOA AND EXISTS "${QT_LIBRARY_DIR}/Resources/qt_menu.nib")
install(DIRECTORY "${QT_LIBRARY_DIR}/Resources/qt_menu.nib"
DESTINATION "${DATA_INSTALL_DIR}")
@@ -291,7 +219,7 @@ if(APPLE AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
install_qt4_executable(${PROGNAME}.app "qjpeg;qgif;qico;qtaccessiblewidgets")
endif()
if(MINGW AND NOT (${CMAKE_VERSION} VERSION_LESS 2.8.8))
if(MINGW )
set(CPACK_GENERATOR "ZIP")
set(CPACK_STRIP_FILES ON)
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSX_VERSION_NUM}")

View File

@@ -32,7 +32,7 @@
#include "core/Tools.h"
#include "gui/MessageBox.h"
AutoType* AutoType::m_instance = Q_NULLPTR;
AutoType* AutoType::m_instance = nullptr;
AutoType::AutoType(QObject* parent, bool test)
: QObject(parent)
@@ -40,8 +40,8 @@ AutoType::AutoType(QObject* parent, bool test)
, m_currentGlobalKey(static_cast<Qt::Key>(0))
, m_currentGlobalModifiers(0)
, m_pluginLoader(new QPluginLoader(this))
, m_plugin(Q_NULLPTR)
, m_executor(Q_NULLPTR)
, m_plugin(nullptr)
, m_executor(nullptr)
, m_windowFromGlobal(0)
{
// prevent crash when the plugin has unresolved symbols
@@ -49,7 +49,7 @@ AutoType::AutoType(QObject* parent, bool test)
QString pluginName = "keepassx-autotype-";
if (!test) {
pluginName += Tools::platform();
pluginName += QApplication::platformName();
}
else {
pluginName += "test";
@@ -68,7 +68,7 @@ AutoType::~AutoType()
{
if (m_executor) {
delete m_executor;
m_executor = Q_NULLPTR;
m_executor = nullptr;
}
}
@@ -79,9 +79,16 @@ void AutoType::loadPlugin(const QString& pluginPath)
QObject* pluginInstance = m_pluginLoader->instance();
if (pluginInstance) {
m_plugin = qobject_cast<AutoTypePlatformInterface*>(pluginInstance);
m_executor = nullptr;
if (m_plugin) {
m_executor = m_plugin->createExecutor();
connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered()));
if (m_plugin->isAvailable()) {
m_executor = m_plugin->createExecutor();
connect(pluginInstance, SIGNAL(globalShortcutTriggered()), SIGNAL(globalShortcutTriggered()));
}
else {
unloadPlugin();
}
}
}
@@ -150,7 +157,7 @@ void AutoType::performAutoType(const Entry* entry, QWidget* hideWindow, const QS
QCoreApplication::processEvents(QEventLoop::AllEvents, 10);
Q_FOREACH (AutoTypeAction* action, actions) {
for (AutoTypeAction* action : asConst(actions)) {
if (m_plugin->activeWindow() != window) {
qWarning("Active window changed, interrupting auto-type.");
break;
@@ -180,8 +187,9 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
QList<Entry*> entryList;
QHash<Entry*, QString> sequenceHash;
Q_FOREACH (Database* db, dbList) {
Q_FOREACH (Entry* entry, db->rootGroup()->entriesRecursive()) {
for (Database* db : dbList) {
const QList<Entry*> dbEntries = db->rootGroup()->entriesRecursive();
for (Entry* entry : dbEntries) {
QString sequence = autoTypeSequence(entry, windowTitle);
if (!sequence.isEmpty()) {
entryList << entry;
@@ -195,11 +203,11 @@ void AutoType::performGlobalAutoType(const QList<Database*>& dbList)
QString message = tr("Couldn't find an entry that matches the window title:");
message.append("\n\n");
message.append(windowTitle);
MessageBox::information(Q_NULLPTR, tr("Auto-Type - KeePassX"), message);
MessageBox::information(nullptr, tr("Auto-Type - KeePassX"), message);
}
else if ((entryList.size() == 1) && !config()->get("security/autotypeask").toBool()) {
m_inAutoType = false;
performAutoType(entryList.first(), Q_NULLPTR, sequenceHash[entryList.first()]);
performAutoType(entryList.first(), nullptr, sequenceHash[entryList.first()]);
}
else {
m_windowFromGlobal = m_plugin->activeWindow();
@@ -218,8 +226,10 @@ void AutoType::performAutoTypeFromGlobal(Entry* entry, const QString& sequence)
{
Q_ASSERT(m_inAutoType);
m_plugin->raiseWindow(m_windowFromGlobal);
m_inAutoType = false;
performAutoType(entry, Q_NULLPTR, sequence, m_windowFromGlobal);
performAutoType(entry, nullptr, sequence, m_windowFromGlobal);
}
void AutoType::resetInAutoType()
@@ -233,12 +243,12 @@ void AutoType::unloadPlugin()
{
if (m_executor) {
delete m_executor;
m_executor = Q_NULLPTR;
m_executor = nullptr;
}
if (m_plugin) {
m_plugin->unload();
m_plugin = Q_NULLPTR;
m_plugin = nullptr;
}
}
@@ -291,7 +301,7 @@ bool AutoType::parseActions(const QString& sequence, const Entry* entry, QList<A
QString tmpl;
bool inTmpl = false;
Q_FOREACH (const QChar& ch, sequence) {
for (const QChar& ch : sequence) {
// TODO: implement support for {{}, {}} and {DELAY=X}
if (inTmpl) {
@@ -473,10 +483,10 @@ QList<AutoTypeAction*> AutoType::createActionFromTemplate(const QString& tmpl, c
}
QString placeholder = QString("{%1}").arg(tmplName);
QString resolved = entry->resolvePlaceholders(placeholder);
const QString placeholder = QString("{%1}").arg(tmplName);
const QString resolved = entry->resolvePlaceholders(placeholder);
if (placeholder != resolved) {
Q_FOREACH (const QChar& ch, resolved) {
for (const QChar& ch : resolved) {
if (ch == '\n') {
list.append(new AutoTypeKey(Qt::Key_Enter));
}
@@ -502,7 +512,8 @@ QString AutoType::autoTypeSequence(const Entry* entry, const QString& windowTitl
QString sequence;
if (!windowTitle.isEmpty()) {
bool match = false;
Q_FOREACH (const AutoTypeAssociations::Association& assoc, entry->autoTypeAssociations()->getAll()) {
const QList<AutoTypeAssociations::Association> assocList = entry->autoTypeAssociations()->getAll();
for (const AutoTypeAssociations::Association& assoc : assocList) {
if (windowMatches(windowTitle, assoc.window)) {
if (!assoc.sequence.isEmpty()) {
sequence = assoc.sequence;
@@ -566,7 +577,7 @@ bool AutoType::windowMatches(const QString& windowTitle, const QString& windowPa
{
if (windowPattern.startsWith("//") && windowPattern.endsWith("//") && windowPattern.size() >= 4) {
QRegExp regExp(windowPattern.mid(2, windowPattern.size() - 4), Qt::CaseInsensitive, QRegExp::RegExp2);
return regExp.exactMatch(windowTitle);
return (regExp.indexIn(windowTitle) != -1);
}
else {
return WildcardMatcher(windowTitle).match(windowPattern);

View File

@@ -22,8 +22,6 @@
#include <QStringList>
#include <QWidget>
#include "core/Global.h"
class AutoTypeAction;
class AutoTypeExecutor;
class AutoTypePlatformInterface;
@@ -37,7 +35,7 @@ class AutoType : public QObject
public:
QStringList windowTitles();
void performAutoType(const Entry* entry, QWidget* hideWindow = Q_NULLPTR,
void performAutoType(const Entry* entry, QWidget* hideWindow = nullptr,
const QString& customSequence = QString(), WId window = 0);
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
void unregisterGlobalShortcut();
@@ -62,7 +60,7 @@ private Q_SLOTS:
void unloadPlugin();
private:
explicit AutoType(QObject* parent = Q_NULLPTR, bool test = false);
explicit AutoType(QObject* parent = nullptr, bool test = false);
~AutoType();
void loadPlugin(const QString& pluginPath);
bool parseActions(const QString& sequence, const Entry* entry, QList<AutoTypeAction*>& actions);

View File

@@ -66,7 +66,7 @@ public:
class KEEPASSX_EXPORT AutoTypeClearField : public AutoTypeAction
{
public:
explicit AutoTypeClearField();
AutoTypeClearField();
AutoTypeAction* clone();
void accept(AutoTypeExecutor* executor);
};

View File

@@ -26,6 +26,7 @@ class AutoTypePlatformInterface
{
public:
virtual ~AutoTypePlatformInterface() {}
virtual bool isAvailable() = 0;
virtual QStringList windowTitles() = 0;
virtual WId activeWindow() = 0;
virtual QString activeWindowTitle() = 0;
@@ -33,6 +34,7 @@ public:
virtual void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) = 0;
virtual int platformEventFilter(void* event) = 0;
virtual int initialTimeout() = 0;
virtual bool raiseWindow(WId window) = 0;
virtual void unload() {}
virtual AutoTypeExecutor* createExecutor() = 0;

View File

@@ -20,10 +20,12 @@
#include <QApplication>
#include <QDesktopWidget>
#include <QDialogButtonBox>
#include <QHeaderView>
#include <QLabel>
#include <QVBoxLayout>
#include "autotype/AutoTypeSelectView.h"
#include "core/Config.h"
#include "core/FilePath.h"
#include "gui/entry/EntryModel.h"
@@ -33,15 +35,20 @@ AutoTypeSelectDialog::AutoTypeSelectDialog(QWidget* parent)
, m_entryActivatedEmitted(false)
{
setAttribute(Qt::WA_DeleteOnClose);
// Places the window on the active (virtual) desktop instead of where the main window is.
setAttribute(Qt::WA_X11BypassTransientForHint);
setWindowFlags(windowFlags() | Qt::WindowStaysOnTopHint);
setWindowTitle(tr("Auto-Type - KeePassX"));
setWindowIcon(filePath()->applicationIcon());
QSize size(400, 250);
QRect screenGeometry = QApplication::desktop()->availableGeometry(QCursor::pos());
QSize size = config()->get("GUI/AutoTypeSelectDialogSize", QSize(400, 250)).toSize();
size.setWidth(qMin(size.width(), screenGeometry.width()));
size.setHeight(qMin(size.height(), screenGeometry.height()));
resize(size);
// move dialog to the center of the screen
QPoint screenCenter = QApplication::desktop()->screenGeometry(QCursor::pos()).center();
QPoint screenCenter = screenGeometry.center();
move(screenCenter.x() - (size.width() / 2), screenCenter.y() - (size.height() / 2));
QVBoxLayout* layout = new QVBoxLayout(this);
@@ -63,6 +70,15 @@ void AutoTypeSelectDialog::setEntries(const QList<Entry*>& entries, const QHash<
{
m_sequences = sequences;
m_view->setEntryList(entries);
m_view->header()->resizeSections(QHeaderView::ResizeToContents);
}
void AutoTypeSelectDialog::done(int r)
{
config()->set("GUI/AutoTypeSelectDialogSize", size());
QDialog::done(r);
}
void AutoTypeSelectDialog::emitEntryActivated(const QModelIndex& index)

View File

@@ -22,8 +22,6 @@
#include <QDialog>
#include <QHash>
#include "core/Global.h"
class AutoTypeSelectView;
class Entry;
@@ -32,12 +30,15 @@ class AutoTypeSelectDialog : public QDialog
Q_OBJECT
public:
explicit AutoTypeSelectDialog(QWidget* parent = Q_NULLPTR);
explicit AutoTypeSelectDialog(QWidget* parent = nullptr);
void setEntries(const QList<Entry*>& entries, const QHash<Entry*, QString>& sequences);
Q_SIGNALS:
void entryActivated(Entry* entry, const QString& sequence);
public Q_SLOTS:
void done(int r) override;
private Q_SLOTS:
void emitEntryActivated(const QModelIndex& index);
void entryRemoved();

View File

@@ -18,7 +18,6 @@
#ifndef KEEPASSX_AUTOTYPESELECTVIEW_H
#define KEEPASSX_AUTOTYPESELECTVIEW_H
#include "core/Global.h"
#include "gui/entry/EntryView.h"
class Entry;
@@ -28,10 +27,10 @@ class AutoTypeSelectView : public EntryView
Q_OBJECT
public:
explicit AutoTypeSelectView(QWidget* parent = Q_NULLPTR);
explicit AutoTypeSelectView(QWidget* parent = nullptr);
protected:
void mouseMoveEvent(QMouseEvent* event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent* event) override;
private Q_SLOTS:
void selectFirstEntry();

View File

@@ -1,11 +1,14 @@
if(Q_WS_X11)
if(UNIX AND NOT APPLE)
find_package(X11)
find_package(Qt5X11Extras 5.2)
if(PRINT_SUMMARY)
add_feature_info(libXtest X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
add_feature_info(libXi X11_Xi_FOUND "The X11 Xi Protocol library is required for auto-type")
add_feature_info(libXtst X11_XTest_FOUND "The X11 XTEST Protocol library is required for auto-type")
add_feature_info(Qt5X11Extras Qt5X11Extras_FOUND "The Qt5X11Extras library is required for auto-type")
endif()
if(X11_FOUND AND X11_XTest_FOUND)
add_subdirectory(x11)
if(X11_FOUND AND X11_Xi_FOUND AND X11_XTest_FOUND AND Qt5X11Extras_FOUND)
add_subdirectory(xcb)
endif()
endif()

View File

@@ -20,21 +20,19 @@
#include <QLineEdit>
#include "core/Global.h"
class ShortcutWidget : public QLineEdit
{
Q_OBJECT
public:
explicit ShortcutWidget(QWidget* parent = Q_NULLPTR);
explicit ShortcutWidget(QWidget* parent = nullptr);
Qt::Key key() const;
Qt::KeyboardModifiers modifiers() const;
void setShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
protected:
void keyPressEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
void keyReleaseEvent(QKeyEvent* event) Q_DECL_OVERRIDE;
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
private:
void keyEvent(QKeyEvent* event);

View File

@@ -70,7 +70,7 @@ bool WildcardMatcher::startOrEndDoesNotMatch(const QStringList& parts)
bool WildcardMatcher::partsMatch(const QStringList& parts)
{
int index = 0;
Q_FOREACH (const QString& part, parts) {
for (const QString& part : parts) {
int matchIndex = getMatchIndex(part, index);
if (noMatchFound(matchIndex)) {
return false;

View File

@@ -20,19 +20,17 @@
#include <QComboBox>
#include "core/Global.h"
class WindowSelectComboBox : public QComboBox
{
Q_OBJECT
public:
explicit WindowSelectComboBox(QWidget* parent = Q_NULLPTR);
explicit WindowSelectComboBox(QWidget* parent = nullptr);
void refreshWindowList();
void showPopup() Q_DECL_OVERRIDE;
QSize sizeHint() const Q_DECL_OVERRIDE;
QSize minimumSizeHint() const Q_DECL_OVERRIDE;
void showPopup() override;
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
};
#endif // KEEPASSX_WINDOWSELECTCOMBOBOX_H

View File

@@ -17,6 +17,11 @@
#include "AutoTypeTest.h"
bool AutoTypePlatformTest::isAvailable()
{
return true;
}
QString AutoTypePlatformTest::keyToString(Qt::Key key)
{
return QString("[Key0x%1]").arg(key, 0, 16);
@@ -103,6 +108,13 @@ int AutoTypePlatformTest::initialTimeout()
return 0;
}
bool AutoTypePlatformTest::raiseWindow(WId window)
{
Q_UNUSED(window);
return false;
}
AutoTypeExecturorTest::AutoTypeExecturorTest(AutoTypePlatformTest* platform)
: m_platform(platform)
{
@@ -117,5 +129,3 @@ void AutoTypeExecturorTest::execKey(AutoTypeKey* action)
{
m_platform->addActionKey(action);
}
Q_EXPORT_PLUGIN2(keepassx-autotype-test, AutoTypePlatformTest)

View File

@@ -23,32 +23,34 @@
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h"
#include "autotype/test/AutoTypeTestInterface.h"
#include "core/Global.h"
class AutoTypePlatformTest : public QObject,
public AutoTypePlatformInterface,
public AutoTypeTestInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformInterface")
Q_INTERFACES(AutoTypePlatformInterface AutoTypeTestInterface)
public:
QString keyToString(Qt::Key key);
QString keyToString(Qt::Key key) override;
QStringList windowTitles();
WId activeWindow();
QString activeWindowTitle();
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
int platformEventFilter(void* event);
int initialTimeout();
AutoTypeExecutor* createExecutor();
bool isAvailable() override;
QStringList windowTitles() override;
WId activeWindow() override;
QString activeWindowTitle() override;
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;
void setActiveWindowTitle(const QString& title);
void setActiveWindowTitle(const QString& title) override;
QString actionChars();
int actionCount();
void clearActions();
QString actionChars() override;
int actionCount() override;
void clearActions() override;
void addActionChar(AutoTypeChar* action);
void addActionKey(AutoTypeKey* action);
@@ -67,8 +69,8 @@ class AutoTypeExecturorTest : public AutoTypeExecutor
public:
explicit AutoTypeExecturorTest(AutoTypePlatformTest* platform);
void execChar(AutoTypeChar* action);
void execKey(AutoTypeKey* action);
void execChar(AutoTypeChar* action) override;
void execKey(AutoTypeKey* action) override;
private:
AutoTypePlatformTest* const m_platform;

View File

@@ -2,11 +2,5 @@ set(autotype_test_SOURCES
AutoTypeTest.cpp
)
set(autotype_test_MOC
AutoTypeTest.h
)
qt4_wrap_cpp(autotype_test_SOURCES ${autotype_test_MOC})
add_library(keepassx-autotype-test MODULE ${autotype_test_SOURCES})
target_link_libraries(keepassx-autotype-test testautotype ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
target_link_libraries(keepassx-autotype-test testautotype Qt5::Core Qt5::Widgets)

View File

@@ -1,17 +0,0 @@
include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
set(autotype_X11_SOURCES
AutoTypeX11.cpp
)
set(autotype_X11_MOC
AutoTypeX11.h
)
qt4_wrap_cpp(autotype_X11_SOURCES ${autotype_X11_MOC})
add_library(keepassx-autotype-x11 MODULE ${autotype_X11_SOURCES})
target_link_libraries(keepassx-autotype-x11 ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${X11_X11_LIB} ${X11_XTest_LIB})
install(TARGETS keepassx-autotype-x11
BUNDLE DESTINATION . COMPONENT Runtime
LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)

View File

@@ -16,25 +16,28 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AutoTypeX11.h"
#include "AutoTypeXCB.h"
#include "KeySymMap.h"
#include "core/Tools.h"
#include <time.h>
#include <xcb/xcb.h>
bool AutoTypePlatformX11::m_catchXErrors = false;
bool AutoTypePlatformX11::m_xErrorOccured = false;
int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = Q_NULLPTR;
int (*AutoTypePlatformX11::m_oldXErrorHandler)(Display*, XErrorEvent*) = nullptr;
AutoTypePlatformX11::AutoTypePlatformX11()
{
m_dpy = QX11Info::display();
m_rootWindow = QX11Info::appRootWindow();
m_atomWmState = XInternAtom(m_dpy, "WM_STATE", true);
m_atomWmName = XInternAtom(m_dpy, "WM_NAME", true);
m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", true);
m_atomString = XInternAtom(m_dpy, "STRING", true);
m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", true);
m_atomWmState = XInternAtom(m_dpy, "WM_STATE", True);
m_atomWmName = XInternAtom(m_dpy, "WM_NAME", True);
m_atomNetWmName = XInternAtom(m_dpy, "_NET_WM_NAME", True);
m_atomString = XInternAtom(m_dpy, "STRING", True);
m_atomUtf8String = XInternAtom(m_dpy, "UTF8_STRING", True);
m_atomNetActiveWindow = XInternAtom(m_dpy, "_NET_ACTIVE_WINDOW", True);
m_classBlacklist << "desktop_window" << "gnome-panel"; // Gnome
m_classBlacklist << "kdesktop" << "kicker"; // KDE 3
@@ -45,8 +48,8 @@ AutoTypePlatformX11::AutoTypePlatformX11()
m_currentGlobalKey = static_cast<Qt::Key>(0);
m_currentGlobalModifiers = 0;
m_keysymTable = Q_NULLPTR;
m_xkb = Q_NULLPTR;
m_keysymTable = nullptr;
m_xkb = nullptr;
m_remapKeycode = 0;
m_currentRemapKeysym = NoSymbol;
m_modifierMask = ControlMask | ShiftMask | Mod1Mask | Mod4Mask;
@@ -56,6 +59,31 @@ AutoTypePlatformX11::AutoTypePlatformX11()
updateKeymap();
}
bool AutoTypePlatformX11::isAvailable()
{
int ignore;
if (!XQueryExtension(m_dpy, "XInputExtension", &ignore, &ignore, &ignore)) {
return false;
}
if (!XQueryExtension(m_dpy, "XTEST", &ignore, &ignore, &ignore)) {
return false;
}
if (!m_xkb) {
XkbDescPtr kbd = getKeyboard();
if (!kbd) {
return false;
}
XkbFreeKeyboard(kbd, XkbAllComponentsMask, True);
}
return true;
}
void AutoTypePlatformX11::unload()
{
// Restore the KeyboardMapping to its original state.
@@ -93,7 +121,7 @@ WId AutoTypePlatformX11::activeWindow()
Window root;
Window parent;
Window* children = Q_NULLPTR;
Window* children = nullptr;
unsigned int numChildren;
tree = XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren);
window = parent;
@@ -116,12 +144,12 @@ bool AutoTypePlatformX11::registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifi
uint nativeModifiers = qtToNativeModifiers(modifiers);
startCatchXErrors();
XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, true, GrabModeAsync, GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, true, GrabModeAsync,
XGrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow, True, GrabModeAsync, GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask, m_rootWindow, True, GrabModeAsync,
GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, true, GrabModeAsync,
XGrabKey(m_dpy, keycode, nativeModifiers | LockMask, m_rootWindow, True, GrabModeAsync,
GrabModeAsync);
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, true,
XGrabKey(m_dpy, keycode, nativeModifiers | Mod2Mask | LockMask, m_rootWindow, True,
GrabModeAsync, GrabModeAsync);
stopCatchXErrors();
@@ -160,7 +188,7 @@ uint AutoTypePlatformX11::qtToNativeModifiers(Qt::KeyboardModifiers modifiers)
void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers)
{
KeyCode keycode = XKeysymToKeycode(m_dpy, keyToKeySym(key));
KeyCode keycode = XKeysymToKeycode(m_dpy, charToKeySym(key));
uint nativeModifiers = qtToNativeModifiers(modifiers);
XUngrabKey(m_dpy, keycode, nativeModifiers, m_rootWindow);
@@ -176,22 +204,42 @@ void AutoTypePlatformX11::unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModi
int AutoTypePlatformX11::platformEventFilter(void* event)
{
XEvent* xevent = static_cast<XEvent*>(event);
xcb_generic_event_t* genericEvent = static_cast<xcb_generic_event_t*>(event);
quint8 type = genericEvent->response_type & 0x7f;
if ((xevent->type == KeyPress || xevent->type == KeyRelease)
&& m_currentGlobalKey
&& xevent->xkey.keycode == m_currentGlobalKeycode
&& (xevent->xkey.state & m_modifierMask) == m_currentGlobalNativeModifiers
&& !QApplication::focusWidget()
&& m_loaded) {
if (xevent->type == KeyPress) {
Q_EMIT globalShortcutTriggered();
if (type == XCB_KEY_PRESS || type == XCB_KEY_RELEASE) {
xcb_key_press_event_t* keyPressEvent = static_cast<xcb_key_press_event_t*>(event);
if (keyPressEvent->detail == m_currentGlobalKeycode
&& (keyPressEvent->state & m_modifierMask) == m_currentGlobalNativeModifiers
&& (!QApplication::activeWindow() || QApplication::activeWindow()->isMinimized())
&& m_loaded) {
if (type == XCB_KEY_PRESS) {
Q_EMIT globalShortcutTriggered();
}
return 1;
}
return 1;
}
if (xevent->type == MappingNotify && m_loaded) {
XRefreshKeyboardMapping(reinterpret_cast<XMappingEvent*>(xevent));
updateKeymap();
else if (type == XCB_MAPPING_NOTIFY) {
xcb_mapping_notify_event_t* mappingNotifyEvent = static_cast<xcb_mapping_notify_event_t*>(event);
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD
|| mappingNotifyEvent->request == XCB_MAPPING_MODIFIER)
{
XMappingEvent xMappingEvent;
memset(&xMappingEvent, 0, sizeof(xMappingEvent));
xMappingEvent.type = MappingNotify;
xMappingEvent.display = m_dpy;
if (mappingNotifyEvent->request == XCB_MAPPING_KEYBOARD) {
xMappingEvent.request = MappingKeyboard;
}
else {
xMappingEvent.request = MappingModifier;
}
xMappingEvent.first_keycode = mappingNotifyEvent->first_keycode;
xMappingEvent.count = mappingNotifyEvent->count;
XRefreshKeyboardMapping(&xMappingEvent);
updateKeymap();
}
}
return -1;
@@ -210,11 +258,11 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
int format;
unsigned long nitems;
unsigned long after;
unsigned char* data = Q_NULLPTR;
unsigned char* data = nullptr;
// the window manager spec says we should read _NET_WM_NAME first, then fall back to WM_NAME
int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, false, m_atomUtf8String,
int retVal = XGetWindowProperty(m_dpy, window, m_atomNetWmName, 0, 1000, False, m_atomUtf8String,
&type, &format, &nitems, &after, &data);
if ((retVal == 0) && data) {
@@ -224,7 +272,7 @@ QString AutoTypePlatformX11::windowTitle(Window window, bool useBlacklist)
XTextProperty textProp;
retVal = XGetTextProperty(m_dpy, window, &textProp, m_atomWmName);
if ((retVal != 0) && textProp.value) {
char** textList = Q_NULLPTR;
char** textList = nullptr;
int count;
if (textProp.encoding == m_atomUtf8String) {
@@ -276,8 +324,8 @@ QString AutoTypePlatformX11::windowClassName(Window window)
QString className;
XClassHint wmClass;
wmClass.res_name = Q_NULLPTR;
wmClass.res_class = Q_NULLPTR;
wmClass.res_name = nullptr;
wmClass.res_class = nullptr;
if (XGetClassHint(m_dpy, window, &wmClass) && wmClass.res_name) {
className = QString::fromLocal8Bit(wmClass.res_name);
@@ -296,7 +344,7 @@ QList<Window> AutoTypePlatformX11::widgetsToX11Windows(const QWidgetList& widget
{
QList<Window> windows;
Q_FOREACH (const QWidget* widget, widgetList) {
for (const QWidget* widget : widgetList) {
windows.append(widget->effectiveWinId());
}
@@ -316,7 +364,7 @@ QStringList AutoTypePlatformX11::windowTitlesRecursive(Window window)
Window root;
Window parent;
Window* children = Q_NULLPTR;
Window* children = nullptr;
unsigned int numChildren;
if (XQueryTree(m_dpy, window, &root, &parent, &children, &numChildren) && children) {
for (uint i = 0; i < numChildren; i++) {
@@ -337,13 +385,21 @@ bool AutoTypePlatformX11::isTopLevelWindow(Window window)
unsigned long nitems;
unsigned long after;
unsigned char* data = Q_NULLPTR;
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 0, false, AnyPropertyType, &type, &format,
int retVal = XGetWindowProperty(m_dpy, window, m_atomWmState, 0, 2, False, m_atomWmState, &type, &format,
&nitems, &after, &data);
if (data) {
bool result = false;
if (retVal == 0 && data) {
if (type == m_atomWmState && format == 32 && nitems > 0) {
qint32 state = static_cast<qint32>(*data);
result = (state != WithdrawnState);
}
XFree(data);
}
return (retVal == 0) && type;
return result;
}
KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
@@ -357,9 +413,9 @@ KeySym AutoTypePlatformX11::charToKeySym(const QChar& ch)
}
/* mapping table generated from keysymdef.h */
const uint* match = qBinaryFind(m_unicodeToKeysymKeys,
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
unicode);
const uint* match = Tools::binaryFind(m_unicodeToKeysymKeys,
m_unicodeToKeysymKeys + m_unicodeToKeysymLen,
unicode);
int index = match - m_unicodeToKeysymKeys;
if (index != m_unicodeToKeysymLen) {
return m_unicodeToKeysymValues[index];
@@ -436,21 +492,10 @@ void AutoTypePlatformX11::updateKeymap()
int mod_index, mod_key;
XModifierKeymap *modifiers;
if (m_xkb != NULL) XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
XDeviceInfo* devices;
int num_devices;
XID keyboard_id = XkbUseCoreKbd;
devices = XListInputDevices(m_dpy, &num_devices);
for (int i = 0; i < num_devices; i++) {
if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
keyboard_id = devices[i].id;
break;
}
if (m_xkb) {
XkbFreeKeyboard(m_xkb, XkbAllComponentsMask, True);
}
m_xkb = XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
m_xkb = getKeyboard();
XDisplayKeycodes(m_dpy, &m_minKeycode, &m_maxKeycode);
if (m_keysymTable != NULL) XFree(m_keysymTable);
@@ -491,7 +536,7 @@ void AutoTypePlatformX11::updateKeymap()
timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 30 * 1000 * 1000;
nanosleep(&ts, Q_NULLPTR);
nanosleep(&ts, nullptr);
}
bool AutoTypePlatformX11::isRemapKeycodeValid()
@@ -519,7 +564,7 @@ void AutoTypePlatformX11::stopCatchXErrors()
{
Q_ASSERT(m_catchXErrors);
XSync(m_dpy, false);
XSync(m_dpy, False);
XSetErrorHandler(m_oldXErrorHandler);
m_catchXErrors = false;
}
@@ -536,6 +581,27 @@ int AutoTypePlatformX11::x11ErrorHandler(Display* display, XErrorEvent* error)
return 1;
}
XkbDescPtr AutoTypePlatformX11::getKeyboard()
{
int num_devices;
XID keyboard_id = XkbUseCoreKbd;
XDeviceInfo* devices = XListInputDevices(m_dpy, &num_devices);
if (!devices) {
return nullptr;
}
for (int i = 0; i < num_devices; i++) {
if (QString(devices[i].name) == "Virtual core XTEST keyboard") {
keyboard_id = devices[i].id;
break;
}
}
XFreeDeviceList(devices);
return XkbGetKeyboard(m_dpy, XkbCompatMapMask | XkbGeometryMask, keyboard_id);
}
// --------------------------------------------------------------------------
// The following code is taken from xvkbd 3.0 and has been slightly modified.
// --------------------------------------------------------------------------
@@ -568,11 +634,18 @@ int AutoTypePlatformX11::AddKeysym(KeySym keysym)
*/
void AutoTypePlatformX11::SendEvent(XKeyEvent* event, int event_type)
{
XSync(event->display, FALSE);
XSync(event->display, False);
int (*oldHandler) (Display*, XErrorEvent*) = XSetErrorHandler(MyErrorHandler);
event->type = event_type;
XTestFakeKeyEvent(event->display, event->keycode, event->type == KeyPress, 0);
Bool press;
if (event->type == KeyPress) {
press = True;
}
else {
press = False;
}
XTestFakeKeyEvent(event->display, event->keycode, press, 0);
XFlush(event->display);
XSetErrorHandler(oldHandler);
@@ -670,7 +743,7 @@ void AutoTypePlatformX11::SendKeyPressedEvent(KeySym keysym)
event.y = 1;
event.x_root = 1;
event.y_root = 1;
event.same_screen = TRUE;
event.same_screen = True;
Window root, child;
int root_x, root_y, x, y;
@@ -770,4 +843,36 @@ int AutoTypePlatformX11::initialTimeout()
return 500;
}
Q_EXPORT_PLUGIN2(keepassx-autotype-x11, AutoTypePlatformX11)
bool AutoTypePlatformX11::raiseWindow(WId window)
{
if (m_atomNetActiveWindow == None) {
return false;
}
XRaiseWindow(m_dpy, window);
XEvent event;
event.xclient.type = ClientMessage;
event.xclient.serial = 0;
event.xclient.send_event = True;
event.xclient.window = window;
event.xclient.message_type = m_atomNetActiveWindow;
event.xclient.format = 32;
event.xclient.data.l[0] = 1; // FromApplication
event.xclient.data.l[1] = QX11Info::appUserTime();
QWidget* activeWindow = QApplication::activeWindow();
if (activeWindow) {
event.xclient.data.l[2] = activeWindow->internalWinId();
}
else {
event.xclient.data.l[2] = 0;
}
event.xclient.data.l[3] = 0;
event.xclient.data.l[4] = 0;
XSendEvent(m_dpy, m_rootWindow, False,
SubstructureRedirectMask | SubstructureNotifyMask,
&event);
XFlush(m_dpy);
return true;
}

View File

@@ -16,8 +16,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef KEEPASSX_AUTOTYPEX11_H
#define KEEPASSX_AUTOTYPEX11_H
#ifndef KEEPASSX_AUTOTYPEXCB_H
#define KEEPASSX_AUTOTYPEXCB_H
#include <QApplication>
#include <QSet>
@@ -31,26 +31,28 @@
#include "autotype/AutoTypePlatformPlugin.h"
#include "autotype/AutoTypeAction.h"
#include "core/Global.h"
#define N_MOD_INDICES (Mod5MapIndex + 1)
class AutoTypePlatformX11 : public QObject, public AutoTypePlatformInterface
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.keepassx.AutoTypePlatformX11")
Q_INTERFACES(AutoTypePlatformInterface)
public:
AutoTypePlatformX11();
void unload() Q_DECL_OVERRIDE;
QStringList windowTitles();
WId activeWindow();
QString activeWindowTitle();
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers);
int platformEventFilter(void* event);
int initialTimeout();
AutoTypeExecutor* createExecutor();
bool isAvailable() override;
void unload() override;
QStringList windowTitles() override;
WId activeWindow() override;
QString activeWindowTitle() override;
bool registerGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
void unregisterGlobalShortcut(Qt::Key key, Qt::KeyboardModifiers modifiers) override;
int platformEventFilter(void* event) override;
int initialTimeout() override;
bool raiseWindow(WId window) override;
AutoTypeExecutor* createExecutor() override;
KeySym charToKeySym(const QChar& ch);
KeySym keyToKeySym(Qt::Key key);
@@ -71,6 +73,7 @@ private:
void stopCatchXErrors();
static int x11ErrorHandler(Display* display, XErrorEvent* error);
XkbDescPtr getKeyboard();
void updateKeymap();
bool isRemapKeycodeValid();
int AddKeysym(KeySym keysym);
@@ -89,6 +92,7 @@ private:
Atom m_atomNetWmName;
Atom m_atomString;
Atom m_atomUtf8String;
Atom m_atomNetActiveWindow;
QSet<QString> m_classBlacklist;
Qt::Key m_currentGlobalKey;
Qt::KeyboardModifiers m_currentGlobalModifiers;
@@ -120,11 +124,11 @@ class AutoTypeExecturorX11 : public AutoTypeExecutor
public:
explicit AutoTypeExecturorX11(AutoTypePlatformX11* platform);
void execChar(AutoTypeChar* action);
void execKey(AutoTypeKey* action);
void execChar(AutoTypeChar* action) override;
void execKey(AutoTypeKey* action) override;
private:
AutoTypePlatformX11* const m_platform;
};
#endif // KEEPASSX_AUTOTYPEX11_H
#endif // KEEPASSX_AUTOTYPEXCB_H

View File

@@ -0,0 +1,11 @@
include_directories(SYSTEM ${X11_X11_INCLUDE_PATH})
set(autotype_XCB_SOURCES
AutoTypeXCB.cpp
)
add_library(keepassx-autotype-xcb MODULE ${autotype_XCB_SOURCES})
target_link_libraries(keepassx-autotype-xcb Qt5::Core Qt5::Widgets Qt5::X11Extras ${X11_X11_LIB} ${X11_Xi_LIB} ${X11_XTest_LIB})
install(TARGETS keepassx-autotype-xcb
BUNDLE DESTINATION . COMPONENT Runtime
LIBRARY DESTINATION ${PLUGIN_INSTALL_DIR} COMPONENT Runtime)

View File

@@ -16,6 +16,4 @@
#cmakedefine HAVE_RLIMIT_CORE 1
#cmakedefine HAVE_PT_DENY_ATTACH 1
#cmakedefine GCRYPT_HAS_SALSA20
#endif // KEEPASSX_CONFIG_KEEPASSX_H

View File

@@ -20,8 +20,6 @@
#include <QObject>
#include "core/Global.h"
class AutoTypeAssociations : public QObject
{
Q_OBJECT
@@ -36,7 +34,7 @@ public:
bool operator!=(const AutoTypeAssociations::Association& other) const;
};
explicit AutoTypeAssociations(QObject* parent = Q_NULLPTR);
explicit AutoTypeAssociations(QObject* parent = nullptr);
void copyDataFrom(const AutoTypeAssociations* other);
void add(const AutoTypeAssociations::Association& association);
void remove(int index);

View File

@@ -18,12 +18,12 @@
#include "Config.h"
#include <QCoreApplication>
#include <QDesktopServices>
#include <QDir>
#include <QSettings>
#include <QStandardPaths>
#include <QTemporaryFile>
Config* Config::m_instance(Q_NULLPTR);
Config* Config::m_instance(nullptr);
QVariant Config::get(const QString& key)
{
@@ -53,7 +53,7 @@ Config::Config(QObject* parent)
QString homePath = QDir::homePath();
#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
// we can't use QDesktopServices on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
// we can't use QStandardPaths on X11 as it uses XDG_DATA_HOME instead of XDG_CONFIG_HOME
QByteArray env = qgetenv("XDG_CONFIG_HOME");
if (env.isEmpty()) {
userPath = homePath;
@@ -70,7 +70,7 @@ Config::Config(QObject* parent)
userPath += "/keepassx/";
#else
userPath = QDir::fromNativeSeparators(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
userPath = QDir::fromNativeSeparators(QStandardPaths::writableLocation(QStandardPaths::DataLocation));
// storageLocation() appends the application name ("/keepassx") to the end
userPath += "/";
#endif
@@ -106,6 +106,7 @@ void Config::init(const QString& fileName)
m_defaults.insert("GUI/Language", "system");
m_defaults.insert("GUI/ShowTrayIcon", false);
m_defaults.insert("GUI/MinimizeToTray", false);
m_defaults.insert("GUI/MinimizeOnClose", false);
}
Config* Config::instance()

View File

@@ -21,8 +21,6 @@
#include <QScopedPointer>
#include <QVariant>
#include "core/Global.h"
class QSettings;
class Config : public QObject

View File

@@ -23,7 +23,6 @@
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/Tools.h"
#include "crypto/Random.h"
#include "format/KeePass2.h"
@@ -92,20 +91,22 @@ Entry* Database::resolveEntry(const Uuid& uuid)
Entry* Database::recFindEntry(const Uuid& uuid, Group* group)
{
Q_FOREACH (Entry* entry, group->entries()) {
const QList<Entry*> entryList = group->entries();
for (Entry* entry : entryList) {
if (entry->uuid() == uuid) {
return entry;
}
}
Q_FOREACH (Group* child, group->children()) {
const QList<Group*> children = group->children();
for (Group* child : children) {
Entry* result = recFindEntry(uuid, child);
if (result) {
return result;
}
}
return Q_NULLPTR;
return nullptr;
}
Group* Database::resolveGroup(const Uuid& uuid)
@@ -119,14 +120,15 @@ Group* Database::recFindGroup(const Uuid& uuid, Group* group)
return group;
}
Q_FOREACH (Group* child, group->children()) {
const QList<Group*> children = group->children();
for (Group* child : children) {
Group* result = recFindGroup(uuid, child);
if (result) {
return result;
}
}
return Q_NULLPTR;
return nullptr;
}
QList<DeletedObject> Database::deletedObjects()
@@ -143,7 +145,7 @@ void Database::addDeletedObject(const DeletedObject& delObj)
void Database::addDeletedObject(const Uuid& uuid)
{
DeletedObject delObj;
delObj.deletionTime = Tools::currentDateTimeUtc();
delObj.deletionTime = QDateTime::currentDateTimeUtc();
delObj.uuid = uuid;
addDeletedObject(delObj);
@@ -223,7 +225,7 @@ bool Database::setKey(const CompositeKey& key, const QByteArray& transformSeed,
m_data.transformedMasterKey = transformedMasterKey;
m_data.hasKey = true;
if (updateChangedTime) {
m_metadata->setMasterKeyChanged(Tools::currentDateTimeUtc());
m_metadata->setMasterKeyChanged(QDateTime::currentDateTimeUtc());
}
Q_EMIT modifiedImmediate();

View File

@@ -20,6 +20,7 @@
#include <QDateTime>
#include <QHash>
#include <QObject>
#include "core/Uuid.h"
#include "keys/CompositeKey.h"

View File

@@ -19,7 +19,7 @@
#include "core/FilePath.h"
DatabaseIcons* DatabaseIcons::m_instance(Q_NULLPTR);
DatabaseIcons* DatabaseIcons::m_instance(nullptr);
const int DatabaseIcons::IconCount(69);
const int DatabaseIcons::ExpiredIconIndex(45);
const char* const DatabaseIcons::m_indexToName[] = {

View File

@@ -23,8 +23,6 @@
#include <QPixmapCache>
#include <QVector>
#include "core/Global.h"
class DatabaseIcons
{
public:

View File

@@ -21,7 +21,6 @@
#include "core/DatabaseIcons.h"
#include "core/Group.h"
#include "core/Metadata.h"
#include "core/Tools.h"
const int Entry::DefaultIconNumber = 0;
@@ -29,7 +28,7 @@ Entry::Entry()
: m_attributes(new EntryAttributes(this))
, m_attachments(new EntryAttachments(this))
, m_autoTypeAssociations(new AutoTypeAssociations(this))
, m_tmpHistoryItem(Q_NULLPTR)
, m_tmpHistoryItem(nullptr)
, m_modifiedSinceBegin(false)
, m_updateTimeinfo(true)
{
@@ -74,8 +73,8 @@ template <class T> inline bool Entry::set(T& property, const T& value)
void Entry::updateTimeinfo()
{
if (m_updateTimeinfo) {
m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
}
}
@@ -114,13 +113,25 @@ QPixmap Entry::iconPixmap() const
else {
Q_ASSERT(database());
QPixmap pixmap;
if (database() && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
pixmap = QPixmap::fromImage(database()->metadata()->customIcon(m_data.customIcon));
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
if (database()) {
return database()->metadata()->customIconPixmap(m_data.customIcon);
}
else {
return QPixmap();
}
}
}
return pixmap;
QPixmap Entry::iconScaledPixmap() const
{
if (m_data.customIcon.isNull()) {
// built-in icons are 16x16 so don't need to be scaled
return databaseIcons()->iconPixmap(m_data.iconNumber);
}
else {
Q_ASSERT(database());
return database()->metadata()->customIconScaledPixmap(m_data.customIcon);
}
}
@@ -211,7 +222,7 @@ QString Entry::notes() const
bool Entry::isExpired() const
{
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
}
EntryAttributes* Entry::attributes()
@@ -248,8 +259,6 @@ void Entry::setIcon(int iconNumber)
m_data.iconNumber = iconNumber;
m_data.customIcon = Uuid();
m_pixmapCacheKey = QPixmapCache::Key();
Q_EMIT modified();
emitDataChanged();
}
@@ -263,8 +272,6 @@ void Entry::setIcon(const Uuid& uuid)
m_data.customIcon = uuid;
m_data.iconNumber = 0;
m_pixmapCacheKey = QPixmapCache::Key();
Q_EMIT modified();
emitDataChanged();
}
@@ -364,7 +371,6 @@ const QList<Entry*>& Entry::historyItems() const
void Entry::addHistoryItem(Entry* entry)
{
Q_ASSERT(!entry->parent());
Q_ASSERT(entry->uuid() == uuid());
m_history.append(entry);
Q_EMIT modified();
@@ -376,7 +382,7 @@ void Entry::removeHistoryItems(const QList<Entry*>& historyEntries)
return;
}
Q_FOREACH (Entry* entry, historyEntries) {
for (Entry* entry : historyEntries) {
Q_ASSERT(!entry->parent());
Q_ASSERT(entry->uuid() == uuid());
Q_ASSERT(m_history.contains(entry));
@@ -425,8 +431,8 @@ void Entry::truncateHistory()
if (size <= histMaxSize) {
size += historyItem->attributes()->attributesSize();
QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachements;
Q_FOREACH (const QByteArray& attachment, newAttachments) {
const QSet<QByteArray> newAttachments = historyItem->attachments()->values().toSet() - foundAttachements;
for (const QByteArray& attachment : newAttachments) {
size += attachment.size();
}
foundAttachements += newAttachments;
@@ -455,7 +461,7 @@ Entry* Entry::clone(CloneFlags flags) const
entry->m_attachments->copyDataFrom(m_attachments);
entry->m_autoTypeAssociations->copyDataFrom(this->m_autoTypeAssociations);
if (flags & CloneIncludeHistory) {
Q_FOREACH (Entry* historyItem, m_history) {
for (Entry* historyItem : m_history) {
Entry* historyItemClone = historyItem->clone(flags & ~CloneIncludeHistory & ~CloneNewUuid);
historyItemClone->setUpdateTimeinfo(false);
historyItemClone->setUuid(entry->uuid());
@@ -466,7 +472,7 @@ Entry* Entry::clone(CloneFlags flags) const
entry->setUpdateTimeinfo(true);
if (flags & CloneResetTimeInfo) {
QDateTime now = Tools::currentDateTimeUtc();
QDateTime now = QDateTime::currentDateTimeUtc();
entry->m_data.timeInfo.setCreationTime(now);
entry->m_data.timeInfo.setLastModificationTime(now);
entry->m_data.timeInfo.setLastAccessTime(now);
@@ -502,7 +508,7 @@ void Entry::beginUpdate()
m_modifiedSinceBegin = false;
}
void Entry::endUpdate()
bool Entry::endUpdate()
{
Q_ASSERT(m_tmpHistoryItem);
if (m_modifiedSinceBegin) {
@@ -514,7 +520,9 @@ void Entry::endUpdate()
delete m_tmpHistoryItem;
}
m_tmpHistoryItem = Q_NULLPTR;
m_tmpHistoryItem = nullptr;
return m_modifiedSinceBegin;
}
void Entry::updateModifiedSinceBegin()
@@ -560,7 +568,7 @@ void Entry::setGroup(Group* group)
QObject::setParent(group);
if (m_updateTimeinfo) {
m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
}
}
@@ -575,7 +583,7 @@ const Database* Entry::database() const
return m_group->database();
}
else {
return Q_NULLPTR;
return nullptr;
}
}

View File

@@ -22,7 +22,6 @@
#include <QImage>
#include <QMap>
#include <QPixmap>
#include <QPixmapCache>
#include <QPointer>
#include <QSet>
#include <QUrl>
@@ -30,7 +29,6 @@
#include "core/AutoTypeAssociations.h"
#include "core/EntryAttachments.h"
#include "core/EntryAttributes.h"
#include "core/Global.h"
#include "core/TimeInfo.h"
#include "core/Uuid.h"
@@ -61,6 +59,7 @@ public:
Uuid uuid() const;
QImage icon() const;
QPixmap iconPixmap() const;
QPixmap iconScaledPixmap() const;
int iconNumber() const;
Uuid iconUuid() const;
QColor foregroundColor() const;
@@ -134,7 +133,7 @@ public:
* if the entry has been changed.
*/
void beginUpdate();
void endUpdate();
bool endUpdate();
Group* group();
const Group* group() const;
@@ -169,7 +168,6 @@ private:
Entry* m_tmpHistoryItem;
bool m_modifiedSinceBegin;
QPointer<Group> m_group;
mutable QPixmapCache::Key m_pixmapCacheKey;
bool m_updateTimeinfo;
};

View File

@@ -21,14 +21,12 @@
#include <QMap>
#include <QObject>
#include "core/Global.h"
class EntryAttachments : public QObject
{
Q_OBJECT
public:
explicit EntryAttachments(QObject* parent = Q_NULLPTR);
explicit EntryAttachments(QObject* parent = nullptr);
QList<QString> keys() const;
bool hasKey(const QString& key) const;
QList<QByteArray> values() const;

View File

@@ -44,7 +44,8 @@ bool EntryAttributes::hasKey(const QString& key) const
QList<QString> EntryAttributes::customKeys()
{
QList<QString> customKeys;
Q_FOREACH (const QString& key, keys()) {
const QList<QString> keyList = keys();
for (const QString& key : keyList) {
if (!isDefaultAttribute(key)) {
customKeys.append(key);
}
@@ -57,6 +58,11 @@ QString EntryAttributes::value(const QString& key) const
return m_attributes.value(key);
}
bool EntryAttributes::contains(const QString &key) const
{
return m_attributes.contains(key);
}
bool EntryAttributes::isProtected(const QString& key) const
{
return m_protectedAttributes.contains(key);
@@ -162,14 +168,16 @@ void EntryAttributes::copyCustomKeysFrom(const EntryAttributes* other)
Q_EMIT aboutToBeReset();
// remove all non-default keys
Q_FOREACH (const QString& key, keys()) {
const QList<QString> keyList = keys();
for (const QString& key : keyList) {
if (!isDefaultAttribute(key)) {
m_attributes.remove(key);
m_protectedAttributes.remove(key);
}
}
Q_FOREACH (const QString& key, other->keys()) {
const QList<QString> otherKeyList = other->keys();
for (const QString& key : otherKeyList) {
if (!isDefaultAttribute(key)) {
m_attributes.insert(key, other->value(key));
if (other->isProtected(key)) {
@@ -189,7 +197,8 @@ bool EntryAttributes::areCustomKeysDifferent(const EntryAttributes* other)
return true;
}
Q_FOREACH (const QString& key, keys()) {
const QList<QString> keyList = keys();
for (const QString& key : keyList) {
if (isDefaultAttribute(key)) {
continue;
}
@@ -234,7 +243,7 @@ void EntryAttributes::clear()
m_attributes.clear();
m_protectedAttributes.clear();
Q_FOREACH (const QString& key, DefaultAttributes) {
for (const QString& key : DefaultAttributes) {
m_attributes.insert(key, "");
}

View File

@@ -23,18 +23,17 @@
#include <QSet>
#include <QStringList>
#include "core/Global.h"
class EntryAttributes : public QObject
{
Q_OBJECT
public:
explicit EntryAttributes(QObject* parent = Q_NULLPTR);
explicit EntryAttributes(QObject* parent = nullptr);
QList<QString> keys() const;
bool hasKey(const QString& key) const;
QList<QString> customKeys();
QString value(const QString& key) const;
bool contains(const QString& key) const;
bool isProtected(const QString& key) const;
void set(const QString& key, const QString& value, bool protect = false);
void remove(const QString& key);

View File

@@ -19,7 +19,8 @@
#include "core/Group.h"
QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
QList<Entry*> EntrySearcher::search(const QString& searchTerm, const Group* group,
Qt::CaseSensitivity caseSensitivity)
{
if (!group->resolveSearchingEnabled()) {
return QList<Entry*>();
@@ -28,14 +29,18 @@ QList<Entry*> EntrySearcher::search(const QString &searchTerm, const Group* grou
return searchEntries(searchTerm, group, caseSensitivity);
}
QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity)
QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Group* group,
Qt::CaseSensitivity caseSensitivity)
{
QList<Entry*> searchResult;
Q_FOREACH (Entry* entry, group->entries()) {
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
const QList<Entry*> entryList = group->entries();
for (Entry* entry : entryList) {
searchResult.append(matchEntry(searchTerm, entry, caseSensitivity));
}
Q_FOREACH (Group* childGroup, group->children()) {
const QList<Group*> children = group->children();
for (Group* childGroup : children) {
if (childGroup->searchingEnabled() != Group::Disable) {
searchResult.append(searchEntries(searchTerm, childGroup, caseSensitivity));
}
@@ -44,10 +49,11 @@ QList<Entry*> EntrySearcher::searchEntries(const QString& searchTerm, const Grou
return searchResult;
}
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity)
QList<Entry*> EntrySearcher::matchEntry(const QString& searchTerm, Entry* entry,
Qt::CaseSensitivity caseSensitivity)
{
QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
Q_FOREACH (const QString& word, wordList) {
const QStringList wordList = searchTerm.split(QRegExp("\\s"), QString::SkipEmptyParts);
for (const QString& word : wordList) {
if (!wordMatch(word, entry, caseSensitivity)) {
return QList<Entry*>();
}

View File

@@ -28,10 +28,11 @@ class EntrySearcher
{
public:
QList<Entry*> search(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
private:
QList<Entry*> searchEntries(const QString& searchTerm, const Group* group, Qt::CaseSensitivity caseSensitivity);
QList<Entry*> matchEntry(const QString& searchTerm, Entry* entry, Qt::CaseSensitivity caseSensitivity);
bool wordMatch(const QString &word, Entry *entry, Qt::CaseSensitivity caseSensitivity);
bool wordMatch(const QString& word, Entry* entry, Qt::CaseSensitivity caseSensitivity);
};
#endif // KEEPASSX_ENTRYSEARCHER_H

View File

@@ -22,8 +22,9 @@
#include <QLibrary>
#include "config-keepassx.h"
#include "core/Global.h"
FilePath* FilePath::m_instance(Q_NULLPTR);
FilePath* FilePath::m_instance(nullptr);
QString FilePath::dataPath(const QString& name)
{
@@ -40,7 +41,8 @@ QString FilePath::pluginPath(const QString& name)
QStringList pluginPaths;
QDir buildDir(QCoreApplication::applicationDirPath() + "/autotype");
Q_FOREACH (const QString& dir, buildDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot)) {
const QStringList buildDirEntryList = buildDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QString& dir : buildDirEntryList) {
pluginPaths << QCoreApplication::applicationDirPath() + "/autotype/" + dir;
}
@@ -68,10 +70,10 @@ QString FilePath::pluginPath(const QString& name)
QStringList dirFilter;
dirFilter << QString("*%1*").arg(name);
Q_FOREACH (const QString& path, pluginPaths) {
QStringList fileCandidates = QDir(path).entryList(dirFilter, QDir::Files);
for (const QString& path : asConst(pluginPaths)) {
const QStringList fileCandidates = QDir(path).entryList(dirFilter, QDir::Files);
Q_FOREACH (const QString& file, fileCandidates) {
for (const QString& file : fileCandidates) {
QString filePath = path + "/" + file;
if (QLibrary::isLibrary(filePath)) {
@@ -103,17 +105,16 @@ QIcon FilePath::icon(const QString& category, const QString& name, bool fromThem
}
if (icon.isNull()) {
QList<int> pngSizes;
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
QString filename;
Q_FOREACH (int size, pngSizes) {
for (int size : pngSizes) {
filename = QString("%1/icons/application/%2x%2/%3.png").arg(m_dataPath, QString::number(size),
combinedName);
if (QFile::exists(filename)) {
icon.addFile(filename, QSize(size, size));
}
}
filename = QString("%1/icons/application/scalable/%3.svgz").arg(m_dataPath, combinedName);
filename = QString("%1/icons/application/scalable/%2.svgz").arg(m_dataPath, combinedName);
if (QFile::exists(filename)) {
icon.addFile(filename);
}
@@ -148,17 +149,16 @@ QIcon FilePath::onOffIcon(const QString& category, const QString& name)
stateName = "on";
}
QList<int> pngSizes;
pngSizes << 16 << 22 << 24 << 32 << 48 << 64 << 128;
const QList<int> pngSizes = { 16, 22, 24, 32, 48, 64, 128 };
QString filename;
Q_FOREACH (int size, pngSizes) {
for (int size : pngSizes) {
filename = QString("%1/icons/application/%2x%2/%3-%4.png").arg(m_dataPath, QString::number(size),
combinedName, stateName);
if (QFile::exists(filename)) {
icon.addFile(filename, QSize(size, size), QIcon::Normal, state);
}
}
filename = QString("%1/icons/application/scalable/%3-%4.svgz").arg(m_dataPath, combinedName, stateName);
filename = QString("%1/icons/application/scalable/%2-%3.svgz").arg(m_dataPath, combinedName, stateName);
if (QFile::exists(filename)) {
icon.addFile(filename, QSize(), QIcon::Normal, state);
}

View File

@@ -22,8 +22,6 @@
#include <QIcon>
#include <QString>
#include "core/Global.h"
class FilePath
{
public:

View File

@@ -20,104 +20,8 @@
#ifndef KEEPASSX_GLOBAL_H
#define KEEPASSX_GLOBAL_H
// mostly copied from qcompilerdetection.h which is part of Qt 5
#include <QtGlobal>
#ifdef Q_CC_CLANG
# if __cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)
# if __has_feature(cxx_strong_enums)
# define COMPILER_CLASS_ENUM
# endif
# if __has_feature(cxx_constexpr)
# define COMPILER_CONSTEXPR
# endif
# if __has_feature(cxx_decltype) /* && __has_feature(cxx_decltype_incomplete_return_types) */
# define COMPILER_DECLTYPE
# endif
# if __has_feature(cxx_override_control)
# define COMPILER_EXPLICIT_OVERRIDES
# endif
# if __has_feature(cxx_nullptr)
# define COMPILER_NULLPTR
# endif
# if __has_feature(cxx_static_assert)
# define COMPILER_STATIC_ASSERT
# endif
# endif
#endif // Q_CC_CLANG
#if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && !defined(Q_CC_CLANG)
# if defined(__GXX_EXPERIMENTAL_CXX0X__) || __cplusplus >= 201103L
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 403
# define COMPILER_DECLTYPE
# define COMPILER_STATIC_ASSERT
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 404
# define COMPILER_CLASS_ENUM
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
# define COMPILER_CONSTEXPR
# define COMPILER_NULLPTR
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 407
# define COMPILER_EXPLICIT_OVERRIDES
# endif
# endif
#endif
/*
* C++11 keywords and expressions
*/
#if !defined(Q_NULLPTR)
# ifdef COMPILER_NULLPTR
# define Q_NULLPTR nullptr
# else
# define Q_NULLPTR 0
# endif
#endif
#if !defined(Q_DECL_CONSTEXPR)
# ifdef COMPILER_CONSTEXPR
# define Q_DECL_CONSTEXPR constexpr
# else
# define Q_DECL_CONSTEXPR
# endif
#endif
#if !defined(Q_DECL_OVERRIDE) && !defined(Q_DECL_FINAL) && !defined(Q_DECL_FINAL_CLASS)
# ifdef COMPILER_EXPLICIT_OVERRIDES
# define Q_DECL_OVERRIDE override
# define Q_DECL_FINAL final
# ifdef COMPILER_DECLTYPE
# define Q_DECL_FINAL_CLASS final
# else
# define Q_DECL_FINAL_CLASS
# endif
# else
# define Q_DECL_OVERRIDE
# define Q_DECL_FINAL
# define Q_DECL_FINAL_CLASS
# endif
#endif
#if !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
#ifdef COMPILER_STATIC_ASSERT
#define Q_STATIC_ASSERT(Condition) static_assert(static_cast<bool>(Condition), #Condition)
#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(static_cast<bool>(Condition), Message)
#else
// Intentionally undefined
template <bool Test> class QStaticAssertFailure;
template <> class QStaticAssertFailure<true> {};
#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B)
#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B
#define Q_STATIC_ASSERT(Condition) \
enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<!!(Condition)>)}
#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition)
#endif // COMPILER_STATIC_ASSERT
#endif // !defined(Q_STATIC_ASSERT) && !defined(Q_STATIC_ASSERT_X)
#if defined(Q_OS_WIN)
# if defined(KEEPASSX_BUILDING_CORE)
# define KEEPASSX_EXPORT Q_DECL_EXPORT
@@ -132,4 +36,13 @@ template <> class QStaticAssertFailure<true> {};
#define QUINT32_MAX 4294967295U
#endif
template <typename T> struct AddConst { typedef const T Type; };
// this adds const to non-const objects (like std::as_const)
template <typename T>
constexpr typename AddConst<T>::Type& asConst(T &t) noexcept { return t; }
// prevent rvalue arguments:
template <typename T>
void asConst(const T&&) = delete;
#endif // KEEPASSX_GLOBAL_H

View File

@@ -18,9 +18,9 @@
#include "Group.h"
#include "core/Config.h"
#include "core/Global.h"
#include "core/DatabaseIcons.h"
#include "core/Metadata.h"
#include "core/Tools.h"
const int Group::DefaultIconNumber = 48;
const int Group::RecycleBinIconNumber = 43;
@@ -38,19 +38,19 @@ Group::~Group()
{
// Destroy entries and children manually so DeletedObjects can be added
// to database.
QList<Entry*> entries = m_entries;
Q_FOREACH (Entry* entry, entries) {
const QList<Entry*> entries = m_entries;
for (Entry* entry : entries) {
delete entry;
}
QList<Group*> children = m_children;
Q_FOREACH (Group* group, children) {
const QList<Group*> children = m_children;
for (Group* group : children) {
delete group;
}
if (m_db && m_parent) {
DeletedObject delGroup;
delGroup.deletionTime = Tools::currentDateTimeUtc();
delGroup.deletionTime = QDateTime::currentDateTimeUtc();
delGroup.uuid = m_uuid;
m_db->addDeletedObject(delGroup);
}
@@ -84,8 +84,8 @@ template <class P, class V> inline bool Group::set(P& property, const V& value)
void Group::updateTimeinfo()
{
if (m_updateTimeinfo) {
m_data.timeInfo.setLastModificationTime(Tools::currentDateTimeUtc());
m_data.timeInfo.setLastAccessTime(Tools::currentDateTimeUtc());
m_data.timeInfo.setLastModificationTime(QDateTime::currentDateTimeUtc());
m_data.timeInfo.setLastAccessTime(QDateTime::currentDateTimeUtc());
}
}
@@ -134,13 +134,30 @@ QPixmap Group::iconPixmap() const
else {
Q_ASSERT(m_db);
QPixmap pixmap;
if (m_db && !QPixmapCache::find(m_pixmapCacheKey, &pixmap)) {
pixmap = QPixmap::fromImage(m_db->metadata()->customIcon(m_data.customIcon));
m_pixmapCacheKey = QPixmapCache::insert(pixmap);
if (m_db) {
return m_db->metadata()->customIconPixmap(m_data.customIcon);
}
else {
return QPixmap();
}
}
}
return pixmap;
QPixmap Group::iconScaledPixmap() const
{
if (m_data.customIcon.isNull()) {
// built-in icons are 16x16 so don't need to be scaled
return databaseIcons()->iconPixmap(m_data.iconNumber);
}
else {
Q_ASSERT(m_db);
if (m_db) {
return m_db->metadata()->customIconScaledPixmap(m_data.customIcon);
}
else {
return QPixmap();
}
}
}
@@ -186,7 +203,7 @@ Entry* Group::lastTopVisibleEntry() const
bool Group::isExpired() const
{
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < Tools::currentDateTimeUtc();
return m_data.timeInfo.expires() && m_data.timeInfo.expiryTime() < QDateTime::currentDateTimeUtc();
}
void Group::setUuid(const Uuid& uuid)
@@ -214,8 +231,6 @@ void Group::setIcon(int iconNumber)
m_data.iconNumber = iconNumber;
m_data.customIcon = Uuid();
m_pixmapCacheKey = QPixmapCache::Key();
updateTimeinfo();
Q_EMIT modified();
Q_EMIT dataChanged(this);
@@ -230,8 +245,6 @@ void Group::setIcon(const Uuid& uuid)
m_data.customIcon = uuid;
m_data.iconNumber = 0;
m_pixmapCacheKey = QPixmapCache::Key();
updateTimeinfo();
Q_EMIT modified();
Q_EMIT dataChanged(this);
@@ -352,7 +365,7 @@ void Group::setParent(Group* parent, int index)
}
if (m_updateTimeinfo) {
m_data.timeInfo.setLocationChanged(Tools::currentDateTimeUtc());
m_data.timeInfo.setLocationChanged(QDateTime::currentDateTimeUtc());
}
Q_EMIT modified();
@@ -372,7 +385,7 @@ void Group::setParent(Database* db)
cleanupParent();
m_parent = Q_NULLPTR;
m_parent = nullptr;
recSetDatabase(db);
QObject::setParent(db);
@@ -415,12 +428,12 @@ QList<Entry*> Group::entriesRecursive(bool includeHistoryItems) const
entryList.append(m_entries);
if (includeHistoryItems) {
Q_FOREACH (Entry* entry, m_entries) {
for (Entry* entry : m_entries) {
entryList.append(entry->historyItems());
}
}
Q_FOREACH (Group* group, m_children) {
for (Group* group : m_children) {
entryList.append(group->entriesRecursive(includeHistoryItems));
}
@@ -434,7 +447,7 @@ QList<const Group*> Group::groupsRecursive(bool includeSelf) const
groupList.append(this);
}
Q_FOREACH (const Group* group, m_children) {
for (const Group* group : m_children) {
groupList.append(group->groupsRecursive(true));
}
@@ -448,7 +461,7 @@ QList<Group*> Group::groupsRecursive(bool includeSelf)
groupList.append(this);
}
Q_FOREACH (Group* group, m_children) {
for (Group* group : asConst(m_children)) {
groupList.append(group->groupsRecursive(true));
}
@@ -463,13 +476,14 @@ QSet<Uuid> Group::customIconsRecursive() const
result.insert(iconUuid());
}
Q_FOREACH (Entry* entry, entriesRecursive(true)) {
const QList<Entry*> entryList = entriesRecursive(true);
for (Entry* entry : entryList) {
if (!entry->iconUuid().isNull()) {
result.insert(entry->iconUuid());
}
}
Q_FOREACH (Group* group, m_children) {
for (Group* group : m_children) {
result.unite(group->customIconsRecursive());
}
@@ -485,19 +499,21 @@ Group* Group::clone(Entry::CloneFlags entryFlags) const
clonedGroup->setUuid(Uuid::random());
clonedGroup->m_data = m_data;
Q_FOREACH (Entry* entry, entries()) {
const QList<Entry*> entryList = entries();
for (Entry* entry : entryList) {
Entry* clonedEntry = entry->clone(entryFlags);
clonedEntry->setGroup(clonedGroup);
}
Q_FOREACH (Group* groupChild, children()) {
Group* clonedGroupChild = groupChild->clone();
const QList<Group*> childrenGroups = children();
for (Group* groupChild : childrenGroups) {
Group* clonedGroupChild = groupChild->clone(entryFlags);
clonedGroupChild->setParent(clonedGroup);
}
clonedGroup->setUpdateTimeinfo(true);
QDateTime now = Tools::currentDateTimeUtc();
QDateTime now = QDateTime::currentDateTimeUtc();
clonedGroup->m_data.timeInfo.setCreationTime(now);
clonedGroup->m_data.timeInfo.setLastModificationTime(now);
clonedGroup->m_data.timeInfo.setLastAccessTime(now);
@@ -557,7 +573,7 @@ void Group::recSetDatabase(Database* db)
disconnect(SIGNAL(modified()), m_db);
}
Q_FOREACH (Entry* entry, m_entries) {
for (Entry* entry : asConst(m_entries)) {
if (m_db) {
entry->disconnect(m_db);
}
@@ -579,7 +595,7 @@ void Group::recSetDatabase(Database* db)
m_db = db;
Q_FOREACH (Group* group, m_children) {
for (Group* group : asConst(m_children)) {
group->recSetDatabase(db);
}
}
@@ -597,11 +613,11 @@ void Group::cleanupParent()
void Group::recCreateDelObjects()
{
if (m_db) {
Q_FOREACH (Entry* entry, m_entries) {
for (Entry* entry : asConst(m_entries)) {
m_db->addDeletedObject(entry->uuid());
}
Q_FOREACH (Group* group, m_children) {
for (Group* group : asConst(m_children)) {
group->recCreateDelObjects();
}
m_db->addDeletedObject(m_uuid);

View File

@@ -58,6 +58,7 @@ public:
QString notes() const;
QImage icon() const;
QPixmap iconPixmap() const;
QPixmap iconScaledPixmap() const;
int iconNumber() const;
Uuid iconUuid() const;
TimeInfo timeInfo() const;
@@ -155,7 +156,6 @@ private:
QList<Entry*> m_entries;
QPointer<Group> m_parent;
mutable QPixmapCache::Key m_pixmapCacheKey;
bool m_updateTimeinfo;

View File

@@ -21,8 +21,6 @@
#include <QMutex>
#include <QObject>
#include "core/Global.h"
class QTimer;
class InactivityTimer : public QObject
@@ -30,7 +28,7 @@ class InactivityTimer : public QObject
Q_OBJECT
public:
explicit InactivityTimer(QObject* parent = Q_NULLPTR);
explicit InactivityTimer(QObject* parent = nullptr);
void setInactivityTimeout(int inactivityTimeout);
void activate();
void deactivate();

View File

@@ -42,7 +42,7 @@ Metadata::Metadata(QObject* parent)
m_data.protectNotes = false;
// m_data.autoEnableVisualHiding = false;
QDateTime now = Tools::currentDateTimeUtc();
QDateTime now = QDateTime::currentDateTimeUtc();
m_data.nameChanged = now;
m_data.descriptionChanged = now;
m_data.defaultUserNameChanged = now;
@@ -67,7 +67,7 @@ template <class P, class V> bool Metadata::set(P& property, const V& value, QDat
if (property != value) {
property = value;
if (m_updateDatetime) {
dateTime = Tools::currentDateTimeUtc();
dateTime = QDateTime::currentDateTimeUtc();
}
Q_EMIT modified();
return true;
@@ -167,6 +167,43 @@ QImage Metadata::customIcon(const Uuid& uuid) const
return m_customIcons.value(uuid);
}
QPixmap Metadata::customIconPixmap(const Uuid& uuid) const
{
QPixmap pixmap;
if (!m_customIcons.contains(uuid)) {
return pixmap;
}
QPixmapCache::Key& cacheKey = m_customIconCacheKeys[uuid];
if (!QPixmapCache::find(cacheKey, &pixmap)) {
pixmap = QPixmap::fromImage(m_customIcons.value(uuid));
cacheKey = QPixmapCache::insert(pixmap);
}
return pixmap;
}
QPixmap Metadata::customIconScaledPixmap(const Uuid& uuid) const
{
QPixmap pixmap;
if (!m_customIcons.contains(uuid)) {
return pixmap;
}
QPixmapCache::Key& cacheKey = m_customIconScaledCacheKeys[uuid];
if (!QPixmapCache::find(cacheKey, &pixmap)) {
QImage image = m_customIcons.value(uuid).scaled(16, 16, Qt::KeepAspectRatio, Qt::SmoothTransformation);
pixmap = QPixmap::fromImage(image);
cacheKey = QPixmapCache::insert(pixmap);
}
return pixmap;
}
bool Metadata::containsCustomIcon(const Uuid& uuid) const
{
return m_customIcons.contains(uuid);
@@ -177,6 +214,17 @@ QHash<Uuid, QImage> Metadata::customIcons() const
return m_customIcons;
}
QHash<Uuid, QPixmap> Metadata::customIconsScaledPixmaps() const
{
QHash<Uuid, QPixmap> result;
for (const Uuid& uuid : m_customIconsOrder) {
result.insert(uuid, customIconScaledPixmap(uuid));
}
return result;
}
QList<Uuid> Metadata::customIconsOrder() const
{
return m_customIconsOrder;
@@ -338,6 +386,9 @@ void Metadata::addCustomIcon(const Uuid& uuid, const QImage& icon)
Q_ASSERT(!m_customIcons.contains(uuid));
m_customIcons.insert(uuid, icon);
// reset cache in case there is also an icon with that uuid
m_customIconCacheKeys[uuid] = QPixmapCache::Key();
m_customIconScaledCacheKeys[uuid] = QPixmapCache::Key();
m_customIconsOrder.append(uuid);
Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
Q_EMIT modified();
@@ -365,6 +416,10 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
Q_ASSERT(m_customIcons.contains(uuid));
m_customIcons.remove(uuid);
QPixmapCache::remove(m_customIconCacheKeys.value(uuid));
m_customIconCacheKeys.remove(uuid);
QPixmapCache::remove(m_customIconScaledCacheKeys.value(uuid));
m_customIconScaledCacheKeys.remove(uuid);
m_customIconsOrder.removeAll(uuid);
Q_ASSERT(m_customIcons.count() == m_customIconsOrder.count());
Q_EMIT modified();
@@ -372,7 +427,7 @@ void Metadata::removeCustomIcon(const Uuid& uuid)
void Metadata::copyCustomIcons(const QSet<Uuid>& iconList, const Metadata* otherMetadata)
{
Q_FOREACH (const Uuid& uuid, iconList) {
for (const Uuid& uuid : iconList) {
Q_ASSERT(otherMetadata->containsCustomIcon(uuid));
if (!containsCustomIcon(uuid) && otherMetadata->containsCustomIcon(uuid)) {

View File

@@ -22,9 +22,10 @@
#include <QDateTime>
#include <QHash>
#include <QImage>
#include <QPixmap>
#include <QPixmapCache>
#include <QPointer>
#include "core/Global.h"
#include "core/Uuid.h"
class Database;
@@ -35,7 +36,7 @@ class Metadata : public QObject
Q_OBJECT
public:
explicit Metadata(QObject* parent = Q_NULLPTR);
explicit Metadata(QObject* parent = nullptr);
struct MetadataData
{
@@ -78,10 +79,13 @@ public:
bool protectNotes() const;
// bool autoEnableVisualHiding() const;
QImage customIcon(const Uuid& uuid) const;
QPixmap customIconPixmap(const Uuid& uuid) const;
QPixmap customIconScaledPixmap(const Uuid& uuid) const;
bool containsCustomIcon(const Uuid& uuid) const;
QHash<Uuid, QImage> customIcons() const;
QList<Uuid> customIconsOrder() const;
bool recycleBinEnabled() const;
QHash<Uuid, QPixmap> customIconsScaledPixmaps() const;
Group* recycleBin();
const Group* recycleBin() const;
QDateTime recycleBinChanged() const;
@@ -153,6 +157,8 @@ private:
MetadataData m_data;
QHash<Uuid, QImage> m_customIcons;
mutable QHash<Uuid, QPixmapCache::Key> m_customIconCacheKeys;
mutable QHash<Uuid, QPixmapCache::Key> m_customIconScaledCacheKeys;
QList<Uuid> m_customIconsOrder;
QPointer<Group> m_recycleBin;

View File

@@ -45,11 +45,11 @@ QString PasswordGenerator::generatePassword() const
{
Q_ASSERT(isValid());
QVector<PasswordGroup> groups = passwordGroups();
const QVector<PasswordGroup> groups = passwordGroups();
QVector<QChar> passwordChars;
Q_FOREACH (const PasswordGroup& group, groups) {
Q_FOREACH (QChar ch, group) {
for (const PasswordGroup& group : groups) {
for (QChar ch : group) {
passwordChars.append(ch);
}
}
@@ -89,6 +89,22 @@ QString PasswordGenerator::generatePassword() const
return password;
}
int PasswordGenerator::getbits() const
{
QVector<PasswordGroup> groups = passwordGroups();
int bits = 0;
QVector<QChar> passwordChars;
Q_FOREACH (const PasswordGroup& group, groups) {
bits += group.size();
}
bits *= m_length;
return bits;
}
bool PasswordGenerator::isValid() const
{
if (m_classes == 0) {

View File

@@ -22,8 +22,6 @@
#include <QString>
#include <QVector>
#include "core/Global.h"
typedef QVector<QChar> PasswordGroup;
class PasswordGenerator
@@ -55,6 +53,7 @@ public:
bool isValid() const;
QString generatePassword() const;
int getbits() const;
private:
QVector<PasswordGroup> passwordGroups() const;

View File

@@ -17,6 +17,8 @@
#include "SignalMultiplexer.h"
#include "core/Global.h"
SignalMultiplexer::SignalMultiplexer()
{
}
@@ -24,7 +26,7 @@ SignalMultiplexer::SignalMultiplexer()
SignalMultiplexer::~SignalMultiplexer()
{
// disconnect all connections
setCurrentObject(Q_NULLPTR);
setCurrentObject(nullptr);
}
QObject* SignalMultiplexer::currentObject() const
@@ -45,7 +47,7 @@ void SignalMultiplexer::setCurrentObject(QObject* object)
}
if (m_currentObject) {
Q_FOREACH (const Connection& con, m_connections) {
for (const Connection& con : asConst(m_connections)) {
disconnect(con);
}
}
@@ -53,7 +55,7 @@ void SignalMultiplexer::setCurrentObject(QObject* object)
m_currentObject = object;
if (object) {
Q_FOREACH (const Connection& con, m_connections) {
for (const Connection& con : asConst(m_connections)) {
connect(con);
}
}

View File

@@ -21,8 +21,6 @@
#include <QObject>
#include <QPointer>
#include "core/Global.h"
class SignalMultiplexer
{
public:

View File

@@ -23,7 +23,7 @@ TimeInfo::TimeInfo()
: m_expires(false)
, m_usageCount(0)
{
QDateTime now = Tools::currentDateTimeUtc();
QDateTime now = QDateTime::currentDateTimeUtc();
m_lastModificationTime = now;
m_creationTime = now;
m_lastAccessTime = now;

View File

@@ -23,14 +23,10 @@
#include <QLocale>
#include <QStringList>
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
#include <QElapsedTimer>
#else
#include <QTime>
#endif
#ifdef Q_OS_WIN
#include <windows.h> // for Sleep()
#include <windows.h> // for Sleep(), SetDllDirectoryA() and SetSearchPathMode()
#endif
#ifdef Q_OS_UNIX
@@ -75,7 +71,9 @@ bool hasChild(const QObject* parent, const QObject* child)
if (!parent || !child) {
return false;
}
Q_FOREACH (QObject* c, parent->children()) {
const QObjectList children = parent->children();
for (QObject* c : children) {
if (child == c || hasChild(c, child)) {
return true;
}
@@ -122,21 +120,12 @@ bool readAllFromDevice(QIODevice* device, QByteArray& data)
}
}
QDateTime currentDateTimeUtc()
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
return QDateTime::currentDateTimeUtc();
#else
return QDateTime::currentDateTime().toUTC();
#endif
}
QString imageReaderFilter()
{
QList<QByteArray> formats = QImageReader::supportedImageFormats();
const QList<QByteArray> formats = QImageReader::supportedImageFormats();
QStringList formatsStringList;
Q_FOREACH (const QByteArray& format, formats) {
for (const QByteArray& format : formats) {
for (int i = 0; i < format.size(); i++) {
if (!QChar(format.at(i)).isLetterOrNumber()) {
continue;
@@ -151,7 +140,7 @@ QString imageReaderFilter()
bool isHex(const QByteArray& ba)
{
Q_FOREACH (char c, ba) {
for (char c : ba) {
if ( !( (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) ) {
return false;
}
@@ -160,6 +149,16 @@ bool isHex(const QByteArray& ba)
return true;
}
bool isBase64(const QByteArray& ba)
{
QRegExp regexp("^(?:[a-z0-9+/]{4})*(?:[a-z0-9+/]{3}=|[a-z0-9+/]{2}==)?$",
Qt::CaseInsensitive, QRegExp::RegExp2);
QString base64 = QString::fromLatin1(ba.constData(), ba.size());
return regexp.exactMatch(base64);
}
void sleep(int ms)
{
Q_ASSERT(ms >= 0);
@@ -174,7 +173,7 @@ void sleep(int ms)
timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000 * 1000;
nanosleep(&ts, Q_NULLPTR);
nanosleep(&ts, nullptr);
#endif
}
@@ -186,11 +185,7 @@ void wait(int ms)
return;
}
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
QElapsedTimer timer;
#else
QTime timer;
#endif
timer.start();
if (ms <= 50) {
@@ -205,23 +200,10 @@ void wait(int ms)
QCoreApplication::processEvents(QEventLoop::AllEvents, timeLeft);
sleep(10);
}
} while (timer.elapsed() < ms);
} while (!timer.hasExpired(ms));
}
}
QString platform()
{
#if defined(Q_WS_X11)
return "x11";
#elif defined(Q_WS_MAC)
return "mac";
#elif defined(Q_WS_WIN)
return "win";
#else
return QString();
#endif
}
void disableCoreDumps()
{
// default to true
@@ -249,4 +231,13 @@ void disableCoreDumps()
}
}
void setupSearchPaths()
{
#ifdef Q_OS_WIN
// Make sure Windows doesn't load DLLs from the current working directory
SetDllDirectoryA("");
SetSearchPathMode(BASE_SEARCH_PATH_ENABLE_SAFE_SEARCHMODE);
#endif
}
} // namespace Tools

View File

@@ -18,11 +18,13 @@
#ifndef KEEPASSX_TOOLS_H
#define KEEPASSX_TOOLS_H
#include "core/Global.h"
#include <QDateTime>
#include <QObject>
#include <QString>
#include "core/Global.h"
#include <algorithm>
class QIODevice;
@@ -32,13 +34,26 @@ QString humanReadableFileSize(qint64 bytes);
bool hasChild(const QObject* parent, const QObject* child);
bool readFromDevice(QIODevice* device, QByteArray& data, int size = 16384);
bool readAllFromDevice(QIODevice* device, QByteArray& data);
QDateTime currentDateTimeUtc();
QString imageReaderFilter();
bool isHex(const QByteArray& ba);
bool isBase64(const QByteArray& ba);
void sleep(int ms);
void wait(int ms);
QString platform();
void disableCoreDumps();
void setupSearchPaths();
template <typename RandomAccessIterator, typename T>
RandomAccessIterator binaryFind(RandomAccessIterator begin, RandomAccessIterator end, const T& value)
{
RandomAccessIterator it = std::lower_bound(begin, end, value);
if ((it == end) || (value < *it)) {
return end;
}
else {
return it;
}
}
} // namespace Tools

View File

@@ -49,18 +49,20 @@ void Translator::installTranslator()
QList<QPair<QString, QString> > Translator::availableLanguages()
{
QStringList paths;
const QStringList paths = {
#ifdef QT_DEBUG
paths.append(QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR));
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
#endif
paths.append(filePath()->dataPath("translations"));
filePath()->dataPath("translations")
};
QList<QPair<QString, QString> > languages;
languages.append(QPair<QString, QString>("system", "System default"));
QRegExp regExp("keepassx_([a-zA-Z_]+)\\.qm", Qt::CaseInsensitive, QRegExp::RegExp2);
Q_FOREACH (const QString& path, paths) {
Q_FOREACH (const QString& filename, QDir(path).entryList()) {
for (const QString& path : paths) {
const QStringList fileList = QDir(path).entryList();
for (const QString& filename : fileList) {
if (regExp.exactMatch(filename)) {
QString langcode = regExp.cap(1);
if (langcode == "en_plurals") {
@@ -85,13 +87,14 @@ QList<QPair<QString, QString> > Translator::availableLanguages()
bool Translator::installTranslator(const QString& language)
{
QStringList paths;
const QStringList paths = {
#ifdef QT_DEBUG
paths.append(QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR));
QString("%1/share/translations").arg(KEEPASSX_BINARY_DIR),
#endif
paths.append(filePath()->dataPath("translations"));
filePath()->dataPath("translations")
};
Q_FOREACH (const QString& path, paths) {
for (const QString& path : paths) {
if (installTranslator(language, path)) {
return true;
}
@@ -116,7 +119,7 @@ bool Translator::installTranslator(const QString& language, const QString& path)
bool Translator::installQtTranslator(const QString& language)
{
QTranslator* qtTranslator = new QTranslator(qApp);
if (qtTranslator->load(QString("%1/qt_%2").arg(QLibraryInfo::location(QLibraryInfo::TranslationsPath), language))) {
if (qtTranslator->load(QString("%1/qtbase_%2").arg(QLibraryInfo::location(QLibraryInfo::TranslationsPath), language))) {
QCoreApplication::installTranslator(qtTranslator);
return true;
}

View File

@@ -89,6 +89,12 @@ Uuid Uuid::fromBase64(const QString& str)
return Uuid(data);
}
Uuid Uuid::fromHex(const QString& str)
{
QByteArray data = QByteArray::fromHex(str.toLatin1());
return Uuid(data);
}
uint qHash(const Uuid& key)
{
return qHash(key.toByteArray());

View File

@@ -37,6 +37,7 @@ public:
bool operator!=(const Uuid& other) const;
static const int Length;
static Uuid fromBase64(const QString& str);
static Uuid fromHex(const QString& str);
private:
QByteArray m_data;

View File

@@ -1,305 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Copyright (C) 2013 David Faure <faure@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcommandlineoption.h"
#include <QSet>
class QCommandLineOptionPrivate : public QSharedData
{
public:
inline QCommandLineOptionPrivate()
{ }
void setNames(const QStringList &nameList);
//! The list of names used for this option.
QStringList names;
//! The documentation name for the value, if one is expected
//! Example: "-o <file>" means valueName == "file"
QString valueName;
//! The description used for this option.
QString description;
//! The list of default values used for this option.
QStringList defaultValues;
};
/*!
\since 5.2
\class QCommandLineOption
\brief The QCommandLineOption class defines a possible command-line option.
\inmodule QtCore
\ingroup shared
\ingroup tools
This class is used to describe an option on the command line. It allows
different ways of defining the same option with multiple aliases possible.
It is also used to describe how the option is used - it may be a flag (e.g. \c{-v})
or take an argument (e.g. \c{-o file}).
Examples:
\snippet code/src_corelib_tools_qcommandlineoption.cpp 0
\sa QCommandLineParser
*/
/*!
Constructs a command line option object with the given arguments.
The name of the option is set to \a name.
The name can be either short or long. If the name is one character in
length, it is considered a short name. Option names must not be empty,
must not start with a dash or a slash character, must not contain a \c{=}
and cannot be repeated.
The description is set to \a description. It is customary to add a "."
at the end of the description.
In addition, the \a valueName can be set if the option expects a value.
The default value for the option is set to \a defaultValue.
\sa setDescription(), setValueName(), setDefaultValues()
*/
QCommandLineOption::QCommandLineOption(const QString &name, const QString &description,
const QString &valueName,
const QString &defaultValue)
: d(new QCommandLineOptionPrivate)
{
d->setNames(QStringList(name));
setValueName(valueName);
setDescription(description);
setDefaultValue(defaultValue);
}
/*!
Constructs a command line option object with the given arguments.
This overload allows to set multiple names for the option, for instance
\c{o} and \c{output}.
The names of the option are set to \a names.
The names can be either short or long. Any name in the list that is one
character in length is a short name. Option names must not be empty,
must not start with a dash or a slash character, must not contain a \c{=}
and cannot be repeated.
The description is set to \a description. It is customary to add a "."
at the end of the description.
In addition, the \a valueName can be set if the option expects a value.
The default value for the option is set to \a defaultValue.
\sa setDescription(), setValueName(), setDefaultValues()
*/
QCommandLineOption::QCommandLineOption(const QStringList &names, const QString &description,
const QString &valueName,
const QString &defaultValue)
: d(new QCommandLineOptionPrivate)
{
d->setNames(names);
setValueName(valueName);
setDescription(description);
setDefaultValue(defaultValue);
}
/*!
Constructs a QCommandLineOption object that is a copy of the QCommandLineOption
object \a other.
\sa operator=()
*/
QCommandLineOption::QCommandLineOption(const QCommandLineOption &other)
: d(other.d)
{
}
/*!
Destroys the command line option object.
*/
QCommandLineOption::~QCommandLineOption()
{
}
/*!
Makes a copy of the \a other object and assigns it to this QCommandLineOption
object.
*/
QCommandLineOption &QCommandLineOption::operator=(const QCommandLineOption &other)
{
d = other.d;
return *this;
}
/*!
Returns the names set for this option.
*/
QStringList QCommandLineOption::names() const
{
return d->names;
}
void QCommandLineOptionPrivate::setNames(const QStringList &nameList)
{
QStringList newNames;
if (nameList.isEmpty())
qWarning("QCommandLineOption: Options must have at least one name");
Q_FOREACH (const QString &name, nameList) {
if (name.isEmpty()) {
qWarning("QCommandLineOption: Option names cannot be empty");
} else {
const QChar c = name.at(0);
if (c == QLatin1Char('-'))
qWarning("QCommandLineOption: Option names cannot start with a '-'");
else if (c == QLatin1Char('/'))
qWarning("QCommandLineOption: Option names cannot start with a '/'");
else if (name.contains(QLatin1Char('=')))
qWarning("QCommandLineOption: Option names cannot contain a '='");
else
newNames.append(name);
}
}
// commit
names = newNames;
}
/*!
Sets the name of the expected value, for the documentation, to \a valueName.
Options without a value assigned have a boolean-like behavior:
either the user specifies --option or they don't.
Options with a value assigned need to set a name for the expected value,
for the documentation of the option in the help output. An option with names \c{o} and \c{output},
and a value name of \c{file} will appear as \c{-o, --output <file>}.
Call QCommandLineParser::argument() if you expect the option to be present
only once, and QCommandLineParser::arguments() if you expect that option
to be present multiple times.
\sa valueName()
*/
void QCommandLineOption::setValueName(const QString &valueName)
{
d->valueName = valueName;
}
/*!
Returns the name of the expected value.
If empty, the option doesn't take a value.
\sa setValueName()
*/
QString QCommandLineOption::valueName() const
{
return d->valueName;
}
/*!
Sets the description used for this option to \a description.
It is customary to add a "." at the end of the description.
The description is used by QCommandLineParser::showHelp().
\sa description()
*/
void QCommandLineOption::setDescription(const QString &description)
{
d->description = description;
}
/*!
Returns the description set for this option.
\sa setDescription()
*/
QString QCommandLineOption::description() const
{
return d->description;
}
/*!
Sets the default value used for this option to \a defaultValue.
The default value is used if the user of the application does not specify
the option on the command line.
If \a defaultValue is empty, the option has no default values.
\sa defaultValues() setDefaultValues()
*/
void QCommandLineOption::setDefaultValue(const QString &defaultValue)
{
QStringList newDefaultValues;
if (!defaultValue.isEmpty()) {
newDefaultValues << defaultValue;
}
// commit:
d->defaultValues = newDefaultValues;
}
/*!
Sets the list of default values used for this option to \a defaultValues.
The default values are used if the user of the application does not specify
the option on the command line.
\sa defaultValues() setDefaultValue()
*/
void QCommandLineOption::setDefaultValues(const QStringList &defaultValues)
{
d->defaultValues = defaultValues;
}
/*!
Returns the default values set for this option.
\sa setDefaultValues()
*/
QStringList QCommandLineOption::defaultValues() const
{
return d->defaultValues;
}

View File

@@ -1,81 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOMMANDLINEOPTION_H
#define QCOMMANDLINEOPTION_H
#include <QStringList>
#include <QSharedData>
class QCommandLineOptionPrivate;
class QCommandLineOption
{
public:
explicit QCommandLineOption(const QString &name, const QString &description = QString(),
const QString &valueName = QString(),
const QString &defaultValue = QString());
explicit QCommandLineOption(const QStringList &names, const QString &description = QString(),
const QString &valueName = QString(),
const QString &defaultValue = QString());
QCommandLineOption(const QCommandLineOption &other);
~QCommandLineOption();
QCommandLineOption &operator=(const QCommandLineOption &other);
QStringList names() const;
void setValueName(const QString &name);
QString valueName() const;
void setDescription(const QString &description);
QString description() const;
void setDefaultValue(const QString &defaultValue);
void setDefaultValues(const QStringList &defaultValues);
QStringList defaultValues() const;
private:
QSharedDataPointer<QCommandLineOptionPrivate> d;
};
#endif // QCOMMANDLINEOPTION_H

View File

@@ -1,944 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Copyright (C) 2013 David Faure <faure@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qcommandlineparser.h"
#include <QCoreApplication>
#include <QHash>
#include <QVector>
#include <stdio.h>
#include <stdlib.h>
typedef QHash<QString, int> NameHash_t;
class QCommandLineParserPrivate
{
public:
inline QCommandLineParserPrivate()
: singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions),
builtinVersionOption(false),
builtinHelpOption(false),
needsParsing(true)
{ }
bool parse(const QStringList &args);
void checkParsed(const char *method);
QStringList aliases(const QString &name) const;
QString helpText() const;
bool registerFoundOption(const QString &optionName);
bool parseOptionValue(const QString &optionName, const QString &argument,
QStringList::const_iterator *argumentIterator,
QStringList::const_iterator argsEnd);
//! Error text set when parse() returns false
QString errorText;
//! The command line options used for parsing
QList<QCommandLineOption> commandLineOptionList;
//! Hash mapping option names to their offsets in commandLineOptionList and optionArgumentList.
NameHash_t nameHash;
//! Option values found (only for options with a value)
QHash<int, QStringList> optionValuesHash;
//! Names of options found on the command line.
QStringList optionNames;
//! Arguments which did not belong to any option.
QStringList positionalArgumentList;
//! Names of options which were unknown.
QStringList unknownOptionNames;
//! Application description
QString description;
//! Documentation for positional arguments
struct PositionalArgumentDefinition
{
QString name;
QString description;
QString syntax;
};
QVector<PositionalArgumentDefinition> positionalArgumentDefinitions;
//! The parsing mode for "-abc"
QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode;
//! Whether addVersionOption was called
bool builtinVersionOption;
//! Whether addHelpOption was called
bool builtinHelpOption;
//! True if parse() needs to be called
bool needsParsing;
};
QStringList QCommandLineParserPrivate::aliases(const QString &optionName) const
{
const NameHash_t::const_iterator it = nameHash.find(optionName);
if (it == nameHash.end()) {
qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
return QStringList();
}
return commandLineOptionList.at(*it).names();
}
/*!
\since 5.2
\class QCommandLineParser
\inmodule QtCore
\ingroup tools
\brief The QCommandLineParser class provides a means for handling the
command line options.
QCoreApplication provides the command-line arguments as a simple list of strings.
QCommandLineParser provides the ability to define a set of options, parse the
command-line arguments, and store which options have actually been used, as
well as option values.
Any argument that isn't an option (i.e. doesn't start with a \c{-}) is stored
as a "positional argument".
The parser handles short names, long names, more than one name for the same
option, and option values.
Options on the command line are recognized as starting with a single or
double \c{-} character(s).
The option \c{-} (single dash alone) is a special case, often meaning standard
input, and not treated as an option. The parser will treat everything after the
option \c{--} (double dash) as positional arguments.
Short options are single letters. The option \c{v} would be specified by
passing \c{-v} on the command line. In the default parsing mode, short options
can be written in a compact form, for instance \c{-abc} is equivalent to \c{-a -b -c}.
The parsing mode for can be set to ParseAsLongOptions, in which case \c{-abc}
will be parsed as the long option \c{abc}.
Long options are more than one letter long and cannot be compacted together.
The long option \c{verbose} would be passed as \c{--verbose} or \c{-verbose}.
Passing values to options can be done using the assignment operator: \c{-v=value}
\c{--verbose=value}, or a space: \c{-v value} \c{--verbose value}, i.e. the next
argument is used as value (even if it starts with a \c{-}).
The parser does not support optional values - if an option is set to
require a value, one must be present. If such an option is placed last
and has no value, the option will be treated as if it had not been
specified.
The parser does not automatically support negating or disabling long options
by using the format \c{--disable-option} or \c{--no-option}. However, it is
possible to handle this case explicitly by making an option with \c{no-option}
as one of its names, and handling the option explicitly.
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Known limitation: the parsing of Qt options inside QCoreApplication and subclasses
happens before QCommandLineParser exists, so it can't take it into account. This
means any option value that looks like a builtin Qt option, will be treated by
QCoreApplication as a builtin Qt option. Example: \c{--profile -reverse} will
lead to QGuiApplication seeing the -reverse option set, and removing it from
QCoreApplication::arguments() before QCommandLineParser defines the \c{profile}
option and parses the command line.
\sa QCommandLineOption, QCoreApplication
*/
/*!
Constructs a command line parser object.
*/
QCommandLineParser::QCommandLineParser()
: d(new QCommandLineParserPrivate)
{
}
/*!
Destroys the command line parser object.
*/
QCommandLineParser::~QCommandLineParser()
{
delete d;
}
/*!
\enum QCommandLineParser::SingleDashWordOptionMode
This enum describes the way the parser interprets command-line
options that use a single dash followed by multiple letters, as as \c{-abc}.
\value ParseAsCompactedShortOptions \c{-abc} is interpreted as \c{-a -b -c},
i.e. as three short options that have been compacted on the command-line,
if none of the options take a value. If \c{a} takes a value, then it
is interpreted as \c{-a bc}, i.e. the short option \c{a} followed by the value \c{bc}.
This is typically used in tools that behave like compilers, in order
to handle options such as \c{-DDEFINE=VALUE} or \c{-I/include/path}.
This is the default parsing mode. New applications are recommended to
use this mode.
\value ParseAsLongOptions \c{-abc} is interpreted as \c{--abc},
i.e. as the long option named \c{abc}. This is how Qt's own tools
(uic, rcc...) have always been parsing arguments. This mode should be
used for preserving compatibility in applications that were parsing
arguments in such a way.
\sa setSingleDashWordOptionMode()
*/
/*!
Sets the parsing mode to \a singleDashWordOptionMode.
This must be called before process() or parse().
*/
void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode)
{
d->singleDashWordOptionMode = singleDashWordOptionMode;
}
/*!
Adds the option \a option to look for while parsing.
Returns \c true if adding the option was successful; otherwise returns \c false.
Adding the option fails if there is no name attached to the option, or
the option has a name that clashes with an option name added before.
*/
bool QCommandLineParser::addOption(const QCommandLineOption &option)
{
QStringList optionNames = option.names();
if (!optionNames.isEmpty()) {
Q_FOREACH (const QString &name, optionNames) {
if (d->nameHash.contains(name))
return false;
}
d->commandLineOptionList.append(option);
const int offset = d->commandLineOptionList.size() - 1;
Q_FOREACH (const QString &name, optionNames)
d->nameHash.insert(name, offset);
return true;
}
return false;
}
/*!
Adds the \c{-v} / \c{--version} option, which displays the version string of the application.
This option is handled automatically by QCommandLineParser.
You can set the actual version string by using QCoreApplication::setApplicationVersion().
Returns the option instance, which can be used to call isSet().
*/
QCommandLineOption QCommandLineParser::addVersionOption()
{
QCommandLineOption opt(QStringList() << "v" << "version", tr("Displays version information."));
addOption(opt);
d->builtinVersionOption = true;
return opt;
}
/*!
Adds the help option (\c{-h}, \c{--help} and \c{-?} on Windows)
This option is handled automatically by QCommandLineParser.
Remember to use setApplicationDescription to set the application description,
which will be displayed when this option is used.
Example:
\snippet code/src_corelib_tools_qcommandlineparser_main.cpp 0
Returns the option instance, which can be used to call isSet().
*/
QCommandLineOption QCommandLineParser::addHelpOption()
{
QCommandLineOption opt(QStringList()
#ifdef Q_OS_WIN
<< "?"
#endif
<< "h"
<< "help", tr("Displays this help."));
addOption(opt);
d->builtinHelpOption = true;
return opt;
}
/*!
Sets the application \a description shown by helpText().
*/
void QCommandLineParser::setApplicationDescription(const QString &description)
{
d->description = description;
}
/*!
Returns the application description set in setApplicationDescription().
*/
QString QCommandLineParser::applicationDescription() const
{
return d->description;
}
/*!
Defines an additional argument to the application, for the benefit of the help text.
The argument \a name and \a description will appear under the \c{Arguments:} section
of the help. If \a syntax is specified, it will be appended to the Usage line, otherwise
the \a name will be appended.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 2
\sa addHelpOption(), helpText()
*/
void QCommandLineParser::addPositionalArgument(const QString &name, const QString &description, const QString &syntax)
{
QCommandLineParserPrivate::PositionalArgumentDefinition arg;
arg.name = name;
arg.description = description;
arg.syntax = syntax.isEmpty() ? name : syntax;
d->positionalArgumentDefinitions.append(arg);
}
/*!
Clears the definitions of additional arguments from the help text.
This is only needed for the special case of tools which support multiple commands
with different options. Once the actual command has been identified, the options
for this command can be defined, and the help text for the command can be adjusted
accordingly.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 3
*/
void QCommandLineParser::clearPositionalArguments()
{
d->positionalArgumentDefinitions.clear();
}
/*!
Parses the command line \a arguments.
Most programs don't need to call this, a simple call to process() is enough.
parse() is more low-level, and only does the parsing. The application will have to
take care of the error handling, using errorText() if parse() returns \c false.
This can be useful for instance to show a graphical error message in graphical programs.
Calling parse() instead of process() can also be useful in order to ignore unknown
options temporarily, because more option definitions will be provided later on
(depending on one of the arguments), before calling process().
Don't forget that \a arguments must start with the name of the executable (ignored, though).
Returns \c false in case of a parse error (unknown option or missing value); returns \c true otherwise.
\sa process()
*/
bool QCommandLineParser::parse(const QStringList &arguments)
{
return d->parse(arguments);
}
/*!
Returns a translated error text for the user.
This should only be called when parse() returns \c false.
*/
QString QCommandLineParser::errorText() const
{
if (!d->errorText.isEmpty())
return d->errorText;
if (d->unknownOptionNames.count() == 1)
return tr("Unknown option '%1'.").arg(d->unknownOptionNames.first());
if (d->unknownOptionNames.count() > 1)
return tr("Unknown options: %1.").arg(d->unknownOptionNames.join(", "));
return QString();
}
/*!
Processes the command line \a arguments.
In addition to parsing the options (like parse()), this function also handles the builtin
options and handles errors.
The builtin options are \c{--version} if addVersionOption was called and \c{--help} if addHelpOption was called.
When invoking one of these options, or when an error happens (for instance an unknown option was
passed), the current process will then stop, using the exit() function.
\sa QCoreApplication::arguments(), parse()
*/
void QCommandLineParser::process(const QStringList &arguments)
{
if (!d->parse(arguments)) {
fprintf(stderr, "%s\n", qPrintable(errorText()));
::exit(EXIT_FAILURE);
}
if (d->builtinVersionOption && isSet("version")) {
printf("%s %s\n", qPrintable(QCoreApplication::applicationName()), qPrintable(QCoreApplication::applicationVersion()));
::exit(EXIT_SUCCESS);
}
if (d->builtinHelpOption && isSet("help"))
showHelp(EXIT_SUCCESS);
}
/*!
\overload
The command line is obtained from the QCoreApplication instance \a app.
*/
void QCommandLineParser::process(const QCoreApplication &app)
{
// QCoreApplication::arguments() is static, but the app instance must exist so we require it as parameter
Q_UNUSED(app);
process(QCoreApplication::arguments());
}
void QCommandLineParserPrivate::checkParsed(const char *method)
{
if (needsParsing)
qWarning("QCommandLineParser: call process() or parse() before %s", method);
}
/*!
\internal
Looks up the option \a optionName (found on the command line) and register it as found.
Returns \c true on success.
*/
bool QCommandLineParserPrivate::registerFoundOption(const QString &optionName)
{
if (nameHash.contains(optionName)) {
optionNames.append(optionName);
return true;
} else {
unknownOptionNames.append(optionName);
return false;
}
}
/*!
\internal
\brief Parse the value for a given option, if it was defined to expect one.
The value is taken from the next argument, or after the equal sign in \a argument.
\param optionName the short option name
\param argument the argument from the command line currently parsed. Only used for -k=value parsing.
\param argumentIterator iterator to the currently parsed argument. Incremented if the next argument contains the value.
\param argsEnd args.end(), to check if ++argumentIterator goes out of bounds
Returns \c true on success.
*/
bool QCommandLineParserPrivate::parseOptionValue(const QString &optionName, const QString &argument,
QStringList::const_iterator *argumentIterator, QStringList::const_iterator argsEnd)
{
const QLatin1Char assignChar('=');
const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
if (nameHashIt != nameHash.constEnd()) {
const int assignPos = argument.indexOf(assignChar);
const NameHash_t::mapped_type optionOffset = *nameHashIt;
const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
if (withValue) {
if (assignPos == -1) {
++(*argumentIterator);
if (*argumentIterator == argsEnd) {
errorText = QCommandLineParser::tr("Missing value after '%1'.").arg(argument);
return false;
}
optionValuesHash[optionOffset].append(*(*argumentIterator));
} else {
optionValuesHash[optionOffset].append(argument.mid(assignPos + 1));
}
} else {
if (assignPos != -1) {
errorText = QCommandLineParser::tr("Unexpected value after '%1'.").arg(argument.left(assignPos));
return false;
}
}
}
return true;
}
/*!
\internal
Parse the list of arguments \a args, and fills in
optionNames, optionValuesHash, unknownOptionNames, positionalArguments, and errorText.
Any results from a previous parse operation are removed.
The parser will not look for further options once it encounters the option
\c{--}; this does not include when \c{--} follows an option that requires a value.
*/
bool QCommandLineParserPrivate::parse(const QStringList &args)
{
needsParsing = false;
bool error = false;
const QString doubleDashString("--");
const QLatin1Char dashChar('-');
const QLatin1Char assignChar('=');
bool doubleDashFound = false;
errorText.clear();
positionalArgumentList.clear();
optionNames.clear();
unknownOptionNames.clear();
optionValuesHash.clear();
if (args.isEmpty()) {
qWarning("QCommandLineParser: argument list cannot be empty, it should contain at least the executable name");
return false;
}
QStringList::const_iterator argumentIterator = args.begin();
++argumentIterator; // skip executable name
for (; argumentIterator != args.end() ; ++argumentIterator) {
QString argument = *argumentIterator;
if (doubleDashFound) {
positionalArgumentList.append(argument);
} else if (argument.startsWith(doubleDashString)) {
if (argument.length() > 2) {
QString optionName = argument.mid(2).section(assignChar, 0, 0);
if (registerFoundOption(optionName)) {
if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
} else {
error = true;
}
} else {
doubleDashFound = true;
}
} else if (argument.startsWith(dashChar)) {
if (argument.size() == 1) { // single dash ("stdin")
positionalArgumentList.append(argument);
continue;
}
switch (singleDashWordOptionMode) {
case QCommandLineParser::ParseAsCompactedShortOptions:
{
QString optionName;
bool valueFound = false;
for (int pos = 1 ; pos < argument.size(); ++pos) {
optionName = argument.mid(pos, 1);
if (!registerFoundOption(optionName)) {
error = true;
} else {
const NameHash_t::const_iterator nameHashIt = nameHash.constFind(optionName);
Q_ASSERT(nameHashIt != nameHash.constEnd()); // checked by registerFoundOption
const NameHash_t::mapped_type optionOffset = *nameHashIt;
const bool withValue = !commandLineOptionList.at(optionOffset).valueName().isEmpty();
if (withValue) {
if (pos + 1 < argument.size()) {
if (argument.at(pos + 1) == assignChar)
++pos;
optionValuesHash[optionOffset].append(argument.mid(pos + 1));
valueFound = true;
}
break;
}
if (pos + 1 < argument.size() && argument.at(pos + 1) == assignChar)
break;
}
}
if (!valueFound && !parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
break;
}
case QCommandLineParser::ParseAsLongOptions:
{
const QString optionName = argument.mid(1).section(assignChar, 0, 0);
if (registerFoundOption(optionName)) {
if (!parseOptionValue(optionName, argument, &argumentIterator, args.end()))
error = true;
} else {
error = true;
}
break;
}
}
} else {
positionalArgumentList.append(argument);
}
if (argumentIterator == args.end())
break;
}
return !error;
}
/*!
Checks whether the option \a name was passed to the application.
Returns \c true if the option \a name was set, false otherwise.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present,
false is returned.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 0
*/
bool QCommandLineParser::isSet(const QString &name) const
{
d->checkParsed("isSet");
if (d->optionNames.contains(name))
return true;
const QStringList aliases = d->aliases(name);
Q_FOREACH (const QString &optionName, d->optionNames) {
if (aliases.contains(optionName))
return true;
}
return false;
}
/*!
Returns the option value found for the given option name \a optionName, or
an empty string if not found.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the option names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty string is returned.
For options found by the parser, the last value found for
that option is returned. If the option wasn't specified on the command line,
the default value is returned.
An empty string is returned if the option does not take a value.
\sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QString &optionName) const
{
d->checkParsed("value");
const QStringList valueList = values(optionName);
if (!valueList.isEmpty())
return valueList.last();
return QString();
}
/*!
Returns a list of option values found for the given option name \a
optionName, or an empty list if not found.
The name provided can be any long or short name of any option that was
added with \c addOption(). All the options names are treated as being
equivalent. If the name is not recognized or that option was not present, an
empty list is returned.
For options found by the parser, the list will contain an entry for
each time the option was encountered by the parser. If the option wasn't
specified on the command line, the default values are returned.
An empty list is returned if the option does not take a value.
\sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QString &optionName) const
{
d->checkParsed("values");
const NameHash_t::const_iterator it = d->nameHash.constFind(optionName);
if (it != d->nameHash.constEnd()) {
const int optionOffset = *it;
QStringList values = d->optionValuesHash.value(optionOffset);
if (values.isEmpty())
values = d->commandLineOptionList.at(optionOffset).defaultValues();
return values;
}
qWarning("QCommandLineParser: option not defined: \"%s\"", qPrintable(optionName));
return QStringList();
}
/*!
\overload
Checks whether the \a option was passed to the application.
Returns \c true if the \a option was set, false otherwise.
This is the recommended way to check for options with no values.
Example:
\snippet code/src_corelib_tools_qcommandlineparser.cpp 1
*/
bool QCommandLineParser::isSet(const QCommandLineOption &option) const
{
// option.names() might be empty if the constructor failed
return !option.names().isEmpty() && isSet(option.names().first());
}
/*!
\overload
Returns the option value found for the given \a option, or
an empty string if not found.
For options found by the parser, the last value found for
that option is returned. If the option wasn't specified on the command line,
the default value is returned.
An empty string is returned if the option does not take a value.
\sa values(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QString QCommandLineParser::value(const QCommandLineOption &option) const
{
return value(option.names().first());
}
/*!
\overload
Returns a list of option values found for the given \a option,
or an empty list if not found.
For options found by the parser, the list will contain an entry for
each time the option was encountered by the parser. If the option wasn't
specified on the command line, the default values are returned.
An empty list is returned if the option does not take a value.
\sa value(), QCommandLineOption::setDefaultValue(), QCommandLineOption::setDefaultValues()
*/
QStringList QCommandLineParser::values(const QCommandLineOption &option) const
{
return values(option.names().first());
}
/*!
Returns a list of positional arguments.
These are all of the arguments that were not recognized as part of an
option.
*/
QStringList QCommandLineParser::positionalArguments() const
{
d->checkParsed("positionalArguments");
return d->positionalArgumentList;
}
/*!
Returns a list of option names that were found.
This returns a list of all the recognized option names found by the
parser, in the order in which they were found. For any long options
that were in the form {--option=value}, the value part will have been
dropped.
The names in this list do not include the preceding dash characters.
Names may appear more than once in this list if they were encountered
more than once by the parser.
Any entry in the list can be used with \c value() or with
\c values() to get any relevant option values.
*/
QStringList QCommandLineParser::optionNames() const
{
d->checkParsed("optionNames");
return d->optionNames;
}
/*!
Returns a list of unknown option names.
This list will include both long an short name options that were not
recognized. For any long options that were in the form {--option=value},
the value part will have been dropped and only the long name is added.
The names in this list do not include the preceding dash characters.
Names may appear more than once in this list if they were encountered
more than once by the parser.
\sa optionNames()
*/
QStringList QCommandLineParser::unknownOptionNames() const
{
d->checkParsed("unknownOptionNames");
return d->unknownOptionNames;
}
/*!
Displays the help information, and exits the application.
This is automatically triggered by the --help option, but can also
be used to display the help when the user is not invoking the
application correctly.
The exit code is set to \a exitCode. It should be set to 0 if the
user requested to see the help, and to any other value in case of
an error.
\sa helpText()
*/
void QCommandLineParser::showHelp(int exitCode)
{
fprintf(stdout, "%s", qPrintable(d->helpText()));
::exit(exitCode);
}
/*!
Returns a string containing the complete help information.
\sa showHelp()
*/
QString QCommandLineParser::helpText() const
{
return d->helpText();
}
static QString wrapText(const QString &names, int longestOptionNameString, const QString &description)
{
const QLatin1Char nl('\n');
QString text = QString(" ") + names.leftJustified(longestOptionNameString) + QLatin1Char(' ');
const int indent = text.length();
int lineStart = 0;
int lastBreakable = -1;
const int max = 79 - indent;
int x = 0;
const int len = description.length();
for (int i = 0; i < len; ++i) {
++x;
const QChar c = description.at(i);
if (c.isSpace())
lastBreakable = i;
int breakAt = -1;
int nextLineStart = -1;
if (x > max && lastBreakable != -1) {
// time to break and we know where
breakAt = lastBreakable;
nextLineStart = lastBreakable + 1;
} else if ((x > max - 1 && lastBreakable == -1) || i == len - 1) {
// time to break but found nowhere [-> break here], or end of last line
breakAt = i + 1;
nextLineStart = breakAt;
} else if (c == nl) {
// forced break
breakAt = i;
nextLineStart = i + 1;
}
if (breakAt != -1) {
const int numChars = breakAt - lineStart;
//qDebug() << "breakAt=" << description.at(breakAt) << "breakAtSpace=" << breakAtSpace << lineStart << "to" << breakAt << description.mid(lineStart, numChars);
if (lineStart > 0)
text += QString(indent, QLatin1Char(' '));
text += description.mid(lineStart, numChars) + nl;
x = 0;
lastBreakable = -1;
lineStart = nextLineStart;
if (lineStart < len && description.at(lineStart).isSpace())
++lineStart; // don't start a line with a space
i = lineStart;
}
}
return text;
}
QString QCommandLineParserPrivate::helpText() const
{
const QLatin1Char nl('\n');
QString text;
const QString exeName = QCoreApplication::instance()->arguments().first();
QString usage = exeName;
if (!commandLineOptionList.isEmpty()) {
usage += QLatin1Char(' ');
usage += QCommandLineParser::tr("[options]");
}
Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
usage += QLatin1Char(' ');
usage += arg.syntax;
}
text += QCommandLineParser::tr("Usage: %1").arg(usage) + nl;
if (!description.isEmpty())
text += description + nl;
text += nl;
if (!commandLineOptionList.isEmpty())
text += QCommandLineParser::tr("Options:") + nl;
QStringList optionNameList;
int longestOptionNameString = 0;
Q_FOREACH (const QCommandLineOption &option, commandLineOptionList) {
QStringList optionNames;
Q_FOREACH (const QString &optionName, option.names()) {
if (optionName.length() == 1)
optionNames.append(QLatin1Char('-') + optionName);
else
optionNames.append(QString("--") + optionName);
}
QString optionNamesString = optionNames.join(", ");
if (!option.valueName().isEmpty())
optionNamesString += QString(" <") + option.valueName() + QLatin1Char('>');
optionNameList.append(optionNamesString);
longestOptionNameString = qMax(longestOptionNameString, optionNamesString.length());
}
++longestOptionNameString;
for (int i = 0; i < commandLineOptionList.count(); ++i) {
const QCommandLineOption &option = commandLineOptionList.at(i);
text += wrapText(optionNameList.at(i), longestOptionNameString, option.description());
}
if (!positionalArgumentDefinitions.isEmpty()) {
if (!commandLineOptionList.isEmpty())
text += nl;
text += QCommandLineParser::tr("Arguments:") + nl;
Q_FOREACH (const PositionalArgumentDefinition &arg, positionalArgumentDefinitions) {
text += wrapText(arg.name, longestOptionNameString, arg.description);
}
}
return text;
}

View File

@@ -1,102 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 Laszlo Papp <lpapp@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QCOMMANDLINEPARSER_H
#define QCOMMANDLINEPARSER_H
#include <QStringList>
#include <QCoreApplication>
#include "qcommandlineoption.h"
class QCommandLineParserPrivate;
class QCoreApplication;
class QCommandLineParser
{
Q_DECLARE_TR_FUNCTIONS(QCommandLineParser)
public:
QCommandLineParser();
~QCommandLineParser();
enum SingleDashWordOptionMode {
ParseAsCompactedShortOptions,
ParseAsLongOptions
};
void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode);
bool addOption(const QCommandLineOption &commandLineOption);
QCommandLineOption addVersionOption();
QCommandLineOption addHelpOption();
void setApplicationDescription(const QString &description);
QString applicationDescription() const;
void addPositionalArgument(const QString &name, const QString &description, const QString &syntax = QString());
void clearPositionalArguments();
void process(const QStringList &arguments);
void process(const QCoreApplication &app);
bool parse(const QStringList &arguments);
QString errorText() const;
bool isSet(const QString &name) const;
QString value(const QString &name) const;
QStringList values(const QString &name) const;
bool isSet(const QCommandLineOption &option) const;
QString value(const QCommandLineOption &option) const;
QStringList values(const QCommandLineOption &option) const;
QStringList positionalArguments() const;
QStringList optionNames() const;
QStringList unknownOptionNames() const;
void showHelp(int exitCode = 0);
QString helpText() const;
private:
Q_DISABLE_COPY(QCommandLineParser)
QCommandLineParserPrivate * const d;
};
#endif // QCOMMANDLINEPARSER_H

View File

@@ -1,344 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qlockfile.h"
#include "qlockfile_p.h"
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
# include <QElapsedTimer>
#else
# include <QTime>
#endif
#include <QDateTime>
QT_BEGIN_NAMESPACE
/*!
\class QLockFile
\inmodule QtCore
\brief The QLockFile class provides locking between processes using a file.
\since 5.1
A lock file can be used to prevent multiple processes from accessing concurrently
the same resource. For instance, a configuration file on disk, or a socket, a port,
a region of shared memory...
Serialization is only guaranteed if all processes that access the shared resource
use QLockFile, with the same file path.
QLockFile supports two use cases:
to protect a resource for a short-term operation (e.g. verifying if a configuration
file has changed before saving new settings), and for long-lived protection of a
resource (e.g. a document opened by a user in an editor) for an indefinite amount of time.
When protecting for a short-term operation, it is acceptable to call lock() and wait
until any running operation finishes.
When protecting a resource over a long time, however, the application should always
call setStaleLockTime(0) and then tryLock() with a short timeout, in order to
warn the user that the resource is locked.
If the process holding the lock crashes, the lock file stays on disk and can prevent
any other process from accessing the shared resource, ever. For this reason, QLockFile
tries to detect such a "stale" lock file, based on the process ID written into the file,
and (in case that process ID got reused meanwhile), on the last modification time of
the lock file (30s by default, for the use case of a short-lived operation).
If the lock file is found to be stale, it will be deleted.
For the use case of protecting a resource over a long time, you should therefore call
setStaleLockTime(0), and when tryLock() returns LockFailedError, inform the user
that the document is locked, possibly using getLockInfo() for more details.
*/
/*!
\enum QLockFile::LockError
This enum describes the result of the last call to lock() or tryLock().
\value NoError The lock was acquired successfully.
\value LockFailedError The lock could not be acquired because another process holds it.
\value PermissionError The lock file could not be created, for lack of permissions
in the parent directory.
\value UnknownError Another error happened, for instance a full partition
prevented writing out the lock file.
*/
/*!
Constructs a new lock file object.
The object is created in an unlocked state.
When calling lock() or tryLock(), a lock file named \a fileName will be created,
if it doesn't already exist.
\sa lock(), unlock()
*/
QLockFile::QLockFile(const QString &fileName)
: d_ptr(new QLockFilePrivate(fileName))
{
}
/*!
Destroys the lock file object.
If the lock was acquired, this will release the lock, by deleting the lock file.
*/
QLockFile::~QLockFile()
{
unlock();
}
/*!
Sets \a staleLockTime to be the time in milliseconds after which
a lock file is considered stale.
The default value is 30000, i.e. 30 seconds.
If your application typically keeps the file locked for more than 30 seconds
(for instance while saving megabytes of data for 2 minutes), you should set
a bigger value using setStaleLockTime().
The value of \a staleLockTime is used by lock() and tryLock() in order
to determine when an existing lock file is considered stale, i.e. left over
by a crashed process. This is useful for the case where the PID got reused
meanwhile, so the only way to detect a stale lock file is by the fact that
it has been around for a long time.
\sa staleLockTime()
*/
void QLockFile::setStaleLockTime(int staleLockTime)
{
Q_D(QLockFile);
d->staleLockTime = staleLockTime;
}
/*!
Returns the time in milliseconds after which
a lock file is considered stale.
\sa setStaleLockTime()
*/
int QLockFile::staleLockTime() const
{
Q_D(const QLockFile);
return d->staleLockTime;
}
/*!
Returns \c true if the lock was acquired by this QLockFile instance,
otherwise returns \c false.
\sa lock(), unlock(), tryLock()
*/
bool QLockFile::isLocked() const
{
Q_D(const QLockFile);
return d->isLocked;
}
/*!
Creates the lock file.
If another process (or another thread) has created the lock file already,
this function will block until that process (or thread) releases it.
Calling this function multiple times on the same lock from the same
thread without unlocking first is not allowed. This function will
\e dead-lock when the file is locked recursively.
Returns \c true if the lock was acquired, false if it could not be acquired
due to an unrecoverable error, such as no permissions in the parent directory.
\sa unlock(), tryLock()
*/
bool QLockFile::lock()
{
return tryLock(-1);
}
/*!
Attempts to create the lock file. This function returns \c true if the
lock was obtained; otherwise it returns \c false. If another process (or
another thread) has created the lock file already, this function will
wait for at most \a timeout milliseconds for the lock file to become
available.
Note: Passing a negative number as the \a timeout is equivalent to
calling lock(), i.e. this function will wait forever until the lock
file can be locked if \a timeout is negative.
If the lock was obtained, it must be released with unlock()
before another process (or thread) can successfully lock it.
Calling this function multiple times on the same lock from the same
thread without unlocking first is not allowed, this function will
\e always return false when attempting to lock the file recursively.
\sa lock(), unlock()
*/
bool QLockFile::tryLock(int timeout)
{
Q_D(QLockFile);
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
QElapsedTimer timer;
#else
QTime timer;
#endif
if (timeout > 0)
timer.start();
int sleepTime = 100;
Q_FOREVER {
d->lockError = d->tryLock_sys();
switch (d->lockError) {
case NoError:
d->isLocked = true;
return true;
case PermissionError:
case UnknownError:
return false;
case LockFailedError:
if (!d->isLocked && d->isApparentlyStale()) {
// Stale lock from another thread/process
// Ensure two processes don't remove it at the same time
QLockFile rmlock(d->fileName + QLatin1String(".rmlock"));
if (rmlock.tryLock()) {
if (d->isApparentlyStale() && d->removeStaleLock())
continue;
}
}
break;
}
if (timeout == 0 || (timeout > 0 && (timer.elapsed() > timeout)))
return false;
QLockFileThread::msleep(sleepTime);
if (sleepTime < 5 * 1000)
sleepTime *= 2;
}
// not reached
return false;
}
/*!
\fn void QLockFile::unlock()
Releases the lock, by deleting the lock file.
Calling unlock() without locking the file first, does nothing.
\sa lock(), tryLock()
*/
/*!
Retrieves information about the current owner of the lock file.
If tryLock() returns \c false, and error() returns LockFailedError,
this function can be called to find out more information about the existing
lock file:
\list
\li the PID of the application (returned in \a pid)
\li the \a hostname it's running on (useful in case of networked filesystems),
\li the name of the application which created it (returned in \a appname),
\endlist
Note that tryLock() automatically deleted the file if there is no
running application with this PID, so LockFailedError can only happen if there is
an application with this PID (it could be unrelated though).
This can be used to inform users about the existing lock file and give them
the choice to delete it. After removing the file using removeStaleLockFile(),
the application can call tryLock() again.
This function returns \c true if the information could be successfully retrieved, false
if the lock file doesn't exist or doesn't contain the expected data.
This can happen if the lock file was deleted between the time where tryLock() failed
and the call to this function. Simply call tryLock() again if this happens.
*/
bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
{
Q_D(const QLockFile);
return d->getLockInfo(pid, hostname, appname);
}
bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const
{
QFile reader(fileName);
if (!reader.open(QIODevice::ReadOnly))
return false;
QByteArray pidLine = reader.readLine();
pidLine.chop(1);
QByteArray appNameLine = reader.readLine();
appNameLine.chop(1);
QByteArray hostNameLine = reader.readLine();
hostNameLine.chop(1);
if (pidLine.isEmpty())
return false;
qint64 thePid = pidLine.toLongLong();
if (pid)
*pid = thePid;
if (appname)
*appname = QString::fromUtf8(appNameLine);
if (hostname)
*hostname = QString::fromUtf8(hostNameLine);
return thePid > 0;
}
/*!
Attempts to forcefully remove an existing lock file.
Calling this is not recommended when protecting a short-lived operation: QLockFile
already takes care of removing lock files after they are older than staleLockTime().
This method should only be called when protecting a resource for a long time, i.e.
with staleLockTime(0), and after tryLock() returned LockFailedError, and the user
agreed on removing the lock file.
Returns \c true on success, false if the lock file couldn't be removed. This happens
on Windows, when the application owning the lock is still running.
*/
bool QLockFile::removeStaleLockFile()
{
Q_D(QLockFile);
if (d->isLocked) {
qWarning("removeStaleLockFile can only be called when not holding the lock");
return false;
}
return d->removeStaleLock();
}
/*!
Returns the lock file error status.
If tryLock() returns \c false, this function can be called to find out
the reason why the locking failed.
*/
QLockFile::LockError QLockFile::error() const
{
Q_D(const QLockFile);
return d->lockError;
}
QT_END_NAMESPACE

View File

@@ -1,79 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QLOCKFILE_H
#define QLOCKFILE_H
#include <QString>
#include <QScopedPointer>
QT_BEGIN_NAMESPACE
class QLockFilePrivate;
class QLockFile
{
public:
QLockFile(const QString &fileName);
~QLockFile();
bool lock();
bool tryLock(int timeout = 0);
void unlock();
void setStaleLockTime(int);
int staleLockTime() const;
bool isLocked() const;
bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
bool removeStaleLockFile();
enum LockError {
NoError = 0,
LockFailedError = 1,
PermissionError = 2,
UnknownError = 3
};
LockError error() const;
protected:
QScopedPointer<QLockFilePrivate> d_ptr;
private:
Q_DECLARE_PRIVATE(QLockFile)
Q_DISABLE_COPY(QLockFile)
};
QT_END_NAMESPACE
#endif // QLOCKFILE_H

View File

@@ -1,104 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QLOCKFILE_P_H
#define QLOCKFILE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include "qlockfile.h"
#include <QFile>
#include <QThread>
#ifdef Q_OS_WIN
#include <qt_windows.h>
#endif
QT_BEGIN_NAMESPACE
class QLockFileThread : public QThread
{
public:
static void msleep(unsigned long msecs) { QThread::msleep(msecs); }
};
class QLockFilePrivate
{
public:
QLockFilePrivate(const QString &fn)
: fileName(fn),
#ifdef Q_OS_WIN
fileHandle(INVALID_HANDLE_VALUE),
#else
fileHandle(-1),
#endif
staleLockTime(30 * 1000), // 30 seconds
lockError(QLockFile::NoError),
isLocked(false)
{
}
QLockFile::LockError tryLock_sys();
bool removeStaleLock();
bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const;
// Returns \c true if the lock belongs to dead PID, or is old.
// The attempt to delete it will tell us if it was really stale or not, though.
bool isApparentlyStale() const;
#ifdef Q_OS_UNIX
static int checkFcntlWorksAfterFlock();
#endif
QString fileName;
#ifdef Q_OS_WIN
Qt::HANDLE fileHandle;
#else
int fileHandle;
#endif
int staleLockTime; // "int milliseconds" is big enough for 24 days
QLockFile::LockError lockError;
bool isLocked;
};
QT_END_NAMESPACE
#endif /* QLOCKFILE_P_H */

View File

@@ -1,199 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
** Contact: http://www.qt-project.org/legal
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qlockfile_p.h"
#include <QTemporaryFile>
#include <QCoreApplication>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>
#include <sys/file.h> // flock
#include <sys/types.h> // kill
#include <signal.h> // kill
#include <unistd.h>
#include <errno.h>
QT_BEGIN_NAMESPACE
#define EINTR_LOOP(var, cmd) \
do { \
var = cmd; \
} while (var == -1 && errno == EINTR)
// don't call QT_OPEN or ::open
// call qt_safe_open
static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777)
{
#ifdef O_CLOEXEC
flags |= O_CLOEXEC;
#endif
int fd;
EINTR_LOOP(fd, ::open(pathname, flags, mode));
// unknown flags are ignored, so we have no way of verifying if
// O_CLOEXEC was accepted
if (fd != -1)
::fcntl(fd, F_SETFD, FD_CLOEXEC);
return fd;
}
static inline qint64 qt_safe_write(int fd, const void *data, qint64 len)
{
qint64 ret = 0;
EINTR_LOOP(ret, ::write(fd, data, len));
return ret;
}
static QString localHostName() // from QHostInfo::localHostName()
{
char hostName[512];
if (gethostname(hostName, sizeof(hostName)) == -1)
return QString();
hostName[sizeof(hostName) - 1] = '\0';
return QString::fromLocal8Bit(hostName);
}
// ### merge into qt_safe_write?
static qint64 qt_write_loop(int fd, const char *data, qint64 len)
{
qint64 pos = 0;
while (pos < len) {
const qint64 ret = qt_safe_write(fd, data + pos, len - pos);
if (ret == -1) // e.g. partition full
return pos;
pos += ret;
}
return pos;
}
static bool setNativeLocks(int fd)
{
#if defined(LOCK_EX) && defined(LOCK_NB)
if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs
return false;
#endif
struct flock flockData;
flockData.l_type = F_WRLCK;
flockData.l_whence = SEEK_SET;
flockData.l_start = 0;
flockData.l_len = 0; // 0 = entire file
flockData.l_pid = getpid();
if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems
return false;
return true;
}
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
// Assemble data, to write in a single call to write
// (otherwise we'd have to check every write call)
// Use operator% from the fast builder to avoid multiple memory allocations.
QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) + '\n'
+ qAppName().toUtf8() + '\n'
+ localHostName().toUtf8() + '\n';
const QByteArray lockFileName = QFile::encodeName(fileName);
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644);
if (fd < 0) {
switch (errno) {
case EEXIST:
return QLockFile::LockFailedError;
case EACCES:
case EROFS:
return QLockFile::PermissionError;
default:
return QLockFile::UnknownError;
}
}
// Ensure nobody else can delete the file while we have it
if (!setNativeLocks(fd))
qWarning() << "setNativeLocks failed:" << strerror(errno);
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
close(fd);
if (!QFile::remove(fileName))
qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName));
return QLockFile::UnknownError; // partition full
}
// We hold the lock, continue.
fileHandle = fd;
return QLockFile::NoError;
}
bool QLockFilePrivate::removeStaleLock()
{
const QByteArray lockFileName = QFile::encodeName(fileName);
const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644);
if (fd < 0) // gone already?
return false;
bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0);
close(fd);
return success;
}
bool QLockFilePrivate::isApparentlyStale() const
{
qint64 pid;
QString hostname, appname;
if (!getLockInfo(&pid, &hostname, &appname))
return false;
if (hostname.isEmpty() || hostname == localHostName()) {
if (::kill(pid, 0) == -1 && errno == ESRCH)
return true; // PID doesn't exist anymore
}
const qint64 age = QFileInfo(fileName).lastModified().secsTo(QDateTime::currentDateTime()) * 1000;
return staleLockTime > 0 && age > staleLockTime;
}
void QLockFile::unlock()
{
Q_D(QLockFile);
if (!d->isLocked)
return;
close(d->fileHandle);
d->fileHandle = -1;
if (!QFile::remove(d->fileName)) {
qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?";
// This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
}
QFile::remove(d->fileName);
d->lockError = QLockFile::NoError;
d->isLocked = false;
}
QT_END_NAMESPACE

View File

@@ -1,178 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2013 David Faure <faure+bluesystems@kde.org>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL21$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see http://www.qt.io/terms-conditions. For further
** information use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file. Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** As a special exception, The Qt Company gives you certain additional
** rights. These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef _UNICODE
#define _UNICODE
#endif
#ifndef UNICODE
#define UNICODE
#endif
#include "qlockfile_p.h"
#include <qt_windows.h>
#include <QCoreApplication>
#include <QDir>
#include <QFileInfo>
#include <QDateTime>
#include <QDebug>
QT_BEGIN_NAMESPACE
static inline QByteArray localHostName()
{
return qgetenv("COMPUTERNAME");
}
static inline bool fileExists(const wchar_t *fileName)
{
WIN32_FILE_ATTRIBUTE_DATA data;
return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data);
}
QLockFile::LockError QLockFilePrivate::tryLock_sys()
{
const ushort* nativePath = QDir::toNativeSeparators(fileName).utf16();
// When writing, allow others to read.
// When reading, QFile will allow others to read and write, all good.
// Adding FILE_SHARE_DELETE would allow forceful deletion of stale files,
// but Windows doesn't allow recreating it while this handle is open anyway,
// so this would only create confusion (can't lock, but no lock file to read from).
const DWORD dwShareMode = FILE_SHARE_READ;
#ifndef Q_OS_WINRT
SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
HANDLE fh = CreateFile((const wchar_t*)nativePath,
GENERIC_WRITE,
dwShareMode,
&securityAtts,
CREATE_NEW, // error if already exists
FILE_ATTRIBUTE_NORMAL,
NULL);
#else // !Q_OS_WINRT
HANDLE fh = CreateFile2((const wchar_t*)nativePath,
GENERIC_WRITE,
dwShareMode,
CREATE_NEW, // error if already exists
NULL);
#endif // Q_OS_WINRT
if (fh == INVALID_HANDLE_VALUE) {
const DWORD lastError = GetLastError();
switch (lastError) {
case ERROR_SHARING_VIOLATION:
case ERROR_ALREADY_EXISTS:
case ERROR_FILE_EXISTS:
return QLockFile::LockFailedError;
case ERROR_ACCESS_DENIED:
// readonly file, or file still in use by another process.
// Assume the latter if the file exists, since we don't create it readonly.
return fileExists((const wchar_t*)nativePath)
? QLockFile::LockFailedError
: QLockFile::PermissionError;
default:
qWarning() << "Got unexpected locking error" << lastError;
return QLockFile::UnknownError;
}
}
// We hold the lock, continue.
fileHandle = fh;
// Assemble data, to write in a single call to write
// (otherwise we'd have to check every write call)
QByteArray fileData;
fileData += QByteArray::number(QCoreApplication::applicationPid());
fileData += '\n';
fileData += QCoreApplication::applicationName().toUtf8();
fileData += '\n';
fileData += localHostName();
fileData += '\n';
DWORD bytesWritten = 0;
QLockFile::LockError error = QLockFile::NoError;
if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh))
error = QLockFile::UnknownError; // partition full
return error;
}
bool QLockFilePrivate::removeStaleLock()
{
// QFile::remove fails on Windows if the other process is still using the file, so it's not stale.
return QFile::remove(fileName);
}
bool QLockFilePrivate::isApparentlyStale() const
{
qint64 pid;
QString hostname, appname;
if (!getLockInfo(&pid, &hostname, &appname))
return false;
// On WinRT there seems to be no way of obtaining information about other
// processes due to sandboxing
#ifndef Q_OS_WINRT
if (hostname == QString::fromLocal8Bit(localHostName())) {
HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
if (!procHandle)
return true;
// We got a handle but check if process is still alive
DWORD dwR = ::WaitForSingleObject(procHandle, 0);
::CloseHandle(procHandle);
if (dwR == WAIT_TIMEOUT)
return true;
}
#endif // !Q_OS_WINRT
const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime());
return staleLockTime > 0 && age > staleLockTime;
}
void QLockFile::unlock()
{
Q_D(QLockFile);
if (!d->isLocked)
return;
CloseHandle(d->fileHandle);
int attempts = 0;
static const int maxAttempts = 500; // 500ms
while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) {
// Someone is reading the lock file right now (on Windows this prevents deleting it).
QLockFileThread::msleep(1);
}
if (attempts == maxAttempts) {
qWarning() << "Could not remove our own lock file" << d->fileName << ". Either other users of the lock file are reading it constantly for 500 ms, or we (no longer) have permissions to delete the file";
// This is bad because other users of this lock file will now have to wait for the stale-lock-timeout...
}
d->lockError = QLockFile::NoError;
d->isLocked = false;
}
QT_END_NAMESPACE

View File

@@ -1,452 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qsavefile.h"
#include "qsavefile_p.h"
#include <QAbstractFileEngine>
#include <QFileInfo>
#include <QTemporaryFile>
#ifdef Q_OS_WIN
# include <windows.h>
#else
# include <unistd.h>
#endif
QSaveFilePrivate::QSaveFilePrivate()
: tempFile(0), error(QFile::NoError)
{
}
QSaveFilePrivate::~QSaveFilePrivate()
{
}
/*!
\class QSaveFile
\brief The QSaveFile class provides an interface for safely writing to files.
\ingroup io
\reentrant
QSaveFile is an I/O device for writing text and binary files, without losing
existing data if the writing operation fails.
While writing, the contents will be written to a temporary file, and if
no error happened, commit() will move it to the final file. This ensures that
no data at the final file is lost in case an error happens while writing,
and no partially-written file is ever present at the final location. Always
use QSaveFile when saving entire documents to disk.
QSaveFile automatically detects errors while writing, such as the full partition
situation, where write() cannot write all the bytes. It will remember that
an error happened, and will discard the temporary file in commit().
Much like with QFile, the file is opened with open(). Data is usually read
and written using QDataStream or QTextStream, but you can also call the
QIODevice-inherited functions read(), readLine(), readAll(), write().
Unlike QFile, calling close() is not allowed. commit() replaces it. If commit()
was not called and the QSaveFile instance is destroyed, the temporary file is
discarded.
\sa QTextStream, QDataStream, QFileInfo, QDir, QFile, QTemporaryFile
*/
/*!
\internal
*/
QSaveFile::QSaveFile()
: QIODevice(), d_ptr(new QSaveFilePrivate)
{
}
/*!
Constructs a new file object with the given \a parent.
*/
QSaveFile::QSaveFile(QObject *parent)
: QIODevice(parent), d_ptr(new QSaveFilePrivate)
{
}
/*!
Constructs a new file object to represent the file with the given \a name.
*/
QSaveFile::QSaveFile(const QString &name)
: QIODevice(0), d_ptr(new QSaveFilePrivate)
{
Q_D(QSaveFile);
d->fileName = name;
}
/*!
Constructs a new file object with the given \a parent to represent the
file with the specified \a name.
*/
QSaveFile::QSaveFile(const QString &name, QObject *parent)
: QIODevice(parent), d_ptr(new QSaveFilePrivate)
{
Q_D(QSaveFile);
d->fileName = name;
}
/*!
Destroys the file object, discarding the saved contents unless commit() was called.
*/
QSaveFile::~QSaveFile()
{
Q_D(QSaveFile);
if (d->tempFile) {
d->tempFile->setAutoRemove(true);
delete d->tempFile;
}
QIODevice::close();
delete d;
}
/*!
Returns false since temporary files support random access.
\sa QIODevice::isSequential()
*/
bool QSaveFile::isSequential() const
{
return false;
}
/*!
Returns the file error status.
The I/O device status returns an error code. For example, if open()
returns false, or a read/write operation returns -1, this function can
be called to find out the reason why the operation failed.
Unlike QFile which clears the error on the next operation, QSaveFile remembers
the error until the file is closed, in order to discard the file contents in close().
\sa unsetError()
*/
QFile::FileError QSaveFile::error() const
{
return d_func()->error;
}
/*!
Sets the file's error to QFile::NoError.
This will make QSaveFile forget that an error happened during saving, so you
probably don't want to call this, unless you're really sure that you want to
save the file anyway.
\sa error()
*/
void QSaveFile::unsetError()
{
d_func()->error = QFile::NoError;
setErrorString(QString());
}
/*!
Returns the name set by setFileName() or to the QSaveFile
constructor.
\sa setFileName()
*/
QString QSaveFile::fileName() const
{
return d_func()->fileName;
}
/*!
Sets the \a name of the file. The name can have no path, a
relative path, or an absolute path.
\sa QFile::setFileName(), fileName()
*/
void QSaveFile::setFileName(const QString &name)
{
d_func()->fileName = name;
}
/*!
Opens the file using OpenMode \a mode, returning true if successful;
otherwise false.
Important: the \a mode must be QIODevice::WriteOnly.
It may also have additional flags, such as QIODevice::Text and QIODevice::Unbuffered.
QIODevice::ReadWrite and QIODevice::Append are not supported at the moment.
\sa QIODevice::OpenMode, setFileName()
*/
bool QSaveFile::open(OpenMode mode)
{
Q_D(QSaveFile);
if (isOpen()) {
qWarning("QSaveFile::open: File (%s) already open", qPrintable(fileName()));
return false;
}
unsetError();
if ((mode & (ReadOnly | WriteOnly)) == 0) {
qWarning("QSaveFile::open: Open mode not specified");
return false;
}
// In the future we could implement Append and ReadWrite by copying from the existing file to the temp file...
if ((mode & ReadOnly) || (mode & Append)) {
qWarning("QSaveFile::open: Unsupported open mode %d", int(mode));
return false;
}
// check if existing file is writable
QFileInfo existingFile(d->fileName);
if (existingFile.exists() && !existingFile.isWritable()) {
d->error = QFile::WriteError;
setErrorString(QSaveFile::tr("Existing file %1 is not writable").arg(d->fileName));
return false;
}
d->tempFile = new QTemporaryFile;
d->tempFile->setAutoRemove(false);
d->tempFile->setFileTemplate(d->fileName);
if (!d->tempFile->open()) {
d->error = d->tempFile->error();
setErrorString(d->tempFile->errorString());
delete d->tempFile;
d->tempFile = 0;
return false;
}
QIODevice::open(mode);
if (existingFile.exists())
d->tempFile->setPermissions(existingFile.permissions());
return true;
}
/*!
\reimp
Cannot be called.
Call commit() instead.
*/
void QSaveFile::close()
{
qFatal("QSaveFile::close called");
}
/*
Commits the changes to disk, if all previous writes were successful.
It is mandatory to call this at the end of the saving operation, otherwise the file will be
discarded.
If an error happened during writing, deletes the temporary file and returns false.
Otherwise, renames it to the final fileName and returns true on success.
Finally, closes the device.
\sa cancelWriting()
*/
bool QSaveFile::commit()
{
Q_D(QSaveFile);
if (!d->tempFile)
return false;
if (!isOpen()) {
qWarning("QSaveFile::commit: File (%s) is not open", qPrintable(fileName()));
return false;
}
flush();
#ifdef Q_OS_WIN
FlushFileBuffers(reinterpret_cast<HANDLE>(handle()));
#elif defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0
fdatasync(d->tempFile->handle());
#else
fsync(d->tempFile->handle());
#endif
QIODevice::close();
if (d->error != QFile::NoError) {
d->tempFile->remove();
unsetError();
delete d->tempFile;
d->tempFile = 0;
return false;
}
d->tempFile->close();
#ifdef Q_OS_WIN
// On Windows QAbstractFileEngine::rename() fails if the the target exists,
// so we have to rename the target.
// Ideally the winapi ReplaceFile() method should be used.
QString bakname = d->fileName + "~";
QFile::remove(bakname);
QFile::rename(d->fileName, bakname);
#endif
QAbstractFileEngine* fileEngine = d->tempFile->fileEngine();
Q_ASSERT(fileEngine);
if (!fileEngine->rename(d->fileName)) {
d->error = fileEngine->error();
setErrorString(fileEngine->errorString());
d->tempFile->remove();
delete d->tempFile;
d->tempFile = 0;
#ifdef Q_OS_WIN
QFile::rename(bakname, d->fileName);
#endif
return false;
}
delete d->tempFile;
d->tempFile = 0;
#ifdef Q_OS_WIN
QFile::remove(bakname);
#endif
return true;
}
/*!
Sets an error code so that commit() discards the temporary file.
Further write operations are possible after calling this method, but none
of it will have any effect, the written file will be discarded.
\sa commit()
*/
void QSaveFile::cancelWriting()
{
if (!isOpen())
return;
d_func()->error = QFile::WriteError;
setErrorString(QSaveFile::tr("Writing canceled by application"));
}
/*!
Returns the size of the file.
\sa QFile::size()
*/
qint64 QSaveFile::size() const
{
Q_D(const QSaveFile);
return d->tempFile ? d->tempFile->size() : qint64(-1);
}
/*!
\reimp
*/
qint64 QSaveFile::pos() const
{
Q_D(const QSaveFile);
return d->tempFile ? d->tempFile->pos() : qint64(-1);
}
/*!
\reimp
*/
bool QSaveFile::seek(qint64 offset)
{
Q_D(QSaveFile);
return d->tempFile ? d->tempFile->seek(offset) : false;
}
/*!
\reimp
*/
bool QSaveFile::atEnd() const
{
Q_D(const QSaveFile);
return d->tempFile ? d->tempFile->atEnd() : true;
}
/*!
Flushes any buffered data to the file. Returns true if successful;
otherwise returns false.
*/
bool QSaveFile::flush()
{
Q_D(QSaveFile);
if (d->tempFile) {
if (!d->tempFile->flush()) {
d->error = d->tempFile->error();
setErrorString(d->tempFile->errorString());
return false;
}
return true;
}
return false;
}
/*!
Returns the file handle of the temporary file.
\sa QFile::handle()
*/
int QSaveFile::handle() const
{
Q_D(const QSaveFile);
return d->tempFile ? d->tempFile->handle() : -1;
}
/*!
\reimp
*/
qint64 QSaveFile::readData(char *data, qint64 maxlen)
{
Q_D(QSaveFile);
return d->tempFile ? d->tempFile->read(data, maxlen) : -1;
}
/*!
\reimp
*/
qint64 QSaveFile::writeData(const char *data, qint64 len)
{
Q_D(QSaveFile);
if (!d->tempFile)
return -1;
const qint64 written = d->tempFile->write(data, len);
if (written != len) {
d->error = QFile::WriteError;
setErrorString(QSaveFile::tr("Partial write. Partition full?"));
}
return written;
}
/*!
\reimp
*/
qint64 QSaveFile::readLineData(char *data, qint64 maxlen)
{
Q_D(QSaveFile);
return d->tempFile ? d->tempFile->readLine(data, maxlen) : -1;
}

View File

@@ -1,105 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSAVEFILE_H
#define QSAVEFILE_H
#include <QFile>
#include <QString>
#ifdef open
#error qsavefile.h must be included before any header file that defines open
#endif
class QAbstractFileEngine;
class QSaveFilePrivate;
class QSaveFile : public QIODevice
{
Q_OBJECT
Q_DECLARE_PRIVATE(QSaveFile)
public:
QSaveFile();
explicit QSaveFile(const QString &name);
explicit QSaveFile(QObject *parent);
QSaveFile(const QString &name, QObject *parent);
~QSaveFile();
QFile::FileError error() const;
void unsetError();
QString fileName() const;
void setFileName(const QString &name);
bool isSequential() const;
virtual bool open(OpenMode flags);
bool commit();
void cancelWriting();
qint64 size() const;
qint64 pos() const;
bool seek(qint64 offset);
bool atEnd() const;
bool flush();
bool resize(qint64 sz);
int handle() const;
protected:
qint64 readData(char *data, qint64 maxlen);
qint64 writeData(const char *data, qint64 len);
qint64 readLineData(char *data, qint64 maxlen);
private:
virtual void close();
private:
Q_DISABLE_COPY(QSaveFile)
QSaveFilePrivate* const d_ptr;
};
#endif // QSAVEFILE_H

View File

@@ -1,71 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/
**
** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QSAVEFILE_P_H
#define QSAVEFILE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QTemporaryFile>
class QSaveFilePrivate
{
public:
QSaveFilePrivate();
~QSaveFilePrivate();
QString fileName;
QTemporaryFile *tempFile;
QFile::FileError error;
};
#endif // QSAVEFILE_P_H

View File

@@ -27,43 +27,7 @@
bool Crypto::m_initalized(false);
QString Crypto::m_errorStr;
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
static int gcry_qt_mutex_init(void** p_sys)
{
*p_sys = new QMutex();
return 0;
}
static int gcry_qt_mutex_destroy(void** p_sys)
{
delete reinterpret_cast<QMutex*>(*p_sys);
return 0;
}
static int gcry_qt_mutex_lock(void** p_sys)
{
reinterpret_cast<QMutex*>(*p_sys)->lock();
return 0;
}
static int gcry_qt_mutex_unlock(void** p_sys)
{
reinterpret_cast<QMutex*>(*p_sys)->unlock();
return 0;
}
static const struct gcry_thread_cbs gcry_threads_qt =
{
GCRY_THREAD_OPTION_USER,
0,
gcry_qt_mutex_init,
gcry_qt_mutex_destroy,
gcry_qt_mutex_lock,
gcry_qt_mutex_unlock,
0, 0, 0, 0, 0, 0, 0, 0
};
#endif
QString Crypto::m_backendVersion;
Crypto::Crypto()
{
@@ -76,11 +40,7 @@ bool Crypto::init()
return true;
}
// libgcrypt >= 1.6 doesn't allow custom thread callbacks anymore.
#if !defined(GCRYPT_VERSION_NUMBER) || (GCRYPT_VERSION_NUMBER < 0x010600)
gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_qt);
#endif
gcry_check_version(0);
m_backendVersion = QString::fromLocal8Bit(gcry_check_version(0));
gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0);
if (!checkAlgorithms()) {
@@ -108,6 +68,11 @@ QString Crypto::errorString()
return m_errorStr;
}
QString Crypto::backendVersion()
{
return QString("libgcrypt ").append(m_backendVersion);
}
bool Crypto::backendSelfTest()
{
return (gcry_control(GCRYCTL_SELFTEST) == 0);
@@ -115,23 +80,21 @@ bool Crypto::backendSelfTest()
bool Crypto::checkAlgorithms()
{
if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
if (gcry_cipher_algo_info(GCRY_CIPHER_AES256, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
m_errorStr = "GCRY_CIPHER_AES256 not found.";
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
return false;
}
if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
if (gcry_cipher_algo_info(GCRY_CIPHER_TWOFISH, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
m_errorStr = "GCRY_CIPHER_TWOFISH not found.";
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
return false;
}
#ifdef GCRYPT_HAS_SALSA20
if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, Q_NULLPTR, Q_NULLPTR) != 0) {
if (gcry_cipher_algo_info(GCRY_CIPHER_SALSA20, GCRYCTL_TEST_ALGO, nullptr, nullptr) != 0) {
m_errorStr = "GCRY_CIPHER_SALSA20 not found.";
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));
return false;
}
#endif
if (gcry_md_test_algo(GCRY_MD_SHA256) != 0) {
m_errorStr = "GCRY_MD_SHA256 not found.";
qWarning("Crypto::checkAlgorithms: %s", qPrintable(m_errorStr));

View File

@@ -20,8 +20,6 @@
#include <QString>
#include "core/Global.h"
class Crypto
{
public:
@@ -29,6 +27,7 @@ public:
static bool initalized();
static bool backendSelfTest();
static QString errorString();
static QString backendVersion();
private:
Crypto();
@@ -43,6 +42,7 @@ private:
static bool m_initalized;
static QString m_errorStr;
static QString m_backendVersion;
};
#endif // KEEPASSX_CRYPTO_H

View File

@@ -19,15 +19,16 @@
#include <gcrypt.h>
#include "core/Global.h"
#include "crypto/Crypto.h"
class RandomBackendGcrypt : public RandomBackend
{
public:
void randomize(void* data, int len) Q_DECL_OVERRIDE;
void randomize(void* data, int len) override;
};
Random* Random::m_instance(Q_NULLPTR);
Random* Random::m_instance(nullptr);
void Random::randomize(QByteArray& ba)
{

View File

@@ -19,7 +19,6 @@
#include "config-keepassx.h"
#include "crypto/SymmetricCipherGcrypt.h"
#include "crypto/SymmetricCipherSalsa20.h"
SymmetricCipher::SymmetricCipher(SymmetricCipher::Algorithm algo, SymmetricCipher::Mode mode,
SymmetricCipher::Direction direction)
@@ -61,19 +60,12 @@ SymmetricCipherBackend* SymmetricCipher::createBackend(SymmetricCipher::Algorith
switch (algo) {
case SymmetricCipher::Aes256:
case SymmetricCipher::Twofish:
#if defined(GCRYPT_HAS_SALSA20)
case SymmetricCipher::Salsa20:
#endif
return new SymmetricCipherGcrypt(algo, mode, direction);
#if !defined(GCRYPT_HAS_SALSA20)
case SymmetricCipher::Salsa20:
return new SymmetricCipherSalsa20(algo, mode, direction);
#endif
default:
Q_ASSERT(false);
return Q_NULLPTR;
return nullptr;
}
}

View File

@@ -22,7 +22,6 @@
#include <QScopedPointer>
#include <QString>
#include "core/Global.h"
#include "crypto/SymmetricCipherBackend.h"
class SymmetricCipher

Some files were not shown because too many files have changed in this diff Show More