aboutsummaryrefslogtreecommitdiffstats
path: root/OpenPGP-Keychain
diff options
context:
space:
mode:
authorDominik Schürmann <dominik@dominikschuermann.de>2014-01-12 15:50:09 -0800
committerDominik Schürmann <dominik@dominikschuermann.de>2014-01-12 15:50:09 -0800
commit92aa5b36bba57e4927f146d49c9f124a37b7b5f9 (patch)
tree865d3962e54225fc4f13e0d19852ddc061e7e05f /OpenPGP-Keychain
parent536c4db48f12287eaf1875e2d208c0ad07e31ee6 (diff)
parente3bcf64d9e63e293c51db921572a9b87533d26ad (diff)
downloadopen-keychain-92aa5b36bba57e4927f146d49c9f124a37b7b5f9.tar.gz
open-keychain-92aa5b36bba57e4927f146d49c9f124a37b7b5f9.tar.bz2
open-keychain-92aa5b36bba57e4927f146d49c9f124a37b7b5f9.zip
Merge pull request #179 from dschuermann/key-details
Key details
Diffstat (limited to 'OpenPGP-Keychain')
-rw-r--r--OpenPGP-Keychain/AndroidManifest.xml68
-rw-r--r--OpenPGP-Keychain/assets/fontawesome-webfont.ttfbin0 -> 80776 bytes
-rw-r--r--OpenPGP-Keychain/build.gradle7
-rw-r--r--OpenPGP-Keychain/libs/android-support-v4.jarbin271754 -> 621451 bytes
-rw-r--r--OpenPGP-Keychain/project.properties4
-rw-r--r--OpenPGP-Keychain/res/drawable-finger/btn_circle.xml32
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable.pngbin2631 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable_focused.pngbin3001 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_normal.pngbin1974 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_pressed.pngbin2624 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_selected.pngbin2554 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_minus.pngbin536 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_plus.pngbin1316 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_default.pngbin4996 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_pressed.pngbin5032 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_default.pngbin4926 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_pressed.pngbin4967 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_default.pngbin8607 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_pressed.pngbin8343 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_default.pngbin5195 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_pressed.pngbin4973 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_default.pngbin7306 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_pressed.pngbin7147 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_default.pngbin5438 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_pressed.pngbin5414 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/drawer_shadow.9.pngbin0 -> 171 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/ic_drawer.pngbin0 -> 2842 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-hdpi/ic_menu_filebrowser.pngbin1443 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable.pngbin938 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable_focused.pngbin1436 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_normal.pngbin1249 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_pressed.pngbin1613 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_selected.pngbin1645 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_minus.pngbin288 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_plus.pngbin526 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi/drawer_shadow.9.pngbin0 -> 158 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi/ic_drawer.pngbin0 -> 2837 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-mdpi/ic_menu_filebrowser.pngbin1307 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-xhdpi/drawer_shadow.9.pngbin0 -> 182 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-xhdpi/ic_drawer.pngbin0 -> 1056 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable-xhdpi/ic_menu_filebrowser.pngbin1604 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/btn_circle_disable.pngbin938 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/btn_circle_disable_focused.pngbin1436 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/btn_circle_normal.pngbin1249 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/btn_circle_pressed.pngbin1613 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/btn_circle_selected.pngbin1645 -> 0 bytes
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_decrypt.xml28
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_encrypt.xml28
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_help.xml28
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_import.xml28
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_manage_keys.xml28
-rw-r--r--OpenPGP-Keychain/res/drawable/dashboard_my_keys.xml28
-rw-r--r--OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml18
-rw-r--r--OpenPGP-Keychain/res/layout/api_apps_list_activity.xml22
-rw-r--r--OpenPGP-Keychain/res/layout/create_key_dialog.xml (renamed from OpenPGP-Keychain/res/layout/create_key.xml)26
-rw-r--r--OpenPGP-Keychain/res/layout/decrypt.xml180
-rw-r--r--OpenPGP-Keychain/res/layout/decrypt_activity.xml177
-rw-r--r--OpenPGP-Keychain/res/layout/drawer_list.xml18
-rw-r--r--OpenPGP-Keychain/res/layout/drawer_list_item.xml28
-rw-r--r--OpenPGP-Keychain/res/layout/edit_key_activity.xml (renamed from OpenPGP-Keychain/res/layout/edit_key.xml)7
-rw-r--r--OpenPGP-Keychain/res/layout/edit_key_key_item.xml44
-rw-r--r--OpenPGP-Keychain/res/layout/edit_key_section.xml36
-rw-r--r--OpenPGP-Keychain/res/layout/edit_key_user_id_item.xml41
-rw-r--r--OpenPGP-Keychain/res/layout/encrypt.xml306
-rw-r--r--OpenPGP-Keychain/res/layout/encrypt_activity.xml307
-rw-r--r--OpenPGP-Keychain/res/layout/file_dialog.xml9
-rw-r--r--OpenPGP-Keychain/res/layout/help_about_fragment.xml (renamed from OpenPGP-Keychain/res/layout/help_fragment_about.xml)0
-rw-r--r--OpenPGP-Keychain/res/layout/help_activity.xml27
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys.xml51
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_activity.xml63
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_clipboard_fragment.xml12
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_file_fragment.xml9
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_keyserver_fragment.xml10
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_nfc_fragment.xml10
-rw-r--r--OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml11
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_child_item.xml102
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_item.xml (renamed from OpenPGP-Keychain/res/layout/key_list_group_item.xml)20
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_public_activity.xml33
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_public_fragment.xml75
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_public_header.xml16
-rw-r--r--OpenPGP-Keychain/res/layout/key_list_secret_activity.xml33
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_editor.xml60
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_export.xml18
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_export_layout.xml34
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_preference.xml26
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_query.xml (renamed from OpenPGP-Keychain/res/layout/key_server_query_layout.xml)26
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_query_result_item.xml88
-rw-r--r--OpenPGP-Keychain/res/layout/key_server_query_result_user_id.xml28
-rw-r--r--OpenPGP-Keychain/res/layout/main.xml70
-rw-r--r--OpenPGP-Keychain/res/layout/passphrase.xml40
-rw-r--r--OpenPGP-Keychain/res/layout/passphrase_dialog.xml24
-rw-r--r--OpenPGP-Keychain/res/layout/passphrase_repeat_dialog.xml (renamed from OpenPGP-Keychain/res/layout/passphrase_repeat.xml)22
-rw-r--r--OpenPGP-Keychain/res/layout/select_key_item.xml20
-rw-r--r--OpenPGP-Keychain/res/layout/share_nfc_beam.xml14
-rw-r--r--OpenPGP-Keychain/res/layout/share_qr_code_dialog.xml16
-rw-r--r--OpenPGP-Keychain/res/layout/sign_key_activity.xml54
-rw-r--r--OpenPGP-Keychain/res/layout/sign_key_layout.xml40
-rw-r--r--OpenPGP-Keychain/res/layout/view_key_activity.xml216
-rw-r--r--OpenPGP-Keychain/res/layout/view_key_keys_item.xml63
-rw-r--r--OpenPGP-Keychain/res/layout/view_key_userids_item.xml17
-rw-r--r--OpenPGP-Keychain/res/menu/key_edit.xml17
-rw-r--r--OpenPGP-Keychain/res/menu/key_list_public.xml13
-rw-r--r--OpenPGP-Keychain/res/menu/key_list_public_multi.xml12
-rw-r--r--OpenPGP-Keychain/res/menu/key_list_secret.xml21
-rw-r--r--OpenPGP-Keychain/res/menu/key_list_secret_multi.xml9
-rw-r--r--OpenPGP-Keychain/res/menu/key_view.xml57
-rw-r--r--OpenPGP-Keychain/res/menu/nfc_beam.xml10
-rw-r--r--OpenPGP-Keychain/res/raw/help_about.html12
-rw-r--r--OpenPGP-Keychain/res/values-sw600dp/dimens.xml8
-rw-r--r--OpenPGP-Keychain/res/values-sw720dp-land/dimens.xml9
-rw-r--r--OpenPGP-Keychain/res/values/colors.xml2
-rw-r--r--OpenPGP-Keychain/res/values/dimens.xml7
-rw-r--r--OpenPGP-Keychain/res/values/strings.xml50
-rw-r--r--OpenPGP-Keychain/res/values/styles.xml12
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/BarcodeFormat.java106
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/Binarizer.java80
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/BinaryBitmap.java128
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/ChecksumException.java37
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/DecodeHintType.java79
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/EncodeHintType.java39
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/FormatException.java38
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/LuminanceSource.java113
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/NotFoundException.java37
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/Reader.java64
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/ReaderException.java98
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/Result.java143
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/ResultMetadataType.java109
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/ResultPoint.java129
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/ResultPointCallback.java29
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/Writer.java54
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/WriterException.java35
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/BitArray.java246
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/BitMatrix.java247
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/BitSource.java97
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/CharacterSetECI.java110
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/Collections.java53
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/Comparator.java27
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/DecoderResult.java61
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/DefaultGridSampler.java86
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/DetectorResult.java46
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/ECI.java52
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/GlobalHistogramBinarizer.java194
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/GridSampler.java156
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/HybridBinarizer.java185
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/PerspectiveTransform.java148
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/StringUtils.java192
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/detector/MonochromeRectangleDetector.java209
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/detector/WhiteRectangleDetector.java347
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGF.java188
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGFPoly.java263
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java194
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java75
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonException.java31
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/multi/ByQuadrantReader.java96
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/multi/GenericMultipleBarcodeReader.java156
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/multi/MultipleBarcodeReader.java37
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiDetector.java72
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java324
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/QRCodeWriter.java108
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java203
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java123
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java155
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java322
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java86
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java171
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java117
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java586
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPattern.java48
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java279
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/Detector.java406
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPattern.java63
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java585
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternInfo.java49
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/BlockPair.java37
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/ByteMatrix.java97
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/Encoder.java557
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MaskUtil.java218
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MatrixUtil.java524
-rw-r--r--OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/QRCode.java239
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java43
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ExportHelper.java205
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java19
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java41
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java20
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java12
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java19
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java31
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java8
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java35
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DrawerActivity.java485
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java256
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java51
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpActivity.java55
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpFragmentAbout.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java101
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java6
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java9
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListActivity.java314
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListFragment.java88
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java109
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java343
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java70
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java210
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerUploadActivity.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java109
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/PreferencesActivity.java31
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java17
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareActivity.java79
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareNfcBeamActivity.java226
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java515
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListAdapter.java273
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java200
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java126
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java5
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java90
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java55
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java52
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java22
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java2
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java101
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/DashboardLayout.java186
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/FixedListView.java55
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java48
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java12
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UnderlineTextView.java69
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java7
-rw-r--r--OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/SectionCursorAdapter.java266
234 files changed, 4653 insertions, 13729 deletions
diff --git a/OpenPGP-Keychain/AndroidManifest.xml b/OpenPGP-Keychain/AndroidManifest.xml
index 8027715af..da655ba02 100644
--- a/OpenPGP-Keychain/AndroidManifest.xml
+++ b/OpenPGP-Keychain/AndroidManifest.xml
@@ -1,24 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.sufficientlysecure.keychain"
android:installLocation="auto"
- android:versionCode="21103"
+ android:versionCode="21106"
android:versionName="2.1.1" >
<!--
@@ -75,21 +59,15 @@
android:label="@string/app_name"
android:theme="@style/Theme.Sherlock.Light" >
<activity
- android:name=".ui.MainActivity"
+ android:name=".ui.KeyListPublicActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/app_name" >
+ android:label="@string/app_name"
+ android:launchMode="singleTop" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- </activity>
- <activity
- android:name=".ui.KeyListPublicActivity"
- android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
- android:label="@string/title_manage_public_keys"
- android:launchMode="singleTop"
- android:uiOptions="splitActionBarWhenNarrow" >
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
@@ -104,8 +82,7 @@
android:name=".ui.KeyListSecretActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_manage_secret_keys"
- android:launchMode="singleTop"
- android:uiOptions="splitActionBarWhenNarrow" >
+ android:launchMode="singleTop" >
<!-- <intent-filter> -->
<!-- <action android:name="android.intent.action.SEARCH" /> -->
@@ -120,9 +97,17 @@
android:name=".ui.EditKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_edit_key"
- android:uiOptions="splitActionBarWhenNarrow"
android:windowSoftInputMode="stateHidden" />
<activity
+ android:name=".ui.ViewKeyActivity"
+ android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
+ android:label="@string/title_key_details"
+ android:parentActivityName=".ui.KeyListPublicActivity" >
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".ui.KeyListPublicActivity" />
+ </activity>
+ <activity
android:name=".ui.SelectPublicKeyActivity"
android:configChanges="orientation|screenSize|keyboardHidden|keyboard"
android:label="@string/title_select_recipients"
@@ -269,8 +254,17 @@
<activity
android:name=".ui.ImportKeysActivity"
android:label="@string/title_import_keys"
+ android:launchMode="singleTop"
android:windowSoftInputMode="stateHidden" >
+ <!-- Handle NFC tags detected from outside our application -->
+ <intent-filter>
+ <action android:name="android.nfc.action.NDEF_DISCOVERED" />
+
+ <category android:name="android.intent.category.DEFAULT" />
+ <!-- mime type as defined in http://tools.ietf.org/html/rfc3156, section 7 -->
+ <data android:mimeType="application/pgp-keys" />
+ </intent-filter>
<!-- Keychain's own Actions -->
<intent-filter android:label="@string/intent_import_key" >
<action android:name="org.sufficientlysecure.keychain.action.IMPORT_KEY" />
@@ -330,22 +324,6 @@
</intent-filter>
</activity>
<activity
- android:name=".ui.ShareNfcBeamActivity"
- android:label="@string/title_share_by_nfc"
- android:launchMode="singleTop"
- android:uiOptions="splitActionBarWhenNarrow" >
-
- <!-- Handle NFC tags detected from outside our application -->
- <intent-filter>
- <action android:name="android.nfc.action.NDEF_DISCOVERED" />
-
- <category android:name="android.intent.category.DEFAULT" />
- <!-- mime type as defined in http://tools.ietf.org/html/rfc3156, section 7 -->
- <data android:mimeType="application/pgp-keys" />
- </intent-filter>
- </activity>
- <activity android:name=".ui.ShareActivity" />
- <activity
android:name=".ui.HelpActivity"
android:label="@string/title_help" />
diff --git a/OpenPGP-Keychain/assets/fontawesome-webfont.ttf b/OpenPGP-Keychain/assets/fontawesome-webfont.ttf
new file mode 100644
index 000000000..7ec2e1de8
--- /dev/null
+++ b/OpenPGP-Keychain/assets/fontawesome-webfont.ttf
Binary files differ
diff --git a/OpenPGP-Keychain/build.gradle b/OpenPGP-Keychain/build.gradle
index 80c0f05cd..0fffd1fd3 100644
--- a/OpenPGP-Keychain/build.gradle
+++ b/OpenPGP-Keychain/build.gradle
@@ -4,6 +4,7 @@ buildscript {
}
dependencies {
+ // NOTE: Avoid using dynamic versions (+). This breaks offline builds!
classpath 'com.android.tools.build:gradle:0.6.3'
}
}
@@ -19,10 +20,12 @@ repositories {
*/
dependencies {
compile fileTree(dir: 'libs', includes: ['*.jar'], excludes: ['android-support-v4.jar'])
- compile 'com.android.support:support-v4:18.0.+' // already in actionbarsherlock
+ compile 'com.android.support:support-v4:19.0.+' // already in actionbarsherlock
compile project(':libraries:ActionBarSherlock')
compile project(':libraries:HtmlTextView')
- compile project(':libraries:pinned-section-listview:library')
+ compile project(':libraries:StickyListHeaders:library')
+ compile project(':libraries:zxing')
+ compile project(':libraries:AndroidBootstrap')
}
android {
diff --git a/OpenPGP-Keychain/libs/android-support-v4.jar b/OpenPGP-Keychain/libs/android-support-v4.jar
index 99e063b33..9056828a0 100644
--- a/OpenPGP-Keychain/libs/android-support-v4.jar
+++ b/OpenPGP-Keychain/libs/android-support-v4.jar
Binary files differ
diff --git a/OpenPGP-Keychain/project.properties b/OpenPGP-Keychain/project.properties
index 7347abfcd..76caac668 100644
--- a/OpenPGP-Keychain/project.properties
+++ b/OpenPGP-Keychain/project.properties
@@ -11,4 +11,6 @@
target=android-19
android.library.reference.1=../libraries/ActionBarSherlock
android.library.reference.2=../libraries/HtmlTextView
-android.library.reference.3=../libraries/pinned-section-listview/library
+android.library.reference.3=../libraries/StickyListHeaders/library
+android.library.reference.4=../libraries/zxing
+android.library.reference.5=../libraries/AndroidBootstrap
diff --git a/OpenPGP-Keychain/res/drawable-finger/btn_circle.xml b/OpenPGP-Keychain/res/drawable-finger/btn_circle.xml
deleted file mode 100644
index 6c3c7fc1a..000000000
--- a/OpenPGP-Keychain/res/drawable-finger/btn_circle.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_window_focused="false" android:state_enabled="true"
- android:drawable="@drawable/btn_circle_normal" />
- <item android:state_window_focused="false" android:state_enabled="false"
- android:drawable="@drawable/btn_circle_disable" />
- <item android:state_pressed="true"
- android:drawable="@drawable/btn_circle_pressed" />
- <item android:state_focused="true" android:state_enabled="true"
- android:drawable="@drawable/btn_circle_selected" />
- <item android:state_enabled="true"
- android:drawable="@drawable/btn_circle_normal" />
- <item android:state_focused="true"
- android:drawable="@drawable/btn_circle_disable_focused" />
- <item
- android:drawable="@drawable/btn_circle_disable" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable.png
deleted file mode 100644
index ae063b545..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable_focused.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable_focused.png
deleted file mode 100644
index 7a5d4fe4e..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_disable_focused.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_normal.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_normal.png
deleted file mode 100644
index 5eda66883..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_normal.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_pressed.png
deleted file mode 100644
index 88848bac2..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_selected.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_selected.png
deleted file mode 100644
index 74690705f..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/btn_circle_selected.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_minus.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_minus.png
deleted file mode 100644
index 27af3faf4..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_minus.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_plus.png b/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_plus.png
deleted file mode 100644
index b24168c32..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi-finger/ic_btn_round_plus.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_default.png
deleted file mode 100644
index 0d51bcb68..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_pressed.png
deleted file mode 100644
index d4cc0f8ea..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_decrypt_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_default.png
deleted file mode 100644
index 07617bb9d..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_pressed.png
deleted file mode 100644
index b8fe6e1d6..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_encrypt_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_default.png
deleted file mode 100644
index 233fddffc..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_pressed.png
deleted file mode 100644
index dad8694f8..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_help_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_default.png
deleted file mode 100644
index 7be4837a0..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_pressed.png
deleted file mode 100644
index a4fe3c903..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_import_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_default.png
deleted file mode 100644
index de83398c2..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_pressed.png
deleted file mode 100644
index a86bc1bf9..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_manage_keys_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_default.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_default.png
deleted file mode 100644
index f8b54961e..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_default.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_pressed.png b/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_pressed.png
deleted file mode 100644
index 6a5c92138..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/dashboard_my_keys_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/drawer_shadow.9.png b/OpenPGP-Keychain/res/drawable-hdpi/drawer_shadow.9.png
new file mode 100644
index 000000000..224cc4ff4
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-hdpi/drawer_shadow.9.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/ic_drawer.png b/OpenPGP-Keychain/res/drawable-hdpi/ic_drawer.png
new file mode 100644
index 000000000..ff7b1def9
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-hdpi/ic_drawer.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-hdpi/ic_menu_filebrowser.png b/OpenPGP-Keychain/res/drawable-hdpi/ic_menu_filebrowser.png
deleted file mode 100644
index 3db304fa8..000000000
--- a/OpenPGP-Keychain/res/drawable-hdpi/ic_menu_filebrowser.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable.png
deleted file mode 100644
index 33b74a66c..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable_focused.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable_focused.png
deleted file mode 100644
index 005ad8dca..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_disable_focused.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_normal.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_normal.png
deleted file mode 100644
index fc5af1c9f..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_normal.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_pressed.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_pressed.png
deleted file mode 100644
index 8f40afdfc..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_selected.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_selected.png
deleted file mode 100644
index c74fac227..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/btn_circle_selected.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_minus.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_minus.png
deleted file mode 100644
index 96dbb17d2..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_minus.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_plus.png b/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_plus.png
deleted file mode 100644
index 1ec8a956a..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi-finger/ic_btn_round_plus.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi/drawer_shadow.9.png b/OpenPGP-Keychain/res/drawable-mdpi/drawer_shadow.9.png
new file mode 100644
index 000000000..3797f99c0
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-mdpi/drawer_shadow.9.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi/ic_drawer.png b/OpenPGP-Keychain/res/drawable-mdpi/ic_drawer.png
new file mode 100644
index 000000000..fb681ba26
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-mdpi/ic_drawer.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-mdpi/ic_menu_filebrowser.png b/OpenPGP-Keychain/res/drawable-mdpi/ic_menu_filebrowser.png
deleted file mode 100644
index fda13f1be..000000000
--- a/OpenPGP-Keychain/res/drawable-mdpi/ic_menu_filebrowser.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-xhdpi/drawer_shadow.9.png b/OpenPGP-Keychain/res/drawable-xhdpi/drawer_shadow.9.png
new file mode 100644
index 000000000..fa3d853e9
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-xhdpi/drawer_shadow.9.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-xhdpi/ic_drawer.png b/OpenPGP-Keychain/res/drawable-xhdpi/ic_drawer.png
new file mode 100644
index 000000000..b9bc3d70f
--- /dev/null
+++ b/OpenPGP-Keychain/res/drawable-xhdpi/ic_drawer.png
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable-xhdpi/ic_menu_filebrowser.png b/OpenPGP-Keychain/res/drawable-xhdpi/ic_menu_filebrowser.png
deleted file mode 100644
index d1324014d..000000000
--- a/OpenPGP-Keychain/res/drawable-xhdpi/ic_menu_filebrowser.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/btn_circle_disable.png b/OpenPGP-Keychain/res/drawable/btn_circle_disable.png
deleted file mode 100644
index 33b74a66c..000000000
--- a/OpenPGP-Keychain/res/drawable/btn_circle_disable.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/btn_circle_disable_focused.png b/OpenPGP-Keychain/res/drawable/btn_circle_disable_focused.png
deleted file mode 100644
index 005ad8dca..000000000
--- a/OpenPGP-Keychain/res/drawable/btn_circle_disable_focused.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/btn_circle_normal.png b/OpenPGP-Keychain/res/drawable/btn_circle_normal.png
deleted file mode 100644
index fc5af1c9f..000000000
--- a/OpenPGP-Keychain/res/drawable/btn_circle_normal.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/btn_circle_pressed.png b/OpenPGP-Keychain/res/drawable/btn_circle_pressed.png
deleted file mode 100644
index 8f40afdfc..000000000
--- a/OpenPGP-Keychain/res/drawable/btn_circle_pressed.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/btn_circle_selected.png b/OpenPGP-Keychain/res/drawable/btn_circle_selected.png
deleted file mode 100644
index c74fac227..000000000
--- a/OpenPGP-Keychain/res/drawable/btn_circle_selected.png
+++ /dev/null
Binary files differ
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_decrypt.xml b/OpenPGP-Keychain/res/drawable/dashboard_decrypt.xml
deleted file mode 100644
index 981e38a0b..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_decrypt.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_decrypt_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_decrypt_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_decrypt_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_decrypt_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_encrypt.xml b/OpenPGP-Keychain/res/drawable/dashboard_encrypt.xml
deleted file mode 100644
index af812dc51..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_encrypt.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_encrypt_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_encrypt_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_encrypt_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_encrypt_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_help.xml b/OpenPGP-Keychain/res/drawable/dashboard_help.xml
deleted file mode 100644
index e121ea0d1..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_help.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_help_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_help_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_help_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_help_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_import.xml b/OpenPGP-Keychain/res/drawable/dashboard_import.xml
deleted file mode 100644
index e5857dc6c..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_import.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_import_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_import_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_import_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_import_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_manage_keys.xml b/OpenPGP-Keychain/res/drawable/dashboard_manage_keys.xml
deleted file mode 100644
index ebc519253..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_manage_keys.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_manage_keys_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_manage_keys_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_manage_keys_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_manage_keys_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/drawable/dashboard_my_keys.xml b/OpenPGP-Keychain/res/drawable/dashboard_my_keys.xml
deleted file mode 100644
index d4045db45..000000000
--- a/OpenPGP-Keychain/res/drawable/dashboard_my_keys.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
- Copyright 2011 Google Inc.
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
- -->
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:drawable="@drawable/dashboard_my_keys_pressed"
- android:state_focused="true"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_my_keys_pressed"
- android:state_focused="false"
- android:state_pressed="true" />
- <item android:drawable="@drawable/dashboard_my_keys_pressed"
- android:state_focused="true" />
- <item android:drawable="@drawable/dashboard_my_keys_default"
- android:state_focused="false"
- android:state_pressed="false" />
-</selector>
diff --git a/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml b/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
index a40444e0f..a88d7afd2 100644
--- a/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/api_app_settings_fragment.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
@@ -41,12 +42,16 @@
android:layout_height="wrap_content"
android:orientation="horizontal" >
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/api_app_settings_select_key_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:text="@string/api_settings_select_key" />
+ android:layout_margin="4dp"
+ android:text="@string/api_settings_select_key"
+ bootstrapbutton:bb_icon_left="fa-key"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
<LinearLayout
android:layout_width="match_parent"
@@ -76,11 +81,16 @@
</LinearLayout>
</LinearLayout>
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/api_app_settings_advanced_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:text="@string/api_settings_show_advanced" />
+ android:layout_gravity="center_vertical"
+ android:layout_margin="4dp"
+ android:text="@string/api_settings_show_advanced"
+ bootstrapbutton:bb_icon_left="fa-caret-up"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
<LinearLayout
android:id="@+id/api_app_settings_advanced"
diff --git a/OpenPGP-Keychain/res/layout/api_apps_list_activity.xml b/OpenPGP-Keychain/res/layout/api_apps_list_activity.xml
index 11f663f7f..71fbcfb12 100644
--- a/OpenPGP-Keychain/res/layout/api_apps_list_activity.xml
+++ b/OpenPGP-Keychain/res/layout/api_apps_list_activity.xml
@@ -1,12 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent">
+ android:layout_height="match_parent" >
- <fragment
- android:id="@+id/crypto_consumers_list_fragment"
- android:name="org.sufficientlysecure.keychain.service.remote.RegisteredAppsListFragment"
+ <FrameLayout
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent" >
-</LinearLayout> \ No newline at end of file
+ <fragment
+ android:id="@+id/crypto_consumers_list_fragment"
+ android:name="org.sufficientlysecure.keychain.service.remote.RegisteredAppsListFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+
+ <include layout="@layout/drawer_list" />
+
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/create_key.xml b/OpenPGP-Keychain/res/layout/create_key_dialog.xml
index 888f9f898..a2e908433 100644
--- a/OpenPGP-Keychain/res/layout/create_key.xml
+++ b/OpenPGP-Keychain/res/layout/create_key_dialog.xml
@@ -1,26 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
<TableLayout
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
@@ -44,7 +28,7 @@
<Spinner
android:id="@+id/create_key_algorithm"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp" />
</TableRow>
@@ -60,7 +44,7 @@
<Spinner
android:id="@+id/create_key_size"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:padding="4dp" />
diff --git a/OpenPGP-Keychain/res/layout/decrypt.xml b/OpenPGP-Keychain/res/layout/decrypt.xml
deleted file mode 100644
index 0533e6d72..000000000
--- a/OpenPGP-Keychain/res/layout/decrypt.xml
+++ /dev/null
@@ -1,180 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:fillViewport="true"
- android:orientation="vertical" >
-
- <ScrollView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:fillViewport="true" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="10dp"
- android:paddingRight="10dp" >
-
- <LinearLayout
- android:id="@+id/signature"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:clickable="true"
- android:orientation="horizontal"
- android:padding="4dp"
- android:paddingLeft="10dp"
- android:paddingRight="10dp" >
-
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" >
-
- <ImageView
- android:id="@+id/ic_signature"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/signed_large" />
-
- <ImageView
- android:id="@+id/ic_signature_status"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/overlay_error" />
- </RelativeLayout>
-
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="5dip" >
-
- <TextView
- android:id="@+id/mainUserId"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:text="Main User Id"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/mainUserIdRest"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="left"
- android:text="Main User Id Rest"
- android:textAppearance="?android:attr/textAppearanceSmall" />
- </LinearLayout>
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <ImageView
- android:id="@+id/sourcePrevious"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous" />
-
- <TextView
- android:id="@+id/sourceLabel"
- style="@style/SectionHeader"
- android:layout_width="0dip"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center_horizontal|center_vertical"
- android:text="@string/label_message"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <ImageView
- android:id="@+id/sourceNext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next" />
- </LinearLayout>
-
- <ViewFlipper
- android:id="@+id/source"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1" >
-
- <LinearLayout
- android:id="@+id/sourceMessage"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="4dp" >
-
- <EditText
- android:id="@+id/message"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="top"
- android:inputType="text|textCapSentences|textMultiLine|textLongMessage"
- android:scrollHorizontally="true" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/sourceFile"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="4dp" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <EditText
- android:id="@+id/filename"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:inputType="textNoSuggestions" />
-
- <ImageButton
- android:id="@+id/btn_browse"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_menu_filebrowser" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <CheckBox
- android:id="@+id/deleteAfterDecryption"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/label_delete_after_decryption" />
- </LinearLayout>
- </LinearLayout>
- </ViewFlipper>
- </LinearLayout>
- </ScrollView>
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/decrypt_activity.xml b/OpenPGP-Keychain/res/layout/decrypt_activity.xml
new file mode 100644
index 000000000..9d9e1a1e8
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/decrypt_activity.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true"
+ android:orientation="vertical" >
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+ <LinearLayout
+ android:id="@+id/signature"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clickable="true"
+ android:orientation="horizontal"
+ android:padding="4dp"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" >
+
+ <ImageView
+ android:id="@+id/ic_signature"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/signed_large" />
+
+ <ImageView
+ android:id="@+id/ic_signature_status"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/overlay_error" />
+ </RelativeLayout>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="5dip" >
+
+ <TextView
+ android:id="@+id/mainUserId"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:text="Main User Id"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/mainUserIdRest"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="left"
+ android:text="Main User Id Rest"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <ImageView
+ android:id="@+id/sourcePrevious"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_previous" />
+
+ <TextView
+ android:id="@+id/sourceLabel"
+ style="@style/SectionHeader"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_horizontal|center_vertical"
+ android:text="@string/label_message"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ImageView
+ android:id="@+id/sourceNext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_next" />
+ </LinearLayout>
+
+ <ViewFlipper
+ android:id="@+id/source"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" >
+
+ <LinearLayout
+ android:id="@+id/sourceMessage"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="4dp" >
+
+ <EditText
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:inputType="text|textCapSentences|textMultiLine|textLongMessage"
+ android:scrollHorizontally="true" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/sourceFile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="4dp" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <EditText
+ android:id="@+id/filename"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="textNoSuggestions" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/btn_browse"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ bootstrapbutton:bb_icon_left="fa-folder-open"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <CheckBox
+ android:id="@+id/deleteAfterDecryption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/label_delete_after_decryption" />
+ </LinearLayout>
+ </LinearLayout>
+ </ViewFlipper>
+ </LinearLayout>
+ </ScrollView>
+ </LinearLayout>
+
+ <include layout="@layout/drawer_list" />
+
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/drawer_list.xml b/OpenPGP-Keychain/res/layout/drawer_list.xml
new file mode 100644
index 000000000..18210afc5
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/drawer_list.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ android:layout_gravity="start" tells DrawerLayout to treat
+ this as a sliding drawer on the left side for left-to-right
+ languages and on the right side for right-to-left languages.
+ The drawer is given a fixed width in dp and extends the full height of
+ the container. A solid background is used for contrast
+ with the content view.
+-->
+<ListView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/left_drawer"
+ android:layout_width="240dp"
+ android:layout_height="match_parent"
+ android:layout_gravity="start"
+ android:background="#fff"
+ android:choiceMode="singleChoice"
+ android:divider="@color/bg_gray"
+ android:dividerHeight="1dp" />
diff --git a/OpenPGP-Keychain/res/layout/drawer_list_item.xml b/OpenPGP-Keychain/res/layout/drawer_list_item.xml
new file mode 100644
index 000000000..14760e79d
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/drawer_list_item.xml
@@ -0,0 +1,28 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:fontawesometext="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <com.beardedhen.androidbootstrap.FontAwesomeText
+ android:id="@+id/drawer_item_icon"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_margin="10dp"
+ android:gravity="center_vertical"
+ android:textSize="24sp"
+ fontawesometext:fa_icon="fa-github" />
+
+ <TextView
+ android:id="@+id/drawer_item_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_vertical"
+ android:paddingBottom="16dp"
+ android:paddingLeft="4dp"
+ android:paddingRight="16dp"
+ android:paddingTop="16dp"
+ android:textAppearance="@android:style/TextAppearance.Medium"
+ android:textColor="#111" />
+
+</LinearLayout>
diff --git a/OpenPGP-Keychain/res/layout/edit_key.xml b/OpenPGP-Keychain/res/layout/edit_key_activity.xml
index 20cc9f2ac..f8597b0df 100644
--- a/OpenPGP-Keychain/res/layout/edit_key.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_activity.xml
@@ -16,6 +16,7 @@
-->
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
@@ -41,12 +42,14 @@
android:layout_height="wrap_content"
android:text="@string/label_no_passphrase" />
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/edit_key_btn_change_pass_phrase"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="4dp"
- android:text="@string/btn_set_passphrase" />
+ android:text="@string/btn_set_passphrase"
+ bootstrapbutton:bb_icon_left="fa-pencil"
+ bootstrapbutton:bb_type="info" />
<LinearLayout
android:id="@+id/edit_key_container"
diff --git a/OpenPGP-Keychain/res/layout/edit_key_key_item.xml b/OpenPGP-Keychain/res/layout/edit_key_key_item.xml
index 521e8ce2c..11bce64ee 100644
--- a/OpenPGP-Keychain/res/layout/edit_key_key_item.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_key_item.xml
@@ -1,27 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<org.sufficientlysecure.keychain.ui.widget.KeyEditor xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
@@ -80,7 +65,7 @@
<TextView
android:id="@+id/creation"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
@@ -94,10 +79,12 @@
android:paddingRight="10dip"
android:text="@string/label_expiry" />
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/expiry"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" />
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:text="@string/none"
+ bootstrapbutton:bb_type="default" />
</TableRow>
<TableRow>
@@ -112,22 +99,25 @@
<Spinner
android:id="@+id/usage"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content" />
</TableRow>
</TableLayout>
- <ImageButton
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/delete"
- style="@style/MinusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical" />
+ android:layout_margin="10dp"
+ bootstrapbutton:bb_icon_left="fa-minus"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="small"
+ bootstrapbutton:bb_type="danger" />
</LinearLayout>
<View
android:id="@+id/separator"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
diff --git a/OpenPGP-Keychain/res/layout/edit_key_section.xml b/OpenPGP-Keychain/res/layout/edit_key_section.xml
index dd0a5d4bd..9f10ff8c1 100644
--- a/OpenPGP-Keychain/res/layout/edit_key_section.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_section.xml
@@ -1,31 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<org.sufficientlysecure.keychain.ui.widget.SectionView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<LinearLayout
android:id="@+id/header"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:clickable="true"
- android:focusable="true"
android:gravity="center_vertical"
android:orientation="horizontal" >
@@ -40,19 +23,22 @@
android:singleLine="true"
android:text="Section Name" />
- <ImageView
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/plusbutton"
- style="@style/PlusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:duplicateParentState="true" />
+ android:layout_margin="10dp"
+ bootstrapbutton:bb_icon_left="fa-plus"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="small"
+ bootstrapbutton:bb_type="success" />
</LinearLayout>
<LinearLayout
android:id="@+id/editors"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="6dip" />
-</org.sufficientlysecure.keychain.ui.widget.SectionView>
+</org.sufficientlysecure.keychain.ui.widget.SectionView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/edit_key_user_id_item.xml b/OpenPGP-Keychain/res/layout/edit_key_user_id_item.xml
index a3955389f..663949d8e 100644
--- a/OpenPGP-Keychain/res/layout/edit_key_user_id_item.xml
+++ b/OpenPGP-Keychain/res/layout/edit_key_user_id_item.xml
@@ -1,22 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<org.sufficientlysecure.keychain.ui.widget.UserIdEditor xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
@@ -27,7 +12,7 @@
android:text="@string/label_main_user_id" />
<LinearLayout
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
@@ -48,7 +33,7 @@
<EditText
android:id="@+id/name"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textPersonName|textCapWords" />
@@ -66,7 +51,7 @@
<EditText
android:id="@+id/email"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="textEmailAddress" />
@@ -84,23 +69,29 @@
<EditText
android:id="@+id/comment"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1" />
</TableRow>
</TableLayout>
- <ImageButton
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/delete"
- style="@style/MinusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center_vertical" />
+ android:layout_gravity="center_vertical"
+ android:layout_margin="10dp"
+ android:layout_marginLeft="4dip"
+ android:layout_marginRight="6dip"
+ bootstrapbutton:bb_icon_left="fa-minus"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="small"
+ bootstrapbutton:bb_type="danger" />
</LinearLayout>
<View
android:id="@+id/separator"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="1dip"
android:background="?android:attr/listDivider" />
diff --git a/OpenPGP-Keychain/res/layout/encrypt.xml b/OpenPGP-Keychain/res/layout/encrypt.xml
deleted file mode 100644
index c9c6be5df..000000000
--- a/OpenPGP-Keychain/res/layout/encrypt.xml
+++ /dev/null
@@ -1,306 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:fillViewport="true" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="10dp"
- android:paddingRight="10dp" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="4dp" >
-
- <ImageView
- android:id="@+id/modePrevious"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous" />
-
- <TextView
- android:id="@+id/modeLabel"
- style="@style/SectionHeader"
- android:layout_width="0dip"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center_horizontal|center_vertical"
- android:text="@string/label_asymmetric" />
-
- <ImageView
- android:id="@+id/modeNext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next" />
- </LinearLayout>
-
- <ViewFlipper
- android:id="@+id/mode"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
-
- <LinearLayout
- android:id="@+id/modeAsymmetric"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:padding="4dp" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <CheckBox
- android:id="@+id/sign"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/label_sign" />
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical"
- android:paddingLeft="16dp" >
-
- <TextView
- android:id="@+id/mainUserId"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="Sign User Id"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <TextView
- android:id="@+id/mainUserIdRest"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="right"
- android:ellipsize="end"
- android:singleLine="true"
- android:text="Sign email"
- android:textAppearance="?android:attr/textAppearanceSmall" />
- </LinearLayout>
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingBottom="3dip" >
-
- <TextView
- android:id="@+id/label_selectPublicKeys"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:text="@string/label_select_public_keys"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <Button
- android:id="@+id/btn_selectEncryptKeys"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/btn_select_encrypt_keys" />
- </LinearLayout>
- </LinearLayout>
-
- <TableLayout
- android:id="@+id/modeSymmetric"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:padding="4dp"
- android:stretchColumns="1" >
-
- <TableRow>
-
- <TextView
- android:id="@+id/label_passPhrase"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="10dip"
- android:text="@string/label_passphrase"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/passPhrase"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:inputType="textPassword" />
- </TableRow>
-
- <TableRow>
-
- <TextView
- android:id="@+id/label_passPhraseAgain"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="10dip"
- android:text="@string/label_passphrase_again"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <EditText
- android:id="@+id/passPhraseAgain"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:inputType="textPassword" />
- </TableRow>
- </TableLayout>
- </ViewFlipper>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:padding="4dp" >
-
- <ImageView
- android:id="@+id/sourcePrevious"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_previous" />
-
- <TextView
- android:id="@+id/sourceLabel"
- style="@style/SectionHeader"
- android:layout_width="0dip"
- android:layout_height="fill_parent"
- android:layout_weight="1"
- android:gravity="center_horizontal|center_vertical"
- android:text="@string/label_message"
- android:textAppearance="?android:attr/textAppearanceMedium" />
-
- <ImageView
- android:id="@+id/sourceNext"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_next" />
- </LinearLayout>
-
- <ViewFlipper
- android:id="@+id/source"
- android:layout_width="fill_parent"
- android:layout_height="0dip"
- android:layout_weight="1" >
-
- <LinearLayout
- android:id="@+id/sourceMessage"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="4dp" >
-
- <EditText
- android:id="@+id/message"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:gravity="top"
- android:inputType="text|textCapSentences|textMultiLine|textLongMessage" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/sourceFile"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:padding="4dp" >
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <EditText
- android:id="@+id/filename"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:inputType="textNoSuggestions" />
-
- <ImageButton
- android:id="@+id/btn_browse"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/ic_menu_filebrowser" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <TextView
- android:id="@+id/label_fileCompression"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:layout_weight="1"
- android:paddingRight="10dip"
- android:text="@string/label_file_compression"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <Spinner
- android:id="@+id/fileCompression"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <CheckBox
- android:id="@+id/deleteAfterEncryption"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/label_delete_after_encryption" />
- </LinearLayout>
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal" >
-
- <CheckBox
- android:id="@+id/asciiArmour"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:text="@string/label_ascii_armor" />
- </LinearLayout>
- </LinearLayout>
- </ViewFlipper>
- </LinearLayout>
-
-</ScrollView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/encrypt_activity.xml b/OpenPGP-Keychain/res/layout/encrypt_activity.xml
new file mode 100644
index 000000000..eea484df2
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/encrypt_activity.xml
@@ -0,0 +1,307 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <ScrollView
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport="true" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="4dp" >
+
+ <ImageView
+ android:id="@+id/modePrevious"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_previous" />
+
+ <TextView
+ android:id="@+id/modeLabel"
+ style="@style/SectionHeader"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_horizontal|center_vertical"
+ android:text="@string/label_asymmetric" />
+
+ <ImageView
+ android:id="@+id/modeNext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_next" />
+ </LinearLayout>
+
+ <ViewFlipper
+ android:id="@+id/mode"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <LinearLayout
+ android:id="@+id/modeAsymmetric"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:padding="4dp" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <CheckBox
+ android:id="@+id/sign"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/label_sign" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:paddingLeft="16dp" >
+
+ <TextView
+ android:id="@+id/mainUserId"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:text="Sign User Id"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <TextView
+ android:id="@+id/mainUserIdRest"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="right"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:text="Sign email"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:paddingBottom="3dip" >
+
+ <TextView
+ android:id="@+id/label_selectPublicKeys"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:text="@string/label_select_public_keys"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/btn_selectEncryptKeys"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_margin="4dp"
+ android:text="@string/btn_select_encrypt_keys"
+ bootstrapbutton:bb_icon_left="fa-user"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
+ </LinearLayout>
+ </LinearLayout>
+
+ <TableLayout
+ android:id="@+id/modeSymmetric"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:stretchColumns="1" >
+
+ <TableRow>
+
+ <TextView
+ android:id="@+id/label_passPhrase"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_passphrase"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/passPhrase"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:id="@+id/label_passPhraseAgain"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_passphrase_again"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <EditText
+ android:id="@+id/passPhraseAgain"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:inputType="textPassword" />
+ </TableRow>
+ </TableLayout>
+ </ViewFlipper>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:padding="4dp" >
+
+ <ImageView
+ android:id="@+id/sourcePrevious"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_previous" />
+
+ <TextView
+ android:id="@+id/sourceLabel"
+ style="@style/SectionHeader"
+ android:layout_width="0dip"
+ android:layout_height="match_parent"
+ android:layout_weight="1"
+ android:gravity="center_horizontal|center_vertical"
+ android:text="@string/label_message"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
+
+ <ImageView
+ android:id="@+id/sourceNext"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_next" />
+ </LinearLayout>
+
+ <ViewFlipper
+ android:id="@+id/source"
+ android:layout_width="match_parent"
+ android:layout_height="0dip"
+ android:layout_weight="1" >
+
+ <LinearLayout
+ android:id="@+id/sourceMessage"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="4dp" >
+
+ <EditText
+ android:id="@+id/message"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="top"
+ android:inputType="text|textCapSentences|textMultiLine|textLongMessage" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:id="@+id/sourceFile"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:padding="4dp" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <EditText
+ android:id="@+id/filename"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_weight="1"
+ android:inputType="textNoSuggestions" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/btn_browse"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="4dp"
+ bootstrapbutton:bb_icon_left="fa-folder-open"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/label_fileCompression"
+ android:layout_width="0dip"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_weight="1"
+ android:paddingRight="10dip"
+ android:text="@string/label_file_compression"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <Spinner
+ android:id="@+id/fileCompression"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <CheckBox
+ android:id="@+id/deleteAfterEncryption"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/label_delete_after_encryption" />
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <CheckBox
+ android:id="@+id/asciiArmour"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:text="@string/label_ascii_armor" />
+ </LinearLayout>
+ </LinearLayout>
+ </ViewFlipper>
+ </LinearLayout>
+ </ScrollView>
+
+ <include layout="@layout/drawer_list" />
+
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/file_dialog.xml b/OpenPGP-Keychain/res/layout/file_dialog.xml
index ce3b1ea60..87816067f 100644
--- a/OpenPGP-Keychain/res/layout/file_dialog.xml
+++ b/OpenPGP-Keychain/res/layout/file_dialog.xml
@@ -16,6 +16,7 @@
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
@@ -39,13 +40,17 @@
android:minLines="2"
android:scrollbars="vertical" />
- <ImageButton
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/btn_browse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:layout_margin="4dp"
android:contentDescription="@string/filemanager_title_open"
- android:src="@drawable/ic_menu_filebrowser" />
+ bootstrapbutton:bb_icon_left="fa-folder-open"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
</LinearLayout>
<CheckBox
diff --git a/OpenPGP-Keychain/res/layout/help_fragment_about.xml b/OpenPGP-Keychain/res/layout/help_about_fragment.xml
index 71788e720..71788e720 100644
--- a/OpenPGP-Keychain/res/layout/help_fragment_about.xml
+++ b/OpenPGP-Keychain/res/layout/help_about_fragment.xml
diff --git a/OpenPGP-Keychain/res/layout/help_activity.xml b/OpenPGP-Keychain/res/layout/help_activity.xml
index 89aac6476..77c62e03f 100644
--- a/OpenPGP-Keychain/res/layout/help_activity.xml
+++ b/OpenPGP-Keychain/res/layout/help_activity.xml
@@ -1,13 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <android.support.v4.view.ViewPager
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/pager"
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
android:layout_width="match_parent"
- android:layout_height="match_parent" />
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <android.support.v4.view.ViewPager
+ android:id="@+id/pager"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </LinearLayout>
+
+ <include layout="@layout/drawer_list" />
-</LinearLayout> \ No newline at end of file
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys.xml b/OpenPGP-Keychain/res/layout/import_keys.xml
deleted file mode 100644
index ae391e2fd..000000000
--- a/OpenPGP-Keychain/res/layout/import_keys.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerHorizontal="true" >
-
- <FrameLayout
- android:id="@+id/import_navigation_fragment"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:orientation="vertical"
- android:paddingLeft="4dp"
- android:paddingRight="4dp" />
-
- <LinearLayout
- android:id="@+id/import_footer"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:orientation="vertical"
- android:paddingLeft="10dp"
- android:paddingRight="10dp" >
-
- <Button
- android:id="@+id/import_import"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="importOnClick"
- android:text="@string/import_import" />
-
- <Button
- android:id="@+id/import_sign_and_upload"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:onClick="signAndUploadOnClick"
- android:text="@string/import_sign_and_upload" />
- </LinearLayout>
-
- <FrameLayout
- android:id="@+id/import_keys_list_container"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_above="@+id/import_footer"
- android:layout_alignParentLeft="true"
- android:layout_below="@+id/import_navigation_fragment"
- android:orientation="vertical"
- android:paddingLeft="4dp"
- android:paddingRight="4dp" />
-
-</RelativeLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys_activity.xml b/OpenPGP-Keychain/res/layout/import_keys_activity.xml
new file mode 100644
index 000000000..c2217d2ec
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/import_keys_activity.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/drawer_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <RelativeLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true" >
+
+ <FrameLayout
+ android:id="@+id/import_navigation_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentTop="true"
+ android:orientation="vertical"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp" />
+
+ <LinearLayout
+ android:id="@+id/import_footer"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ android:orientation="vertical"
+ android:paddingLeft="10dp"
+ android:paddingRight="10dp" >
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/import_import"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:padding="4dp"
+ android:text="@string/import_import"
+ bootstrapbutton:bb_icon_left="fa-download"
+ bootstrapbutton:bb_type="info" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/import_sign_and_upload"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:padding="4dp"
+ android:text="@string/import_sign_and_upload"
+ bootstrapbutton:bb_type="info" />
+ </LinearLayout>
+
+ <FrameLayout
+ android:id="@+id/import_keys_list_container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_above="@+id/import_footer"
+ android:layout_alignParentLeft="true"
+ android:layout_below="@+id/import_navigation_fragment"
+ android:orientation="vertical"
+ android:paddingLeft="4dp"
+ android:paddingRight="4dp" />
+ </RelativeLayout>
+
+ <include layout="@layout/drawer_list" />
+
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys_clipboard_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_clipboard_fragment.xml
index bb3b8a1cb..961c6523a 100644
--- a/OpenPGP-Keychain/res/layout/import_keys_clipboard_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/import_keys_clipboard_fragment.xml
@@ -1,13 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/import_clipboard_button"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/import_from_clipboard" />
+ android:layout_height="60dp"
+ android:layout_margin="10dp"
+ android:text="@string/import_from_clipboard"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys_file_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_file_fragment.xml
index 896be3989..126bcd8a6 100644
--- a/OpenPGP-Keychain/res/layout/import_keys_file_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/import_keys_file_fragment.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
@@ -16,12 +17,16 @@
android:minLines="2"
android:scrollbars="vertical" />
- <ImageButton
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/import_keys_file_browse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:layout_margin="4dp"
android:contentDescription="@string/filemanager_title_open"
- android:src="@drawable/ic_menu_filebrowser" />
+ bootstrapbutton:bb_icon_left="fa-folder-open"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys_keyserver_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_keyserver_fragment.xml
index 18e87205b..74a2d7853 100644
--- a/OpenPGP-Keychain/res/layout/import_keys_keyserver_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/import_keys_keyserver_fragment.xml
@@ -1,13 +1,17 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/import_keyserver_button"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/menu_key_server" />
+ android:layout_height="60dp"
+ android:layout_margin="10dp"
+ android:text="@string/menu_key_server"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
<!-- <Spinner -->
<!-- android:id="@+id/import_keys_server_key_server" -->
diff --git a/OpenPGP-Keychain/res/layout/import_keys_nfc_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_nfc_fragment.xml
index b34bb80c3..6d70578af 100644
--- a/OpenPGP-Keychain/res/layout/import_keys_nfc_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/import_keys_nfc_fragment.xml
@@ -1,13 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/import_nfc_button"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/menu_import_from_nfc" />
+ android:layout_height="60dp"
+ android:layout_margin="10dp"
+ android:text="@string/menu_import_from_nfc"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml b/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml
index 0a49b014a..f3c09a41d 100644
--- a/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml
+++ b/OpenPGP-Keychain/res/layout/import_keys_qr_code_fragment.xml
@@ -1,14 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
- <Button
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/import_qrcode_button"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="@string/menu_import_from_qr_code" />
+ android:layout_height="60dp"
+ android:layout_margin="10dp"
+ android:text="@string/menu_import_from_qr_code"
+ bootstrapbutton:bb_icon_left="fa-barcode"
+ bootstrapbutton:bb_size="default"
+ bootstrapbutton:bb_type="default" />
<TextView
android:id="@+id/import_qrcode_text"
diff --git a/OpenPGP-Keychain/res/layout/key_list_child_item.xml b/OpenPGP-Keychain/res/layout/key_list_child_item.xml
deleted file mode 100644
index 81d843529..000000000
--- a/OpenPGP-Keychain/res/layout/key_list_child_item.xml
+++ /dev/null
@@ -1,102 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="?android:attr/listPreferredItemHeight"
- android:layout_marginRight="?android:attr/scrollbarSize"
- android:orientation="vertical"
- android:singleLine="true" >
-
- <LinearLayout
- android:id="@+id/keyLayout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:orientation="horizontal"
- android:paddingLeft="8dip"
- android:paddingRight="3dip" >
-
- <ImageView
- android:id="@+id/ic_masterKey"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:paddingRight="6dip"
- android:src="@drawable/key_small" />
-
- <TextView
- android:id="@+id/keyId"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="5dip"
- android:text="Key ID"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:typeface="monospace" />
-
- <TextView
- android:id="@+id/keyDetails"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="(RSA, 1024bit)"
- android:textAppearance="?android:attr/textAppearanceSmall" />
-
- <LinearLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:layout_gravity="center_vertical"
- android:gravity="right"
- android:orientation="horizontal"
- android:paddingBottom="2dip"
- android:paddingTop="2dip" >
-
- <ImageView
- android:id="@+id/ic_certifyKey"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/certify_small" />
-
- <ImageView
- android:id="@+id/ic_encryptKey"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/encrypted_small" />
-
- <ImageView
- android:id="@+id/ic_signKey"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/signed_small" />
- </LinearLayout>
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/userIdLayout"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="36dip"
- android:singleLine="true" >
-
- <TextView
- android:id="@+id/userId"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:paddingRight="3dip"
- android:text="User ID"
- android:textAppearance="?android:attr/textAppearanceSmall" />
- </LinearLayout>
-
-</LinearLayout>
diff --git a/OpenPGP-Keychain/res/layout/key_list_group_item.xml b/OpenPGP-Keychain/res/layout/key_list_item.xml
index 240be54b0..2571bb6e7 100644
--- a/OpenPGP-Keychain/res/layout/key_list_group_item.xml
+++ b/OpenPGP-Keychain/res/layout/key_list_item.xml
@@ -1,26 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:layout_marginRight="?android:attr/scrollbarSize"
android:orientation="vertical"
- android:paddingLeft="36dip"
+ android:paddingLeft="8dp"
android:singleLine="true" >
<TextView
diff --git a/OpenPGP-Keychain/res/layout/key_list_public_activity.xml b/OpenPGP-Keychain/res/layout/key_list_public_activity.xml
index a35e23038..f0e843e56 100644
--- a/OpenPGP-Keychain/res/layout/key_list_public_activity.xml
+++ b/OpenPGP-Keychain/res/layout/key_list_public_activity.xml
@@ -1,25 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
+ android:layout_height="match_parent" >
- <fragment
- android:id="@+id/key_list_public_fragment"
- android:name="org.sufficientlysecure.keychain.ui.KeyListPublicFragment"
+ <FrameLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1" />
+ android:layout_height="match_parent" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="90dp"
- android:layout_weight="1"
- android:background="@drawable/abs__ab_bottom_solid_light_holo"
- android:paddingBottom="3dp"
- android:paddingLeft="10dp"
- android:paddingRight="10dp"
- android:paddingTop="3dp"
- android:text="@string/list_information" />
+ <fragment
+ android:id="@+id/key_list_public_fragment"
+ android:name="org.sufficientlysecure.keychain.ui.KeyListPublicFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+
+ <include layout="@layout/drawer_list" />
-</LinearLayout> \ No newline at end of file
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_list_public_fragment.xml b/OpenPGP-Keychain/res/layout/key_list_public_fragment.xml
new file mode 100644
index 000000000..828809601
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/key_list_public_fragment.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <se.emilsjolander.stickylistheaders.StickyListHeadersListView
+ android:id="@+id/list"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:clipToPadding="false"
+ android:drawSelectorOnTop="true"
+ android:fastScrollEnabled="true"
+ android:paddingBottom="16dp"
+ android:paddingLeft="16dp"
+ android:paddingRight="32dp"
+ android:scrollbarStyle="outsideOverlay" />
+
+ <LinearLayout
+ android:id="@+id/empty"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:gravity="center"
+ android:orientation="vertical"
+ android:visibility="gone" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/key_list_empty_text1"
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text=""
+ android:textAppearance="?android:attr/textAppearanceLarge" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/key_list_empty_text2"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/key_list_empty_button_create"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:text="@string/key_list_empty_button_create"
+ bootstrapbutton:bb_icon_left="fa-plus"
+ bootstrapbutton:bb_type="default" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:text="@string/key_list_empty_text3"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/key_list_empty_button_import"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:text="@string/key_list_empty_button_import"
+ bootstrapbutton:bb_icon_left="fa-download"
+ bootstrapbutton:bb_type="default" />
+ </LinearLayout>
+
+</FrameLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_list_public_header.xml b/OpenPGP-Keychain/res/layout/key_list_public_header.xml
new file mode 100644
index 000000000..5768e4153
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/key_list_public_header.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" >
+
+ <org.sufficientlysecure.keychain.ui.widget.UnderlineTextView
+ android:id="@+id/stickylist_header_text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="start|left"
+ android:padding="8dp"
+ android:textColor="@color/emphasis"
+ android:textSize="17sp"
+ android:textStyle="bold" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_list_secret_activity.xml b/OpenPGP-Keychain/res/layout/key_list_secret_activity.xml
index d4397c444..13370f2e5 100644
--- a/OpenPGP-Keychain/res/layout/key_list_secret_activity.xml
+++ b/OpenPGP-Keychain/res/layout/key_list_secret_activity.xml
@@ -1,25 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/drawer_layout"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
+ android:layout_height="match_parent" >
- <fragment
- android:id="@+id/key_list_secret_fragment"
- android:name="org.sufficientlysecure.keychain.ui.KeyListSecretFragment"
+ <FrameLayout
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:layout_weight="1" />
+ android:layout_height="match_parent" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="90dp"
- android:layout_weight="1"
- android:background="@drawable/abs__ab_bottom_solid_light_holo"
- android:paddingBottom="3dp"
- android:paddingLeft="10dp"
- android:paddingRight="10dp"
- android:paddingTop="3dp"
- android:text="@string/list_information" />
+ <fragment
+ android:id="@+id/key_list_secret_fragment"
+ android:name="org.sufficientlysecure.keychain.ui.KeyListSecretFragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+ </FrameLayout>
+
+ <include layout="@layout/drawer_list" />
-</LinearLayout> \ No newline at end of file
+</android.support.v4.widget.DrawerLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_server_editor.xml b/OpenPGP-Keychain/res/layout/key_server_editor.xml
index 51ff8a663..058a43eaf 100644
--- a/OpenPGP-Keychain/res/layout/key_server_editor.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_editor.xml
@@ -1,52 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<org.sufficientlysecure.keychain.ui.widget.KeyServerEditor
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+<org.sufficientlysecure.keychain.ui.widget.KeyServerEditor xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical">
+ android:orientation="vertical" >
<LinearLayout
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:orientation="horizontal"
- android:layout_marginLeft="3dip">
+ android:layout_marginLeft="3dip"
+ android:orientation="horizontal" >
<EditText
android:id="@+id/server"
- android:layout_weight="1"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:inputType="textUri"/>
-
- <ImageButton
- android:id="@+id/delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- style="@style/MinusButton"
- android:layout_gravity="center_vertical"
- android:layout_marginRight="3dip"/>
+ android:layout_weight="1"
+ android:inputType="textUri" />
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/delete"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:layout_margin="10dp"
+ android:layout_marginRight="3dip"
+ bootstrapbutton:bb_icon_left="fa-minus"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="small"
+ bootstrapbutton:bb_type="danger" />
</LinearLayout>
<View
android:id="@+id/separator"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="1dip"
- android:background="?android:attr/listDivider"/>
+ android:background="?android:attr/listDivider" />
-</org.sufficientlysecure.keychain.ui.widget.KeyServerEditor>
+</org.sufficientlysecure.keychain.ui.widget.KeyServerEditor> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_server_export.xml b/OpenPGP-Keychain/res/layout/key_server_export.xml
new file mode 100644
index 000000000..30e4e0644
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/key_server_export.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <Spinner
+ android:id="@+id/keyServer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <Button
+ android:id="@+id/btn_export_to_server"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/btn_export_to_server" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_server_export_layout.xml b/OpenPGP-Keychain/res/layout/key_server_export_layout.xml
deleted file mode 100644
index 257f087ee..000000000
--- a/OpenPGP-Keychain/res/layout/key_server_export_layout.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <Spinner
- android:id="@+id/keyServer"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <Button
- android:id="@+id/btn_export_to_server"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/btn_export_to_server" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_server_preference.xml b/OpenPGP-Keychain/res/layout/key_server_preference.xml
index e9b1d5a95..8b99e5d2f 100644
--- a/OpenPGP-Keychain/res/layout/key_server_preference.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_preference.xml
@@ -1,21 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
@@ -57,15 +42,18 @@
android:textAppearance="?android:attr/textAppearanceSmall" />
</RelativeLayout>
- <ImageView
+ <com.beardedhen.androidbootstrap.BootstrapButton
android:id="@+id/add"
- style="@style/PlusButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
+ android:layout_margin="10dp"
android:layout_marginLeft="4dip"
android:layout_marginRight="6dip"
- android:clickable="true" />
+ bootstrapbutton:bb_icon_left="fa-plus"
+ bootstrapbutton:bb_roundedCorners="true"
+ bootstrapbutton:bb_size="small"
+ bootstrapbutton:bb_type="success" />
</LinearLayout>
<View
diff --git a/OpenPGP-Keychain/res/layout/key_server_query_layout.xml b/OpenPGP-Keychain/res/layout/key_server_query.xml
index 5eca10c45..20f260a95 100644
--- a/OpenPGP-Keychain/res/layout/key_server_query_layout.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_query.xml
@@ -1,32 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
android:orientation="vertical" >
<Spinner
android:id="@+id/keyServer"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
@@ -49,7 +33,7 @@
<ListView
android:id="@+id/list"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" />
diff --git a/OpenPGP-Keychain/res/layout/key_server_query_result_item.xml b/OpenPGP-Keychain/res/layout/key_server_query_result_item.xml
index 29c8b88f4..6d883d26d 100644
--- a/OpenPGP-Keychain/res/layout/key_server_query_result_item.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_query_result_item.xml
@@ -1,97 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:singleLine="true"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
android:paddingLeft="3dip"
android:paddingRight="?android:attr/scrollbarSize"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:orientation="vertical">
+ android:singleLine="true" >
<LinearLayout
- android:orientation="horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
<LinearLayout
- android:orientation="vertical"
- android:paddingLeft="5dip"
- android:paddingRight="5dip"
android:layout_width="0dip"
android:layout_height="wrap_content"
- android:layout_weight="1">
+ android:layout_weight="1"
+ android:orientation="vertical"
+ android:paddingLeft="5dip"
+ android:paddingRight="5dip" >
<TextView
android:id="@+id/mainUserId"
- android:text="Main User ID"
- android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:text="Main User ID"
+ android:textAppearance="?android:attr/textAppearanceMedium" />
<TextView
android:id="@+id/mainUserIdRest"
- android:text="&lt;user@somewhere.com&gt;"
- android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
-
+ android:layout_height="wrap_content"
+ android:text="&lt;user@somewhere.com>"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
<LinearLayout
- android:orientation="vertical"
- android:minWidth="90dip"
- android:paddingLeft="3dip"
- android:gravity="right"
android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:layout_height="wrap_content"
+ android:gravity="right"
+ android:minWidth="90dip"
+ android:orientation="vertical"
+ android:paddingLeft="3dip" >
<TextView
android:id="@+id/keyId"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
android:text="BBBBBBBB"
android:textAppearance="?android:attr/textAppearanceSmall"
- android:typeface="monospace"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"/>
+ android:typeface="monospace" />
<TextView
android:id="@+id/algorithm"
- android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"/>
+ android:layout_height="wrap_content"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
<TextView
android:id="@+id/status"
- android:textAppearance="?android:attr/textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:textColor="#e00"/>
-
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textColor="#e00" />
</LinearLayout>
-
</LinearLayout>
<LinearLayout
android:id="@+id/list"
- android:orientation="vertical"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginLeft="30dip">
-
+ android:layout_marginLeft="30dip"
+ android:orientation="vertical" >
</LinearLayout>
-</LinearLayout>
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/key_server_query_result_user_id.xml b/OpenPGP-Keychain/res/layout/key_server_query_result_user_id.xml
index 9d3a4a1ab..c69735e67 100644
--- a/OpenPGP-Keychain/res/layout/key_server_query_result_user_id.xml
+++ b/OpenPGP-Keychain/res/layout/key_server_query_result_user_id.xml
@@ -1,26 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_marginRight="?android:attr/scrollbarSize"
- android:singleLine="true"
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:paddingRight="3dip">
+ android:layout_marginRight="?android:attr/scrollbarSize"
+ android:paddingRight="3dip"
+ android:singleLine="true"
+ android:textAppearance="?android:attr/textAppearanceSmall" >
-</TextView>
+</TextView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/main.xml b/OpenPGP-Keychain/res/layout/main.xml
deleted file mode 100644
index 71967271b..000000000
--- a/OpenPGP-Keychain/res/layout/main.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <org.sufficientlysecure.keychain.ui.widget.DashboardLayout
- android:layout_width="fill_parent"
- android:layout_height="fill_parent" >
-
- <Button
- android:id="@+id/dashboard_manage_keys"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_manage_keys"
- android:onClick="manageKeysOnClick"
- android:text="@string/dashboard_manage_keys" />
-
- <Button
- android:id="@+id/dashboard_my_keys"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_my_keys"
- android:onClick="myKeysOnClick"
- android:text="@string/dashboard_my_keys" />
-
- <Button
- android:id="@+id/dashboard_encrypt"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_encrypt"
- android:onClick="encryptOnClick"
- android:text="@string/dashboard_encrypt" />
-
- <Button
- android:id="@+id/dashboard_decrypt"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_decrypt"
- android:onClick="decryptOnClick"
- android:text="@string/dashboard_decrypt" />
-
- <Button
- android:id="@+id/dashboard_scan_qrcode"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_import"
- android:onClick="scanQrcodeOnClick"
- android:text="@string/dashboard_import_keys" />
-
- <Button
- android:id="@+id/dashboard_help"
- style="@style/DashboardButton"
- android:drawableTop="@drawable/dashboard_help"
- android:onClick="helpOnClick"
- android:text="@string/dashboard_help" />
- </org.sufficientlysecure.keychain.ui.widget.DashboardLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/passphrase.xml b/OpenPGP-Keychain/res/layout/passphrase.xml
deleted file mode 100644
index 778ae6b80..000000000
--- a/OpenPGP-Keychain/res/layout/passphrase.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:paddingLeft="16dp"
- android:paddingRight="16dp" >
-
- <TextView
- android:id="@+id/passphrase_label_passphrase"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical"
- android:padding="4dp"
- android:text="@string/label_passphrase" />
-
- <EditText
- android:id="@+id/passphrase_passphrase"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:imeOptions="actionDone"
- android:inputType="textPassword"
- android:padding="4dp" />
-
-</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/passphrase_dialog.xml b/OpenPGP-Keychain/res/layout/passphrase_dialog.xml
new file mode 100644
index 000000000..4b331f0f2
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/passphrase_dialog.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp" >
+
+ <TextView
+ android:id="@+id/passphrase_label_passphrase"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:padding="4dp"
+ android:text="@string/label_passphrase" />
+
+ <EditText
+ android:id="@+id/passphrase_passphrase"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:imeOptions="actionDone"
+ android:inputType="textPassword"
+ android:padding="4dp" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/passphrase_repeat.xml b/OpenPGP-Keychain/res/layout/passphrase_repeat_dialog.xml
index 1eef4eb68..2bdd231ee 100644
--- a/OpenPGP-Keychain/res/layout/passphrase_repeat.xml
+++ b/OpenPGP-Keychain/res/layout/passphrase_repeat_dialog.xml
@@ -1,22 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
@@ -34,7 +18,7 @@
<EditText
android:id="@+id/passphrase_passphrase"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:padding="4dp" />
@@ -52,7 +36,7 @@
<EditText
android:id="@+id/passphrase_passphrase_again"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textPassword"
diff --git a/OpenPGP-Keychain/res/layout/select_key_item.xml b/OpenPGP-Keychain/res/layout/select_key_item.xml
index d5b1655ed..bbfe17c44 100644
--- a/OpenPGP-Keychain/res/layout/select_key_item.xml
+++ b/OpenPGP-Keychain/res/layout/select_key_item.xml
@@ -1,22 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
+ android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:paddingLeft="3dip"
android:paddingRight="?android:attr/scrollbarSize"
@@ -63,7 +47,7 @@
<TextView
android:id="@+id/keyId"
android:layout_width="wrap_content"
- android:layout_height="fill_parent"
+ android:layout_height="match_parent"
android:text="BBBBBBBB"
android:textAppearance="?android:attr/textAppearanceSmall"
android:typeface="monospace" />
diff --git a/OpenPGP-Keychain/res/layout/share_nfc_beam.xml b/OpenPGP-Keychain/res/layout/share_nfc_beam.xml
deleted file mode 100644
index 692f53e4e..000000000
--- a/OpenPGP-Keychain/res/layout/share_nfc_beam.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <org.sufficientlysecure.htmltextview.HtmlTextView
- android:id="@+id/nfc_beam_text"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="16dp"
- android:text="" />
-
-</ScrollView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/share_qr_code_dialog.xml b/OpenPGP-Keychain/res/layout/share_qr_code_dialog.xml
index 88b06b698..66102d3e5 100644
--- a/OpenPGP-Keychain/res/layout/share_qr_code_dialog.xml
+++ b/OpenPGP-Keychain/res/layout/share_qr_code_dialog.xml
@@ -1,20 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
-<!--
- Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/OpenPGP-Keychain/res/layout/sign_key_activity.xml b/OpenPGP-Keychain/res/layout/sign_key_activity.xml
new file mode 100644
index 000000000..b9f66db7f
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/sign_key_activity.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <TextView
+ android:id="@+id/textView1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/label_send_key"
+ android:textAppearance="?android:attr/textAppearanceMedium" >
+ </TextView>
+
+ <CheckBox
+ android:id="@+id/sendKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:checked="true"
+ android:text="" >
+ </CheckBox>
+ </LinearLayout>
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal" >
+
+ <Spinner
+ android:id="@+id/keyServer"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_weight="1" />
+ </LinearLayout>
+
+ <Button
+ android:id="@+id/sign"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/btn_sign" >
+ </Button>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/sign_key_layout.xml b/OpenPGP-Keychain/res/layout/sign_key_layout.xml
deleted file mode 100644
index 4530831ee..000000000
--- a/OpenPGP-Keychain/res/layout/sign_key_layout.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- Copyright (C) 2010 Thialfihar <thi@thialfihar.org> Licensed under the
- Apache License, Version 2.0 (the "License"); you may not use this file except
- in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
- Unless required by applicable law or agreed to in writing, software distributed
- under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
- OR CONDITIONS OF ANY KIND, either express or implied. See the License for
- the specific language governing permissions and limitations under the License. -->
-
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent" android:layout_height="fill_parent"
- android:orientation="vertical">
-
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:orientation="horizontal">
- </LinearLayout>
-
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:orientation="horizontal">
-
- <TextView android:id="@+id/textView1" android:layout_height="wrap_content"
- android:text="@string/label_send_key" android:textAppearance="?android:attr/textAppearanceMedium"
- android:layout_width="wrap_content"></TextView>
- <CheckBox android:text="" android:id="@+id/sendKey"
- android:layout_width="wrap_content" android:layout_height="wrap_content"
- android:checked="true"></CheckBox>
- </LinearLayout>
-
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="wrap_content" android:orientation="horizontal">
-
- <Spinner android:id="@+id/keyServer" android:layout_width="wrap_content"
- android:layout_height="wrap_content" android:layout_weight="1" />
- </LinearLayout>
-
- <Button android:layout_height="wrap_content"
- android:layout_width="wrap_content" android:text="@string/btn_sign"
- android:id="@+id/sign"></Button>
-
-</LinearLayout>
diff --git a/OpenPGP-Keychain/res/layout/view_key_activity.xml b/OpenPGP-Keychain/res/layout/view_key_activity.xml
new file mode 100644
index 000000000..babec70f6
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/view_key_activity.xml
@@ -0,0 +1,216 @@
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:bootstrapbutton="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" >
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginRight="?android:attr/scrollbarSize"
+ android:orientation="vertical"
+ android:paddingLeft="16dp"
+ android:paddingRight="16dp" >
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:text="@string/section_master_user_id" />
+
+ <TableLayout
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:stretchColumns="1" >
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_name" />
+
+ <TextView
+ android:id="@+id/name"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text="" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_email" />
+
+ <TextView
+ android:id="@+id/email"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text="" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_comment" />
+
+ <TextView
+ android:id="@+id/comment"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text="" />
+ </TableRow>
+ </TableLayout>
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:text="@string/section_master_key" />
+
+ <TableLayout
+ android:layout_width="wrap_content"
+ android:layout_height="0dp"
+ android:layout_weight="1"
+ android:stretchColumns="1" >
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_key_id" />
+
+ <TextView
+ android:id="@+id/key_id"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text=""
+ android:typeface="monospace" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:id="@+id/label_algorithm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_algorithm" />
+
+ <TextView
+ android:id="@+id/algorithm"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text="" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_creation" />
+
+ <TextView
+ android:id="@+id/creation"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_expiry" />
+
+ <TextView
+ android:id="@+id/expiry"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content" />
+ </TableRow>
+
+ <TableRow>
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="10dip"
+ android:text="@string/label_fingerprint" />
+
+ <TextView
+ android:id="@+id/fingerprint"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:typeface="monospace" />
+ </TableRow>
+ </TableLayout>
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:text="@string/section_user_ids" />
+
+ <org.sufficientlysecure.keychain.ui.widget.FixedListView
+ android:id="@+id/user_ids"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:text="@string/section_keys" />
+
+ <org.sufficientlysecure.keychain.ui.widget.FixedListView
+ android:id="@+id/keys"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ style="@style/SectionHeader"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="4dp"
+ android:text="@string/section_actions" />
+
+ <com.beardedhen.androidbootstrap.BootstrapButton
+ android:id="@+id/action_encrypt"
+ android:layout_width="match_parent"
+ android:layout_height="60dp"
+ android:padding="4dp"
+ android:text="@string/key_view_action_encrypt"
+ bootstrapbutton:bb_icon_left="fa-lock"
+ bootstrapbutton:bb_type="info" />
+ </LinearLayout>
+
+</ScrollView> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/view_key_keys_item.xml b/OpenPGP-Keychain/res/layout/view_key_keys_item.xml
new file mode 100644
index 000000000..b50253980
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/view_key_keys_item.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginRight="?android:attr/scrollbarSize"
+ android:orientation="horizontal"
+ android:paddingLeft="8dip"
+ android:paddingRight="3dip"
+ android:singleLine="true" >
+
+ <ImageView
+ android:id="@+id/ic_masterKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical"
+ android:paddingRight="6dip"
+ android:src="@drawable/key_small" />
+
+ <TextView
+ android:id="@+id/keyId"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="5dip"
+ android:text="Key ID"
+ android:textAppearance="?android:attr/textAppearanceMedium"
+ android:typeface="monospace" />
+
+ <TextView
+ android:id="@+id/keyDetails"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="(RSA, 1024bit)"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="center_vertical"
+ android:gravity="right"
+ android:orientation="horizontal"
+ android:paddingBottom="2dip"
+ android:paddingTop="2dip" >
+
+ <ImageView
+ android:id="@+id/ic_certifyKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/certify_small" />
+
+ <ImageView
+ android:id="@+id/ic_encryptKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/encrypted_small" />
+
+ <ImageView
+ android:id="@+id/ic_signKey"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/signed_small" />
+ </LinearLayout>
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/layout/view_key_userids_item.xml b/OpenPGP-Keychain/res/layout/view_key_userids_item.xml
new file mode 100644
index 000000000..2d022ba13
--- /dev/null
+++ b/OpenPGP-Keychain/res/layout/view_key_userids_item.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:layout_marginRight="?android:attr/scrollbarSize"
+ android:orientation="vertical"
+ android:singleLine="true" >
+
+ <TextView
+ android:id="@+id/userId"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:paddingRight="3dip"
+ android:text="User ID"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
+
+</LinearLayout> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_edit.xml b/OpenPGP-Keychain/res/menu/key_edit.xml
new file mode 100644
index 000000000..38c52e7f0
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_edit.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_edit_export_file"
+ android:showAsAction="never"
+ android:title="@string/menu_export_key"/>
+ <item
+ android:id="@+id/menu_key_edit_delete"
+ android:showAsAction="never"
+ android:title="@string/menu_delete_key"/>
+ <item
+ android:id="@+id/menu_key_edit_cancel"
+ android:showAsAction="never"
+ android:title="@string/menu_key_edit_cancel"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_list_public.xml b/OpenPGP-Keychain/res/menu/key_list_public.xml
new file mode 100644
index 000000000..7b6261558
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_list_public.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_list_public_import"
+ android:showAsAction="always|withText"
+ android:title="@string/menu_import"/>
+ <item
+ android:id="@+id/menu_key_list_public_export"
+ android:showAsAction="never"
+ android:title="@string/menu_export_keys"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_list_public_multi.xml b/OpenPGP-Keychain/res/menu/key_list_public_multi.xml
new file mode 100644
index 000000000..92481e9cb
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_list_public_multi.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_list_public_multi_encrypt"
+ android:title="@string/menu_encrypt_to"/>
+ <item
+ android:id="@+id/menu_key_list_public_multi_delete"
+ android:icon="@android:drawable/ic_menu_delete"
+ android:title="@string/menu_delete_key"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_list_secret.xml b/OpenPGP-Keychain/res/menu/key_list_secret.xml
new file mode 100644
index 000000000..c610eda35
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_list_secret.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_list_secret_create"
+ android:showAsAction="always|withText"
+ android:title="@string/menu_create_key"/>
+ <item
+ android:id="@+id/menu_key_list_secret_create_expert"
+ android:showAsAction="never"
+ android:title="@string/menu_create_key_expert"/>
+ <item
+ android:id="@+id/menu_key_list_secret_import"
+ android:showAsAction="never"
+ android:title="@string/menu_import"/>
+ <item
+ android:id="@+id/menu_key_list_secret_export"
+ android:showAsAction="never"
+ android:title="@string/menu_export_keys"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_list_secret_multi.xml b/OpenPGP-Keychain/res/menu/key_list_secret_multi.xml
new file mode 100644
index 000000000..a10d1e2fa
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_list_secret_multi.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_list_public_multi_delete"
+ android:icon="@android:drawable/ic_menu_delete"
+ android:title="@string/menu_delete_key"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/key_view.xml b/OpenPGP-Keychain/res/menu/key_view.xml
new file mode 100644
index 000000000..1078cd937
--- /dev/null
+++ b/OpenPGP-Keychain/res/menu/key_view.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <item
+ android:id="@+id/menu_key_view_share"
+ android:icon="@android:drawable/ic_menu_share"
+ android:showAsAction="always"
+ android:title="@string/menu_share">
+ <menu>
+ <item
+ android:id="@+id/menu_key_view_share_default"
+ android:showAsAction="never"
+ android:title="@string/menu_share"/>
+ <item
+ android:id="@+id/menu_key_view_share_qr_code"
+ android:showAsAction="never"
+ android:title="@string/menu_share_qr_code"/>
+ <item
+ android:id="@+id/menu_key_view_share_nfc"
+ android:showAsAction="never"
+ android:title="@string/menu_share_nfc"/>
+ <item
+ android:id="@+id/menu_key_view_share_clipboard"
+ android:showAsAction="never"
+ android:title="@string/menu_copy_to_clipboard"/>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/menu_key_keyserver"
+ android:icon="@android:drawable/ic_menu_upload"
+ android:showAsAction="always"
+ android:title="@string/menu_share">
+ <menu>
+ <item
+ android:id="@+id/menu_key_view_update"
+ android:showAsAction="never"
+ android:title="@string/menu_update_key"/>
+ <item
+ android:id="@+id/menu_key_view_export_keyserver"
+ android:showAsAction="never"
+ android:title="@string/menu_export_key_to_server"/>
+ </menu>
+ </item>
+ <item
+ android:id="@+id/menu_key_view_sign"
+ android:showAsAction="never"
+ android:title="@string/menu_sign_key"/>
+ <item
+ android:id="@+id/menu_key_view_export_file"
+ android:showAsAction="never"
+ android:title="@string/menu_export_key"/>
+ <item
+ android:id="@+id/menu_key_view_delete"
+ android:showAsAction="never"
+ android:title="@string/menu_delete_key"/>
+
+</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/menu/nfc_beam.xml b/OpenPGP-Keychain/res/menu/nfc_beam.xml
deleted file mode 100644
index e1c088b86..000000000
--- a/OpenPGP-Keychain/res/menu/nfc_beam.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android" >
-
- <item
- android:id="@+id/menu_settings"
- android:icon="@drawable/ic_menu_settings"
- android:showAsAction="always|withText"
- android:title="@string/menu_beam_preferences"/>
-
-</menu> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/raw/help_about.html b/OpenPGP-Keychain/res/raw/help_about.html
index 0ed0d3b05..54af42b16 100644
--- a/OpenPGP-Keychain/res/raw/help_about.html
+++ b/OpenPGP-Keychain/res/raw/help_about.html
@@ -12,13 +12,15 @@ And don't add newlines before or after p tags because of transifex -->
<h2>Developers OpenPGP Keychain</h2>
<ul>
<li>Dominik Schürmann (Lead developer)</li>
-<li>Ash Hughes</li>
+<li>Ash Hughes (crypto patches)</li>
<li>Brian C. Barnes</li>
+<li>Bahtiar 'kalkin' Gadimov (UI)</li>
+
</ul>
<h2>Developers APG 1.x</h2>
<ul>
-<li>Thialfihar (Lead developer)</li>
-<li>Senecaso (QRCode, sign key, upload key)</li>
+<li>'Thialfihar' (Lead developer)</li>
+<li>'Senecaso' (QRCode, sign key, upload key)</li>
<li>Oliver Runge</li>
<li>Markus Doits</li>
</ul>
@@ -26,7 +28,9 @@ And don't add newlines before or after p tags because of transifex -->
<h2>Libraries</h2>
<ul>
<li><a href="http://actionbarsherlock.com">ActionBarSherlock</a> (Apache License v2)</li>
-<li><a href="http://code.google.com/p/zxing/">ZXing QRCode Integration</a> (Apache License v2)</li>
+<li><a href="https://github.com/emilsjolander/StickyListHeaders">StickyListHeaders</a> (Apache License v2)</li>
+<li><a href="https://github.com/Bearded-Hen/Android-Bootstrap">Android-Bootstrap</a> (MIT License)</li>
+<li><a href="http://code.google.com/p/zxing/">ZXing</a> (Apache License v2)</li>
<li><a href="http://rtyley.github.com/spongycastle/">SpongyCastle</a> (MIT X11 License)</li>
<li><a href="https://github.com/dschuermann/html-textview">HtmlTextView</a> (Apache License v2)</li>
<li>Icons from <a href="http://rrze-icon-set.berlios.de/">RRZE Icon Set</a> (Creative Commons Attribution Share-Alike licence 3.0)</li>
diff --git a/OpenPGP-Keychain/res/values-sw600dp/dimens.xml b/OpenPGP-Keychain/res/values-sw600dp/dimens.xml
new file mode 100644
index 000000000..1ba777d65
--- /dev/null
+++ b/OpenPGP-Keychain/res/values-sw600dp/dimens.xml
@@ -0,0 +1,8 @@
+<resources>
+
+ <!--
+ Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw600dp devices (e.g. 7" tablets) here.
+ -->
+
+</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values-sw720dp-land/dimens.xml b/OpenPGP-Keychain/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 000000000..eee741a51
--- /dev/null
+++ b/OpenPGP-Keychain/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,9 @@
+<resources>
+
+ <!--
+ Customize dimensions originally defined in res/values/dimens.xml (such as
+ screen margins) for sw720dp devices (e.g. 10" tablets) in landscape here.
+ -->
+ <dimen name="activity_horizontal_margin">128dp</dimen>
+
+</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values/colors.xml b/OpenPGP-Keychain/res/values/colors.xml
index d1dc6c1f4..780137181 100644
--- a/OpenPGP-Keychain/res/values/colors.xml
+++ b/OpenPGP-Keychain/res/values/colors.xml
@@ -3,5 +3,5 @@
<color name="emphasis">#31b6e7</color>
<color name="bg_gray">#cecbce</color>
-
+
</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values/dimens.xml b/OpenPGP-Keychain/res/values/dimens.xml
new file mode 100644
index 000000000..a6dd14032
--- /dev/null
+++ b/OpenPGP-Keychain/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values/strings.xml b/OpenPGP-Keychain/res/values/strings.xml
index 807daaeb4..87f7c5a8f 100644
--- a/OpenPGP-Keychain/res/values/strings.xml
+++ b/OpenPGP-Keychain/res/values/strings.xml
@@ -19,8 +19,8 @@
<resources>
<!-- title -->
- <string name="title_manage_public_keys">Manage Public Keys</string>
- <string name="title_manage_secret_keys">Manage Secret Keys</string>
+ <string name="title_manage_public_keys">Contacts</string>
+ <string name="title_manage_secret_keys">Secret Keys</string>
<string name="title_select_recipients">Select Public Key</string>
<string name="title_select_secret_key">Select Secret Key</string>
<string name="title_encrypt">Encrypt</string>
@@ -44,6 +44,7 @@
<string name="title_send_key">Export to Key Server</string>
<string name="title_unknown_signature_key">Unknown Signature Key</string>
<string name="title_sign_key">Sign Key</string>
+ <string name="title_key_details">Key Details</string>
<string name="title_help">Help</string>
<string name="title_share_by_nfc">Share key with NFC</string>
@@ -53,6 +54,9 @@
<string name="section_general">General</string>
<string name="section_defaults">Defaults</string>
<string name="section_advanced">Advanced</string>
+ <string name="section_master_key">Master Key</string>
+ <string name="section_master_user_id">Master User ID</string>
+ <string name="section_actions">Actions</string>
<!-- button -->
<string name="btn_sign_to_clipboard">Sign (Clipboard)</string>
@@ -78,9 +82,11 @@
<!-- menu -->
<string name="menu_preferences">Settings</string>
+ <string name="menu_help">Help</string>
<string name="menu_api_app_settings">Registered Apps</string>
<string name="menu_import_from_file">Import from file</string>
<string name="menu_import_from_qr_code">Import from QR Code</string>
+ <string name="menu_import">Import</string>
<string name="menu_import_from_nfc">Import from NFC</string>
<string name="menu_export_keys">Export all keys</string>
<string name="menu_export_key">Export to file</string>
@@ -95,8 +101,11 @@
<string name="menu_share">Share with…</string>
<string name="menu_share_qr_code">Share with QR Code</string>
<string name="menu_share_nfc">Share with NFC</string>
+ <string name="menu_copy_to_clipboard">Copy to clipboard</string>
<string name="menu_sign_key">Sign key</string>
<string name="menu_beam_preferences">Beam settings</string>
+ <string name="menu_key_edit_cancel">Cancel</string>
+ <string name="menu_encrypt_to">Encrypt to…</string>
<!-- label -->
<string name="label_sign">Sign</string>
@@ -129,6 +138,7 @@
<string name="label_comment">Comment</string>
<string name="label_email">Email</string>
<string name="label_send_key">Send Key to Server?</string>
+ <string name="label_fingerprint">Fingerprint</string>
<string name="no_keys_selected">Select</string>
<string name="one_key_selected">1 Selected</string>
<string name="n_keys_selected">Selected</string>
@@ -142,6 +152,8 @@
<string name="n_key_servers">%s key server(s)</string>
<string name="fingerprint">Fingerprint:</string>
<string name="secret_key">Secret Key:</string>
+ <string name="notValid">not valid</string>
+ <string name="secretKeyring">Secret Keyring</string>
<!-- choice -->
<string name="choice_none">None</string>
@@ -190,6 +202,7 @@
<string name="specify_file_to_export_to">Please specify which file to export to.\nWARNING! File will be overwritten if it exists.</string>
<string name="specify_file_to_export_secret_keys_to">Please specify which file to export to.\nWARNING! You are about to export SECRET keys.\nWARNING! File will be overwritten if it exists.</string>
<string name="key_deletion_confirmation">Do you really want to delete the key \'%s\'?\nYou can\'t undo this!</string>
+ <string name="key_deletion_confirmation_multi">Do you really want to delete all selected keys?\nYou can\'t undo this!</string>
<string name="secret_key_deletion_confirmation">Do you really want to delete the SECRET key \'%s\'?\nYou can\'t undo this!</string>
<string name="keys_added_and_updated">Successfully added %1$s key(s) and updated %2$s key(s).</string>
<string name="keys_added">Successfully added %s key(s).</string>
@@ -206,7 +219,6 @@
<string name="lookup_unknown_key">Unknown key %s, do you want to try finding it on a keyserver?</string>
<string name="key_send_success">Successfully sent key to server</string>
<string name="key_sign_success">Successfully signed key</string>
- <string name="list_information">Long press one entry in this list to show more options!</string>
<string name="list_empty">This list is empty!</string>
<string name="nfc_successfull">Successfully sent key with NFC Beam!</string>
@@ -292,7 +304,7 @@
<string name="compression_very_slow">very slow</string>
<!-- Dashboard -->
- <string name="dashboard_manage_keys">Manage Public Keys</string>
+ <string name="dashboard_manage_keys">Contacts</string>
<string name="dashboard_my_keys">My Secret Keys</string>
<string name="dashboard_encrypt">Encrypt</string>
<string name="dashboard_decrypt">Decrypt</string>
@@ -322,8 +334,8 @@
<!-- Remote API -->
<string name="api_no_apps">No registered applications!</string>
- <string name="api_settings_show_advanced">Show advanced settings…</string>
- <string name="api_settings_hide_advanced">Hide advanced settings…</string>
+ <string name="api_settings_show_advanced">Show advanced settings</string>
+ <string name="api_settings_hide_advanced">Hide advanced settings</string>
<string name="api_settings_no_key">No key selected</string>
<string name="api_settings_select_key">Select key</string>
<string name="api_settings_save">Save</string>
@@ -343,5 +355,31 @@
<!-- Share -->
<string name="share_qr_code_dialog_start">Go through all QR Codes using \'Next\', and scan them one by one.</string>
<string name="share_qr_code_dialog_progress">QR Code %1$d of %2$d</string>
+ <string name="share_nfc_dialog">Share with NFC</string>
+
+ <!-- Key list -->
+ <plurals name="key_list_selected_keys">
+ <item quantity="one">1 key selected.</item>
+ <item quantity="other">%d keys selected.</item>
+ </plurals>
+
+ <string name="key_list_empty_text1">No keys available yet…</string>
+ <string name="key_list_empty_text2">You can start by</string>
+ <string name="key_list_empty_text3">or</string>
+ <string name="key_list_empty_button_create">creating your own key pair</string>
+ <string name="key_list_empty_button_import">importing keys.</string>
+
+ <!-- Key view -->
+ <string name="key_view_action_encrypt">Encrypt to this contact</string>
+
+ <!-- Navigation Drawer -->
+ <string name="nav_contacts">Contacts</string>
+ <string name="nav_encrypt">Encrypt</string>
+ <string name="nav_decrypt">Decrypt</string>
+ <string name="nav_import">Import Keys</string>
+ <string name="nav_secret_keys">My Keys</string>
+ <string name="nav_apps">Registered Apps</string>
+ <string name="drawer_open">Open navigation drawer</string>
+ <string name="drawer_close">Close navigation drawer</string>
</resources> \ No newline at end of file
diff --git a/OpenPGP-Keychain/res/values/styles.xml b/OpenPGP-Keychain/res/values/styles.xml
index ef3ff63f6..15214fa62 100644
--- a/OpenPGP-Keychain/res/values/styles.xml
+++ b/OpenPGP-Keychain/res/values/styles.xml
@@ -18,16 +18,6 @@
<resources>
- <style name="MinusButton">
- <item name="android:background">@drawable/btn_circle</item>
- <item name="android:src">@drawable/ic_btn_round_minus</item>
- </style>
-
- <style name="PlusButton">
- <item name="android:background">@drawable/btn_circle</item>
- <item name="android:src">@drawable/ic_btn_round_plus</item>
- </style>
-
<style name="DashboardButton">
<item name="android:layout_gravity">center_vertical</item>
<item name="android:layout_width">wrap_content</item>
@@ -44,7 +34,7 @@
<item name="android:drawablePadding">4dp</item>
<item name="android:layout_marginTop">8dp</item>
<item name="android:paddingLeft">4dp</item>
- <item name="android:textAllCaps">true</item>
+<!-- <item name="android:textAllCaps">true</item> -->
<item name="android:textColor">@color/emphasis</item>
<item name="android:textSize">14sp</item>
</style>
diff --git a/OpenPGP-Keychain/src/com/google/zxing/BarcodeFormat.java b/OpenPGP-Keychain/src/com/google/zxing/BarcodeFormat.java
deleted file mode 100644
index 1e5d47958..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/BarcodeFormat.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import java.util.Hashtable;
-
-/**
- * Enumerates barcode formats known to this package. Please keep alphabetized.
- *
- * @author Sean Owen
- */
-public final class BarcodeFormat {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- private static final Hashtable VALUES = new Hashtable();
-
- /** Aztec 2D barcode format. */
- public static final BarcodeFormat AZTEC = new BarcodeFormat("AZTEC");
-
- /** CODABAR 1D format. */
- public static final BarcodeFormat CODABAR = new BarcodeFormat("CODABAR");
-
- /** Code 39 1D format. */
- public static final BarcodeFormat CODE_39 = new BarcodeFormat("CODE_39");
-
- /** Code 93 1D format. */
- public static final BarcodeFormat CODE_93 = new BarcodeFormat("CODE_93");
-
- /** Code 128 1D format. */
- public static final BarcodeFormat CODE_128 = new BarcodeFormat("CODE_128");
-
- /** Data Matrix 2D barcode format. */
- public static final BarcodeFormat DATA_MATRIX = new BarcodeFormat("DATA_MATRIX");
-
- /** EAN-8 1D format. */
- public static final BarcodeFormat EAN_8 = new BarcodeFormat("EAN_8");
-
- /** EAN-13 1D format. */
- public static final BarcodeFormat EAN_13 = new BarcodeFormat("EAN_13");
-
- /** ITF (Interleaved Two of Five) 1D format. */
- public static final BarcodeFormat ITF = new BarcodeFormat("ITF");
-
- /** PDF417 format. */
- public static final BarcodeFormat PDF_417 = new BarcodeFormat("PDF_417");
-
- /** QR Code 2D barcode format. */
- public static final BarcodeFormat QR_CODE = new BarcodeFormat("QR_CODE");
-
- /** RSS 14 */
- public static final BarcodeFormat RSS_14 = new BarcodeFormat("RSS_14");
-
- /** RSS EXPANDED */
- public static final BarcodeFormat RSS_EXPANDED = new BarcodeFormat("RSS_EXPANDED");
-
- /** UPC-A 1D format. */
- public static final BarcodeFormat UPC_A = new BarcodeFormat("UPC_A");
-
- /** UPC-E 1D format. */
- public static final BarcodeFormat UPC_E = new BarcodeFormat("UPC_E");
-
- /** UPC/EAN extension format. Not a stand-alone format. */
- public static final BarcodeFormat UPC_EAN_EXTENSION = new BarcodeFormat("UPC_EAN_EXTENSION");
-
- private final String name;
-
- private BarcodeFormat(String name) {
- this.name = name;
- VALUES.put(name, this);
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
- public static BarcodeFormat valueOf(String name) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException();
- }
- BarcodeFormat format = (BarcodeFormat) VALUES.get(name);
- if (format == null) {
- throw new IllegalArgumentException();
- }
- return format;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/Binarizer.java b/OpenPGP-Keychain/src/com/google/zxing/Binarizer.java
deleted file mode 100644
index 912a3b556..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/Binarizer.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import com.google.zxing.common.BitArray;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * This class hierarchy provides a set of methods to convert luminance data to 1 bit data.
- * It allows the algorithm to vary polymorphically, for example allowing a very expensive
- * thresholding technique for servers and a fast one for mobile. It also permits the implementation
- * to vary, e.g. a JNI version for Android and a Java fallback version for other platforms.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public abstract class Binarizer {
-
- private final LuminanceSource source;
-
- protected Binarizer(LuminanceSource source) {
- if (source == null) {
- throw new IllegalArgumentException("Source must be non-null.");
- }
- this.source = source;
- }
-
- public LuminanceSource getLuminanceSource() {
- return source;
- }
-
- /**
- * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
- * cached data. Callers should assume this method is expensive and call it as seldom as possible.
- * This method is intended for decoding 1D barcodes and may choose to apply sharpening.
- * For callers which only examine one row of pixels at a time, the same BitArray should be reused
- * and passed in with each call for performance. However it is legal to keep more than one row
- * at a time if needed.
- *
- * @param y The row to fetch, 0 <= y < bitmap height.
- * @param row An optional preallocated array. If null or too small, it will be ignored.
- * If used, the Binarizer will call BitArray.clear(). Always use the returned object.
- * @return The array of bits for this row (true means black).
- */
- public abstract BitArray getBlackRow(int y, BitArray row) throws NotFoundException;
-
- /**
- * Converts a 2D array of luminance data to 1 bit data. As above, assume this method is expensive
- * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
- * may not apply sharpening. Therefore, a row from this matrix may not be identical to one
- * fetched using getBlackRow(), so don't mix and match between them.
- *
- * @return The 2D array of bits for the image (true means black).
- */
- public abstract BitMatrix getBlackMatrix() throws NotFoundException;
-
- /**
- * Creates a new object with the same type as this Binarizer implementation, but with pristine
- * state. This is needed because Binarizer implementations may be stateful, e.g. keeping a cache
- * of 1 bit data. See Effective Java for why we can't use Java's clone() method.
- *
- * @param source The LuminanceSource this Binarizer will operate on.
- * @return A new concrete Binarizer implementation object.
- */
- public abstract Binarizer createBinarizer(LuminanceSource source);
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/BinaryBitmap.java b/OpenPGP-Keychain/src/com/google/zxing/BinaryBitmap.java
deleted file mode 100644
index b97e46705..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/BinaryBitmap.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import com.google.zxing.common.BitArray;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * This class is the core bitmap class used by ZXing to represent 1 bit data. Reader objects
- * accept a BinaryBitmap and attempt to decode it.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class BinaryBitmap {
-
- private final Binarizer binarizer;
- private BitMatrix matrix;
-
- public BinaryBitmap(Binarizer binarizer) {
- if (binarizer == null) {
- throw new IllegalArgumentException("Binarizer must be non-null.");
- }
- this.binarizer = binarizer;
- matrix = null;
- }
-
- /**
- * @return The width of the bitmap.
- */
- public int getWidth() {
- return binarizer.getLuminanceSource().getWidth();
- }
-
- /**
- * @return The height of the bitmap.
- */
- public int getHeight() {
- return binarizer.getLuminanceSource().getHeight();
- }
-
- /**
- * Converts one row of luminance data to 1 bit data. May actually do the conversion, or return
- * cached data. Callers should assume this method is expensive and call it as seldom as possible.
- * This method is intended for decoding 1D barcodes and may choose to apply sharpening.
- *
- * @param y The row to fetch, 0 <= y < bitmap height.
- * @param row An optional preallocated array. If null or too small, it will be ignored.
- * If used, the Binarizer will call BitArray.clear(). Always use the returned object.
- * @return The array of bits for this row (true means black).
- */
- public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
- return binarizer.getBlackRow(y, row);
- }
-
- /**
- * Converts a 2D array of luminance data to 1 bit. As above, assume this method is expensive
- * and do not call it repeatedly. This method is intended for decoding 2D barcodes and may or
- * may not apply sharpening. Therefore, a row from this matrix may not be identical to one
- * fetched using getBlackRow(), so don't mix and match between them.
- *
- * @return The 2D array of bits for the image (true means black).
- */
- public BitMatrix getBlackMatrix() throws NotFoundException {
- // The matrix is created on demand the first time it is requested, then cached. There are two
- // reasons for this:
- // 1. This work will never be done if the caller only installs 1D Reader objects, or if a
- // 1D Reader finds a barcode before the 2D Readers run.
- // 2. This work will only be done once even if the caller installs multiple 2D Readers.
- if (matrix == null) {
- matrix = binarizer.getBlackMatrix();
- }
- return matrix;
- }
-
- /**
- * @return Whether this bitmap can be cropped.
- */
- public boolean isCropSupported() {
- return binarizer.getLuminanceSource().isCropSupported();
- }
-
- /**
- * Returns a new object with cropped image data. Implementations may keep a reference to the
- * original data rather than a copy. Only callable if isCropSupported() is true.
- *
- * @param left The left coordinate, 0 <= left < getWidth().
- * @param top The top coordinate, 0 <= top <= getHeight().
- * @param width The width of the rectangle to crop.
- * @param height The height of the rectangle to crop.
- * @return A cropped version of this object.
- */
- public BinaryBitmap crop(int left, int top, int width, int height) {
- LuminanceSource newSource = binarizer.getLuminanceSource().crop(left, top, width, height);
- return new BinaryBitmap(binarizer.createBinarizer(newSource));
- }
-
- /**
- * @return Whether this bitmap supports counter-clockwise rotation.
- */
- public boolean isRotateSupported() {
- return binarizer.getLuminanceSource().isRotateSupported();
- }
-
- /**
- * Returns a new object with rotated image data. Only callable if isRotateSupported() is true.
- *
- * @return A rotated version of this object.
- */
- public BinaryBitmap rotateCounterClockwise() {
- LuminanceSource newSource = binarizer.getLuminanceSource().rotateCounterClockwise();
- return new BinaryBitmap(binarizer.createBinarizer(newSource));
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/ChecksumException.java b/OpenPGP-Keychain/src/com/google/zxing/ChecksumException.java
deleted file mode 100644
index dedb4be99..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/ChecksumException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * Thrown when a barcode was successfully detected and decoded, but
- * was not returned because its checksum feature failed.
- *
- * @author Sean Owen
- */
-public final class ChecksumException extends ReaderException {
-
- private static final ChecksumException instance = new ChecksumException();
-
- private ChecksumException() {
- // do nothing
- }
-
- public static ChecksumException getChecksumInstance() {
- return instance;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/DecodeHintType.java b/OpenPGP-Keychain/src/com/google/zxing/DecodeHintType.java
deleted file mode 100644
index 20b922ca1..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/DecodeHintType.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * Encapsulates a type of hint that a caller may pass to a barcode reader to help it
- * more quickly or accurately decode it. It is up to implementations to decide what,
- * if anything, to do with the information that is supplied.
- *
- * @author Sean Owen
- * @author dswitkin@google.com (Daniel Switkin)
- * @see Reader#decode(BinaryBitmap,java.util.Hashtable)
- */
-public final class DecodeHintType {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- /**
- * Unspecified, application-specific hint. Maps to an unspecified {@link Object}.
- */
- public static final DecodeHintType OTHER = new DecodeHintType();
-
- /**
- * Image is a pure monochrome image of a barcode. Doesn't matter what it maps to;
- * use {@link Boolean#TRUE}.
- */
- public static final DecodeHintType PURE_BARCODE = new DecodeHintType();
-
- /**
- * Image is known to be of one of a few possible formats.
- * Maps to a {@link java.util.Vector} of {@link BarcodeFormat}s.
- */
- public static final DecodeHintType POSSIBLE_FORMATS = new DecodeHintType();
-
- /**
- * Spend more time to try to find a barcode; optimize for accuracy, not speed.
- * Doesn't matter what it maps to; use {@link Boolean#TRUE}.
- */
- public static final DecodeHintType TRY_HARDER = new DecodeHintType();
-
- /**
- * Specifies what character encoding to use when decoding, where applicable (type String)
- */
- public static final DecodeHintType CHARACTER_SET = new DecodeHintType();
-
- /**
- * Allowed lengths of encoded data -- reject anything else. Maps to an int[].
- */
- public static final DecodeHintType ALLOWED_LENGTHS = new DecodeHintType();
-
- /**
- * Assume Code 39 codes employ a check digit. Maps to {@link Boolean}.
- */
- public static final DecodeHintType ASSUME_CODE_39_CHECK_DIGIT = new DecodeHintType();
-
- /**
- * The caller needs to be notified via callback when a possible {@link ResultPoint}
- * is found. Maps to a {@link ResultPointCallback}.
- */
- public static final DecodeHintType NEED_RESULT_POINT_CALLBACK = new DecodeHintType();
-
- private DecodeHintType() {
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/EncodeHintType.java b/OpenPGP-Keychain/src/com/google/zxing/EncodeHintType.java
deleted file mode 100644
index 35afc1530..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/EncodeHintType.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * These are a set of hints that you may pass to Writers to specify their behavior.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class EncodeHintType {
-
- /**
- * Specifies what degree of error correction to use, for example in QR Codes (type Integer).
- */
- public static final EncodeHintType ERROR_CORRECTION = new EncodeHintType();
-
- /**
- * Specifies what character encoding to use where applicable (type String)
- */
- public static final EncodeHintType CHARACTER_SET = new EncodeHintType();
-
- private EncodeHintType() {
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/FormatException.java b/OpenPGP-Keychain/src/com/google/zxing/FormatException.java
deleted file mode 100644
index 6967e93de..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/FormatException.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * Thrown when a barcode was successfully detected, but some aspect of
- * the content did not conform to the barcode's format rules. This could have
- * been due to a mis-detection.
- *
- * @author Sean Owen
- */
-public final class FormatException extends ReaderException {
-
- private static final FormatException instance = new FormatException();
-
- private FormatException() {
- // do nothing
- }
-
- public static FormatException getFormatInstance() {
- return instance;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/LuminanceSource.java b/OpenPGP-Keychain/src/com/google/zxing/LuminanceSource.java
deleted file mode 100644
index 4b6d4539f..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/LuminanceSource.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * The purpose of this class hierarchy is to abstract different bitmap implementations across
- * platforms into a standard interface for requesting greyscale luminance values. The interface
- * only provides immutable methods; therefore crop and rotation create copies. This is to ensure
- * that one Reader does not modify the original luminance source and leave it in an unknown state
- * for other Readers in the chain.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public abstract class LuminanceSource {
-
- private final int width;
- private final int height;
-
- protected LuminanceSource(int width, int height) {
- this.width = width;
- this.height = height;
- }
-
- /**
- * Fetches one row of luminance data from the underlying platform's bitmap. Values range from
- * 0 (black) to 255 (white). Because Java does not have an unsigned byte type, callers will have
- * to bitwise and with 0xff for each value. It is preferable for implementations of this method
- * to only fetch this row rather than the whole image, since no 2D Readers may be installed and
- * getMatrix() may never be called.
- *
- * @param y The row to fetch, 0 <= y < getHeight().
- * @param row An optional preallocated array. If null or too small, it will be ignored.
- * Always use the returned object, and ignore the .length of the array.
- * @return An array containing the luminance data.
- */
- public abstract byte[] getRow(int y, byte[] row);
-
- /**
- * Fetches luminance data for the underlying bitmap. Values should be fetched using:
- * int luminance = array[y * width + x] & 0xff;
- *
- * @return A row-major 2D array of luminance values. Do not use result.length as it may be
- * larger than width * height bytes on some platforms. Do not modify the contents
- * of the result.
- */
- public abstract byte[] getMatrix();
-
- /**
- * @return The width of the bitmap.
- */
- public final int getWidth() {
- return width;
- }
-
- /**
- * @return The height of the bitmap.
- */
- public final int getHeight() {
- return height;
- }
-
- /**
- * @return Whether this subclass supports cropping.
- */
- public boolean isCropSupported() {
- return false;
- }
-
- /**
- * Returns a new object with cropped image data. Implementations may keep a reference to the
- * original data rather than a copy. Only callable if isCropSupported() is true.
- *
- * @param left The left coordinate, 0 <= left < getWidth().
- * @param top The top coordinate, 0 <= top <= getHeight().
- * @param width The width of the rectangle to crop.
- * @param height The height of the rectangle to crop.
- * @return A cropped version of this object.
- */
- public LuminanceSource crop(int left, int top, int width, int height) {
- throw new RuntimeException("This luminance source does not support cropping.");
- }
-
- /**
- * @return Whether this subclass supports counter-clockwise rotation.
- */
- public boolean isRotateSupported() {
- return false;
- }
-
- /**
- * Returns a new object with rotated image data. Only callable if isRotateSupported() is true.
- *
- * @return A rotated version of this object.
- */
- public LuminanceSource rotateCounterClockwise() {
- throw new RuntimeException("This luminance source does not support rotation.");
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/NotFoundException.java b/OpenPGP-Keychain/src/com/google/zxing/NotFoundException.java
deleted file mode 100644
index dedab8dfc..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/NotFoundException.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * Thrown when a barcode was not found in the image. It might have been
- * partially detected but could not be confirmed.
- *
- * @author Sean Owen
- */
-public final class NotFoundException extends ReaderException {
-
- private static final NotFoundException instance = new NotFoundException();
-
- private NotFoundException() {
- // do nothing
- }
-
- public static NotFoundException getNotFoundInstance() {
- return instance;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/Reader.java b/OpenPGP-Keychain/src/com/google/zxing/Reader.java
deleted file mode 100644
index 47e843ba6..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/Reader.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import java.util.Hashtable;
-
-/**
- * Implementations of this interface can decode an image of a barcode in some format into
- * the String it encodes. For example, {@link com.google.zxing.qrcode.QRCodeReader} can
- * decode a QR code. The decoder may optionally receive hints from the caller which may help
- * it decode more quickly or accurately.
- *
- * See {@link com.google.zxing.MultiFormatReader}, which attempts to determine what barcode
- * format is present within the image as well, and then decodes it accordingly.
- *
- * @author Sean Owen
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public interface Reader {
-
- /**
- * Locates and decodes a barcode in some format within an image.
- *
- * @param image image of barcode to decode
- * @return String which the barcode encodes
- * @throws NotFoundException if the barcode cannot be located or decoded for any reason
- */
- Result decode(BinaryBitmap image) throws NotFoundException, ChecksumException, FormatException;
-
- /**
- * Locates and decodes a barcode in some format within an image. This method also accepts
- * hints, each possibly associated to some data, which may help the implementation decode.
- *
- * @param image image of barcode to decode
- * @param hints passed as a {@link java.util.Hashtable} from {@link com.google.zxing.DecodeHintType}
- * to arbitrary data. The
- * meaning of the data depends upon the hint type. The implementation may or may not do
- * anything with these hints.
- * @return String which the barcode encodes
- * @throws NotFoundException if the barcode cannot be located or decoded for any reason
- */
- Result decode(BinaryBitmap image, Hashtable hints) throws NotFoundException, ChecksumException, FormatException;
-
- /**
- * Resets any internal state the implementation has after a decode, to prepare it
- * for reuse.
- */
- void reset();
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/ReaderException.java b/OpenPGP-Keychain/src/com/google/zxing/ReaderException.java
deleted file mode 100644
index 224a497e5..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/ReaderException.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * The general exception class throw when something goes wrong during decoding of a barcode.
- * This includes, but is not limited to, failing checksums / error correction algorithms, being
- * unable to locate finder timing patterns, and so on.
- *
- * @author Sean Owen
- */
-public abstract class ReaderException extends Exception {
-
- // TODO: Currently we throw up to 400 ReaderExceptions while scanning a single 240x240 image before
- // rejecting it. This involves a lot of overhead and memory allocation, and affects both performance
- // and latency on continuous scan clients. In the future, we should change all the decoders not to
- // throw exceptions for routine events, like not finding a barcode on a given row. Instead, we
- // should return error codes back to the callers, and simply delete this class. In the mean time, I
- // have altered this class to be as lightweight as possible, by ignoring the exception string, and
- // by disabling the generation of stack traces, which is especially time consuming. These are just
- // temporary measures, pending the big cleanup.
-
- //private static final ReaderException instance = new ReaderException();
-
- // EXCEPTION TRACKING SUPPORT
- // Identifies who is throwing exceptions and how often. To use:
- //
- // 1. Uncomment these lines and the code below which uses them.
- // 2. Uncomment the two corresponding lines in j2se/CommandLineRunner.decode()
- // 3. Change core to build as Java 1.5 temporarily
-// private static int exceptionCount = 0;
-// private static Map<String,Integer> throwers = new HashMap<String,Integer>(32);
-
- ReaderException() {
- // do nothing
- }
-
- //public static ReaderException getInstance() {
-// Exception e = new Exception();
-// // Take the stack frame before this one.
-// StackTraceElement stack = e.getStackTrace()[1];
-// String key = stack.getClassName() + "." + stack.getMethodName() + "(), line " +
-// stack.getLineNumber();
-// if (throwers.containsKey(key)) {
-// Integer value = throwers.get(key);
-// value++;
-// throwers.put(key, value);
-// } else {
-// throwers.put(key, 1);
-// }
-// exceptionCount++;
-
- //return instance;
- //}
-
-// public static int getExceptionCountAndReset() {
-// int temp = exceptionCount;
-// exceptionCount = 0;
-// return temp;
-// }
-//
-// public static String getThrowersAndReset() {
-// StringBuilder builder = new StringBuilder(1024);
-// Object[] keys = throwers.keySet().toArray();
-// for (int x = 0; x < keys.length; x++) {
-// String key = (String) keys[x];
-// Integer value = throwers.get(key);
-// builder.append(key);
-// builder.append(": ");
-// builder.append(value);
-// builder.append("\n");
-// }
-// throwers.clear();
-// return builder.toString();
-// }
-
- // Prevent stack traces from being taken
- // srowen says: huh, my IDE is saying this is not an override. native methods can't be overridden?
- // This, at least, does not hurt. Because we use a singleton pattern here, it doesn't matter anyhow.
- public final Throwable fillInStackTrace() {
- return null;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/Result.java b/OpenPGP-Keychain/src/com/google/zxing/Result.java
deleted file mode 100644
index ee1af527e..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/Result.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-/**
- * <p>Encapsulates the result of decoding a barcode within an image.</p>
- *
- * @author Sean Owen
- */
-public final class Result {
-
- private final String text;
- private final byte[] rawBytes;
- private ResultPoint[] resultPoints;
- private final BarcodeFormat format;
- private Hashtable resultMetadata;
- private final long timestamp;
-
- public Result(String text,
- byte[] rawBytes,
- ResultPoint[] resultPoints,
- BarcodeFormat format) {
- this(text, rawBytes, resultPoints, format, System.currentTimeMillis());
- }
-
- public Result(String text,
- byte[] rawBytes,
- ResultPoint[] resultPoints,
- BarcodeFormat format,
- long timestamp) {
- if (text == null && rawBytes == null) {
- throw new IllegalArgumentException("Text and bytes are null");
- }
- this.text = text;
- this.rawBytes = rawBytes;
- this.resultPoints = resultPoints;
- this.format = format;
- this.resultMetadata = null;
- this.timestamp = timestamp;
- }
-
- /**
- * @return raw text encoded by the barcode, if applicable, otherwise <code>null</code>
- */
- public String getText() {
- return text;
- }
-
- /**
- * @return raw bytes encoded by the barcode, if applicable, otherwise <code>null</code>
- */
- public byte[] getRawBytes() {
- return rawBytes;
- }
-
- /**
- * @return points related to the barcode in the image. These are typically points
- * identifying finder patterns or the corners of the barcode. The exact meaning is
- * specific to the type of barcode that was decoded.
- */
- public ResultPoint[] getResultPoints() {
- return resultPoints;
- }
-
- /**
- * @return {@link BarcodeFormat} representing the format of the barcode that was decoded
- */
- public BarcodeFormat getBarcodeFormat() {
- return format;
- }
-
- /**
- * @return {@link Hashtable} mapping {@link ResultMetadataType} keys to values. May be
- * <code>null</code>. This contains optional metadata about what was detected about the barcode,
- * like orientation.
- */
- public Hashtable getResultMetadata() {
- return resultMetadata;
- }
-
- public void putMetadata(ResultMetadataType type, Object value) {
- if (resultMetadata == null) {
- resultMetadata = new Hashtable(3);
- }
- resultMetadata.put(type, value);
- }
-
- public void putAllMetadata(Hashtable metadata) {
- if (metadata != null) {
- if (resultMetadata == null) {
- resultMetadata = metadata;
- } else {
- Enumeration e = metadata.keys();
- while (e.hasMoreElements()) {
- ResultMetadataType key = (ResultMetadataType) e.nextElement();
- Object value = metadata.get(key);
- resultMetadata.put(key, value);
- }
- }
- }
- }
-
- public void addResultPoints(ResultPoint[] newPoints) {
- if (resultPoints == null) {
- resultPoints = newPoints;
- } else if (newPoints != null && newPoints.length > 0) {
- ResultPoint[] allPoints = new ResultPoint[resultPoints.length + newPoints.length];
- System.arraycopy(resultPoints, 0, allPoints, 0, resultPoints.length);
- System.arraycopy(newPoints, 0, allPoints, resultPoints.length, newPoints.length);
- resultPoints = allPoints;
- }
- }
-
- public long getTimestamp() {
- return timestamp;
- }
-
- public String toString() {
- if (text == null) {
- return "[" + rawBytes.length + " bytes]";
- } else {
- return text;
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/ResultMetadataType.java b/OpenPGP-Keychain/src/com/google/zxing/ResultMetadataType.java
deleted file mode 100644
index 33d69d9c5..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/ResultMetadataType.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import java.util.Hashtable;
-
-/**
- * Represents some type of metadata about the result of the decoding that the decoder
- * wishes to communicate back to the caller.
- *
- * @author Sean Owen
- */
-public final class ResultMetadataType {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- private static final Hashtable VALUES = new Hashtable();
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- /**
- * Unspecified, application-specific metadata. Maps to an unspecified {@link Object}.
- */
- public static final ResultMetadataType OTHER = new ResultMetadataType("OTHER");
-
- /**
- * Denotes the likely approximate orientation of the barcode in the image. This value
- * is given as degrees rotated clockwise from the normal, upright orientation.
- * For example a 1D barcode which was found by reading top-to-bottom would be
- * said to have orientation "90". This key maps to an {@link Integer} whose
- * value is in the range [0,360).
- */
- public static final ResultMetadataType ORIENTATION = new ResultMetadataType("ORIENTATION");
-
- /**
- * <p>2D barcode formats typically encode text, but allow for a sort of 'byte mode'
- * which is sometimes used to encode binary data. While {@link Result} makes available
- * the complete raw bytes in the barcode for these formats, it does not offer the bytes
- * from the byte segments alone.</p>
- *
- * <p>This maps to a {@link java.util.Vector} of byte arrays corresponding to the
- * raw bytes in the byte segments in the barcode, in order.</p>
- */
- public static final ResultMetadataType BYTE_SEGMENTS = new ResultMetadataType("BYTE_SEGMENTS");
-
- /**
- * Error correction level used, if applicable. The value type depends on the
- * format, but is typically a String.
- */
- public static final ResultMetadataType ERROR_CORRECTION_LEVEL = new ResultMetadataType("ERROR_CORRECTION_LEVEL");
-
- /**
- * For some periodicals, indicates the issue number as an {@link Integer}.
- */
- public static final ResultMetadataType ISSUE_NUMBER = new ResultMetadataType("ISSUE_NUMBER");
-
- /**
- * For some products, indicates the suggested retail price in the barcode as a
- * formatted {@link String}.
- */
- public static final ResultMetadataType SUGGESTED_PRICE = new ResultMetadataType("SUGGESTED_PRICE");
-
- /**
- * For some products, the possible country of manufacture as a {@link String} denoting the
- * ISO country code. Some map to multiple possible countries, like "US/CA".
- */
- public static final ResultMetadataType POSSIBLE_COUNTRY = new ResultMetadataType("POSSIBLE_COUNTRY");
-
- private final String name;
-
- private ResultMetadataType(String name) {
- this.name = name;
- VALUES.put(name, this);
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
- public static ResultMetadataType valueOf(String name) {
- if (name == null || name.length() == 0) {
- throw new IllegalArgumentException();
- }
- ResultMetadataType format = (ResultMetadataType) VALUES.get(name);
- if (format == null) {
- throw new IllegalArgumentException();
- }
- return format;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/ResultPoint.java b/OpenPGP-Keychain/src/com/google/zxing/ResultPoint.java
deleted file mode 100644
index 366ae3855..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/ResultPoint.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * <p>Encapsulates a point of interest in an image containing a barcode. Typically, this
- * would be the location of a finder pattern or the corner of the barcode, for example.</p>
- *
- * @author Sean Owen
- */
-public class ResultPoint {
-
- private final float x;
- private final float y;
-
- public ResultPoint(float x, float y) {
- this.x = x;
- this.y = y;
- }
-
- public final float getX() {
- return x;
- }
-
- public final float getY() {
- return y;
- }
-
- public boolean equals(Object other) {
- if (other instanceof ResultPoint) {
- ResultPoint otherPoint = (ResultPoint) other;
- return x == otherPoint.x && y == otherPoint.y;
- }
- return false;
- }
-
- public int hashCode() {
- return 31 * Float.floatToIntBits(x) + Float.floatToIntBits(y);
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(25);
- result.append('(');
- result.append(x);
- result.append(',');
- result.append(y);
- result.append(')');
- return result.toString();
- }
-
- /**
- * <p>Orders an array of three ResultPoints in an order [A,B,C] such that AB < AC and
- * BC < AC and the angle between BC and BA is less than 180 degrees.
- */
- public static void orderBestPatterns(ResultPoint[] patterns) {
-
- // Find distances between pattern centers
- float zeroOneDistance = distance(patterns[0], patterns[1]);
- float oneTwoDistance = distance(patterns[1], patterns[2]);
- float zeroTwoDistance = distance(patterns[0], patterns[2]);
-
- ResultPoint pointA;
- ResultPoint pointB;
- ResultPoint pointC;
- // Assume one closest to other two is B; A and C will just be guesses at first
- if (oneTwoDistance >= zeroOneDistance && oneTwoDistance >= zeroTwoDistance) {
- pointB = patterns[0];
- pointA = patterns[1];
- pointC = patterns[2];
- } else if (zeroTwoDistance >= oneTwoDistance && zeroTwoDistance >= zeroOneDistance) {
- pointB = patterns[1];
- pointA = patterns[0];
- pointC = patterns[2];
- } else {
- pointB = patterns[2];
- pointA = patterns[0];
- pointC = patterns[1];
- }
-
- // Use cross product to figure out whether A and C are correct or flipped.
- // This asks whether BC x BA has a positive z component, which is the arrangement
- // we want for A, B, C. If it's negative, then we've got it flipped around and
- // should swap A and C.
- if (crossProductZ(pointA, pointB, pointC) < 0.0f) {
- ResultPoint temp = pointA;
- pointA = pointC;
- pointC = temp;
- }
-
- patterns[0] = pointA;
- patterns[1] = pointB;
- patterns[2] = pointC;
- }
-
-
- /**
- * @return distance between two points
- */
- public static float distance(ResultPoint pattern1, ResultPoint pattern2) {
- float xDiff = pattern1.getX() - pattern2.getX();
- float yDiff = pattern1.getY() - pattern2.getY();
- return (float) Math.sqrt((double) (xDiff * xDiff + yDiff * yDiff));
- }
-
- /**
- * Returns the z component of the cross product between vectors BC and BA.
- */
- private static float crossProductZ(ResultPoint pointA, ResultPoint pointB, ResultPoint pointC) {
- float bX = pointB.x;
- float bY = pointB.y;
- return ((pointC.x - bX) * (pointA.y - bY)) - ((pointC.y - bY) * (pointA.x - bX));
- }
-
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/ResultPointCallback.java b/OpenPGP-Keychain/src/com/google/zxing/ResultPointCallback.java
deleted file mode 100644
index 0c85410bc..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/ResultPointCallback.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * Callback which is invoked when a possible result point (significant
- * point in the barcode image such as a corner) is found.
- *
- * @see DecodeHintType#NEED_RESULT_POINT_CALLBACK
- */
-public interface ResultPointCallback {
-
- void foundPossibleResultPoint(ResultPoint point);
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/Writer.java b/OpenPGP-Keychain/src/com/google/zxing/Writer.java
deleted file mode 100644
index 6474ca7e2..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/Writer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-import com.google.zxing.common.BitMatrix;
-
-import java.util.Hashtable;
-
-/**
- * The base class for all objects which encode/generate a barcode image.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public interface Writer {
-
- /**
- * Encode a barcode using the default settings.
- *
- * @param contents The contents to encode in the barcode
- * @param format The barcode format to generate
- * @param width The preferred width in pixels
- * @param height The preferred height in pixels
- * @return The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
- */
- BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
- throws WriterException;
-
- /**
- *
- * @param contents The contents to encode in the barcode
- * @param format The barcode format to generate
- * @param width The preferred width in pixels
- * @param height The preferred height in pixels
- * @param hints Additional parameters to supply to the encoder
- * @return The generated barcode as a Matrix of unsigned bytes (0 == black, 255 == white)
- */
- BitMatrix encode(String contents, BarcodeFormat format, int width, int height, Hashtable hints)
- throws WriterException;
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/WriterException.java b/OpenPGP-Keychain/src/com/google/zxing/WriterException.java
deleted file mode 100644
index 0c19af01d..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/WriterException.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing;
-
-/**
- * A base class which covers the range of exceptions which may occur when encoding a barcode using
- * the Writer framework.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class WriterException extends Exception {
-
- public WriterException() {
- super();
- }
-
- public WriterException(String message) {
- super(message);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/BitArray.java b/OpenPGP-Keychain/src/com/google/zxing/common/BitArray.java
deleted file mode 100644
index 6eb0d57c6..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/BitArray.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * <p>A simple, fast array of bits, represented compactly by an array of ints internally.</p>
- *
- * @author Sean Owen
- */
-public final class BitArray {
- // I have changed these members to be public so ProGuard can inline get() and set(). Ideally
- // they'd be private and we'd use the -allowaccessmodification flag, but Dalvik rejects the
- // resulting binary at runtime on Android. If we find a solution to this, these should be changed
- // back to private.
- public int[] bits;
- public int size;
-
- public BitArray() {
- this.size = 0;
- this.bits = new int[1];
- }
-
- public BitArray(int size) {
- this.size = size;
- this.bits = makeArray(size);
- }
-
- public int getSize() {
- return size;
- }
-
- public int getSizeInBytes() {
- return (size + 7) >> 3;
- }
-
- private void ensureCapacity(int size) {
- if (size > bits.length << 5) {
- int[] newBits = makeArray(size);
- System.arraycopy(bits, 0, newBits, 0, bits.length);
- this.bits = newBits;
- }
- }
-
- /**
- * @param i bit to get
- * @return true iff bit i is set
- */
- public boolean get(int i) {
- return (bits[i >> 5] & (1 << (i & 0x1F))) != 0;
- }
-
- /**
- * Sets bit i.
- *
- * @param i bit to set
- */
- public void set(int i) {
- bits[i >> 5] |= 1 << (i & 0x1F);
- }
-
- /**
- * Flips bit i.
- *
- * @param i bit to set
- */
- public void flip(int i) {
- bits[i >> 5] ^= 1 << (i & 0x1F);
- }
-
- /**
- * Sets a block of 32 bits, starting at bit i.
- *
- * @param i first bit to set
- * @param newBits the new value of the next 32 bits. Note again that the least-significant bit
- * corresponds to bit i, the next-least-significant to i+1, and so on.
- */
- public void setBulk(int i, int newBits) {
- bits[i >> 5] = newBits;
- }
-
- /**
- * Clears all bits (sets to false).
- */
- public void clear() {
- int max = bits.length;
- for (int i = 0; i < max; i++) {
- bits[i] = 0;
- }
- }
-
- /**
- * Efficient method to check if a range of bits is set, or not set.
- *
- * @param start start of range, inclusive.
- * @param end end of range, exclusive
- * @param value if true, checks that bits in range are set, otherwise checks that they are not set
- * @return true iff all bits are set or not set in range, according to value argument
- * @throws IllegalArgumentException if end is less than or equal to start
- */
- public boolean isRange(int start, int end, boolean value) {
- if (end < start) {
- throw new IllegalArgumentException();
- }
- if (end == start) {
- return true; // empty range matches
- }
- end--; // will be easier to treat this as the last actually set bit -- inclusive
- int firstInt = start >> 5;
- int lastInt = end >> 5;
- for (int i = firstInt; i <= lastInt; i++) {
- int firstBit = i > firstInt ? 0 : start & 0x1F;
- int lastBit = i < lastInt ? 31 : end & 0x1F;
- int mask;
- if (firstBit == 0 && lastBit == 31) {
- mask = -1;
- } else {
- mask = 0;
- for (int j = firstBit; j <= lastBit; j++) {
- mask |= 1 << j;
- }
- }
-
- // Return false if we're looking for 1s and the masked bits[i] isn't all 1s (that is,
- // equals the mask, or we're looking for 0s and the masked portion is not all 0s
- if ((bits[i] & mask) != (value ? mask : 0)) {
- return false;
- }
- }
- return true;
- }
-
- public void appendBit(boolean bit) {
- ensureCapacity(size + 1);
- if (bit) {
- bits[size >> 5] |= (1 << (size & 0x1F));
- }
- size++;
- }
-
- /**
- * Appends the least-significant bits, from value, in order from most-significant to
- * least-significant. For example, appending 6 bits from 0x000001E will append the bits
- * 0, 1, 1, 1, 1, 0 in that order.
- */
- public void appendBits(int value, int numBits) {
- if (numBits < 0 || numBits > 32) {
- throw new IllegalArgumentException("Num bits must be between 0 and 32");
- }
- ensureCapacity(size + numBits);
- for (int numBitsLeft = numBits; numBitsLeft > 0; numBitsLeft--) {
- appendBit(((value >> (numBitsLeft - 1)) & 0x01) == 1);
- }
- }
-
- public void appendBitArray(BitArray other) {
- int otherSize = other.getSize();
- ensureCapacity(size + otherSize);
- for (int i = 0; i < otherSize; i++) {
- appendBit(other.get(i));
- }
- }
-
- public void xor(BitArray other) {
- if (bits.length != other.bits.length) {
- throw new IllegalArgumentException("Sizes don't match");
- }
- for (int i = 0; i < bits.length; i++) {
- // The last byte could be incomplete (i.e. not have 8 bits in
- // it) but there is no problem since 0 XOR 0 == 0.
- bits[i] ^= other.bits[i];
- }
- }
-
- /**
- *
- * @param bitOffset first bit to start writing
- * @param array array to write into. Bytes are written most-significant byte first. This is the opposite
- * of the internal representation, which is exposed by {@link #getBitArray()}
- * @param offset position in array to start writing
- * @param numBytes how many bytes to write
- */
- public void toBytes(int bitOffset, byte[] array, int offset, int numBytes) {
- for (int i = 0; i < numBytes; i++) {
- int theByte = 0;
- for (int j = 0; j < 8; j++) {
- if (get(bitOffset)) {
- theByte |= 1 << (7 - j);
- }
- bitOffset++;
- }
- array[offset + i] = (byte) theByte;
- }
- }
-
- /**
- * @return underlying array of ints. The first element holds the first 32 bits, and the least
- * significant bit is bit 0.
- */
- public int[] getBitArray() {
- return bits;
- }
-
- /**
- * Reverses all bits in the array.
- */
- public void reverse() {
- int[] newBits = new int[bits.length];
- int size = this.size;
- for (int i = 0; i < size; i++) {
- if (get(size - i - 1)) {
- newBits[i >> 5] |= 1 << (i & 0x1F);
- }
- }
- bits = newBits;
- }
-
- private static int[] makeArray(int size) {
- return new int[(size + 31) >> 5];
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(size);
- for (int i = 0; i < size; i++) {
- if ((i & 0x07) == 0) {
- result.append(' ');
- }
- result.append(get(i) ? 'X' : '.');
- }
- return result.toString();
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/BitMatrix.java b/OpenPGP-Keychain/src/com/google/zxing/common/BitMatrix.java
deleted file mode 100644
index 8bf75b289..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/BitMatrix.java
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * <p>Represents a 2D matrix of bits. In function arguments below, and throughout the common
- * module, x is the column position, and y is the row position. The ordering is always x, y.
- * The origin is at the top-left.</p>
- *
- * <p>Internally the bits are represented in a 1-D array of 32-bit ints. However, each row begins
- * with a new int. This is done intentionally so that we can copy out a row into a BitArray very
- * efficiently.</p>
- *
- * <p>The ordering of bits is row-major. Within each int, the least significant bits are used first,
- * meaning they represent lower x values. This is compatible with BitArray's implementation.</p>
- *
- * @author Sean Owen
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class BitMatrix {
- // Just like BitArray, these need to be public so ProGuard can inline them.
- public final int width;
- public final int height;
- public final int rowSize;
- public final int[] bits;
-
- // A helper to construct a square matrix.
- public BitMatrix(int dimension) {
- this(dimension, dimension);
- }
-
- public BitMatrix(int width, int height) {
- if (width < 1 || height < 1) {
- throw new IllegalArgumentException("Both dimensions must be greater than 0");
- }
- this.width = width;
- this.height = height;
- this.rowSize = (width + 31) >> 5;
- bits = new int[rowSize * height];
- }
-
- /**
- * <p>Gets the requested bit, where true means black.</p>
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- * @return value of given bit in matrix
- */
- public boolean get(int x, int y) {
- int offset = y * rowSize + (x >> 5);
- return ((bits[offset] >>> (x & 0x1f)) & 1) != 0;
- }
-
- /**
- * <p>Sets the given bit to true.</p>
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- */
- public void set(int x, int y) {
- int offset = y * rowSize + (x >> 5);
- bits[offset] |= 1 << (x & 0x1f);
- }
-
- /**
- * <p>Flips the given bit.</p>
- *
- * @param x The horizontal component (i.e. which column)
- * @param y The vertical component (i.e. which row)
- */
- public void flip(int x, int y) {
- int offset = y * rowSize + (x >> 5);
- bits[offset] ^= 1 << (x & 0x1f);
- }
-
- /**
- * Clears all bits (sets to false).
- */
- public void clear() {
- int max = bits.length;
- for (int i = 0; i < max; i++) {
- bits[i] = 0;
- }
- }
-
- /**
- * <p>Sets a square region of the bit matrix to true.</p>
- *
- * @param left The horizontal position to begin at (inclusive)
- * @param top The vertical position to begin at (inclusive)
- * @param width The width of the region
- * @param height The height of the region
- */
- public void setRegion(int left, int top, int width, int height) {
- if (top < 0 || left < 0) {
- throw new IllegalArgumentException("Left and top must be nonnegative");
- }
- if (height < 1 || width < 1) {
- throw new IllegalArgumentException("Height and width must be at least 1");
- }
- int right = left + width;
- int bottom = top + height;
- if (bottom > this.height || right > this.width) {
- throw new IllegalArgumentException("The region must fit inside the matrix");
- }
- for (int y = top; y < bottom; y++) {
- int offset = y * rowSize;
- for (int x = left; x < right; x++) {
- bits[offset + (x >> 5)] |= 1 << (x & 0x1f);
- }
- }
- }
-
- /**
- * A fast method to retrieve one row of data from the matrix as a BitArray.
- *
- * @param y The row to retrieve
- * @param row An optional caller-allocated BitArray, will be allocated if null or too small
- * @return The resulting BitArray - this reference should always be used even when passing
- * your own row
- */
- public BitArray getRow(int y, BitArray row) {
- if (row == null || row.getSize() < width) {
- row = new BitArray(width);
- }
- int offset = y * rowSize;
- for (int x = 0; x < rowSize; x++) {
- row.setBulk(x << 5, bits[offset + x]);
- }
- return row;
- }
-
- /**
- * This is useful in detecting a corner of a 'pure' barcode.
- *
- * @return {x,y} coordinate of top-left-most 1 bit, or null if it is all white
- */
- public int[] getTopLeftOnBit() {
- int bitsOffset = 0;
- while (bitsOffset < bits.length && bits[bitsOffset] == 0) {
- bitsOffset++;
- }
- if (bitsOffset == bits.length) {
- return null;
- }
- int y = bitsOffset / rowSize;
- int x = (bitsOffset % rowSize) << 5;
-
- int theBits = bits[bitsOffset];
- int bit = 0;
- while ((theBits << (31-bit)) == 0) {
- bit++;
- }
- x += bit;
- return new int[] {x, y};
- }
-
- public int[] getBottomRightOnBit() {
- int bitsOffset = bits.length - 1;
- while (bitsOffset >= 0 && bits[bitsOffset] == 0) {
- bitsOffset--;
- }
- if (bitsOffset < 0) {
- return null;
- }
-
- int y = bitsOffset / rowSize;
- int x = (bitsOffset % rowSize) << 5;
-
- int theBits = bits[bitsOffset];
- int bit = 31;
- while ((theBits >>> bit) == 0) {
- bit--;
- }
- x += bit;
-
- return new int[] {x, y};
- }
-
- /**
- * @return The width of the matrix
- */
- public int getWidth() {
- return width;
- }
-
- /**
- * @return The height of the matrix
- */
- public int getHeight() {
- return height;
- }
-
- public boolean equals(Object o) {
- if (!(o instanceof BitMatrix)) {
- return false;
- }
- BitMatrix other = (BitMatrix) o;
- if (width != other.width || height != other.height ||
- rowSize != other.rowSize || bits.length != other.bits.length) {
- return false;
- }
- for (int i = 0; i < bits.length; i++) {
- if (bits[i] != other.bits[i]) {
- return false;
- }
- }
- return true;
- }
-
- public int hashCode() {
- int hash = width;
- hash = 31 * hash + width;
- hash = 31 * hash + height;
- hash = 31 * hash + rowSize;
- for (int i = 0; i < bits.length; i++) {
- hash = 31 * hash + bits[i];
- }
- return hash;
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(height * (width + 1));
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- result.append(get(x, y) ? "X " : " ");
- }
- result.append('\n');
- }
- return result.toString();
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/BitSource.java b/OpenPGP-Keychain/src/com/google/zxing/common/BitSource.java
deleted file mode 100644
index a61ac5105..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/BitSource.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * <p>This provides an easy abstraction to read bits at a time from a sequence of bytes, where the
- * number of bits read is not often a multiple of 8.</p>
- *
- * <p>This class is thread-safe but not reentrant. Unless the caller modifies the bytes array
- * it passed in, in which case all bets are off.</p>
- *
- * @author Sean Owen
- */
-public final class BitSource {
-
- private final byte[] bytes;
- private int byteOffset;
- private int bitOffset;
-
- /**
- * @param bytes bytes from which this will read bits. Bits will be read from the first byte first.
- * Bits are read within a byte from most-significant to least-significant bit.
- */
- public BitSource(byte[] bytes) {
- this.bytes = bytes;
- }
-
- /**
- * @param numBits number of bits to read
- * @return int representing the bits read. The bits will appear as the least-significant
- * bits of the int
- * @throws IllegalArgumentException if numBits isn't in [1,32]
- */
- public int readBits(int numBits) {
- if (numBits < 1 || numBits > 32) {
- throw new IllegalArgumentException();
- }
-
- int result = 0;
-
- // First, read remainder from current byte
- if (bitOffset > 0) {
- int bitsLeft = 8 - bitOffset;
- int toRead = numBits < bitsLeft ? numBits : bitsLeft;
- int bitsToNotRead = bitsLeft - toRead;
- int mask = (0xFF >> (8 - toRead)) << bitsToNotRead;
- result = (bytes[byteOffset] & mask) >> bitsToNotRead;
- numBits -= toRead;
- bitOffset += toRead;
- if (bitOffset == 8) {
- bitOffset = 0;
- byteOffset++;
- }
- }
-
- // Next read whole bytes
- if (numBits > 0) {
- while (numBits >= 8) {
- result = (result << 8) | (bytes[byteOffset] & 0xFF);
- byteOffset++;
- numBits -= 8;
- }
-
- // Finally read a partial byte
- if (numBits > 0) {
- int bitsToNotRead = 8 - numBits;
- int mask = (0xFF >> bitsToNotRead) << bitsToNotRead;
- result = (result << numBits) | ((bytes[byteOffset] & mask) >> bitsToNotRead);
- bitOffset += numBits;
- }
- }
-
- return result;
- }
-
- /**
- * @return number of bits that can be read successfully
- */
- public int available() {
- return 8 * (bytes.length - byteOffset) - bitOffset;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/CharacterSetECI.java b/OpenPGP-Keychain/src/com/google/zxing/common/CharacterSetECI.java
deleted file mode 100644
index 42b7fa9f6..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/CharacterSetECI.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import java.util.Hashtable;
-
-/**
- * Encapsulates a Character Set ECI, according to "Extended Channel Interpretations" 5.3.1.1
- * of ISO 18004.
- *
- * @author Sean Owen
- */
-public final class CharacterSetECI extends ECI {
-
- private static Hashtable VALUE_TO_ECI;
- private static Hashtable NAME_TO_ECI;
-
- private static void initialize() {
- VALUE_TO_ECI = new Hashtable(29);
- NAME_TO_ECI = new Hashtable(29);
- // TODO figure out if these values are even right!
- addCharacterSet(0, "Cp437");
- addCharacterSet(1, new String[] {"ISO8859_1", "ISO-8859-1"});
- addCharacterSet(2, "Cp437");
- addCharacterSet(3, new String[] {"ISO8859_1", "ISO-8859-1"});
- addCharacterSet(4, "ISO8859_2");
- addCharacterSet(5, "ISO8859_3");
- addCharacterSet(6, "ISO8859_4");
- addCharacterSet(7, "ISO8859_5");
- addCharacterSet(8, "ISO8859_6");
- addCharacterSet(9, "ISO8859_7");
- addCharacterSet(10, "ISO8859_8");
- addCharacterSet(11, "ISO8859_9");
- addCharacterSet(12, "ISO8859_10");
- addCharacterSet(13, "ISO8859_11");
- addCharacterSet(15, "ISO8859_13");
- addCharacterSet(16, "ISO8859_14");
- addCharacterSet(17, "ISO8859_15");
- addCharacterSet(18, "ISO8859_16");
- addCharacterSet(20, new String[] {"SJIS", "Shift_JIS"});
- }
-
- private final String encodingName;
-
- private CharacterSetECI(int value, String encodingName) {
- super(value);
- this.encodingName = encodingName;
- }
-
- public String getEncodingName() {
- return encodingName;
- }
-
- private static void addCharacterSet(int value, String encodingName) {
- CharacterSetECI eci = new CharacterSetECI(value, encodingName);
- VALUE_TO_ECI.put(new Integer(value), eci); // can't use valueOf
- NAME_TO_ECI.put(encodingName, eci);
- }
-
- private static void addCharacterSet(int value, String[] encodingNames) {
- CharacterSetECI eci = new CharacterSetECI(value, encodingNames[0]);
- VALUE_TO_ECI.put(new Integer(value), eci); // can't use valueOf
- for (int i = 0; i < encodingNames.length; i++) {
- NAME_TO_ECI.put(encodingNames[i], eci);
- }
- }
-
- /**
- * @param value character set ECI value
- * @return CharacterSetECI representing ECI of given value, or null if it is legal but
- * unsupported
- * @throws IllegalArgumentException if ECI value is invalid
- */
- public static CharacterSetECI getCharacterSetECIByValue(int value) {
- if (VALUE_TO_ECI == null) {
- initialize();
- }
- if (value < 0 || value >= 900) {
- throw new IllegalArgumentException("Bad ECI value: " + value);
- }
- return (CharacterSetECI) VALUE_TO_ECI.get(new Integer(value));
- }
-
- /**
- * @param name character set ECI encoding name
- * @return CharacterSetECI representing ECI for character encoding, or null if it is legal
- * but unsupported
- */
- public static CharacterSetECI getCharacterSetECIByName(String name) {
- if (NAME_TO_ECI == null) {
- initialize();
- }
- return (CharacterSetECI) NAME_TO_ECI.get(name);
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/Collections.java b/OpenPGP-Keychain/src/com/google/zxing/common/Collections.java
deleted file mode 100644
index 319ebfe6d..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/Collections.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import java.util.Vector;
-
-/**
- * <p>This is basically a substitute for <code>java.util.Collections</code>, which is not
- * present in MIDP 2.0 / CLDC 1.1.</p>
- *
- * @author Sean Owen
- */
-public final class Collections {
-
- private Collections() {
- }
-
- /**
- * Sorts its argument (destructively) using insert sort; in the context of this package
- * insertion sort is simple and efficient given its relatively small inputs.
- *
- * @param vector vector to sort
- * @param comparator comparator to define sort ordering
- */
- public static void insertionSort(Vector vector, Comparator comparator) {
- int max = vector.size();
- for (int i = 1; i < max; i++) {
- Object value = vector.elementAt(i);
- int j = i - 1;
- Object valueB;
- while (j >= 0 && comparator.compare((valueB = vector.elementAt(j)), value) > 0) {
- vector.setElementAt(valueB, j + 1);
- j--;
- }
- vector.setElementAt(value, j + 1);
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/Comparator.java b/OpenPGP-Keychain/src/com/google/zxing/common/Comparator.java
deleted file mode 100644
index e1be15e31..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/Comparator.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * This is merely a clone of <code>Comparator</code> since it is not available in
- * CLDC 1.1 / MIDP 2.0.
- */
-public interface Comparator {
-
- int compare(Object o1, Object o2);
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/DecoderResult.java b/OpenPGP-Keychain/src/com/google/zxing/common/DecoderResult.java
deleted file mode 100644
index 7e0855333..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/DecoderResult.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import java.util.Vector;
-
-/**
- * <p>Encapsulates the result of decoding a matrix of bits. This typically
- * applies to 2D barcode formats. For now it contains the raw bytes obtained,
- * as well as a String interpretation of those bytes, if applicable.</p>
- *
- * @author Sean Owen
- */
-public final class DecoderResult {
-
- private final byte[] rawBytes;
- private final String text;
- private final Vector byteSegments;
- private final String ecLevel;
-
- public DecoderResult(byte[] rawBytes, String text, Vector byteSegments, String ecLevel) {
- if (rawBytes == null && text == null) {
- throw new IllegalArgumentException();
- }
- this.rawBytes = rawBytes;
- this.text = text;
- this.byteSegments = byteSegments;
- this.ecLevel = ecLevel;
- }
-
- public byte[] getRawBytes() {
- return rawBytes;
- }
-
- public String getText() {
- return text;
- }
-
- public Vector getByteSegments() {
- return byteSegments;
- }
-
- public String getECLevel() {
- return ecLevel;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/DefaultGridSampler.java b/OpenPGP-Keychain/src/com/google/zxing/common/DefaultGridSampler.java
deleted file mode 100644
index 74c9e7c6b..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/DefaultGridSampler.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import com.google.zxing.NotFoundException;
-
-/**
- * @author Sean Owen
- */
-public final class DefaultGridSampler extends GridSampler {
-
- public BitMatrix sampleGrid(BitMatrix image,
- int dimensionX,
- int dimensionY,
- float p1ToX, float p1ToY,
- float p2ToX, float p2ToY,
- float p3ToX, float p3ToY,
- float p4ToX, float p4ToY,
- float p1FromX, float p1FromY,
- float p2FromX, float p2FromY,
- float p3FromX, float p3FromY,
- float p4FromX, float p4FromY) throws NotFoundException {
-
- PerspectiveTransform transform = PerspectiveTransform.quadrilateralToQuadrilateral(
- p1ToX, p1ToY, p2ToX, p2ToY, p3ToX, p3ToY, p4ToX, p4ToY,
- p1FromX, p1FromY, p2FromX, p2FromY, p3FromX, p3FromY, p4FromX, p4FromY);
-
- return sampleGrid(image, dimensionX, dimensionY, transform);
- }
-
- public BitMatrix sampleGrid(BitMatrix image,
- int dimensionX,
- int dimensionY,
- PerspectiveTransform transform) throws NotFoundException {
- if (dimensionX <= 0 || dimensionY <= 0) {
- throw NotFoundException.getNotFoundInstance();
- }
- BitMatrix bits = new BitMatrix(dimensionX, dimensionY);
- float[] points = new float[dimensionX << 1];
- for (int y = 0; y < dimensionY; y++) {
- int max = points.length;
- float iValue = (float) y + 0.5f;
- for (int x = 0; x < max; x += 2) {
- points[x] = (float) (x >> 1) + 0.5f;
- points[x + 1] = iValue;
- }
- transform.transformPoints(points);
- // Quick check to see if points transformed to something inside the image;
- // sufficient to check the endpoints
- checkAndNudgePoints(image, points);
- try {
- for (int x = 0; x < max; x += 2) {
- if (image.get((int) points[x], (int) points[x + 1])) {
- // Black(-ish) pixel
- bits.set(x >> 1, y);
- }
- }
- } catch (ArrayIndexOutOfBoundsException aioobe) {
- // This feels wrong, but, sometimes if the finder patterns are misidentified, the resulting
- // transform gets "twisted" such that it maps a straight line of points to a set of points
- // whose endpoints are in bounds, but others are not. There is probably some mathematical
- // way to detect this about the transformation that I don't know yet.
- // This results in an ugly runtime exception despite our clever checks above -- can't have
- // that. We could check each point's coordinates but that feels duplicative. We settle for
- // catching and wrapping ArrayIndexOutOfBoundsException.
- throw NotFoundException.getNotFoundInstance();
- }
- }
- return bits;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/DetectorResult.java b/OpenPGP-Keychain/src/com/google/zxing/common/DetectorResult.java
deleted file mode 100644
index ea4794d17..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/DetectorResult.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import com.google.zxing.ResultPoint;
-
-/**
- * <p>Encapsulates the result of detecting a barcode in an image. This includes the raw
- * matrix of black/white pixels corresponding to the barcode, and possibly points of interest
- * in the image, like the location of finder patterns or corners of the barcode in the image.</p>
- *
- * @author Sean Owen
- */
-public class DetectorResult {
-
- private final BitMatrix bits;
- private final ResultPoint[] points;
-
- public DetectorResult(BitMatrix bits, ResultPoint[] points) {
- this.bits = bits;
- this.points = points;
- }
-
- public BitMatrix getBits() {
- return bits;
- }
-
- public ResultPoint[] getPoints() {
- return points;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/ECI.java b/OpenPGP-Keychain/src/com/google/zxing/common/ECI.java
deleted file mode 100644
index 444c779c2..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/ECI.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * Superclass of classes encapsulating types ECIs, according to "Extended Channel Interpretations"
- * 5.3 of ISO 18004.
- *
- * @author Sean Owen
- */
-public abstract class ECI {
-
- private final int value;
-
- ECI(int value) {
- this.value = value;
- }
-
- public int getValue() {
- return value;
- }
-
- /**
- * @param value ECI value
- * @return ECI representing ECI of given value, or null if it is legal but unsupported
- * @throws IllegalArgumentException if ECI value is invalid
- */
- public static ECI getECIByValue(int value) {
- if (value < 0 || value > 999999) {
- throw new IllegalArgumentException("Bad ECI value: " + value);
- }
- if (value < 900) { // Character set ECIs use 000000 - 000899
- return CharacterSetECI.getCharacterSetECIByValue(value);
- }
- return null;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/GlobalHistogramBinarizer.java b/OpenPGP-Keychain/src/com/google/zxing/common/GlobalHistogramBinarizer.java
deleted file mode 100644
index 4fa2a887b..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/GlobalHistogramBinarizer.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import com.google.zxing.Binarizer;
-import com.google.zxing.LuminanceSource;
-import com.google.zxing.NotFoundException;
-
-/**
- * This Binarizer implementation uses the old ZXing global histogram approach. It is suitable
- * for low-end mobile devices which don't have enough CPU or memory to use a local thresholding
- * algorithm. However, because it picks a global black point, it cannot handle difficult shadows
- * and gradients.
- *
- * Faster mobile devices and all desktop applications should probably use HybridBinarizer instead.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- * @author Sean Owen
- */
-public class GlobalHistogramBinarizer extends Binarizer {
-
- private static final int LUMINANCE_BITS = 5;
- private static final int LUMINANCE_SHIFT = 8 - LUMINANCE_BITS;
- private static final int LUMINANCE_BUCKETS = 1 << LUMINANCE_BITS;
-
- private byte[] luminances = null;
- private int[] buckets = null;
-
- public GlobalHistogramBinarizer(LuminanceSource source) {
- super(source);
- }
-
- // Applies simple sharpening to the row data to improve performance of the 1D Readers.
- public BitArray getBlackRow(int y, BitArray row) throws NotFoundException {
- LuminanceSource source = getLuminanceSource();
- int width = source.getWidth();
- if (row == null || row.getSize() < width) {
- row = new BitArray(width);
- } else {
- row.clear();
- }
-
- initArrays(width);
- byte[] localLuminances = source.getRow(y, luminances);
- int[] localBuckets = buckets;
- for (int x = 0; x < width; x++) {
- int pixel = localLuminances[x] & 0xff;
- localBuckets[pixel >> LUMINANCE_SHIFT]++;
- }
- int blackPoint = estimateBlackPoint(localBuckets);
-
- int left = localLuminances[0] & 0xff;
- int center = localLuminances[1] & 0xff;
- for (int x = 1; x < width - 1; x++) {
- int right = localLuminances[x + 1] & 0xff;
- // A simple -1 4 -1 box filter with a weight of 2.
- int luminance = ((center << 2) - left - right) >> 1;
- if (luminance < blackPoint) {
- row.set(x);
- }
- left = center;
- center = right;
- }
- return row;
- }
-
- // Does not sharpen the data, as this call is intended to only be used by 2D Readers.
- public BitMatrix getBlackMatrix() throws NotFoundException {
- LuminanceSource source = getLuminanceSource();
- int width = source.getWidth();
- int height = source.getHeight();
- BitMatrix matrix = new BitMatrix(width, height);
-
- // Quickly calculates the histogram by sampling four rows from the image. This proved to be
- // more robust on the blackbox tests than sampling a diagonal as we used to do.
- initArrays(width);
- int[] localBuckets = buckets;
- for (int y = 1; y < 5; y++) {
- int row = height * y / 5;
- byte[] localLuminances = source.getRow(row, luminances);
- int right = (width << 2) / 5;
- for (int x = width / 5; x < right; x++) {
- int pixel = localLuminances[x] & 0xff;
- localBuckets[pixel >> LUMINANCE_SHIFT]++;
- }
- }
- int blackPoint = estimateBlackPoint(localBuckets);
-
- // We delay reading the entire image luminance until the black point estimation succeeds.
- // Although we end up reading four rows twice, it is consistent with our motto of
- // "fail quickly" which is necessary for continuous scanning.
- byte[] localLuminances = source.getMatrix();
- for (int y = 0; y < height; y++) {
- int offset = y * width;
- for (int x = 0; x< width; x++) {
- int pixel = localLuminances[offset + x] & 0xff;
- if (pixel < blackPoint) {
- matrix.set(x, y);
- }
- }
- }
-
- return matrix;
- }
-
- public Binarizer createBinarizer(LuminanceSource source) {
- return new GlobalHistogramBinarizer(source);
- }
-
- private void initArrays(int luminanceSize) {
- if (luminances == null || luminances.length < luminanceSize) {
- luminances = new byte[luminanceSize];
- }
- if (buckets == null) {
- buckets = new int[LUMINANCE_BUCKETS];
- } else {
- for (int x = 0; x < LUMINANCE_BUCKETS; x++) {
- buckets[x] = 0;
- }
- }
- }
-
- private static int estimateBlackPoint(int[] buckets) throws NotFoundException {
- // Find the tallest peak in the histogram.
- int numBuckets = buckets.length;
- int maxBucketCount = 0;
- int firstPeak = 0;
- int firstPeakSize = 0;
- for (int x = 0; x < numBuckets; x++) {
- if (buckets[x] > firstPeakSize) {
- firstPeak = x;
- firstPeakSize = buckets[x];
- }
- if (buckets[x] > maxBucketCount) {
- maxBucketCount = buckets[x];
- }
- }
-
- // Find the second-tallest peak which is somewhat far from the tallest peak.
- int secondPeak = 0;
- int secondPeakScore = 0;
- for (int x = 0; x < numBuckets; x++) {
- int distanceToBiggest = x - firstPeak;
- // Encourage more distant second peaks by multiplying by square of distance.
- int score = buckets[x] * distanceToBiggest * distanceToBiggest;
- if (score > secondPeakScore) {
- secondPeak = x;
- secondPeakScore = score;
- }
- }
-
- // Make sure firstPeak corresponds to the black peak.
- if (firstPeak > secondPeak) {
- int temp = firstPeak;
- firstPeak = secondPeak;
- secondPeak = temp;
- }
-
- // If there is too little contrast in the image to pick a meaningful black point, throw rather
- // than waste time trying to decode the image, and risk false positives.
- if (secondPeak - firstPeak <= numBuckets >> 4) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- // Find a valley between them that is low and closer to the white peak.
- int bestValley = secondPeak - 1;
- int bestValleyScore = -1;
- for (int x = secondPeak - 1; x > firstPeak; x--) {
- int fromFirst = x - firstPeak;
- int score = fromFirst * fromFirst * (secondPeak - x) * (maxBucketCount - buckets[x]);
- if (score > bestValleyScore) {
- bestValley = x;
- bestValleyScore = score;
- }
- }
-
- return bestValley << LUMINANCE_SHIFT;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/GridSampler.java b/OpenPGP-Keychain/src/com/google/zxing/common/GridSampler.java
deleted file mode 100644
index 7f26c264e..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/GridSampler.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import com.google.zxing.NotFoundException;
-
-/**
- * Implementations of this class can, given locations of finder patterns for a QR code in an
- * image, sample the right points in the image to reconstruct the QR code, accounting for
- * perspective distortion. It is abstracted since it is relatively expensive and should be allowed
- * to take advantage of platform-specific optimized implementations, like Sun's Java Advanced
- * Imaging library, but which may not be available in other environments such as J2ME, and vice
- * versa.
- *
- * The implementation used can be controlled by calling {@link #setGridSampler(GridSampler)}
- * with an instance of a class which implements this interface.
- *
- * @author Sean Owen
- */
-public abstract class GridSampler {
-
- private static GridSampler gridSampler = new DefaultGridSampler();
-
- /**
- * Sets the implementation of GridSampler used by the library. One global
- * instance is stored, which may sound problematic. But, the implementation provided
- * ought to be appropriate for the entire platform, and all uses of this library
- * in the whole lifetime of the JVM. For instance, an Android activity can swap in
- * an implementation that takes advantage of native platform libraries.
- *
- * @param newGridSampler The platform-specific object to install.
- */
- public static void setGridSampler(GridSampler newGridSampler) {
- if (newGridSampler == null) {
- throw new IllegalArgumentException();
- }
- gridSampler = newGridSampler;
- }
-
- /**
- * @return the current implementation of GridSampler
- */
- public static GridSampler getInstance() {
- return gridSampler;
- }
-
- /**
- * Samples an image for a rectangular matrix of bits of the given dimension.
- * @param image image to sample
- * @param dimensionX width of {@link BitMatrix} to sample from image
- * @param dimensionY height of {@link BitMatrix} to sample from image
- * @return {@link BitMatrix} representing a grid of points sampled from the image within a region
- * defined by the "from" parameters
- * @throws NotFoundException if image can't be sampled, for example, if the transformation defined
- * by the given points is invalid or results in sampling outside the image boundaries
- */
- public abstract BitMatrix sampleGrid(BitMatrix image,
- int dimensionX,
- int dimensionY,
- float p1ToX, float p1ToY,
- float p2ToX, float p2ToY,
- float p3ToX, float p3ToY,
- float p4ToX, float p4ToY,
- float p1FromX, float p1FromY,
- float p2FromX, float p2FromY,
- float p3FromX, float p3FromY,
- float p4FromX, float p4FromY) throws NotFoundException;
-
- public abstract BitMatrix sampleGrid(BitMatrix image,
- int dimensionX,
- int dimensionY,
- PerspectiveTransform transform) throws NotFoundException;
-
- /**
- * <p>Checks a set of points that have been transformed to sample points on an image against
- * the image's dimensions to see if the point are even within the image.</p>
- *
- * <p>This method will actually "nudge" the endpoints back onto the image if they are found to be
- * barely (less than 1 pixel) off the image. This accounts for imperfect detection of finder
- * patterns in an image where the QR Code runs all the way to the image border.</p>
- *
- * <p>For efficiency, the method will check points from either end of the line until one is found
- * to be within the image. Because the set of points are assumed to be linear, this is valid.</p>
- *
- * @param image image into which the points should map
- * @param points actual points in x1,y1,...,xn,yn form
- * @throws NotFoundException if an endpoint is lies outside the image boundaries
- */
- protected static void checkAndNudgePoints(BitMatrix image, float[] points) throws NotFoundException {
- int width = image.getWidth();
- int height = image.getHeight();
- // Check and nudge points from start until we see some that are OK:
- boolean nudged = true;
- for (int offset = 0; offset < points.length && nudged; offset += 2) {
- int x = (int) points[offset];
- int y = (int) points[offset + 1];
- if (x < -1 || x > width || y < -1 || y > height) {
- throw NotFoundException.getNotFoundInstance();
- }
- nudged = false;
- if (x == -1) {
- points[offset] = 0.0f;
- nudged = true;
- } else if (x == width) {
- points[offset] = width - 1;
- nudged = true;
- }
- if (y == -1) {
- points[offset + 1] = 0.0f;
- nudged = true;
- } else if (y == height) {
- points[offset + 1] = height - 1;
- nudged = true;
- }
- }
- // Check and nudge points from end:
- nudged = true;
- for (int offset = points.length - 2; offset >= 0 && nudged; offset -= 2) {
- int x = (int) points[offset];
- int y = (int) points[offset + 1];
- if (x < -1 || x > width || y < -1 || y > height) {
- throw NotFoundException.getNotFoundInstance();
- }
- nudged = false;
- if (x == -1) {
- points[offset] = 0.0f;
- nudged = true;
- } else if (x == width) {
- points[offset] = width - 1;
- nudged = true;
- }
- if (y == -1) {
- points[offset + 1] = 0.0f;
- nudged = true;
- } else if (y == height) {
- points[offset + 1] = height - 1;
- nudged = true;
- }
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/HybridBinarizer.java b/OpenPGP-Keychain/src/com/google/zxing/common/HybridBinarizer.java
deleted file mode 100644
index b482c1a22..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/HybridBinarizer.java
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import com.google.zxing.Binarizer;
-import com.google.zxing.LuminanceSource;
-import com.google.zxing.NotFoundException;
-
-/**
- * This class implements a local thresholding algorithm, which while slower than the
- * GlobalHistogramBinarizer, is fairly efficient for what it does. It is designed for
- * high frequency images of barcodes with black data on white backgrounds. For this application,
- * it does a much better job than a global blackpoint with severe shadows and gradients.
- * However it tends to produce artifacts on lower frequency images and is therefore not
- * a good general purpose binarizer for uses outside ZXing.
- *
- * This class extends GlobalHistogramBinarizer, using the older histogram approach for 1D readers,
- * and the newer local approach for 2D readers. 1D decoding using a per-row histogram is already
- * inherently local, and only fails for horizontal gradients. We can revisit that problem later,
- * but for now it was not a win to use local blocks for 1D.
- *
- * This Binarizer is the default for the unit tests and the recommended class for library users.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class HybridBinarizer extends GlobalHistogramBinarizer {
-
- // This class uses 5x5 blocks to compute local luminance, where each block is 8x8 pixels.
- // So this is the smallest dimension in each axis we can accept.
- private static final int MINIMUM_DIMENSION = 40;
-
- private BitMatrix matrix = null;
-
- public HybridBinarizer(LuminanceSource source) {
- super(source);
- }
-
- public BitMatrix getBlackMatrix() throws NotFoundException {
- binarizeEntireImage();
- return matrix;
- }
-
- public Binarizer createBinarizer(LuminanceSource source) {
- return new HybridBinarizer(source);
- }
-
- // Calculates the final BitMatrix once for all requests. This could be called once from the
- // constructor instead, but there are some advantages to doing it lazily, such as making
- // profiling easier, and not doing heavy lifting when callers don't expect it.
- private void binarizeEntireImage() throws NotFoundException {
- if (matrix == null) {
- LuminanceSource source = getLuminanceSource();
- if (source.getWidth() >= MINIMUM_DIMENSION && source.getHeight() >= MINIMUM_DIMENSION) {
- byte[] luminances = source.getMatrix();
- int width = source.getWidth();
- int height = source.getHeight();
- int subWidth = width >> 3;
- if ((width & 0x07) != 0) {
- subWidth++;
- }
- int subHeight = height >> 3;
- if ((height & 0x07) != 0) {
- subHeight++;
- }
- int[][] blackPoints = calculateBlackPoints(luminances, subWidth, subHeight, width, height);
-
- matrix = new BitMatrix(width, height);
- calculateThresholdForBlock(luminances, subWidth, subHeight, width, height, blackPoints, matrix);
- } else {
- // If the image is too small, fall back to the global histogram approach.
- matrix = super.getBlackMatrix();
- }
- }
- }
-
- // For each 8x8 block in the image, calculate the average black point using a 5x5 grid
- // of the blocks around it. Also handles the corner cases (fractional blocks are computed based
- // on the last 8 pixels in the row/column which are also used in the previous block).
- private static void calculateThresholdForBlock(byte[] luminances, int subWidth, int subHeight,
- int width, int height, int[][] blackPoints, BitMatrix matrix) {
- for (int y = 0; y < subHeight; y++) {
- int yoffset = y << 3;
- if ((yoffset + 8) >= height) {
- yoffset = height - 8;
- }
- for (int x = 0; x < subWidth; x++) {
- int xoffset = x << 3;
- if ((xoffset + 8) >= width) {
- xoffset = width - 8;
- }
- int left = x > 1 ? x : 2;
- left = left < subWidth - 2 ? left : subWidth - 3;
- int top = y > 1 ? y : 2;
- top = top < subHeight - 2 ? top : subHeight - 3;
- int sum = 0;
- for (int z = -2; z <= 2; z++) {
- int[] blackRow = blackPoints[top + z];
- sum += blackRow[left - 2];
- sum += blackRow[left - 1];
- sum += blackRow[left];
- sum += blackRow[left + 1];
- sum += blackRow[left + 2];
- }
- int average = sum / 25;
- threshold8x8Block(luminances, xoffset, yoffset, average, width, matrix);
- }
- }
- }
-
- // Applies a single threshold to an 8x8 block of pixels.
- private static void threshold8x8Block(byte[] luminances, int xoffset, int yoffset, int threshold,
- int stride, BitMatrix matrix) {
- for (int y = 0; y < 8; y++) {
- int offset = (yoffset + y) * stride + xoffset;
- for (int x = 0; x < 8; x++) {
- int pixel = luminances[offset + x] & 0xff;
- if (pixel < threshold) {
- matrix.set(xoffset + x, yoffset + y);
- }
- }
- }
- }
-
- // Calculates a single black point for each 8x8 block of pixels and saves it away.
- private static int[][] calculateBlackPoints(byte[] luminances, int subWidth, int subHeight,
- int width, int height) {
- int[][] blackPoints = new int[subHeight][subWidth];
- for (int y = 0; y < subHeight; y++) {
- int yoffset = y << 3;
- if ((yoffset + 8) >= height) {
- yoffset = height - 8;
- }
- for (int x = 0; x < subWidth; x++) {
- int xoffset = x << 3;
- if ((xoffset + 8) >= width) {
- xoffset = width - 8;
- }
- int sum = 0;
- int min = 255;
- int max = 0;
- for (int yy = 0; yy < 8; yy++) {
- int offset = (yoffset + yy) * width + xoffset;
- for (int xx = 0; xx < 8; xx++) {
- int pixel = luminances[offset + xx] & 0xff;
- sum += pixel;
- if (pixel < min) {
- min = pixel;
- }
- if (pixel > max) {
- max = pixel;
- }
- }
- }
-
- // If the contrast is inadequate, use half the minimum, so that this block will be
- // treated as part of the white background, but won't drag down neighboring blocks
- // too much.
- int average;
- if (max - min > 24) {
- average = sum >> 6;
- } else {
- // When min == max == 0, let average be 1 so all is black
- average = max == 0 ? 1 : min >> 1;
- }
- blackPoints[y][x] = average;
- }
- }
- return blackPoints;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/PerspectiveTransform.java b/OpenPGP-Keychain/src/com/google/zxing/common/PerspectiveTransform.java
deleted file mode 100644
index 9e65baff1..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/PerspectiveTransform.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-/**
- * <p>This class implements a perspective transform in two dimensions. Given four source and four
- * destination points, it will compute the transformation implied between them. The code is based
- * directly upon section 3.4.2 of George Wolberg's "Digital Image Warping"; see pages 54-56.</p>
- *
- * @author Sean Owen
- */
-public final class PerspectiveTransform {
-
- private final float a11, a12, a13, a21, a22, a23, a31, a32, a33;
-
- private PerspectiveTransform(float a11, float a21, float a31,
- float a12, float a22, float a32,
- float a13, float a23, float a33) {
- this.a11 = a11;
- this.a12 = a12;
- this.a13 = a13;
- this.a21 = a21;
- this.a22 = a22;
- this.a23 = a23;
- this.a31 = a31;
- this.a32 = a32;
- this.a33 = a33;
- }
-
- public static PerspectiveTransform quadrilateralToQuadrilateral(float x0, float y0,
- float x1, float y1,
- float x2, float y2,
- float x3, float y3,
- float x0p, float y0p,
- float x1p, float y1p,
- float x2p, float y2p,
- float x3p, float y3p) {
-
- PerspectiveTransform qToS = quadrilateralToSquare(x0, y0, x1, y1, x2, y2, x3, y3);
- PerspectiveTransform sToQ = squareToQuadrilateral(x0p, y0p, x1p, y1p, x2p, y2p, x3p, y3p);
- return sToQ.times(qToS);
- }
-
- public void transformPoints(float[] points) {
- int max = points.length;
- float a11 = this.a11;
- float a12 = this.a12;
- float a13 = this.a13;
- float a21 = this.a21;
- float a22 = this.a22;
- float a23 = this.a23;
- float a31 = this.a31;
- float a32 = this.a32;
- float a33 = this.a33;
- for (int i = 0; i < max; i += 2) {
- float x = points[i];
- float y = points[i + 1];
- float denominator = a13 * x + a23 * y + a33;
- points[i] = (a11 * x + a21 * y + a31) / denominator;
- points[i + 1] = (a12 * x + a22 * y + a32) / denominator;
- }
- }
-
- /** Convenience method, not optimized for performance. */
- public void transformPoints(float[] xValues, float[] yValues) {
- int n = xValues.length;
- for (int i = 0; i < n; i ++) {
- float x = xValues[i];
- float y = yValues[i];
- float denominator = a13 * x + a23 * y + a33;
- xValues[i] = (a11 * x + a21 * y + a31) / denominator;
- yValues[i] = (a12 * x + a22 * y + a32) / denominator;
- }
- }
-
- public static PerspectiveTransform squareToQuadrilateral(float x0, float y0,
- float x1, float y1,
- float x2, float y2,
- float x3, float y3) {
- float dy2 = y3 - y2;
- float dy3 = y0 - y1 + y2 - y3;
- if (dy2 == 0.0f && dy3 == 0.0f) {
- return new PerspectiveTransform(x1 - x0, x2 - x1, x0,
- y1 - y0, y2 - y1, y0,
- 0.0f, 0.0f, 1.0f);
- } else {
- float dx1 = x1 - x2;
- float dx2 = x3 - x2;
- float dx3 = x0 - x1 + x2 - x3;
- float dy1 = y1 - y2;
- float denominator = dx1 * dy2 - dx2 * dy1;
- float a13 = (dx3 * dy2 - dx2 * dy3) / denominator;
- float a23 = (dx1 * dy3 - dx3 * dy1) / denominator;
- return new PerspectiveTransform(x1 - x0 + a13 * x1, x3 - x0 + a23 * x3, x0,
- y1 - y0 + a13 * y1, y3 - y0 + a23 * y3, y0,
- a13, a23, 1.0f);
- }
- }
-
- public static PerspectiveTransform quadrilateralToSquare(float x0, float y0,
- float x1, float y1,
- float x2, float y2,
- float x3, float y3) {
- // Here, the adjoint serves as the inverse:
- return squareToQuadrilateral(x0, y0, x1, y1, x2, y2, x3, y3).buildAdjoint();
- }
-
- PerspectiveTransform buildAdjoint() {
- // Adjoint is the transpose of the cofactor matrix:
- return new PerspectiveTransform(a22 * a33 - a23 * a32,
- a23 * a31 - a21 * a33,
- a21 * a32 - a22 * a31,
- a13 * a32 - a12 * a33,
- a11 * a33 - a13 * a31,
- a12 * a31 - a11 * a32,
- a12 * a23 - a13 * a22,
- a13 * a21 - a11 * a23,
- a11 * a22 - a12 * a21);
- }
-
- PerspectiveTransform times(PerspectiveTransform other) {
- return new PerspectiveTransform(a11 * other.a11 + a21 * other.a12 + a31 * other.a13,
- a11 * other.a21 + a21 * other.a22 + a31 * other.a23,
- a11 * other.a31 + a21 * other.a32 + a31 * other.a33,
- a12 * other.a11 + a22 * other.a12 + a32 * other.a13,
- a12 * other.a21 + a22 * other.a22 + a32 * other.a23,
- a12 * other.a31 + a22 * other.a32 + a32 * other.a33,
- a13 * other.a11 + a23 * other.a12 + a33 * other.a13,
- a13 * other.a21 + a23 * other.a22 + a33 * other.a23,
- a13 * other.a31 + a23 * other.a32 + a33 * other.a33);
-
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/StringUtils.java b/OpenPGP-Keychain/src/com/google/zxing/common/StringUtils.java
deleted file mode 100644
index 97999f997..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/StringUtils.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * Copyright (C) 2010 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common;
-
-import java.util.Hashtable;
-
-import com.google.zxing.DecodeHintType;
-
-/**
- * Common string-related functions.
- *
- * @author Sean Owen
- */
-public final class StringUtils {
-
- private static final String PLATFORM_DEFAULT_ENCODING =
- System.getProperty("file.encoding");
- public static final String SHIFT_JIS = "SJIS";
- public static final String GB2312 = "GB2312";
- private static final String EUC_JP = "EUC_JP";
- private static final String UTF8 = "UTF8";
- private static final String ISO88591 = "ISO8859_1";
- private static final boolean ASSUME_SHIFT_JIS =
- SHIFT_JIS.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING) ||
- EUC_JP.equalsIgnoreCase(PLATFORM_DEFAULT_ENCODING);
-
- private StringUtils() {}
-
- /**
- * @param bytes bytes encoding a string, whose encoding should be guessed
- * @param hints decode hints if applicable
- * @return name of guessed encoding; at the moment will only guess one of:
- * {@link #SHIFT_JIS}, {@link #UTF8}, {@link #ISO88591}, or the platform
- * default encoding if none of these can possibly be correct
- */
- public static String guessEncoding(byte[] bytes, Hashtable hints) {
- if (hints != null) {
- String characterSet = (String) hints.get(DecodeHintType.CHARACTER_SET);
- if (characterSet != null) {
- return characterSet;
- }
- }
- // Does it start with the UTF-8 byte order mark? then guess it's UTF-8
- if (bytes.length > 3 &&
- bytes[0] == (byte) 0xEF &&
- bytes[1] == (byte) 0xBB &&
- bytes[2] == (byte) 0xBF) {
- return UTF8;
- }
- // For now, merely tries to distinguish ISO-8859-1, UTF-8 and Shift_JIS,
- // which should be by far the most common encodings. ISO-8859-1
- // should not have bytes in the 0x80 - 0x9F range, while Shift_JIS
- // uses this as a first byte of a two-byte character. If we see this
- // followed by a valid second byte in Shift_JIS, assume it is Shift_JIS.
- // If we see something else in that second byte, we'll make the risky guess
- // that it's UTF-8.
- int length = bytes.length;
- boolean canBeISO88591 = true;
- boolean canBeShiftJIS = true;
- boolean canBeUTF8 = true;
- int utf8BytesLeft = 0;
- int maybeDoubleByteCount = 0;
- int maybeSingleByteKatakanaCount = 0;
- boolean sawLatin1Supplement = false;
- boolean sawUTF8Start = false;
- boolean lastWasPossibleDoubleByteStart = false;
-
- for (int i = 0;
- i < length && (canBeISO88591 || canBeShiftJIS || canBeUTF8);
- i++) {
-
- int value = bytes[i] & 0xFF;
-
- // UTF-8 stuff
- if (value >= 0x80 && value <= 0xBF) {
- if (utf8BytesLeft > 0) {
- utf8BytesLeft--;
- }
- } else {
- if (utf8BytesLeft > 0) {
- canBeUTF8 = false;
- }
- if (value >= 0xC0 && value <= 0xFD) {
- sawUTF8Start = true;
- int valueCopy = value;
- while ((valueCopy & 0x40) != 0) {
- utf8BytesLeft++;
- valueCopy <<= 1;
- }
- }
- }
-
- // ISO-8859-1 stuff
-
- if ((value == 0xC2 || value == 0xC3) && i < length - 1) {
- // This is really a poor hack. The slightly more exotic characters people might want to put in
- // a QR Code, by which I mean the Latin-1 supplement characters (e.g. u-umlaut) have encodings
- // that start with 0xC2 followed by [0xA0,0xBF], or start with 0xC3 followed by [0x80,0xBF].
- int nextValue = bytes[i + 1] & 0xFF;
- if (nextValue <= 0xBF &&
- ((value == 0xC2 && nextValue >= 0xA0) || (value == 0xC3 && nextValue >= 0x80))) {
- sawLatin1Supplement = true;
- }
- }
- if (value >= 0x7F && value <= 0x9F) {
- canBeISO88591 = false;
- }
-
- // Shift_JIS stuff
-
- if (value >= 0xA1 && value <= 0xDF) {
- // count the number of characters that might be a Shift_JIS single-byte Katakana character
- if (!lastWasPossibleDoubleByteStart) {
- maybeSingleByteKatakanaCount++;
- }
- }
- if (!lastWasPossibleDoubleByteStart &&
- ((value >= 0xF0 && value <= 0xFF) || value == 0x80 || value == 0xA0)) {
- canBeShiftJIS = false;
- }
- if ((value >= 0x81 && value <= 0x9F) || (value >= 0xE0 && value <= 0xEF)) {
- // These start double-byte characters in Shift_JIS. Let's see if it's followed by a valid
- // second byte.
- if (lastWasPossibleDoubleByteStart) {
- // If we just checked this and the last byte for being a valid double-byte
- // char, don't check starting on this byte. If this and the last byte
- // formed a valid pair, then this shouldn't be checked to see if it starts
- // a double byte pair of course.
- lastWasPossibleDoubleByteStart = false;
- } else {
- // ... otherwise do check to see if this plus the next byte form a valid
- // double byte pair encoding a character.
- lastWasPossibleDoubleByteStart = true;
- if (i >= bytes.length - 1) {
- canBeShiftJIS = false;
- } else {
- int nextValue = bytes[i + 1] & 0xFF;
- if (nextValue < 0x40 || nextValue > 0xFC) {
- canBeShiftJIS = false;
- } else {
- maybeDoubleByteCount++;
- }
- // There is some conflicting information out there about which bytes can follow which in
- // double-byte Shift_JIS characters. The rule above seems to be the one that matches practice.
- }
- }
- } else {
- lastWasPossibleDoubleByteStart = false;
- }
- }
- if (utf8BytesLeft > 0) {
- canBeUTF8 = false;
- }
-
- // Easy -- if assuming Shift_JIS and no evidence it can't be, done
- if (canBeShiftJIS && ASSUME_SHIFT_JIS) {
- return SHIFT_JIS;
- }
- if (canBeUTF8 && sawUTF8Start) {
- return UTF8;
- }
- // Distinguishing Shift_JIS and ISO-8859-1 can be a little tough. The crude heuristic is:
- // - If we saw
- // - at least 3 bytes that starts a double-byte value (bytes that are rare in ISO-8859-1), or
- // - over 5% of bytes could be single-byte Katakana (also rare in ISO-8859-1),
- // - and, saw no sequences that are invalid in Shift_JIS, then we conclude Shift_JIS
- if (canBeShiftJIS && (maybeDoubleByteCount >= 3 || 20 * maybeSingleByteKatakanaCount > length)) {
- return SHIFT_JIS;
- }
- // Otherwise, we default to ISO-8859-1 unless we know it can't be
- if (!sawLatin1Supplement && canBeISO88591) {
- return ISO88591;
- }
- // Otherwise, we take a wild guess with platform encoding
- return PLATFORM_DEFAULT_ENCODING;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/detector/MonochromeRectangleDetector.java b/OpenPGP-Keychain/src/com/google/zxing/common/detector/MonochromeRectangleDetector.java
deleted file mode 100644
index 950a22364..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/detector/MonochromeRectangleDetector.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.detector;
-
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * <p>A somewhat generic detector that looks for a barcode-like rectangular region within an image.
- * It looks within a mostly white region of an image for a region of black and white, but mostly
- * black. It returns the four corners of the region, as best it can determine.</p>
- *
- * @author Sean Owen
- */
-public final class MonochromeRectangleDetector {
-
- private static final int MAX_MODULES = 32;
-
- private final BitMatrix image;
-
- public MonochromeRectangleDetector(BitMatrix image) {
- this.image = image;
- }
-
- /**
- * <p>Detects a rectangular region of black and white -- mostly black -- with a region of mostly
- * white, in an image.</p>
- *
- * @return {@link ResultPoint}[] describing the corners of the rectangular region. The first and
- * last points are opposed on the diagonal, as are the second and third. The first point will be
- * the topmost point and the last, the bottommost. The second point will be leftmost and the
- * third, the rightmost
- * @throws NotFoundException if no Data Matrix Code can be found
- */
- public ResultPoint[] detect() throws NotFoundException {
- int height = image.getHeight();
- int width = image.getWidth();
- int halfHeight = height >> 1;
- int halfWidth = width >> 1;
- int deltaY = Math.max(1, height / (MAX_MODULES << 3));
- int deltaX = Math.max(1, width / (MAX_MODULES << 3));
-
- int top = 0;
- int bottom = height;
- int left = 0;
- int right = width;
- ResultPoint pointA = findCornerFromCenter(halfWidth, 0, left, right,
- halfHeight, -deltaY, top, bottom, halfWidth >> 1);
- top = (int) pointA.getY() - 1;
- ResultPoint pointB = findCornerFromCenter(halfWidth, -deltaX, left, right,
- halfHeight, 0, top, bottom, halfHeight >> 1);
- left = (int) pointB.getX() - 1;
- ResultPoint pointC = findCornerFromCenter(halfWidth, deltaX, left, right,
- halfHeight, 0, top, bottom, halfHeight >> 1);
- right = (int) pointC.getX() + 1;
- ResultPoint pointD = findCornerFromCenter(halfWidth, 0, left, right,
- halfHeight, deltaY, top, bottom, halfWidth >> 1);
- bottom = (int) pointD.getY() + 1;
-
- // Go try to find point A again with better information -- might have been off at first.
- pointA = findCornerFromCenter(halfWidth, 0, left, right,
- halfHeight, -deltaY, top, bottom, halfWidth >> 2);
-
- return new ResultPoint[] { pointA, pointB, pointC, pointD };
- }
-
- /**
- * Attempts to locate a corner of the barcode by scanning up, down, left or right from a center
- * point which should be within the barcode.
- *
- * @param centerX center's x component (horizontal)
- * @param deltaX same as deltaY but change in x per step instead
- * @param left minimum value of x
- * @param right maximum value of x
- * @param centerY center's y component (vertical)
- * @param deltaY change in y per step. If scanning up this is negative; down, positive;
- * left or right, 0
- * @param top minimum value of y to search through (meaningless when di == 0)
- * @param bottom maximum value of y
- * @param maxWhiteRun maximum run of white pixels that can still be considered to be within
- * the barcode
- * @return a {@link com.google.zxing.ResultPoint} encapsulating the corner that was found
- * @throws NotFoundException if such a point cannot be found
- */
- private ResultPoint findCornerFromCenter(int centerX, int deltaX, int left, int right,
- int centerY, int deltaY, int top, int bottom, int maxWhiteRun) throws NotFoundException {
- int[] lastRange = null;
- for (int y = centerY, x = centerX;
- y < bottom && y >= top && x < right && x >= left;
- y += deltaY, x += deltaX) {
- int[] range;
- if (deltaX == 0) {
- // horizontal slices, up and down
- range = blackWhiteRange(y, maxWhiteRun, left, right, true);
- } else {
- // vertical slices, left and right
- range = blackWhiteRange(x, maxWhiteRun, top, bottom, false);
- }
- if (range == null) {
- if (lastRange == null) {
- throw NotFoundException.getNotFoundInstance();
- }
- // lastRange was found
- if (deltaX == 0) {
- int lastY = y - deltaY;
- if (lastRange[0] < centerX) {
- if (lastRange[1] > centerX) {
- // straddle, choose one or the other based on direction
- return new ResultPoint(deltaY > 0 ? lastRange[0] : lastRange[1], lastY);
- }
- return new ResultPoint(lastRange[0], lastY);
- } else {
- return new ResultPoint(lastRange[1], lastY);
- }
- } else {
- int lastX = x - deltaX;
- if (lastRange[0] < centerY) {
- if (lastRange[1] > centerY) {
- return new ResultPoint(lastX, deltaX < 0 ? lastRange[0] : lastRange[1]);
- }
- return new ResultPoint(lastX, lastRange[0]);
- } else {
- return new ResultPoint(lastX, lastRange[1]);
- }
- }
- }
- lastRange = range;
- }
- throw NotFoundException.getNotFoundInstance();
- }
-
- /**
- * Computes the start and end of a region of pixels, either horizontally or vertically, that could
- * be part of a Data Matrix barcode.
- *
- * @param fixedDimension if scanning horizontally, this is the row (the fixed vertical location)
- * where we are scanning. If scanning vertically it's the column, the fixed horizontal location
- * @param maxWhiteRun largest run of white pixels that can still be considered part of the
- * barcode region
- * @param minDim minimum pixel location, horizontally or vertically, to consider
- * @param maxDim maximum pixel location, horizontally or vertically, to consider
- * @param horizontal if true, we're scanning left-right, instead of up-down
- * @return int[] with start and end of found range, or null if no such range is found
- * (e.g. only white was found)
- */
- private int[] blackWhiteRange(int fixedDimension, int maxWhiteRun, int minDim, int maxDim,
- boolean horizontal) {
-
- int center = (minDim + maxDim) >> 1;
-
- // Scan left/up first
- int start = center;
- while (start >= minDim) {
- if (horizontal ? image.get(start, fixedDimension) : image.get(fixedDimension, start)) {
- start--;
- } else {
- int whiteRunStart = start;
- do {
- start--;
- } while (start >= minDim && !(horizontal ? image.get(start, fixedDimension) :
- image.get(fixedDimension, start)));
- int whiteRunSize = whiteRunStart - start;
- if (start < minDim || whiteRunSize > maxWhiteRun) {
- start = whiteRunStart;
- break;
- }
- }
- }
- start++;
-
- // Then try right/down
- int end = center;
- while (end < maxDim) {
- if (horizontal ? image.get(end, fixedDimension) : image.get(fixedDimension, end)) {
- end++;
- } else {
- int whiteRunStart = end;
- do {
- end++;
- } while (end < maxDim && !(horizontal ? image.get(end, fixedDimension) :
- image.get(fixedDimension, end)));
- int whiteRunSize = end - whiteRunStart;
- if (end >= maxDim || whiteRunSize > maxWhiteRun) {
- end = whiteRunStart;
- break;
- }
- }
- }
- end--;
-
- return end > start ? new int[]{start, end} : null;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/detector/WhiteRectangleDetector.java b/OpenPGP-Keychain/src/com/google/zxing/common/detector/WhiteRectangleDetector.java
deleted file mode 100644
index 31d87e9d0..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/detector/WhiteRectangleDetector.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright 2010 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.detector;
-
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * <p>
- * Detects a candidate barcode-like rectangular region within an image. It
- * starts around the center of the image, increases the size of the candidate
- * region until it finds a white rectangular region. By keeping track of the
- * last black points it encountered, it determines the corners of the barcode.
- * </p>
- *
- * @author David Olivier
- */
-public final class WhiteRectangleDetector {
-
- private static final int INIT_SIZE = 30;
- private static final int CORR = 1;
-
- private final BitMatrix image;
- private final int height;
- private final int width;
- private final int leftInit;
- private final int rightInit;
- private final int downInit;
- private final int upInit;
-
- /**
- * @throws NotFoundException if image is too small
- */
- public WhiteRectangleDetector(BitMatrix image) throws NotFoundException {
- this.image = image;
- height = image.getHeight();
- width = image.getWidth();
- leftInit = (width - INIT_SIZE) >> 1;
- rightInit = (width + INIT_SIZE) >> 1;
- upInit = (height - INIT_SIZE) >> 1;
- downInit = (height + INIT_SIZE) >> 1;
- if (upInit < 0 || leftInit < 0 || downInit >= height || rightInit >= width) {
- throw NotFoundException.getNotFoundInstance();
- }
- }
-
- /**
- * @throws NotFoundException if image is too small
- */
- public WhiteRectangleDetector(BitMatrix image, int initSize, int x, int y) throws NotFoundException {
- this.image = image;
- height = image.getHeight();
- width = image.getWidth();
- int halfsize = initSize >> 1;
- leftInit = x - halfsize;
- rightInit = x + halfsize;
- upInit = y - halfsize;
- downInit = y + halfsize;
- if (upInit < 0 || leftInit < 0 || downInit >= height || rightInit >= width) {
- throw NotFoundException.getNotFoundInstance();
- }
- }
-
- /**
- * <p>
- * Detects a candidate barcode-like rectangular region within an image. It
- * starts around the center of the image, increases the size of the candidate
- * region until it finds a white rectangular region.
- * </p>
- *
- * @return {@link ResultPoint[]} describing the corners of the rectangular
- * region. The first and last points are opposed on the diagonal, as
- * are the second and third. The first point will be the topmost
- * point and the last, the bottommost. The second point will be
- * leftmost and the third, the rightmost
- * @throws NotFoundException if no Data Matrix Code can be found
- */
- public ResultPoint[] detect() throws NotFoundException {
-
- int left = leftInit;
- int right = rightInit;
- int up = upInit;
- int down = downInit;
- boolean sizeExceeded = false;
- boolean aBlackPointFoundOnBorder = true;
- boolean atLeastOneBlackPointFoundOnBorder = false;
-
- while (aBlackPointFoundOnBorder) {
-
- aBlackPointFoundOnBorder = false;
-
- // .....
- // . |
- // .....
- boolean rightBorderNotWhite = true;
- while (rightBorderNotWhite && right < width) {
- rightBorderNotWhite = containsBlackPoint(up, down, right, false);
- if (rightBorderNotWhite) {
- right++;
- aBlackPointFoundOnBorder = true;
- }
- }
-
- if (right >= width) {
- sizeExceeded = true;
- break;
- }
-
- // .....
- // . .
- // .___.
- boolean bottomBorderNotWhite = true;
- while (bottomBorderNotWhite && down < height) {
- bottomBorderNotWhite = containsBlackPoint(left, right, down, true);
- if (bottomBorderNotWhite) {
- down++;
- aBlackPointFoundOnBorder = true;
- }
- }
-
- if (down >= height) {
- sizeExceeded = true;
- break;
- }
-
- // .....
- // | .
- // .....
- boolean leftBorderNotWhite = true;
- while (leftBorderNotWhite && left >= 0) {
- leftBorderNotWhite = containsBlackPoint(up, down, left, false);
- if (leftBorderNotWhite) {
- left--;
- aBlackPointFoundOnBorder = true;
- }
- }
-
- if (left < 0) {
- sizeExceeded = true;
- break;
- }
-
- // .___.
- // . .
- // .....
- boolean topBorderNotWhite = true;
- while (topBorderNotWhite && up >= 0) {
- topBorderNotWhite = containsBlackPoint(left, right, up, true);
- if (topBorderNotWhite) {
- up--;
- aBlackPointFoundOnBorder = true;
- }
- }
-
- if (up < 0) {
- sizeExceeded = true;
- break;
- }
-
- if (aBlackPointFoundOnBorder) {
- atLeastOneBlackPointFoundOnBorder = true;
- }
-
- }
-
- if (!sizeExceeded && atLeastOneBlackPointFoundOnBorder) {
-
- int maxSize = right - left;
-
- ResultPoint z = null;
- for (int i = 1; i < maxSize; i++) {
- z = getBlackPointOnSegment(left, down - i, left + i, down);
- if (z != null) {
- break;
- }
- }
-
- if (z == null) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- ResultPoint t = null;
- //go down right
- for (int i = 1; i < maxSize; i++) {
- t = getBlackPointOnSegment(left, up + i, left + i, up);
- if (t != null) {
- break;
- }
- }
-
- if (t == null) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- ResultPoint x = null;
- //go down left
- for (int i = 1; i < maxSize; i++) {
- x = getBlackPointOnSegment(right, up + i, right - i, up);
- if (x != null) {
- break;
- }
- }
-
- if (x == null) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- ResultPoint y = null;
- //go up left
- for (int i = 1; i < maxSize; i++) {
- y = getBlackPointOnSegment(right, down - i, right - i, down);
- if (y != null) {
- break;
- }
- }
-
- if (y == null) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- return centerEdges(y, z, x, t);
-
- } else {
- throw NotFoundException.getNotFoundInstance();
- }
- }
-
- /**
- * Ends up being a bit faster than Math.round(). This merely rounds its
- * argument to the nearest int, where x.5 rounds up.
- */
- private static int round(float d) {
- return (int) (d + 0.5f);
- }
-
- private ResultPoint getBlackPointOnSegment(float aX, float aY, float bX, float bY) {
- int dist = distanceL2(aX, aY, bX, bY);
- float xStep = (bX - aX) / dist;
- float yStep = (bY - aY) / dist;
-
- for (int i = 0; i < dist; i++) {
- int x = round(aX + i * xStep);
- int y = round(aY + i * yStep);
- if (image.get(x, y)) {
- return new ResultPoint(x, y);
- }
- }
- return null;
- }
-
- private static int distanceL2(float aX, float aY, float bX, float bY) {
- float xDiff = aX - bX;
- float yDiff = aY - bY;
- return round((float) Math.sqrt(xDiff * xDiff + yDiff * yDiff));
- }
-
- /**
- * recenters the points of a constant distance towards the center
- *
- * @param y bottom most point
- * @param z left most point
- * @param x right most point
- * @param t top most point
- * @return {@link ResultPoint}[] describing the corners of the rectangular
- * region. The first and last points are opposed on the diagonal, as
- * are the second and third. The first point will be the topmost
- * point and the last, the bottommost. The second point will be
- * leftmost and the third, the rightmost
- */
- private ResultPoint[] centerEdges(ResultPoint y, ResultPoint z,
- ResultPoint x, ResultPoint t) {
-
- //
- // t t
- // z x
- // x OR z
- // y y
- //
-
- float yi = y.getX();
- float yj = y.getY();
- float zi = z.getX();
- float zj = z.getY();
- float xi = x.getX();
- float xj = x.getY();
- float ti = t.getX();
- float tj = t.getY();
-
- if (yi < width / 2) {
- return new ResultPoint[]{
- new ResultPoint(ti - CORR, tj + CORR),
- new ResultPoint(zi + CORR, zj + CORR),
- new ResultPoint(xi - CORR, xj - CORR),
- new ResultPoint(yi + CORR, yj - CORR)};
- } else {
- return new ResultPoint[]{
- new ResultPoint(ti + CORR, tj + CORR),
- new ResultPoint(zi + CORR, zj - CORR),
- new ResultPoint(xi - CORR, xj + CORR),
- new ResultPoint(yi - CORR, yj - CORR)};
- }
- }
-
- /**
- * Determines whether a segment contains a black point
- *
- * @param a min value of the scanned coordinate
- * @param b max value of the scanned coordinate
- * @param fixed value of fixed coordinate
- * @param horizontal set to true if scan must be horizontal, false if vertical
- * @return true if a black point has been found, else false.
- */
- private boolean containsBlackPoint(int a, int b, int fixed, boolean horizontal) {
-
- if (horizontal) {
- for (int x = a; x <= b; x++) {
- if (image.get(x, fixed)) {
- return true;
- }
- }
- } else {
- for (int y = a; y <= b; y++) {
- if (image.get(fixed, y)) {
- return true;
- }
- }
- }
-
- return false;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGF.java b/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGF.java
deleted file mode 100644
index 859c379ee..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGF.java
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.reedsolomon;
-
-/**
- * <p>This class contains utility methods for performing mathematical operations over
- * the Galois Fields. Operations use a given primitive polynomial in calculations.</p>
- *
- * <p>Throughout this package, elements of the GF are represented as an <code>int</code>
- * for convenience and speed (but at the cost of memory).
- * </p>
- *
- * @author Sean Owen
- * @author David Olivier
- */
-public final class GenericGF {
-
- public static final GenericGF AZTEC_DATA_12 = new GenericGF(0x1069, 4096); // x^12 + x^6 + x^5 + x^3 + 1
- public static final GenericGF AZTEC_DATA_10 = new GenericGF(0x409, 1024); // x^10 + x^3 + 1
- public static final GenericGF AZTEC_DATA_6 = new GenericGF(0x43, 64); // x^6 + x + 1
- public static final GenericGF AZTEC_PARAM = new GenericGF(0x13, 16); // x^4 + x + 1
- public static final GenericGF QR_CODE_FIELD_256 = new GenericGF(0x011D, 256); // x^8 + x^4 + x^3 + x^2 + 1
- public static final GenericGF DATA_MATRIX_FIELD_256 = new GenericGF(0x012D, 256); // x^8 + x^5 + x^3 + x^2 + 1
- public static final GenericGF AZTEC_DATA_8 = DATA_MATRIX_FIELD_256;
-
- private static final int INITIALIZATION_THRESHOLD = 0;
-
- private int[] expTable;
- private int[] logTable;
- private GenericGFPoly zero;
- private GenericGFPoly one;
- private final int size;
- private final int primitive;
- private boolean initialized = false;
-
- /**
- * Create a representation of GF(size) using the given primitive polynomial.
- *
- * @param primitive irreducible polynomial whose coefficients are represented by
- * the bits of an int, where the least-significant bit represents the constant
- * coefficient
- */
- public GenericGF(int primitive, int size) {
- this.primitive = primitive;
- this.size = size;
-
- if (size <= INITIALIZATION_THRESHOLD){
- initialize();
- }
- }
-
- private void initialize(){
- expTable = new int[size];
- logTable = new int[size];
- int x = 1;
- for (int i = 0; i < size; i++) {
- expTable[i] = x;
- x <<= 1; // x = x * 2; we're assuming the generator alpha is 2
- if (x >= size) {
- x ^= primitive;
- x &= size-1;
- }
- }
- for (int i = 0; i < size-1; i++) {
- logTable[expTable[i]] = i;
- }
- // logTable[0] == 0 but this should never be used
- zero = new GenericGFPoly(this, new int[]{0});
- one = new GenericGFPoly(this, new int[]{1});
- initialized = true;
- }
-
- private void checkInit(){
- if (!initialized) {
- initialize();
- }
- }
-
- GenericGFPoly getZero() {
- checkInit();
-
- return zero;
- }
-
- GenericGFPoly getOne() {
- checkInit();
-
- return one;
- }
-
- /**
- * @return the monomial representing coefficient * x^degree
- */
- GenericGFPoly buildMonomial(int degree, int coefficient) {
- checkInit();
-
- if (degree < 0) {
- throw new IllegalArgumentException();
- }
- if (coefficient == 0) {
- return zero;
- }
- int[] coefficients = new int[degree + 1];
- coefficients[0] = coefficient;
- return new GenericGFPoly(this, coefficients);
- }
-
- /**
- * Implements both addition and subtraction -- they are the same in GF(size).
- *
- * @return sum/difference of a and b
- */
- static int addOrSubtract(int a, int b) {
- return a ^ b;
- }
-
- /**
- * @return 2 to the power of a in GF(size)
- */
- int exp(int a) {
- checkInit();
-
- return expTable[a];
- }
-
- /**
- * @return base 2 log of a in GF(size)
- */
- int log(int a) {
- checkInit();
-
- if (a == 0) {
- throw new IllegalArgumentException();
- }
- return logTable[a];
- }
-
- /**
- * @return multiplicative inverse of a
- */
- int inverse(int a) {
- checkInit();
-
- if (a == 0) {
- throw new ArithmeticException();
- }
- return expTable[size - logTable[a] - 1];
- }
-
- /**
- * @param a
- * @param b
- * @return product of a and b in GF(size)
- */
- int multiply(int a, int b) {
- checkInit();
-
- if (a == 0 || b == 0) {
- return 0;
- }
-
- if (a<0 || b <0 || a>=size || b >=size){
- a++;
- }
-
- int logSum = logTable[a] + logTable[b];
- return expTable[(logSum % size) + logSum / size];
- }
-
- public int getSize(){
- return size;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGFPoly.java b/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGFPoly.java
deleted file mode 100644
index 056802287..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/GenericGFPoly.java
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.reedsolomon;
-
-/**
- * <p>Represents a polynomial whose coefficients are elements of a GF.
- * Instances of this class are immutable.</p>
- *
- * <p>Much credit is due to William Rucklidge since portions of this code are an indirect
- * port of his C++ Reed-Solomon implementation.</p>
- *
- * @author Sean Owen
- */
-final class GenericGFPoly {
-
- private final GenericGF field;
- private final int[] coefficients;
-
- /**
- * @param field the {@link GenericGF} instance representing the field to use
- * to perform computations
- * @param coefficients coefficients as ints representing elements of GF(size), arranged
- * from most significant (highest-power term) coefficient to least significant
- * @throws IllegalArgumentException if argument is null or empty,
- * or if leading coefficient is 0 and this is not a
- * constant polynomial (that is, it is not the monomial "0")
- */
- GenericGFPoly(GenericGF field, int[] coefficients) {
- if (coefficients == null || coefficients.length == 0) {
- throw new IllegalArgumentException();
- }
- this.field = field;
- int coefficientsLength = coefficients.length;
- if (coefficientsLength > 1 && coefficients[0] == 0) {
- // Leading term must be non-zero for anything except the constant polynomial "0"
- int firstNonZero = 1;
- while (firstNonZero < coefficientsLength && coefficients[firstNonZero] == 0) {
- firstNonZero++;
- }
- if (firstNonZero == coefficientsLength) {
- this.coefficients = field.getZero().coefficients;
- } else {
- this.coefficients = new int[coefficientsLength - firstNonZero];
- System.arraycopy(coefficients,
- firstNonZero,
- this.coefficients,
- 0,
- this.coefficients.length);
- }
- } else {
- this.coefficients = coefficients;
- }
- }
-
- int[] getCoefficients() {
- return coefficients;
- }
-
- /**
- * @return degree of this polynomial
- */
- int getDegree() {
- return coefficients.length - 1;
- }
-
- /**
- * @return true iff this polynomial is the monomial "0"
- */
- boolean isZero() {
- return coefficients[0] == 0;
- }
-
- /**
- * @return coefficient of x^degree term in this polynomial
- */
- int getCoefficient(int degree) {
- return coefficients[coefficients.length - 1 - degree];
- }
-
- /**
- * @return evaluation of this polynomial at a given point
- */
- int evaluateAt(int a) {
- if (a == 0) {
- // Just return the x^0 coefficient
- return getCoefficient(0);
- }
- int size = coefficients.length;
- if (a == 1) {
- // Just the sum of the coefficients
- int result = 0;
- for (int i = 0; i < size; i++) {
- result = GenericGF.addOrSubtract(result, coefficients[i]);
- }
- return result;
- }
- int result = coefficients[0];
- for (int i = 1; i < size; i++) {
- result = GenericGF.addOrSubtract(field.multiply(a, result), coefficients[i]);
- }
- return result;
- }
-
- GenericGFPoly addOrSubtract(GenericGFPoly other) {
- if (!field.equals(other.field)) {
- throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
- }
- if (isZero()) {
- return other;
- }
- if (other.isZero()) {
- return this;
- }
-
- int[] smallerCoefficients = this.coefficients;
- int[] largerCoefficients = other.coefficients;
- if (smallerCoefficients.length > largerCoefficients.length) {
- int[] temp = smallerCoefficients;
- smallerCoefficients = largerCoefficients;
- largerCoefficients = temp;
- }
- int[] sumDiff = new int[largerCoefficients.length];
- int lengthDiff = largerCoefficients.length - smallerCoefficients.length;
- // Copy high-order terms only found in higher-degree polynomial's coefficients
- System.arraycopy(largerCoefficients, 0, sumDiff, 0, lengthDiff);
-
- for (int i = lengthDiff; i < largerCoefficients.length; i++) {
- sumDiff[i] = GenericGF.addOrSubtract(smallerCoefficients[i - lengthDiff], largerCoefficients[i]);
- }
-
- return new GenericGFPoly(field, sumDiff);
- }
-
- GenericGFPoly multiply(GenericGFPoly other) {
- if (!field.equals(other.field)) {
- throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
- }
- if (isZero() || other.isZero()) {
- return field.getZero();
- }
- int[] aCoefficients = this.coefficients;
- int aLength = aCoefficients.length;
- int[] bCoefficients = other.coefficients;
- int bLength = bCoefficients.length;
- int[] product = new int[aLength + bLength - 1];
- for (int i = 0; i < aLength; i++) {
- int aCoeff = aCoefficients[i];
- for (int j = 0; j < bLength; j++) {
- product[i + j] = GenericGF.addOrSubtract(product[i + j],
- field.multiply(aCoeff, bCoefficients[j]));
- }
- }
- return new GenericGFPoly(field, product);
- }
-
- GenericGFPoly multiply(int scalar) {
- if (scalar == 0) {
- return field.getZero();
- }
- if (scalar == 1) {
- return this;
- }
- int size = coefficients.length;
- int[] product = new int[size];
- for (int i = 0; i < size; i++) {
- product[i] = field.multiply(coefficients[i], scalar);
- }
- return new GenericGFPoly(field, product);
- }
-
- GenericGFPoly multiplyByMonomial(int degree, int coefficient) {
- if (degree < 0) {
- throw new IllegalArgumentException();
- }
- if (coefficient == 0) {
- return field.getZero();
- }
- int size = coefficients.length;
- int[] product = new int[size + degree];
- for (int i = 0; i < size; i++) {
- product[i] = field.multiply(coefficients[i], coefficient);
- }
- return new GenericGFPoly(field, product);
- }
-
- GenericGFPoly[] divide(GenericGFPoly other) {
- if (!field.equals(other.field)) {
- throw new IllegalArgumentException("GenericGFPolys do not have same GenericGF field");
- }
- if (other.isZero()) {
- throw new IllegalArgumentException("Divide by 0");
- }
-
- GenericGFPoly quotient = field.getZero();
- GenericGFPoly remainder = this;
-
- int denominatorLeadingTerm = other.getCoefficient(other.getDegree());
- int inverseDenominatorLeadingTerm = field.inverse(denominatorLeadingTerm);
-
- while (remainder.getDegree() >= other.getDegree() && !remainder.isZero()) {
- int degreeDifference = remainder.getDegree() - other.getDegree();
- int scale = field.multiply(remainder.getCoefficient(remainder.getDegree()), inverseDenominatorLeadingTerm);
- GenericGFPoly term = other.multiplyByMonomial(degreeDifference, scale);
- GenericGFPoly iterationQuotient = field.buildMonomial(degreeDifference, scale);
- quotient = quotient.addOrSubtract(iterationQuotient);
- remainder = remainder.addOrSubtract(term);
- }
-
- return new GenericGFPoly[] { quotient, remainder };
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(8 * getDegree());
- for (int degree = getDegree(); degree >= 0; degree--) {
- int coefficient = getCoefficient(degree);
- if (coefficient != 0) {
- if (coefficient < 0) {
- result.append(" - ");
- coefficient = -coefficient;
- } else {
- if (result.length() > 0) {
- result.append(" + ");
- }
- }
- if (degree == 0 || coefficient != 1) {
- int alphaPower = field.log(coefficient);
- if (alphaPower == 0) {
- result.append('1');
- } else if (alphaPower == 1) {
- result.append('a');
- } else {
- result.append("a^");
- result.append(alphaPower);
- }
- }
- if (degree != 0) {
- if (degree == 1) {
- result.append('x');
- } else {
- result.append("x^");
- result.append(degree);
- }
- }
- }
- }
- return result.toString();
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java b/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java
deleted file mode 100644
index b523fd34b..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonDecoder.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.reedsolomon;
-
-/**
- * <p>Implements Reed-Solomon decoding, as the name implies.</p>
- *
- * <p>The algorithm will not be explained here, but the following references were helpful
- * in creating this implementation:</p>
- *
- * <ul>
- * <li>Bruce Maggs.
- * <a href="http://www.cs.cmu.edu/afs/cs.cmu.edu/project/pscico-guyb/realworld/www/rs_decode.ps">
- * "Decoding Reed-Solomon Codes"</a> (see discussion of Forney's Formula)</li>
- * <li>J.I. Hall. <a href="www.mth.msu.edu/~jhall/classes/codenotes/GRS.pdf">
- * "Chapter 5. Generalized Reed-Solomon Codes"</a>
- * (see discussion of Euclidean algorithm)</li>
- * </ul>
- *
- * <p>Much credit is due to William Rucklidge since portions of this code are an indirect
- * port of his C++ Reed-Solomon implementation.</p>
- *
- * @author Sean Owen
- * @author William Rucklidge
- * @author sanfordsquires
- */
-public final class ReedSolomonDecoder {
-
- private final GenericGF field;
-
- public ReedSolomonDecoder(GenericGF field) {
- this.field = field;
- }
-
- /**
- * <p>Decodes given set of received codewords, which include both data and error-correction
- * codewords. Really, this means it uses Reed-Solomon to detect and correct errors, in-place,
- * in the input.</p>
- *
- * @param received data and error-correction codewords
- * @param twoS number of error-correction codewords available
- * @throws ReedSolomonException if decoding fails for any reason
- */
- public void decode(int[] received, int twoS) throws ReedSolomonException {
- GenericGFPoly poly = new GenericGFPoly(field, received);
- int[] syndromeCoefficients = new int[twoS];
- boolean dataMatrix = field.equals(GenericGF.DATA_MATRIX_FIELD_256);
- boolean noError = true;
- for (int i = 0; i < twoS; i++) {
- // Thanks to sanfordsquires for this fix:
- int eval = poly.evaluateAt(field.exp(dataMatrix ? i + 1 : i));
- syndromeCoefficients[syndromeCoefficients.length - 1 - i] = eval;
- if (eval != 0) {
- noError = false;
- }
- }
- if (noError) {
- return;
- }
- GenericGFPoly syndrome = new GenericGFPoly(field, syndromeCoefficients);
- GenericGFPoly[] sigmaOmega =
- runEuclideanAlgorithm(field.buildMonomial(twoS, 1), syndrome, twoS);
- GenericGFPoly sigma = sigmaOmega[0];
- GenericGFPoly omega = sigmaOmega[1];
- int[] errorLocations = findErrorLocations(sigma);
- int[] errorMagnitudes = findErrorMagnitudes(omega, errorLocations, dataMatrix);
- for (int i = 0; i < errorLocations.length; i++) {
- int position = received.length - 1 - field.log(errorLocations[i]);
- if (position < 0) {
- throw new ReedSolomonException("Bad error location");
- }
- received[position] = GenericGF.addOrSubtract(received[position], errorMagnitudes[i]);
- }
- }
-
- private GenericGFPoly[] runEuclideanAlgorithm(GenericGFPoly a, GenericGFPoly b, int R)
- throws ReedSolomonException {
- // Assume a's degree is >= b's
- if (a.getDegree() < b.getDegree()) {
- GenericGFPoly temp = a;
- a = b;
- b = temp;
- }
-
- GenericGFPoly rLast = a;
- GenericGFPoly r = b;
- GenericGFPoly sLast = field.getOne();
- GenericGFPoly s = field.getZero();
- GenericGFPoly tLast = field.getZero();
- GenericGFPoly t = field.getOne();
-
- // Run Euclidean algorithm until r's degree is less than R/2
- while (r.getDegree() >= R / 2) {
- GenericGFPoly rLastLast = rLast;
- GenericGFPoly sLastLast = sLast;
- GenericGFPoly tLastLast = tLast;
- rLast = r;
- sLast = s;
- tLast = t;
-
- // Divide rLastLast by rLast, with quotient in q and remainder in r
- if (rLast.isZero()) {
- // Oops, Euclidean algorithm already terminated?
- throw new ReedSolomonException("r_{i-1} was zero");
- }
- r = rLastLast;
- GenericGFPoly q = field.getZero();
- int denominatorLeadingTerm = rLast.getCoefficient(rLast.getDegree());
- int dltInverse = field.inverse(denominatorLeadingTerm);
- while (r.getDegree() >= rLast.getDegree() && !r.isZero()) {
- int degreeDiff = r.getDegree() - rLast.getDegree();
- int scale = field.multiply(r.getCoefficient(r.getDegree()), dltInverse);
- q = q.addOrSubtract(field.buildMonomial(degreeDiff, scale));
- r = r.addOrSubtract(rLast.multiplyByMonomial(degreeDiff, scale));
- }
-
- s = q.multiply(sLast).addOrSubtract(sLastLast);
- t = q.multiply(tLast).addOrSubtract(tLastLast);
- }
-
- int sigmaTildeAtZero = t.getCoefficient(0);
- if (sigmaTildeAtZero == 0) {
- throw new ReedSolomonException("sigmaTilde(0) was zero");
- }
-
- int inverse = field.inverse(sigmaTildeAtZero);
- GenericGFPoly sigma = t.multiply(inverse);
- GenericGFPoly omega = r.multiply(inverse);
- return new GenericGFPoly[]{sigma, omega};
- }
-
- private int[] findErrorLocations(GenericGFPoly errorLocator) throws ReedSolomonException {
- // This is a direct application of Chien's search
- int numErrors = errorLocator.getDegree();
- if (numErrors == 1) { // shortcut
- return new int[] { errorLocator.getCoefficient(1) };
- }
- int[] result = new int[numErrors];
- int e = 0;
- for (int i = 1; i < field.getSize() && e < numErrors; i++) {
- if (errorLocator.evaluateAt(i) == 0) {
- result[e] = field.inverse(i);
- e++;
- }
- }
- if (e != numErrors) {
- throw new ReedSolomonException("Error locator degree does not match number of roots");
- }
- return result;
- }
-
- private int[] findErrorMagnitudes(GenericGFPoly errorEvaluator, int[] errorLocations, boolean dataMatrix) {
- // This is directly applying Forney's Formula
- int s = errorLocations.length;
- int[] result = new int[s];
- for (int i = 0; i < s; i++) {
- int xiInverse = field.inverse(errorLocations[i]);
- int denominator = 1;
- for (int j = 0; j < s; j++) {
- if (i != j) {
- //denominator = field.multiply(denominator,
- // GenericGF.addOrSubtract(1, field.multiply(errorLocations[j], xiInverse)));
- // Above should work but fails on some Apple and Linux JDKs due to a Hotspot bug.
- // Below is a funny-looking workaround from Steven Parkes
- int term = field.multiply(errorLocations[j], xiInverse);
- int termPlus1 = (term & 0x1) == 0 ? term | 1 : term & ~1;
- denominator = field.multiply(denominator, termPlus1);
- }
- }
- result[i] = field.multiply(errorEvaluator.evaluateAt(xiInverse),
- field.inverse(denominator));
- // Thanks to sanfordsquires for this fix:
- if (dataMatrix) {
- result[i] = field.multiply(result[i], xiInverse);
- }
- }
- return result;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java b/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java
deleted file mode 100644
index 05e2ae03a..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonEncoder.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.reedsolomon;
-
-import java.util.Vector;
-
-/**
- * <p>Implements Reed-Solomon enbcoding, as the name implies.</p>
- *
- * @author Sean Owen
- * @author William Rucklidge
- */
-public final class ReedSolomonEncoder {
-
- private final GenericGF field;
- private final Vector cachedGenerators;
-
- public ReedSolomonEncoder(GenericGF field) {
- if (!GenericGF.QR_CODE_FIELD_256.equals(field)) {
- throw new IllegalArgumentException("Only QR Code is supported at this time");
- }
- this.field = field;
- this.cachedGenerators = new Vector();
- cachedGenerators.addElement(new GenericGFPoly(field, new int[] { 1 }));
- }
-
- private GenericGFPoly buildGenerator(int degree) {
- if (degree >= cachedGenerators.size()) {
- GenericGFPoly lastGenerator = (GenericGFPoly) cachedGenerators.elementAt(cachedGenerators.size() - 1);
- for (int d = cachedGenerators.size(); d <= degree; d++) {
- GenericGFPoly nextGenerator = lastGenerator.multiply(new GenericGFPoly(field, new int[] { 1, field.exp(d - 1) }));
- cachedGenerators.addElement(nextGenerator);
- lastGenerator = nextGenerator;
- }
- }
- return (GenericGFPoly) cachedGenerators.elementAt(degree);
- }
-
- public void encode(int[] toEncode, int ecBytes) {
- if (ecBytes == 0) {
- throw new IllegalArgumentException("No error correction bytes");
- }
- int dataBytes = toEncode.length - ecBytes;
- if (dataBytes <= 0) {
- throw new IllegalArgumentException("No data bytes provided");
- }
- GenericGFPoly generator = buildGenerator(ecBytes);
- int[] infoCoefficients = new int[dataBytes];
- System.arraycopy(toEncode, 0, infoCoefficients, 0, dataBytes);
- GenericGFPoly info = new GenericGFPoly(field, infoCoefficients);
- info = info.multiplyByMonomial(ecBytes, 1);
- GenericGFPoly remainder = info.divide(generator)[1];
- int[] coefficients = remainder.getCoefficients();
- int numZeroCoefficients = ecBytes - coefficients.length;
- for (int i = 0; i < numZeroCoefficients; i++) {
- toEncode[dataBytes + i] = 0;
- }
- System.arraycopy(coefficients, 0, toEncode, dataBytes + numZeroCoefficients, coefficients.length);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonException.java b/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonException.java
deleted file mode 100644
index d5b45a612..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/common/reedsolomon/ReedSolomonException.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.common.reedsolomon;
-
-/**
- * <p>Thrown when an exception occurs during Reed-Solomon decoding, such as when
- * there are too many errors to correct.</p>
- *
- * @author Sean Owen
- */
-public final class ReedSolomonException extends Exception {
-
- public ReedSolomonException(String message) {
- super(message);
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/multi/ByQuadrantReader.java b/OpenPGP-Keychain/src/com/google/zxing/multi/ByQuadrantReader.java
deleted file mode 100644
index 35904d364..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/multi/ByQuadrantReader.java
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.multi;
-
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.ChecksumException;
-import com.google.zxing.FormatException;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.Reader;
-import com.google.zxing.Result;
-
-import java.util.Hashtable;
-
-/**
- * This class attempts to decode a barcode from an image, not by scanning the whole image,
- * but by scanning subsets of the image. This is important when there may be multiple barcodes in
- * an image, and detecting a barcode may find parts of multiple barcode and fail to decode
- * (e.g. QR Codes). Instead this scans the four quadrants of the image -- and also the center
- * 'quadrant' to cover the case where a barcode is found in the center.
- *
- * @see GenericMultipleBarcodeReader
- */
-public final class ByQuadrantReader implements Reader {
-
- private final Reader delegate;
-
- public ByQuadrantReader(Reader delegate) {
- this.delegate = delegate;
- }
-
- public Result decode(BinaryBitmap image)
- throws NotFoundException, ChecksumException, FormatException {
- return decode(image, null);
- }
-
- public Result decode(BinaryBitmap image, Hashtable hints)
- throws NotFoundException, ChecksumException, FormatException {
-
- int width = image.getWidth();
- int height = image.getHeight();
- int halfWidth = width / 2;
- int halfHeight = height / 2;
-
- BinaryBitmap topLeft = image.crop(0, 0, halfWidth, halfHeight);
- try {
- return delegate.decode(topLeft, hints);
- } catch (NotFoundException re) {
- // continue
- }
-
- BinaryBitmap topRight = image.crop(halfWidth, 0, halfWidth, halfHeight);
- try {
- return delegate.decode(topRight, hints);
- } catch (NotFoundException re) {
- // continue
- }
-
- BinaryBitmap bottomLeft = image.crop(0, halfHeight, halfWidth, halfHeight);
- try {
- return delegate.decode(bottomLeft, hints);
- } catch (NotFoundException re) {
- // continue
- }
-
- BinaryBitmap bottomRight = image.crop(halfWidth, halfHeight, halfWidth, halfHeight);
- try {
- return delegate.decode(bottomRight, hints);
- } catch (NotFoundException re) {
- // continue
- }
-
- int quarterWidth = halfWidth / 2;
- int quarterHeight = halfHeight / 2;
- BinaryBitmap center = image.crop(quarterWidth, quarterHeight, halfWidth, halfHeight);
- return delegate.decode(center, hints);
- }
-
- public void reset() {
- delegate.reset();
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/multi/GenericMultipleBarcodeReader.java b/OpenPGP-Keychain/src/com/google/zxing/multi/GenericMultipleBarcodeReader.java
deleted file mode 100644
index 70d454251..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/multi/GenericMultipleBarcodeReader.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.multi;
-
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.Reader;
-import com.google.zxing.ReaderException;
-import com.google.zxing.Result;
-import com.google.zxing.ResultPoint;
-
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>Attempts to locate multiple barcodes in an image by repeatedly decoding portion of the image.
- * After one barcode is found, the areas left, above, right and below the barcode's
- * {@link com.google.zxing.ResultPoint}s are scanned, recursively.</p>
- *
- * <p>A caller may want to also employ {@link ByQuadrantReader} when attempting to find multiple
- * 2D barcodes, like QR Codes, in an image, where the presence of multiple barcodes might prevent
- * detecting any one of them.</p>
- *
- * <p>That is, instead of passing a {@link Reader} a caller might pass
- * <code>new ByQuadrantReader(reader)</code>.</p>
- *
- * @author Sean Owen
- */
-public final class GenericMultipleBarcodeReader implements MultipleBarcodeReader {
-
- private static final int MIN_DIMENSION_TO_RECUR = 100;
-
- private final Reader delegate;
-
- public GenericMultipleBarcodeReader(Reader delegate) {
- this.delegate = delegate;
- }
-
- public Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException {
- return decodeMultiple(image, null);
- }
-
- public Result[] decodeMultiple(BinaryBitmap image, Hashtable hints)
- throws NotFoundException {
- Vector results = new Vector();
- doDecodeMultiple(image, hints, results, 0, 0);
- if (results.isEmpty()) {
- throw NotFoundException.getNotFoundInstance();
- }
- int numResults = results.size();
- Result[] resultArray = new Result[numResults];
- for (int i = 0; i < numResults; i++) {
- resultArray[i] = (Result) results.elementAt(i);
- }
- return resultArray;
- }
-
- private void doDecodeMultiple(BinaryBitmap image,
- Hashtable hints,
- Vector results,
- int xOffset,
- int yOffset) {
- Result result;
- try {
- result = delegate.decode(image, hints);
- } catch (ReaderException re) {
- return;
- }
- boolean alreadyFound = false;
- for (int i = 0; i < results.size(); i++) {
- Result existingResult = (Result) results.elementAt(i);
- if (existingResult.getText().equals(result.getText())) {
- alreadyFound = true;
- break;
- }
- }
- if (alreadyFound) {
- return;
- }
- results.addElement(translateResultPoints(result, xOffset, yOffset));
- ResultPoint[] resultPoints = result.getResultPoints();
- if (resultPoints == null || resultPoints.length == 0) {
- return;
- }
- int width = image.getWidth();
- int height = image.getHeight();
- float minX = width;
- float minY = height;
- float maxX = 0.0f;
- float maxY = 0.0f;
- for (int i = 0; i < resultPoints.length; i++) {
- ResultPoint point = resultPoints[i];
- float x = point.getX();
- float y = point.getY();
- if (x < minX) {
- minX = x;
- }
- if (y < minY) {
- minY = y;
- }
- if (x > maxX) {
- maxX = x;
- }
- if (y > maxY) {
- maxY = y;
- }
- }
-
- // Decode left of barcode
- if (minX > MIN_DIMENSION_TO_RECUR) {
- doDecodeMultiple(image.crop(0, 0, (int) minX, height),
- hints, results, xOffset, yOffset);
- }
- // Decode above barcode
- if (minY > MIN_DIMENSION_TO_RECUR) {
- doDecodeMultiple(image.crop(0, 0, width, (int) minY),
- hints, results, xOffset, yOffset);
- }
- // Decode right of barcode
- if (maxX < width - MIN_DIMENSION_TO_RECUR) {
- doDecodeMultiple(image.crop((int) maxX, 0, width - (int) maxX, height),
- hints, results, xOffset + (int) maxX, yOffset);
- }
- // Decode below barcode
- if (maxY < height - MIN_DIMENSION_TO_RECUR) {
- doDecodeMultiple(image.crop(0, (int) maxY, width, height - (int) maxY),
- hints, results, xOffset, yOffset + (int) maxY);
- }
- }
-
- private static Result translateResultPoints(Result result, int xOffset, int yOffset) {
- ResultPoint[] oldResultPoints = result.getResultPoints();
- ResultPoint[] newResultPoints = new ResultPoint[oldResultPoints.length];
- for (int i = 0; i < oldResultPoints.length; i++) {
- ResultPoint oldPoint = oldResultPoints[i];
- newResultPoints[i] = new ResultPoint(oldPoint.getX() + xOffset, oldPoint.getY() + yOffset);
- }
- return new Result(result.getText(), result.getRawBytes(), newResultPoints,
- result.getBarcodeFormat());
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/multi/MultipleBarcodeReader.java b/OpenPGP-Keychain/src/com/google/zxing/multi/MultipleBarcodeReader.java
deleted file mode 100644
index 5f0c7eb5d..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/multi/MultipleBarcodeReader.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.multi;
-
-import com.google.zxing.BinaryBitmap;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.Result;
-
-import java.util.Hashtable;
-
-/**
- * Implementation of this interface attempt to read several barcodes from one image.
- *
- * @see com.google.zxing.Reader
- * @author Sean Owen
- */
-public interface MultipleBarcodeReader {
-
- Result[] decodeMultiple(BinaryBitmap image) throws NotFoundException;
-
- Result[] decodeMultiple(BinaryBitmap image, Hashtable hints) throws NotFoundException;
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiDetector.java b/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiDetector.java
deleted file mode 100644
index 584c41404..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiDetector.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.multi.qrcode.detector;
-
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ReaderException;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.DetectorResult;
-import com.google.zxing.qrcode.detector.Detector;
-import com.google.zxing.qrcode.detector.FinderPatternInfo;
-
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>Encapsulates logic that can detect one or more QR Codes in an image, even if the QR Code
- * is rotated or skewed, or partially obscured.</p>
- *
- * @author Sean Owen
- * @author Hannes Erven
- */
-public final class MultiDetector extends Detector {
-
- private static final DetectorResult[] EMPTY_DETECTOR_RESULTS = new DetectorResult[0];
-
- public MultiDetector(BitMatrix image) {
- super(image);
- }
-
- public DetectorResult[] detectMulti(Hashtable hints) throws NotFoundException {
- BitMatrix image = getImage();
- MultiFinderPatternFinder finder = new MultiFinderPatternFinder(image);
- FinderPatternInfo[] info = finder.findMulti(hints);
-
- if (info == null || info.length == 0) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- Vector result = new Vector();
- for (int i = 0; i < info.length; i++) {
- try {
- result.addElement(processFinderPatternInfo(info[i]));
- } catch (ReaderException e) {
- // ignore
- }
- }
- if (result.isEmpty()) {
- return EMPTY_DETECTOR_RESULTS;
- } else {
- DetectorResult[] resultArray = new DetectorResult[result.size()];
- for (int i = 0; i < result.size(); i++) {
- resultArray[i] = (DetectorResult) result.elementAt(i);
- }
- return resultArray;
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java b/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java
deleted file mode 100644
index 1162324e2..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/multi/qrcode/detector/MultiFinderPatternFinder.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright 2009 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.multi.qrcode.detector;
-
-import com.google.zxing.DecodeHintType;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.ResultPointCallback;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.Collections;
-import com.google.zxing.common.Comparator;
-import com.google.zxing.qrcode.detector.FinderPattern;
-import com.google.zxing.qrcode.detector.FinderPatternFinder;
-import com.google.zxing.qrcode.detector.FinderPatternInfo;
-
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square
- * markers at three corners of a QR Code.</p>
- *
- * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.
- *
- * <p>In contrast to {@link FinderPatternFinder}, this class will return an array of all possible
- * QR code locations in the image.</p>
- *
- * <p>Use the TRY_HARDER hint to ask for a more thorough detection.</p>
- *
- * @author Sean Owen
- * @author Hannes Erven
- */
-final class MultiFinderPatternFinder extends FinderPatternFinder {
-
- private static final FinderPatternInfo[] EMPTY_RESULT_ARRAY = new FinderPatternInfo[0];
-
- // TODO MIN_MODULE_COUNT and MAX_MODULE_COUNT would be great hints to ask the user for
- // since it limits the number of regions to decode
-
- // max. legal count of modules per QR code edge (177)
- private static final float MAX_MODULE_COUNT_PER_EDGE = 180;
- // min. legal count per modules per QR code edge (11)
- private static final float MIN_MODULE_COUNT_PER_EDGE = 9;
-
- /**
- * More or less arbitrary cutoff point for determining if two finder patterns might belong
- * to the same code if they differ less than DIFF_MODSIZE_CUTOFF_PERCENT percent in their
- * estimated modules sizes.
- */
- private static final float DIFF_MODSIZE_CUTOFF_PERCENT = 0.05f;
-
- /**
- * More or less arbitrary cutoff point for determining if two finder patterns might belong
- * to the same code if they differ less than DIFF_MODSIZE_CUTOFF pixels/module in their
- * estimated modules sizes.
- */
- private static final float DIFF_MODSIZE_CUTOFF = 0.5f;
-
-
- /**
- * A comparator that orders FinderPatterns by their estimated module size.
- */
- private static class ModuleSizeComparator implements Comparator {
- public int compare(Object center1, Object center2) {
- float value = ((FinderPattern) center2).getEstimatedModuleSize() -
- ((FinderPattern) center1).getEstimatedModuleSize();
- return value < 0.0 ? -1 : value > 0.0 ? 1 : 0;
- }
- }
-
- /**
- * <p>Creates a finder that will search the image for three finder patterns.</p>
- *
- * @param image image to search
- */
- MultiFinderPatternFinder(BitMatrix image) {
- super(image);
- }
-
- MultiFinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) {
- super(image, resultPointCallback);
- }
-
- /**
- * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are
- * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module
- * size differs from the average among those patterns the least
- * @throws NotFoundException if 3 such finder patterns do not exist
- */
- private FinderPattern[][] selectBestPatterns() throws NotFoundException {
- Vector possibleCenters = getPossibleCenters();
- int size = possibleCenters.size();
-
- if (size < 3) {
- // Couldn't find enough finder patterns
- throw NotFoundException.getNotFoundInstance();
- }
-
- /*
- * Begin HE modifications to safely detect multiple codes of equal size
- */
- if (size == 3) {
- return new FinderPattern[][]{
- new FinderPattern[]{
- (FinderPattern) possibleCenters.elementAt(0),
- (FinderPattern) possibleCenters.elementAt(1),
- (FinderPattern) possibleCenters.elementAt(2)
- }
- };
- }
-
- // Sort by estimated module size to speed up the upcoming checks
- Collections.insertionSort(possibleCenters, new ModuleSizeComparator());
-
- /*
- * Now lets start: build a list of tuples of three finder locations that
- * - feature similar module sizes
- * - are placed in a distance so the estimated module count is within the QR specification
- * - have similar distance between upper left/right and left top/bottom finder patterns
- * - form a triangle with 90° angle (checked by comparing top right/bottom left distance
- * with pythagoras)
- *
- * Note: we allow each point to be used for more than one code region: this might seem
- * counterintuitive at first, but the performance penalty is not that big. At this point,
- * we cannot make a good quality decision whether the three finders actually represent
- * a QR code, or are just by chance layouted so it looks like there might be a QR code there.
- * So, if the layout seems right, lets have the decoder try to decode.
- */
-
- Vector results = new Vector(); // holder for the results
-
- for (int i1 = 0; i1 < (size - 2); i1++) {
- FinderPattern p1 = (FinderPattern) possibleCenters.elementAt(i1);
- if (p1 == null) {
- continue;
- }
-
- for (int i2 = i1 + 1; i2 < (size - 1); i2++) {
- FinderPattern p2 = (FinderPattern) possibleCenters.elementAt(i2);
- if (p2 == null) {
- continue;
- }
-
- // Compare the expected module sizes; if they are really off, skip
- float vModSize12 = (p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize()) /
- Math.min(p1.getEstimatedModuleSize(), p2.getEstimatedModuleSize());
- float vModSize12A = Math.abs(p1.getEstimatedModuleSize() - p2.getEstimatedModuleSize());
- if (vModSize12A > DIFF_MODSIZE_CUTOFF && vModSize12 >= DIFF_MODSIZE_CUTOFF_PERCENT) {
- // break, since elements are ordered by the module size deviation there cannot be
- // any more interesting elements for the given p1.
- break;
- }
-
- for (int i3 = i2 + 1; i3 < size; i3++) {
- FinderPattern p3 = (FinderPattern) possibleCenters.elementAt(i3);
- if (p3 == null) {
- continue;
- }
-
- // Compare the expected module sizes; if they are really off, skip
- float vModSize23 = (p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize()) /
- Math.min(p2.getEstimatedModuleSize(), p3.getEstimatedModuleSize());
- float vModSize23A = Math.abs(p2.getEstimatedModuleSize() - p3.getEstimatedModuleSize());
- if (vModSize23A > DIFF_MODSIZE_CUTOFF && vModSize23 >= DIFF_MODSIZE_CUTOFF_PERCENT) {
- // break, since elements are ordered by the module size deviation there cannot be
- // any more interesting elements for the given p1.
- break;
- }
-
- FinderPattern[] test = {p1, p2, p3};
- ResultPoint.orderBestPatterns(test);
-
- // Calculate the distances: a = topleft-bottomleft, b=topleft-topright, c = diagonal
- FinderPatternInfo info = new FinderPatternInfo(test);
- float dA = ResultPoint.distance(info.getTopLeft(), info.getBottomLeft());
- float dC = ResultPoint.distance(info.getTopRight(), info.getBottomLeft());
- float dB = ResultPoint.distance(info.getTopLeft(), info.getTopRight());
-
- // Check the sizes
- float estimatedModuleCount = (dA + dB) / (p1.getEstimatedModuleSize() * 2.0f);
- if (estimatedModuleCount > MAX_MODULE_COUNT_PER_EDGE ||
- estimatedModuleCount < MIN_MODULE_COUNT_PER_EDGE) {
- continue;
- }
-
- // Calculate the difference of the edge lengths in percent
- float vABBC = Math.abs((dA - dB) / Math.min(dA, dB));
- if (vABBC >= 0.1f) {
- continue;
- }
-
- // Calculate the diagonal length by assuming a 90° angle at topleft
- float dCpy = (float) Math.sqrt(dA * dA + dB * dB);
- // Compare to the real distance in %
- float vPyC = Math.abs((dC - dCpy) / Math.min(dC, dCpy));
-
- if (vPyC >= 0.1f) {
- continue;
- }
-
- // All tests passed!
- results.addElement(test);
- } // end iterate p3
- } // end iterate p2
- } // end iterate p1
-
- if (!results.isEmpty()) {
- FinderPattern[][] resultArray = new FinderPattern[results.size()][];
- for (int i = 0; i < results.size(); i++) {
- resultArray[i] = (FinderPattern[]) results.elementAt(i);
- }
- return resultArray;
- }
-
- // Nothing found!
- throw NotFoundException.getNotFoundInstance();
- }
-
- public FinderPatternInfo[] findMulti(Hashtable hints) throws NotFoundException {
- boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
- BitMatrix image = getImage();
- int maxI = image.getHeight();
- int maxJ = image.getWidth();
- // We are looking for black/white/black/white/black modules in
- // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far
-
- // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
- // image, and then account for the center being 3 modules in size. This gives the smallest
- // number of pixels the center could be, so skip this often. When trying harder, look for all
- // QR versions regardless of how dense they are.
- int iSkip = (int) (maxI / (MAX_MODULES * 4.0f) * 3);
- if (iSkip < MIN_SKIP || tryHarder) {
- iSkip = MIN_SKIP;
- }
-
- int[] stateCount = new int[5];
- for (int i = iSkip - 1; i < maxI; i += iSkip) {
- // Get a row of black/white values
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
- stateCount[3] = 0;
- stateCount[4] = 0;
- int currentState = 0;
- for (int j = 0; j < maxJ; j++) {
- if (image.get(j, i)) {
- // Black pixel
- if ((currentState & 1) == 1) { // Counting white pixels
- currentState++;
- }
- stateCount[currentState]++;
- } else { // White pixel
- if ((currentState & 1) == 0) { // Counting black pixels
- if (currentState == 4) { // A winner?
- if (foundPatternCross(stateCount)) { // Yes
- boolean confirmed = handlePossibleCenter(stateCount, i, j);
- if (!confirmed) {
- do { // Advance to next black pixel
- j++;
- } while (j < maxJ && !image.get(j, i));
- j--; // back up to that last white pixel
- }
- // Clear state to start looking again
- currentState = 0;
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
- stateCount[3] = 0;
- stateCount[4] = 0;
- } else { // No, shift counts back by two
- stateCount[0] = stateCount[2];
- stateCount[1] = stateCount[3];
- stateCount[2] = stateCount[4];
- stateCount[3] = 1;
- stateCount[4] = 0;
- currentState = 3;
- }
- } else {
- stateCount[++currentState]++;
- }
- } else { // Counting white pixels
- stateCount[currentState]++;
- }
- }
- } // for j=...
-
- if (foundPatternCross(stateCount)) {
- handlePossibleCenter(stateCount, i, maxJ);
- } // end if foundPatternCross
- } // for i=iSkip-1 ...
- FinderPattern[][] patternInfo = selectBestPatterns();
- Vector result = new Vector();
- for (int i = 0; i < patternInfo.length; i++) {
- FinderPattern[] pattern = patternInfo[i];
- ResultPoint.orderBestPatterns(pattern);
- result.addElement(new FinderPatternInfo(pattern));
- }
-
- if (result.isEmpty()) {
- return EMPTY_RESULT_ARRAY;
- } else {
- FinderPatternInfo[] resultArray = new FinderPatternInfo[result.size()];
- for (int i = 0; i < result.size(); i++) {
- resultArray[i] = (FinderPatternInfo) result.elementAt(i);
- }
- return resultArray;
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/QRCodeWriter.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/QRCodeWriter.java
deleted file mode 100644
index fff4f5d1e..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/QRCodeWriter.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode;
-
-import com.google.zxing.BarcodeFormat;
-import com.google.zxing.EncodeHintType;
-import com.google.zxing.Writer;
-import com.google.zxing.WriterException;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.qrcode.encoder.ByteMatrix;
-import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-import com.google.zxing.qrcode.encoder.Encoder;
-import com.google.zxing.qrcode.encoder.QRCode;
-
-import java.util.Hashtable;
-
-/**
- * This object renders a QR Code as a BitMatrix 2D array of greyscale values.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class QRCodeWriter implements Writer {
-
- private static final int QUIET_ZONE_SIZE = 0; // patched for Bitcoin Wallet
-
- public BitMatrix encode(String contents, BarcodeFormat format, int width, int height)
- throws WriterException {
-
- return encode(contents, format, width, height, null);
- }
-
- public BitMatrix encode(String contents, BarcodeFormat format, int width, int height,
- Hashtable hints) throws WriterException {
-
- if (contents == null || contents.length() == 0) {
- throw new IllegalArgumentException("Found empty contents");
- }
-
- if (format != BarcodeFormat.QR_CODE) {
- throw new IllegalArgumentException("Can only encode QR_CODE, but got " + format);
- }
-
- if (width < 0 || height < 0) {
- throw new IllegalArgumentException("Requested dimensions are too small: " + width + 'x' +
- height);
- }
-
- ErrorCorrectionLevel errorCorrectionLevel = ErrorCorrectionLevel.L;
- if (hints != null) {
- ErrorCorrectionLevel requestedECLevel = (ErrorCorrectionLevel) hints.get(EncodeHintType.ERROR_CORRECTION);
- if (requestedECLevel != null) {
- errorCorrectionLevel = requestedECLevel;
- }
- }
-
- QRCode code = new QRCode();
- Encoder.encode(contents, errorCorrectionLevel, hints, code);
- return renderResult(code, width, height);
- }
-
- // Note that the input matrix uses 0 == white, 1 == black, while the output matrix uses
- // 0 == black, 255 == white (i.e. an 8 bit greyscale bitmap).
- private static BitMatrix renderResult(QRCode code, int width, int height) {
- ByteMatrix input = code.getMatrix();
- int inputWidth = input.getWidth();
- int inputHeight = input.getHeight();
- int qrWidth = inputWidth + (QUIET_ZONE_SIZE << 1);
- int qrHeight = inputHeight + (QUIET_ZONE_SIZE << 1);
- int outputWidth = Math.max(width, qrWidth);
- int outputHeight = Math.max(height, qrHeight);
-
- int multiple = Math.min(outputWidth / qrWidth, outputHeight / qrHeight);
- // Padding includes both the quiet zone and the extra white pixels to accommodate the requested
- // dimensions. For example, if input is 25x25 the QR will be 33x33 including the quiet zone.
- // If the requested size is 200x160, the multiple will be 4, for a QR of 132x132. These will
- // handle all the padding from 100x100 (the actual QR) up to 200x160.
- int leftPadding = (outputWidth - (inputWidth * multiple)) / 2;
- int topPadding = (outputHeight - (inputHeight * multiple)) / 2;
-
- BitMatrix output = new BitMatrix(outputWidth, outputHeight);
-
- for (int inputY = 0, outputY = topPadding; inputY < inputHeight; inputY++, outputY += multiple) {
- // Write the contents of this row of the barcode
- for (int inputX = 0, outputX = leftPadding; inputX < inputWidth; inputX++, outputX += multiple) {
- if (input.get(inputX, inputY) == 1) {
- output.setRegion(outputX, outputY, multiple, multiple);
- }
- }
- }
-
- return output;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
deleted file mode 100644
index 9d131a554..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/BitMatrixParser.java
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * @author Sean Owen
- */
-final class BitMatrixParser {
-
- private final BitMatrix bitMatrix;
- private Version parsedVersion;
- private FormatInformation parsedFormatInfo;
-
- /**
- * @param bitMatrix {@link BitMatrix} to parse
- * @throws FormatException if dimension is not >= 21 and 1 mod 4
- */
- BitMatrixParser(BitMatrix bitMatrix) throws FormatException {
- int dimension = bitMatrix.getHeight();
- if (dimension < 21 || (dimension & 0x03) != 1) {
- throw FormatException.getFormatInstance();
- }
- this.bitMatrix = bitMatrix;
- }
-
- /**
- * <p>Reads format information from one of its two locations within the QR Code.</p>
- *
- * @return {@link FormatInformation} encapsulating the QR Code's format info
- * @throws FormatException if both format information locations cannot be parsed as
- * the valid encoding of format information
- */
- FormatInformation readFormatInformation() throws FormatException {
-
- if (parsedFormatInfo != null) {
- return parsedFormatInfo;
- }
-
- // Read top-left format info bits
- int formatInfoBits1 = 0;
- for (int i = 0; i < 6; i++) {
- formatInfoBits1 = copyBit(i, 8, formatInfoBits1);
- }
- // .. and skip a bit in the timing pattern ...
- formatInfoBits1 = copyBit(7, 8, formatInfoBits1);
- formatInfoBits1 = copyBit(8, 8, formatInfoBits1);
- formatInfoBits1 = copyBit(8, 7, formatInfoBits1);
- // .. and skip a bit in the timing pattern ...
- for (int j = 5; j >= 0; j--) {
- formatInfoBits1 = copyBit(8, j, formatInfoBits1);
- }
-
- // Read the top-right/bottom-left pattern too
- int dimension = bitMatrix.getHeight();
- int formatInfoBits2 = 0;
- int jMin = dimension - 7;
- for (int j = dimension - 1; j >= jMin; j--) {
- formatInfoBits2 = copyBit(8, j, formatInfoBits2);
- }
- for (int i = dimension - 8; i < dimension; i++) {
- formatInfoBits2 = copyBit(i, 8, formatInfoBits2);
- }
-
- parsedFormatInfo = FormatInformation.decodeFormatInformation(formatInfoBits1, formatInfoBits2);
- if (parsedFormatInfo != null) {
- return parsedFormatInfo;
- }
- throw FormatException.getFormatInstance();
- }
-
- /**
- * <p>Reads version information from one of its two locations within the QR Code.</p>
- *
- * @return {@link Version} encapsulating the QR Code's version
- * @throws FormatException if both version information locations cannot be parsed as
- * the valid encoding of version information
- */
- Version readVersion() throws FormatException {
-
- if (parsedVersion != null) {
- return parsedVersion;
- }
-
- int dimension = bitMatrix.getHeight();
-
- int provisionalVersion = (dimension - 17) >> 2;
- if (provisionalVersion <= 6) {
- return Version.getVersionForNumber(provisionalVersion);
- }
-
- // Read top-right version info: 3 wide by 6 tall
- int versionBits = 0;
- int ijMin = dimension - 11;
- for (int j = 5; j >= 0; j--) {
- for (int i = dimension - 9; i >= ijMin; i--) {
- versionBits = copyBit(i, j, versionBits);
- }
- }
-
- parsedVersion = Version.decodeVersionInformation(versionBits);
- if (parsedVersion != null && parsedVersion.getDimensionForVersion() == dimension) {
- return parsedVersion;
- }
-
- // Hmm, failed. Try bottom left: 6 wide by 3 tall
- versionBits = 0;
- for (int i = 5; i >= 0; i--) {
- for (int j = dimension - 9; j >= ijMin; j--) {
- versionBits = copyBit(i, j, versionBits);
- }
- }
-
- parsedVersion = Version.decodeVersionInformation(versionBits);
- if (parsedVersion != null && parsedVersion.getDimensionForVersion() == dimension) {
- return parsedVersion;
- }
- throw FormatException.getFormatInstance();
- }
-
- private int copyBit(int i, int j, int versionBits) {
- return bitMatrix.get(i, j) ? (versionBits << 1) | 0x1 : versionBits << 1;
- }
-
- /**
- * <p>Reads the bits in the {@link BitMatrix} representing the finder pattern in the
- * correct order in order to reconstitute the codewords bytes contained within the
- * QR Code.</p>
- *
- * @return bytes encoded within the QR Code
- * @throws FormatException if the exact number of bytes expected is not read
- */
- byte[] readCodewords() throws FormatException {
-
- FormatInformation formatInfo = readFormatInformation();
- Version version = readVersion();
-
- // Get the data mask for the format used in this QR Code. This will exclude
- // some bits from reading as we wind through the bit matrix.
- DataMask dataMask = DataMask.forReference((int) formatInfo.getDataMask());
- int dimension = bitMatrix.getHeight();
- dataMask.unmaskBitMatrix(bitMatrix, dimension);
-
- BitMatrix functionPattern = version.buildFunctionPattern();
-
- boolean readingUp = true;
- byte[] result = new byte[version.getTotalCodewords()];
- int resultOffset = 0;
- int currentByte = 0;
- int bitsRead = 0;
- // Read columns in pairs, from right to left
- for (int j = dimension - 1; j > 0; j -= 2) {
- if (j == 6) {
- // Skip whole column with vertical alignment pattern;
- // saves time and makes the other code proceed more cleanly
- j--;
- }
- // Read alternatingly from bottom to top then top to bottom
- for (int count = 0; count < dimension; count++) {
- int i = readingUp ? dimension - 1 - count : count;
- for (int col = 0; col < 2; col++) {
- // Ignore bits covered by the function pattern
- if (!functionPattern.get(j - col, i)) {
- // Read a bit
- bitsRead++;
- currentByte <<= 1;
- if (bitMatrix.get(j - col, i)) {
- currentByte |= 1;
- }
- // If we've made a whole byte, save it off
- if (bitsRead == 8) {
- result[resultOffset++] = (byte) currentByte;
- bitsRead = 0;
- currentByte = 0;
- }
- }
- }
- }
- readingUp ^= true; // readingUp = !readingUp; // switch directions
- }
- if (resultOffset != version.getTotalCodewords()) {
- throw FormatException.getFormatInstance();
- }
- return result;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java
deleted file mode 100644
index 12959d9c1..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataBlock.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>Encapsulates a block of data within a QR Code. QR Codes may split their data into
- * multiple blocks, each of which is a unit of data and error-correction codewords. Each
- * is represented by an instance of this class.</p>
- *
- * @author Sean Owen
- */
-final class DataBlock {
-
- private final int numDataCodewords;
- private final byte[] codewords;
-
- private DataBlock(int numDataCodewords, byte[] codewords) {
- this.numDataCodewords = numDataCodewords;
- this.codewords = codewords;
- }
-
- /**
- * <p>When QR Codes use multiple data blocks, they are actually interleaved.
- * That is, the first byte of data block 1 to n is written, then the second bytes, and so on. This
- * method will separate the data into original blocks.</p>
- *
- * @param rawCodewords bytes as read directly from the QR Code
- * @param version version of the QR Code
- * @param ecLevel error-correction level of the QR Code
- * @return DataBlocks containing original bytes, "de-interleaved" from representation in the
- * QR Code
- */
- static DataBlock[] getDataBlocks(byte[] rawCodewords,
- Version version,
- ErrorCorrectionLevel ecLevel) {
-
- if (rawCodewords.length != version.getTotalCodewords()) {
- throw new IllegalArgumentException();
- }
-
- // Figure out the number and size of data blocks used by this version and
- // error correction level
- Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
-
- // First count the total number of data blocks
- int totalBlocks = 0;
- Version.ECB[] ecBlockArray = ecBlocks.getECBlocks();
- for (int i = 0; i < ecBlockArray.length; i++) {
- totalBlocks += ecBlockArray[i].getCount();
- }
-
- // Now establish DataBlocks of the appropriate size and number of data codewords
- DataBlock[] result = new DataBlock[totalBlocks];
- int numResultBlocks = 0;
- for (int j = 0; j < ecBlockArray.length; j++) {
- Version.ECB ecBlock = ecBlockArray[j];
- for (int i = 0; i < ecBlock.getCount(); i++) {
- int numDataCodewords = ecBlock.getDataCodewords();
- int numBlockCodewords = ecBlocks.getECCodewordsPerBlock() + numDataCodewords;
- result[numResultBlocks++] = new DataBlock(numDataCodewords, new byte[numBlockCodewords]);
- }
- }
-
- // All blocks have the same amount of data, except that the last n
- // (where n may be 0) have 1 more byte. Figure out where these start.
- int shorterBlocksTotalCodewords = result[0].codewords.length;
- int longerBlocksStartAt = result.length - 1;
- while (longerBlocksStartAt >= 0) {
- int numCodewords = result[longerBlocksStartAt].codewords.length;
- if (numCodewords == shorterBlocksTotalCodewords) {
- break;
- }
- longerBlocksStartAt--;
- }
- longerBlocksStartAt++;
-
- int shorterBlocksNumDataCodewords = shorterBlocksTotalCodewords - ecBlocks.getECCodewordsPerBlock();
- // The last elements of result may be 1 element longer;
- // first fill out as many elements as all of them have
- int rawCodewordsOffset = 0;
- for (int i = 0; i < shorterBlocksNumDataCodewords; i++) {
- for (int j = 0; j < numResultBlocks; j++) {
- result[j].codewords[i] = rawCodewords[rawCodewordsOffset++];
- }
- }
- // Fill out the last data block in the longer ones
- for (int j = longerBlocksStartAt; j < numResultBlocks; j++) {
- result[j].codewords[shorterBlocksNumDataCodewords] = rawCodewords[rawCodewordsOffset++];
- }
- // Now add in error correction blocks
- int max = result[0].codewords.length;
- for (int i = shorterBlocksNumDataCodewords; i < max; i++) {
- for (int j = 0; j < numResultBlocks; j++) {
- int iOffset = j < longerBlocksStartAt ? i : i + 1;
- result[j].codewords[iOffset] = rawCodewords[rawCodewordsOffset++];
- }
- }
- return result;
- }
-
- int getNumDataCodewords() {
- return numDataCodewords;
- }
-
- byte[] getCodewords() {
- return codewords;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java
deleted file mode 100644
index d29dbd47f..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DataMask.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.common.BitMatrix;
-
-/**
- * <p>Encapsulates data masks for the data bits in a QR code, per ISO 18004:2006 6.8. Implementations
- * of this class can un-mask a raw BitMatrix. For simplicity, they will unmask the entire BitMatrix,
- * including areas used for finder patterns, timing patterns, etc. These areas should be unused
- * after the point they are unmasked anyway.</p>
- *
- * <p>Note that the diagram in section 6.8.1 is misleading since it indicates that i is column position
- * and j is row position. In fact, as the text says, i is row position and j is column position.</p>
- *
- * @author Sean Owen
- */
-abstract class DataMask {
-
- /**
- * See ISO 18004:2006 6.8.1
- */
- private static final DataMask[] DATA_MASKS = {
- new DataMask000(),
- new DataMask001(),
- new DataMask010(),
- new DataMask011(),
- new DataMask100(),
- new DataMask101(),
- new DataMask110(),
- new DataMask111(),
- };
-
- private DataMask() {
- }
-
- /**
- * <p>Implementations of this method reverse the data masking process applied to a QR Code and
- * make its bits ready to read.</p>
- *
- * @param bits representation of QR Code bits
- * @param dimension dimension of QR Code, represented by bits, being unmasked
- */
- final void unmaskBitMatrix(BitMatrix bits, int dimension) {
- for (int i = 0; i < dimension; i++) {
- for (int j = 0; j < dimension; j++) {
- if (isMasked(i, j)) {
- bits.flip(j, i);
- }
- }
- }
- }
-
- abstract boolean isMasked(int i, int j);
-
- /**
- * @param reference a value between 0 and 7 indicating one of the eight possible
- * data mask patterns a QR Code may use
- * @return DataMask encapsulating the data mask pattern
- */
- static DataMask forReference(int reference) {
- if (reference < 0 || reference > 7) {
- throw new IllegalArgumentException();
- }
- return DATA_MASKS[reference];
- }
-
- /**
- * 000: mask bits for which (x + y) mod 2 == 0
- */
- private static class DataMask000 extends DataMask {
- boolean isMasked(int i, int j) {
- return ((i + j) & 0x01) == 0;
- }
- }
-
- /**
- * 001: mask bits for which x mod 2 == 0
- */
- private static class DataMask001 extends DataMask {
- boolean isMasked(int i, int j) {
- return (i & 0x01) == 0;
- }
- }
-
- /**
- * 010: mask bits for which y mod 3 == 0
- */
- private static class DataMask010 extends DataMask {
- boolean isMasked(int i, int j) {
- return j % 3 == 0;
- }
- }
-
- /**
- * 011: mask bits for which (x + y) mod 3 == 0
- */
- private static class DataMask011 extends DataMask {
- boolean isMasked(int i, int j) {
- return (i + j) % 3 == 0;
- }
- }
-
- /**
- * 100: mask bits for which (x/2 + y/3) mod 2 == 0
- */
- private static class DataMask100 extends DataMask {
- boolean isMasked(int i, int j) {
- return (((i >>> 1) + (j /3)) & 0x01) == 0;
- }
- }
-
- /**
- * 101: mask bits for which xy mod 2 + xy mod 3 == 0
- */
- private static class DataMask101 extends DataMask {
- boolean isMasked(int i, int j) {
- int temp = i * j;
- return (temp & 0x01) + (temp % 3) == 0;
- }
- }
-
- /**
- * 110: mask bits for which (xy mod 2 + xy mod 3) mod 2 == 0
- */
- private static class DataMask110 extends DataMask {
- boolean isMasked(int i, int j) {
- int temp = i * j;
- return (((temp & 0x01) + (temp % 3)) & 0x01) == 0;
- }
- }
-
- /**
- * 111: mask bits for which ((x+y)mod 2 + xy mod 3) mod 2 == 0
- */
- private static class DataMask111 extends DataMask {
- boolean isMasked(int i, int j) {
- return ((((i + j) & 0x01) + ((i * j) % 3)) & 0x01) == 0;
- }
- }
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
deleted file mode 100644
index ff374ac50..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitSource;
-import com.google.zxing.common.CharacterSetECI;
-import com.google.zxing.common.DecoderResult;
-import com.google.zxing.common.StringUtils;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>QR Codes can encode text as bits in one of several modes, and can use multiple modes
- * in one QR Code. This class decodes the bits back into text.</p>
- *
- * <p>See ISO 18004:2006, 6.4.3 - 6.4.7</p>
- *
- * @author Sean Owen
- */
-final class DecodedBitStreamParser {
-
- /**
- * See ISO 18004:2006, 6.4.4 Table 5
- */
- private static final char[] ALPHANUMERIC_CHARS = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B',
- 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
- ' ', '$', '%', '*', '+', '-', '.', '/', ':'
- };
- private static final int GB2312_SUBSET = 1;
-
- private DecodedBitStreamParser() {
- }
-
- static DecoderResult decode(byte[] bytes, Version version, ErrorCorrectionLevel ecLevel, Hashtable hints)
- throws FormatException {
- BitSource bits = new BitSource(bytes);
- StringBuffer result = new StringBuffer(50);
- CharacterSetECI currentCharacterSetECI = null;
- boolean fc1InEffect = false;
- Vector byteSegments = new Vector(1);
- Mode mode;
- do {
- // While still another segment to read...
- if (bits.available() < 4) {
- // OK, assume we're done. Really, a TERMINATOR mode should have been recorded here
- mode = Mode.TERMINATOR;
- } else {
- try {
- mode = Mode.forBits(bits.readBits(4)); // mode is encoded by 4 bits
- } catch (IllegalArgumentException iae) {
- throw FormatException.getFormatInstance();
- }
- }
- if (!mode.equals(Mode.TERMINATOR)) {
- if (mode.equals(Mode.FNC1_FIRST_POSITION) || mode.equals(Mode.FNC1_SECOND_POSITION)) {
- // We do little with FNC1 except alter the parsed result a bit according to the spec
- fc1InEffect = true;
- } else if (mode.equals(Mode.STRUCTURED_APPEND)) {
- // not really supported; all we do is ignore it
- // Read next 8 bits (symbol sequence #) and 8 bits (parity data), then continue
- bits.readBits(16);
- } else if (mode.equals(Mode.ECI)) {
- // Count doesn't apply to ECI
- int value = parseECIValue(bits);
- currentCharacterSetECI = CharacterSetECI.getCharacterSetECIByValue(value);
- if (currentCharacterSetECI == null) {
- throw FormatException.getFormatInstance();
- }
- } else {
- // First handle Hanzi mode which does not start with character count
- if (mode.equals(Mode.HANZI)) {
- //chinese mode contains a sub set indicator right after mode indicator
- int subset = bits.readBits(4);
- int countHanzi = bits.readBits(mode.getCharacterCountBits(version));
- if (subset == GB2312_SUBSET) {
- decodeHanziSegment(bits, result, countHanzi);
- }
- } else {
- // "Normal" QR code modes:
- // How many characters will follow, encoded in this mode?
- int count = bits.readBits(mode.getCharacterCountBits(version));
- if (mode.equals(Mode.NUMERIC)) {
- decodeNumericSegment(bits, result, count);
- } else if (mode.equals(Mode.ALPHANUMERIC)) {
- decodeAlphanumericSegment(bits, result, count, fc1InEffect);
- } else if (mode.equals(Mode.BYTE)) {
- decodeByteSegment(bits, result, count, currentCharacterSetECI, byteSegments, hints);
- } else if (mode.equals(Mode.KANJI)) {
- decodeKanjiSegment(bits, result, count);
- } else {
- throw FormatException.getFormatInstance();
- }
- }
- }
- }
- } while (!mode.equals(Mode.TERMINATOR));
-
- return new DecoderResult(bytes,
- result.toString(),
- byteSegments.isEmpty() ? null : byteSegments,
- ecLevel == null ? null : ecLevel.toString());
- }
-
- /**
- * See specification GBT 18284-2000
- */
- private static void decodeHanziSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count * 13 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- // Each character will require 2 bytes. Read the characters as 2-byte pairs
- // and decode as GB2312 afterwards
- byte[] buffer = new byte[2 * count];
- int offset = 0;
- while (count > 0) {
- // Each 13 bits encodes a 2-byte character
- int twoBytes = bits.readBits(13);
- int assembledTwoBytes = ((twoBytes / 0x060) << 8) | (twoBytes % 0x060);
- if (assembledTwoBytes < 0x003BF) {
- // In the 0xA1A1 to 0xAAFE range
- assembledTwoBytes += 0x0A1A1;
- } else {
- // In the 0xB0A1 to 0xFAFE range
- assembledTwoBytes += 0x0A6A1;
- }
- buffer[offset] = (byte) ((assembledTwoBytes >> 8) & 0xFF);
- buffer[offset + 1] = (byte) (assembledTwoBytes & 0xFF);
- offset += 2;
- count--;
- }
-
- try {
- result.append(new String(buffer, StringUtils.GB2312));
- } catch (UnsupportedEncodingException uee) {
- throw FormatException.getFormatInstance();
- }
- }
-
- private static void decodeKanjiSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count * 13 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- // Each character will require 2 bytes. Read the characters as 2-byte pairs
- // and decode as Shift_JIS afterwards
- byte[] buffer = new byte[2 * count];
- int offset = 0;
- while (count > 0) {
- // Each 13 bits encodes a 2-byte character
- int twoBytes = bits.readBits(13);
- int assembledTwoBytes = ((twoBytes / 0x0C0) << 8) | (twoBytes % 0x0C0);
- if (assembledTwoBytes < 0x01F00) {
- // In the 0x8140 to 0x9FFC range
- assembledTwoBytes += 0x08140;
- } else {
- // In the 0xE040 to 0xEBBF range
- assembledTwoBytes += 0x0C140;
- }
- buffer[offset] = (byte) (assembledTwoBytes >> 8);
- buffer[offset + 1] = (byte) assembledTwoBytes;
- offset += 2;
- count--;
- }
- // Shift_JIS may not be supported in some environments:
- try {
- result.append(new String(buffer, StringUtils.SHIFT_JIS));
- } catch (UnsupportedEncodingException uee) {
- throw FormatException.getFormatInstance();
- }
- }
-
- private static void decodeByteSegment(BitSource bits,
- StringBuffer result,
- int count,
- CharacterSetECI currentCharacterSetECI,
- Vector byteSegments,
- Hashtable hints) throws FormatException {
- // Don't crash trying to read more bits than we have available.
- if (count << 3 > bits.available()) {
- throw FormatException.getFormatInstance();
- }
-
- byte[] readBytes = new byte[count];
- for (int i = 0; i < count; i++) {
- readBytes[i] = (byte) bits.readBits(8);
- }
- String encoding;
- if (currentCharacterSetECI == null) {
- // The spec isn't clear on this mode; see
- // section 6.4.5: t does not say which encoding to assuming
- // upon decoding. I have seen ISO-8859-1 used as well as
- // Shift_JIS -- without anything like an ECI designator to
- // give a hint.
- encoding = StringUtils.guessEncoding(readBytes, hints);
- } else {
- encoding = currentCharacterSetECI.getEncodingName();
- }
- try {
- result.append(new String(readBytes, encoding));
- } catch (UnsupportedEncodingException uce) {
- throw FormatException.getFormatInstance();
- }
- byteSegments.addElement(readBytes);
- }
-
- private static char toAlphaNumericChar(int value) throws FormatException {
- if (value >= ALPHANUMERIC_CHARS.length) {
- throw FormatException.getFormatInstance();
- }
- return ALPHANUMERIC_CHARS[value];
- }
-
- private static void decodeAlphanumericSegment(BitSource bits,
- StringBuffer result,
- int count,
- boolean fc1InEffect) throws FormatException {
- // Read two characters at a time
- int start = result.length();
- while (count > 1) {
- int nextTwoCharsBits = bits.readBits(11);
- result.append(toAlphaNumericChar(nextTwoCharsBits / 45));
- result.append(toAlphaNumericChar(nextTwoCharsBits % 45));
- count -= 2;
- }
- if (count == 1) {
- // special case: one character left
- result.append(toAlphaNumericChar(bits.readBits(6)));
- }
- // See section 6.4.8.1, 6.4.8.2
- if (fc1InEffect) {
- // We need to massage the result a bit if in an FNC1 mode:
- for (int i = start; i < result.length(); i++) {
- if (result.charAt(i) == '%') {
- if (i < result.length() - 1 && result.charAt(i + 1) == '%') {
- // %% is rendered as %
- result.deleteCharAt(i + 1);
- } else {
- // In alpha mode, % should be converted to FNC1 separator 0x1D
- result.setCharAt(i, (char) 0x1D);
- }
- }
- }
- }
- }
-
- private static void decodeNumericSegment(BitSource bits,
- StringBuffer result,
- int count) throws FormatException {
- // Read three digits at a time
- while (count >= 3) {
- // Each 10 bits encodes three digits
- int threeDigitsBits = bits.readBits(10);
- if (threeDigitsBits >= 1000) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(threeDigitsBits / 100));
- result.append(toAlphaNumericChar((threeDigitsBits / 10) % 10));
- result.append(toAlphaNumericChar(threeDigitsBits % 10));
- count -= 3;
- }
- if (count == 2) {
- // Two digits left over to read, encoded in 7 bits
- int twoDigitsBits = bits.readBits(7);
- if (twoDigitsBits >= 100) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(twoDigitsBits / 10));
- result.append(toAlphaNumericChar(twoDigitsBits % 10));
- } else if (count == 1) {
- // One digit left over to read
- int digitBits = bits.readBits(4);
- if (digitBits >= 10) {
- throw FormatException.getFormatInstance();
- }
- result.append(toAlphaNumericChar(digitBits));
- }
- }
-
- private static int parseECIValue(BitSource bits) {
- int firstByte = bits.readBits(8);
- if ((firstByte & 0x80) == 0) {
- // just one byte
- return firstByte & 0x7F;
- } else if ((firstByte & 0xC0) == 0x80) {
- // two bytes
- int secondByte = bits.readBits(8);
- return ((firstByte & 0x3F) << 8) | secondByte;
- } else if ((firstByte & 0xE0) == 0xC0) {
- // three bytes
- int secondThirdBytes = bits.readBits(16);
- return ((firstByte & 0x1F) << 16) | secondThirdBytes;
- }
- throw new IllegalArgumentException("Bad ECI bits starting with byte " + firstByte);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java
deleted file mode 100644
index e8d6c2589..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/ErrorCorrectionLevel.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>See ISO 18004:2006, 6.5.1. This enum encapsulates the four error correction levels
- * defined by the QR code standard.</p>
- *
- * @author Sean Owen
- */
-public final class ErrorCorrectionLevel {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- /**
- * L = ~7% correction
- */
- public static final ErrorCorrectionLevel L = new ErrorCorrectionLevel(0, 0x01, "L");
- /**
- * M = ~15% correction
- */
- public static final ErrorCorrectionLevel M = new ErrorCorrectionLevel(1, 0x00, "M");
- /**
- * Q = ~25% correction
- */
- public static final ErrorCorrectionLevel Q = new ErrorCorrectionLevel(2, 0x03, "Q");
- /**
- * H = ~30% correction
- */
- public static final ErrorCorrectionLevel H = new ErrorCorrectionLevel(3, 0x02, "H");
-
- private static final ErrorCorrectionLevel[] FOR_BITS = {M, L, H, Q};
-
- private final int ordinal;
- private final int bits;
- private final String name;
-
- private ErrorCorrectionLevel(int ordinal, int bits, String name) {
- this.ordinal = ordinal;
- this.bits = bits;
- this.name = name;
- }
-
- public int ordinal() {
- return ordinal;
- }
-
- public int getBits() {
- return bits;
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
- /**
- * @param bits int containing the two bits encoding a QR Code's error correction level
- * @return ErrorCorrectionLevel representing the encoded error correction level
- */
- public static ErrorCorrectionLevel forBits(int bits) {
- if (bits < 0 || bits >= FOR_BITS.length) {
- throw new IllegalArgumentException();
- }
- return FOR_BITS[bits];
- }
-
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java
deleted file mode 100644
index 1b76b0de5..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/FormatInformation.java
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>Encapsulates a QR Code's format information, including the data mask used and
- * error correction level.</p>
- *
- * @author Sean Owen
- * @see DataMask
- * @see ErrorCorrectionLevel
- */
-final class FormatInformation {
-
- private static final int FORMAT_INFO_MASK_QR = 0x5412;
-
- /**
- * See ISO 18004:2006, Annex C, Table C.1
- */
- private static final int[][] FORMAT_INFO_DECODE_LOOKUP = {
- {0x5412, 0x00},
- {0x5125, 0x01},
- {0x5E7C, 0x02},
- {0x5B4B, 0x03},
- {0x45F9, 0x04},
- {0x40CE, 0x05},
- {0x4F97, 0x06},
- {0x4AA0, 0x07},
- {0x77C4, 0x08},
- {0x72F3, 0x09},
- {0x7DAA, 0x0A},
- {0x789D, 0x0B},
- {0x662F, 0x0C},
- {0x6318, 0x0D},
- {0x6C41, 0x0E},
- {0x6976, 0x0F},
- {0x1689, 0x10},
- {0x13BE, 0x11},
- {0x1CE7, 0x12},
- {0x19D0, 0x13},
- {0x0762, 0x14},
- {0x0255, 0x15},
- {0x0D0C, 0x16},
- {0x083B, 0x17},
- {0x355F, 0x18},
- {0x3068, 0x19},
- {0x3F31, 0x1A},
- {0x3A06, 0x1B},
- {0x24B4, 0x1C},
- {0x2183, 0x1D},
- {0x2EDA, 0x1E},
- {0x2BED, 0x1F},
- };
-
- /**
- * Offset i holds the number of 1 bits in the binary representation of i
- */
- private static final int[] BITS_SET_IN_HALF_BYTE =
- {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
-
- private final ErrorCorrectionLevel errorCorrectionLevel;
- private final byte dataMask;
-
- private FormatInformation(int formatInfo) {
- // Bits 3,4
- errorCorrectionLevel = ErrorCorrectionLevel.forBits((formatInfo >> 3) & 0x03);
- // Bottom 3 bits
- dataMask = (byte) (formatInfo & 0x07);
- }
-
- static int numBitsDiffering(int a, int b) {
- a ^= b; // a now has a 1 bit exactly where its bit differs with b's
- // Count bits set quickly with a series of lookups:
- return BITS_SET_IN_HALF_BYTE[a & 0x0F] +
- BITS_SET_IN_HALF_BYTE[(a >>> 4 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 8 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 12 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 16 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 20 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 24 & 0x0F)] +
- BITS_SET_IN_HALF_BYTE[(a >>> 28 & 0x0F)];
- }
-
- /**
- * @param maskedFormatInfo1 format info indicator, with mask still applied
- * @param maskedFormatInfo2 second copy of same info; both are checked at the same time
- * to establish best match
- * @return information about the format it specifies, or <code>null</code>
- * if doesn't seem to match any known pattern
- */
- static FormatInformation decodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
- FormatInformation formatInfo = doDecodeFormatInformation(maskedFormatInfo1, maskedFormatInfo2);
- if (formatInfo != null) {
- return formatInfo;
- }
- // Should return null, but, some QR codes apparently
- // do not mask this info. Try again by actually masking the pattern
- // first
- return doDecodeFormatInformation(maskedFormatInfo1 ^ FORMAT_INFO_MASK_QR,
- maskedFormatInfo2 ^ FORMAT_INFO_MASK_QR);
- }
-
- private static FormatInformation doDecodeFormatInformation(int maskedFormatInfo1, int maskedFormatInfo2) {
- // Find the int in FORMAT_INFO_DECODE_LOOKUP with fewest bits differing
- int bestDifference = Integer.MAX_VALUE;
- int bestFormatInfo = 0;
- for (int i = 0; i < FORMAT_INFO_DECODE_LOOKUP.length; i++) {
- int[] decodeInfo = FORMAT_INFO_DECODE_LOOKUP[i];
- int targetInfo = decodeInfo[0];
- if (targetInfo == maskedFormatInfo1 || targetInfo == maskedFormatInfo2) {
- // Found an exact match
- return new FormatInformation(decodeInfo[1]);
- }
- int bitsDifference = numBitsDiffering(maskedFormatInfo1, targetInfo);
- if (bitsDifference < bestDifference) {
- bestFormatInfo = decodeInfo[1];
- bestDifference = bitsDifference;
- }
- if (maskedFormatInfo1 != maskedFormatInfo2) {
- // also try the other option
- bitsDifference = numBitsDiffering(maskedFormatInfo2, targetInfo);
- if (bitsDifference < bestDifference) {
- bestFormatInfo = decodeInfo[1];
- bestDifference = bitsDifference;
- }
- }
- }
- // Hamming distance of the 32 masked codes is 7, by construction, so <= 3 bits
- // differing means we found a match
- if (bestDifference <= 3) {
- return new FormatInformation(bestFormatInfo);
- }
- return null;
- }
-
- ErrorCorrectionLevel getErrorCorrectionLevel() {
- return errorCorrectionLevel;
- }
-
- byte getDataMask() {
- return dataMask;
- }
-
- public int hashCode() {
- return (errorCorrectionLevel.ordinal() << 3) | (int) dataMask;
- }
-
- public boolean equals(Object o) {
- if (!(o instanceof FormatInformation)) {
- return false;
- }
- FormatInformation other = (FormatInformation) o;
- return this.errorCorrectionLevel == other.errorCorrectionLevel &&
- this.dataMask == other.dataMask;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java
deleted file mode 100644
index 3c66217d3..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Mode.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-/**
- * <p>See ISO 18004:2006, 6.4.1, Tables 2 and 3. This enum encapsulates the various modes in which
- * data can be encoded to bits in the QR code standard.</p>
- *
- * @author Sean Owen
- */
-public final class Mode {
-
- // No, we can't use an enum here. J2ME doesn't support it.
-
- public static final Mode TERMINATOR = new Mode(new int[]{0, 0, 0}, 0x00, "TERMINATOR"); // Not really a mode...
- public static final Mode NUMERIC = new Mode(new int[]{10, 12, 14}, 0x01, "NUMERIC");
- public static final Mode ALPHANUMERIC = new Mode(new int[]{9, 11, 13}, 0x02, "ALPHANUMERIC");
- public static final Mode STRUCTURED_APPEND = new Mode(new int[]{0, 0, 0}, 0x03, "STRUCTURED_APPEND"); // Not supported
- public static final Mode BYTE = new Mode(new int[]{8, 16, 16}, 0x04, "BYTE");
- public static final Mode ECI = new Mode(null, 0x07, "ECI"); // character counts don't apply
- public static final Mode KANJI = new Mode(new int[]{8, 10, 12}, 0x08, "KANJI");
- public static final Mode FNC1_FIRST_POSITION = new Mode(null, 0x05, "FNC1_FIRST_POSITION");
- public static final Mode FNC1_SECOND_POSITION = new Mode(null, 0x09, "FNC1_SECOND_POSITION");
- /** See GBT 18284-2000; "Hanzi" is a transliteration of this mode name. */
- public static final Mode HANZI = new Mode(new int[]{8, 10, 12}, 0x0D, "HANZI");
-
- private final int[] characterCountBitsForVersions;
- private final int bits;
- private final String name;
-
- private Mode(int[] characterCountBitsForVersions, int bits, String name) {
- this.characterCountBitsForVersions = characterCountBitsForVersions;
- this.bits = bits;
- this.name = name;
- }
-
- /**
- * @param bits four bits encoding a QR Code data mode
- * @return Mode encoded by these bits
- * @throws IllegalArgumentException if bits do not correspond to a known mode
- */
- public static Mode forBits(int bits) {
- switch (bits) {
- case 0x0:
- return TERMINATOR;
- case 0x1:
- return NUMERIC;
- case 0x2:
- return ALPHANUMERIC;
- case 0x3:
- return STRUCTURED_APPEND;
- case 0x4:
- return BYTE;
- case 0x5:
- return FNC1_FIRST_POSITION;
- case 0x7:
- return ECI;
- case 0x8:
- return KANJI;
- case 0x9:
- return FNC1_SECOND_POSITION;
- case 0xD:
- // 0xD is defined in GBT 18284-2000, may not be supported in foreign country
- return HANZI;
- default:
- throw new IllegalArgumentException();
- }
- }
-
- /**
- * @param version version in question
- * @return number of bits used, in this QR Code symbol {@link Version}, to encode the
- * count of characters that will follow encoded in this Mode
- */
- public int getCharacterCountBits(Version version) {
- if (characterCountBitsForVersions == null) {
- throw new IllegalArgumentException("Character count doesn't apply to this mode");
- }
- int number = version.getVersionNumber();
- int offset;
- if (number <= 9) {
- offset = 0;
- } else if (number <= 26) {
- offset = 1;
- } else {
- offset = 2;
- }
- return characterCountBitsForVersions[offset];
- }
-
- public int getBits() {
- return bits;
- }
-
- public String getName() {
- return name;
- }
-
- public String toString() {
- return name;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java
deleted file mode 100644
index ba795de42..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/decoder/Version.java
+++ /dev/null
@@ -1,586 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.decoder;
-
-import com.google.zxing.FormatException;
-import com.google.zxing.common.BitMatrix;
-
-/**
- * See ISO 18004:2006 Annex D
- *
- * @author Sean Owen
- */
-public final class Version {
-
- /**
- * See ISO 18004:2006 Annex D.
- * Element i represents the raw version bits that specify version i + 7
- */
- private static final int[] VERSION_DECODE_INFO = {
- 0x07C94, 0x085BC, 0x09A99, 0x0A4D3, 0x0BBF6,
- 0x0C762, 0x0D847, 0x0E60D, 0x0F928, 0x10B78,
- 0x1145D, 0x12A17, 0x13532, 0x149A6, 0x15683,
- 0x168C9, 0x177EC, 0x18EC4, 0x191E1, 0x1AFAB,
- 0x1B08E, 0x1CC1A, 0x1D33F, 0x1ED75, 0x1F250,
- 0x209D5, 0x216F0, 0x228BA, 0x2379F, 0x24B0B,
- 0x2542E, 0x26A64, 0x27541, 0x28C69
- };
-
- private static final Version[] VERSIONS = buildVersions();
-
- private final int versionNumber;
- private final int[] alignmentPatternCenters;
- private final ECBlocks[] ecBlocks;
- private final int totalCodewords;
-
- private Version(int versionNumber,
- int[] alignmentPatternCenters,
- ECBlocks ecBlocks1,
- ECBlocks ecBlocks2,
- ECBlocks ecBlocks3,
- ECBlocks ecBlocks4) {
- this.versionNumber = versionNumber;
- this.alignmentPatternCenters = alignmentPatternCenters;
- this.ecBlocks = new ECBlocks[]{ecBlocks1, ecBlocks2, ecBlocks3, ecBlocks4};
- int total = 0;
- int ecCodewords = ecBlocks1.getECCodewordsPerBlock();
- ECB[] ecbArray = ecBlocks1.getECBlocks();
- for (int i = 0; i < ecbArray.length; i++) {
- ECB ecBlock = ecbArray[i];
- total += ecBlock.getCount() * (ecBlock.getDataCodewords() + ecCodewords);
- }
- this.totalCodewords = total;
- }
-
- public int getVersionNumber() {
- return versionNumber;
- }
-
- public int[] getAlignmentPatternCenters() {
- return alignmentPatternCenters;
- }
-
- public int getTotalCodewords() {
- return totalCodewords;
- }
-
- public int getDimensionForVersion() {
- return 17 + 4 * versionNumber;
- }
-
- public ECBlocks getECBlocksForLevel(ErrorCorrectionLevel ecLevel) {
- return ecBlocks[ecLevel.ordinal()];
- }
-
- /**
- * <p>Deduces version information purely from QR Code dimensions.</p>
- *
- * @param dimension dimension in modules
- * @return Version for a QR Code of that dimension
- * @throws FormatException if dimension is not 1 mod 4
- */
- public static Version getProvisionalVersionForDimension(int dimension) throws FormatException {
- if (dimension % 4 != 1) {
- throw FormatException.getFormatInstance();
- }
- try {
- return getVersionForNumber((dimension - 17) >> 2);
- } catch (IllegalArgumentException iae) {
- throw FormatException.getFormatInstance();
- }
- }
-
- public static Version getVersionForNumber(int versionNumber) {
- if (versionNumber < 1 || versionNumber > 40) {
- throw new IllegalArgumentException();
- }
- return VERSIONS[versionNumber - 1];
- }
-
- static Version decodeVersionInformation(int versionBits) {
- int bestDifference = Integer.MAX_VALUE;
- int bestVersion = 0;
- for (int i = 0; i < VERSION_DECODE_INFO.length; i++) {
- int targetVersion = VERSION_DECODE_INFO[i];
- // Do the version info bits match exactly? done.
- if (targetVersion == versionBits) {
- return getVersionForNumber(i + 7);
- }
- // Otherwise see if this is the closest to a real version info bit string
- // we have seen so far
- int bitsDifference = FormatInformation.numBitsDiffering(versionBits, targetVersion);
- if (bitsDifference < bestDifference) {
- bestVersion = i + 7;
- bestDifference = bitsDifference;
- }
- }
- // We can tolerate up to 3 bits of error since no two version info codewords will
- // differ in less than 8 bits.
- if (bestDifference <= 3) {
- return getVersionForNumber(bestVersion);
- }
- // If we didn't find a close enough match, fail
- return null;
- }
-
- /**
- * See ISO 18004:2006 Annex E
- */
- BitMatrix buildFunctionPattern() {
- int dimension = getDimensionForVersion();
- BitMatrix bitMatrix = new BitMatrix(dimension);
-
- // Top left finder pattern + separator + format
- bitMatrix.setRegion(0, 0, 9, 9);
- // Top right finder pattern + separator + format
- bitMatrix.setRegion(dimension - 8, 0, 8, 9);
- // Bottom left finder pattern + separator + format
- bitMatrix.setRegion(0, dimension - 8, 9, 8);
-
- // Alignment patterns
- int max = alignmentPatternCenters.length;
- for (int x = 0; x < max; x++) {
- int i = alignmentPatternCenters[x] - 2;
- for (int y = 0; y < max; y++) {
- if ((x == 0 && (y == 0 || y == max - 1)) || (x == max - 1 && y == 0)) {
- // No alignment patterns near the three finder paterns
- continue;
- }
- bitMatrix.setRegion(alignmentPatternCenters[y] - 2, i, 5, 5);
- }
- }
-
- // Vertical timing pattern
- bitMatrix.setRegion(6, 9, 1, dimension - 17);
- // Horizontal timing pattern
- bitMatrix.setRegion(9, 6, dimension - 17, 1);
-
- if (versionNumber > 6) {
- // Version info, top right
- bitMatrix.setRegion(dimension - 11, 0, 3, 6);
- // Version info, bottom left
- bitMatrix.setRegion(0, dimension - 11, 6, 3);
- }
-
- return bitMatrix;
- }
-
- /**
- * <p>Encapsulates a set of error-correction blocks in one symbol version. Most versions will
- * use blocks of differing sizes within one version, so, this encapsulates the parameters for
- * each set of blocks. It also holds the number of error-correction codewords per block since it
- * will be the same across all blocks within one version.</p>
- */
- public static final class ECBlocks {
- private final int ecCodewordsPerBlock;
- private final ECB[] ecBlocks;
-
- ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks) {
- this.ecCodewordsPerBlock = ecCodewordsPerBlock;
- this.ecBlocks = new ECB[]{ecBlocks};
- }
-
- ECBlocks(int ecCodewordsPerBlock, ECB ecBlocks1, ECB ecBlocks2) {
- this.ecCodewordsPerBlock = ecCodewordsPerBlock;
- this.ecBlocks = new ECB[]{ecBlocks1, ecBlocks2};
- }
-
- public int getECCodewordsPerBlock() {
- return ecCodewordsPerBlock;
- }
-
- public int getNumBlocks() {
- int total = 0;
- for (int i = 0; i < ecBlocks.length; i++) {
- total += ecBlocks[i].getCount();
- }
- return total;
- }
-
- public int getTotalECCodewords() {
- return ecCodewordsPerBlock * getNumBlocks();
- }
-
- public ECB[] getECBlocks() {
- return ecBlocks;
- }
- }
-
- /**
- * <p>Encapsualtes the parameters for one error-correction block in one symbol version.
- * This includes the number of data codewords, and the number of times a block with these
- * parameters is used consecutively in the QR code version's format.</p>
- */
- public static final class ECB {
- private final int count;
- private final int dataCodewords;
-
- ECB(int count, int dataCodewords) {
- this.count = count;
- this.dataCodewords = dataCodewords;
- }
-
- public int getCount() {
- return count;
- }
-
- public int getDataCodewords() {
- return dataCodewords;
- }
- }
-
- public String toString() {
- return String.valueOf(versionNumber);
- }
-
- /**
- * See ISO 18004:2006 6.5.1 Table 9
- */
- private static Version[] buildVersions() {
- return new Version[]{
- new Version(1, new int[]{},
- new ECBlocks(7, new ECB(1, 19)),
- new ECBlocks(10, new ECB(1, 16)),
- new ECBlocks(13, new ECB(1, 13)),
- new ECBlocks(17, new ECB(1, 9))),
- new Version(2, new int[]{6, 18},
- new ECBlocks(10, new ECB(1, 34)),
- new ECBlocks(16, new ECB(1, 28)),
- new ECBlocks(22, new ECB(1, 22)),
- new ECBlocks(28, new ECB(1, 16))),
- new Version(3, new int[]{6, 22},
- new ECBlocks(15, new ECB(1, 55)),
- new ECBlocks(26, new ECB(1, 44)),
- new ECBlocks(18, new ECB(2, 17)),
- new ECBlocks(22, new ECB(2, 13))),
- new Version(4, new int[]{6, 26},
- new ECBlocks(20, new ECB(1, 80)),
- new ECBlocks(18, new ECB(2, 32)),
- new ECBlocks(26, new ECB(2, 24)),
- new ECBlocks(16, new ECB(4, 9))),
- new Version(5, new int[]{6, 30},
- new ECBlocks(26, new ECB(1, 108)),
- new ECBlocks(24, new ECB(2, 43)),
- new ECBlocks(18, new ECB(2, 15),
- new ECB(2, 16)),
- new ECBlocks(22, new ECB(2, 11),
- new ECB(2, 12))),
- new Version(6, new int[]{6, 34},
- new ECBlocks(18, new ECB(2, 68)),
- new ECBlocks(16, new ECB(4, 27)),
- new ECBlocks(24, new ECB(4, 19)),
- new ECBlocks(28, new ECB(4, 15))),
- new Version(7, new int[]{6, 22, 38},
- new ECBlocks(20, new ECB(2, 78)),
- new ECBlocks(18, new ECB(4, 31)),
- new ECBlocks(18, new ECB(2, 14),
- new ECB(4, 15)),
- new ECBlocks(26, new ECB(4, 13),
- new ECB(1, 14))),
- new Version(8, new int[]{6, 24, 42},
- new ECBlocks(24, new ECB(2, 97)),
- new ECBlocks(22, new ECB(2, 38),
- new ECB(2, 39)),
- new ECBlocks(22, new ECB(4, 18),
- new ECB(2, 19)),
- new ECBlocks(26, new ECB(4, 14),
- new ECB(2, 15))),
- new Version(9, new int[]{6, 26, 46},
- new ECBlocks(30, new ECB(2, 116)),
- new ECBlocks(22, new ECB(3, 36),
- new ECB(2, 37)),
- new ECBlocks(20, new ECB(4, 16),
- new ECB(4, 17)),
- new ECBlocks(24, new ECB(4, 12),
- new ECB(4, 13))),
- new Version(10, new int[]{6, 28, 50},
- new ECBlocks(18, new ECB(2, 68),
- new ECB(2, 69)),
- new ECBlocks(26, new ECB(4, 43),
- new ECB(1, 44)),
- new ECBlocks(24, new ECB(6, 19),
- new ECB(2, 20)),
- new ECBlocks(28, new ECB(6, 15),
- new ECB(2, 16))),
- new Version(11, new int[]{6, 30, 54},
- new ECBlocks(20, new ECB(4, 81)),
- new ECBlocks(30, new ECB(1, 50),
- new ECB(4, 51)),
- new ECBlocks(28, new ECB(4, 22),
- new ECB(4, 23)),
- new ECBlocks(24, new ECB(3, 12),
- new ECB(8, 13))),
- new Version(12, new int[]{6, 32, 58},
- new ECBlocks(24, new ECB(2, 92),
- new ECB(2, 93)),
- new ECBlocks(22, new ECB(6, 36),
- new ECB(2, 37)),
- new ECBlocks(26, new ECB(4, 20),
- new ECB(6, 21)),
- new ECBlocks(28, new ECB(7, 14),
- new ECB(4, 15))),
- new Version(13, new int[]{6, 34, 62},
- new ECBlocks(26, new ECB(4, 107)),
- new ECBlocks(22, new ECB(8, 37),
- new ECB(1, 38)),
- new ECBlocks(24, new ECB(8, 20),
- new ECB(4, 21)),
- new ECBlocks(22, new ECB(12, 11),
- new ECB(4, 12))),
- new Version(14, new int[]{6, 26, 46, 66},
- new ECBlocks(30, new ECB(3, 115),
- new ECB(1, 116)),
- new ECBlocks(24, new ECB(4, 40),
- new ECB(5, 41)),
- new ECBlocks(20, new ECB(11, 16),
- new ECB(5, 17)),
- new ECBlocks(24, new ECB(11, 12),
- new ECB(5, 13))),
- new Version(15, new int[]{6, 26, 48, 70},
- new ECBlocks(22, new ECB(5, 87),
- new ECB(1, 88)),
- new ECBlocks(24, new ECB(5, 41),
- new ECB(5, 42)),
- new ECBlocks(30, new ECB(5, 24),
- new ECB(7, 25)),
- new ECBlocks(24, new ECB(11, 12),
- new ECB(7, 13))),
- new Version(16, new int[]{6, 26, 50, 74},
- new ECBlocks(24, new ECB(5, 98),
- new ECB(1, 99)),
- new ECBlocks(28, new ECB(7, 45),
- new ECB(3, 46)),
- new ECBlocks(24, new ECB(15, 19),
- new ECB(2, 20)),
- new ECBlocks(30, new ECB(3, 15),
- new ECB(13, 16))),
- new Version(17, new int[]{6, 30, 54, 78},
- new ECBlocks(28, new ECB(1, 107),
- new ECB(5, 108)),
- new ECBlocks(28, new ECB(10, 46),
- new ECB(1, 47)),
- new ECBlocks(28, new ECB(1, 22),
- new ECB(15, 23)),
- new ECBlocks(28, new ECB(2, 14),
- new ECB(17, 15))),
- new Version(18, new int[]{6, 30, 56, 82},
- new ECBlocks(30, new ECB(5, 120),
- new ECB(1, 121)),
- new ECBlocks(26, new ECB(9, 43),
- new ECB(4, 44)),
- new ECBlocks(28, new ECB(17, 22),
- new ECB(1, 23)),
- new ECBlocks(28, new ECB(2, 14),
- new ECB(19, 15))),
- new Version(19, new int[]{6, 30, 58, 86},
- new ECBlocks(28, new ECB(3, 113),
- new ECB(4, 114)),
- new ECBlocks(26, new ECB(3, 44),
- new ECB(11, 45)),
- new ECBlocks(26, new ECB(17, 21),
- new ECB(4, 22)),
- new ECBlocks(26, new ECB(9, 13),
- new ECB(16, 14))),
- new Version(20, new int[]{6, 34, 62, 90},
- new ECBlocks(28, new ECB(3, 107),
- new ECB(5, 108)),
- new ECBlocks(26, new ECB(3, 41),
- new ECB(13, 42)),
- new ECBlocks(30, new ECB(15, 24),
- new ECB(5, 25)),
- new ECBlocks(28, new ECB(15, 15),
- new ECB(10, 16))),
- new Version(21, new int[]{6, 28, 50, 72, 94},
- new ECBlocks(28, new ECB(4, 116),
- new ECB(4, 117)),
- new ECBlocks(26, new ECB(17, 42)),
- new ECBlocks(28, new ECB(17, 22),
- new ECB(6, 23)),
- new ECBlocks(30, new ECB(19, 16),
- new ECB(6, 17))),
- new Version(22, new int[]{6, 26, 50, 74, 98},
- new ECBlocks(28, new ECB(2, 111),
- new ECB(7, 112)),
- new ECBlocks(28, new ECB(17, 46)),
- new ECBlocks(30, new ECB(7, 24),
- new ECB(16, 25)),
- new ECBlocks(24, new ECB(34, 13))),
- new Version(23, new int[]{6, 30, 54, 78, 102},
- new ECBlocks(30, new ECB(4, 121),
- new ECB(5, 122)),
- new ECBlocks(28, new ECB(4, 47),
- new ECB(14, 48)),
- new ECBlocks(30, new ECB(11, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(16, 15),
- new ECB(14, 16))),
- new Version(24, new int[]{6, 28, 54, 80, 106},
- new ECBlocks(30, new ECB(6, 117),
- new ECB(4, 118)),
- new ECBlocks(28, new ECB(6, 45),
- new ECB(14, 46)),
- new ECBlocks(30, new ECB(11, 24),
- new ECB(16, 25)),
- new ECBlocks(30, new ECB(30, 16),
- new ECB(2, 17))),
- new Version(25, new int[]{6, 32, 58, 84, 110},
- new ECBlocks(26, new ECB(8, 106),
- new ECB(4, 107)),
- new ECBlocks(28, new ECB(8, 47),
- new ECB(13, 48)),
- new ECBlocks(30, new ECB(7, 24),
- new ECB(22, 25)),
- new ECBlocks(30, new ECB(22, 15),
- new ECB(13, 16))),
- new Version(26, new int[]{6, 30, 58, 86, 114},
- new ECBlocks(28, new ECB(10, 114),
- new ECB(2, 115)),
- new ECBlocks(28, new ECB(19, 46),
- new ECB(4, 47)),
- new ECBlocks(28, new ECB(28, 22),
- new ECB(6, 23)),
- new ECBlocks(30, new ECB(33, 16),
- new ECB(4, 17))),
- new Version(27, new int[]{6, 34, 62, 90, 118},
- new ECBlocks(30, new ECB(8, 122),
- new ECB(4, 123)),
- new ECBlocks(28, new ECB(22, 45),
- new ECB(3, 46)),
- new ECBlocks(30, new ECB(8, 23),
- new ECB(26, 24)),
- new ECBlocks(30, new ECB(12, 15),
- new ECB(28, 16))),
- new Version(28, new int[]{6, 26, 50, 74, 98, 122},
- new ECBlocks(30, new ECB(3, 117),
- new ECB(10, 118)),
- new ECBlocks(28, new ECB(3, 45),
- new ECB(23, 46)),
- new ECBlocks(30, new ECB(4, 24),
- new ECB(31, 25)),
- new ECBlocks(30, new ECB(11, 15),
- new ECB(31, 16))),
- new Version(29, new int[]{6, 30, 54, 78, 102, 126},
- new ECBlocks(30, new ECB(7, 116),
- new ECB(7, 117)),
- new ECBlocks(28, new ECB(21, 45),
- new ECB(7, 46)),
- new ECBlocks(30, new ECB(1, 23),
- new ECB(37, 24)),
- new ECBlocks(30, new ECB(19, 15),
- new ECB(26, 16))),
- new Version(30, new int[]{6, 26, 52, 78, 104, 130},
- new ECBlocks(30, new ECB(5, 115),
- new ECB(10, 116)),
- new ECBlocks(28, new ECB(19, 47),
- new ECB(10, 48)),
- new ECBlocks(30, new ECB(15, 24),
- new ECB(25, 25)),
- new ECBlocks(30, new ECB(23, 15),
- new ECB(25, 16))),
- new Version(31, new int[]{6, 30, 56, 82, 108, 134},
- new ECBlocks(30, new ECB(13, 115),
- new ECB(3, 116)),
- new ECBlocks(28, new ECB(2, 46),
- new ECB(29, 47)),
- new ECBlocks(30, new ECB(42, 24),
- new ECB(1, 25)),
- new ECBlocks(30, new ECB(23, 15),
- new ECB(28, 16))),
- new Version(32, new int[]{6, 34, 60, 86, 112, 138},
- new ECBlocks(30, new ECB(17, 115)),
- new ECBlocks(28, new ECB(10, 46),
- new ECB(23, 47)),
- new ECBlocks(30, new ECB(10, 24),
- new ECB(35, 25)),
- new ECBlocks(30, new ECB(19, 15),
- new ECB(35, 16))),
- new Version(33, new int[]{6, 30, 58, 86, 114, 142},
- new ECBlocks(30, new ECB(17, 115),
- new ECB(1, 116)),
- new ECBlocks(28, new ECB(14, 46),
- new ECB(21, 47)),
- new ECBlocks(30, new ECB(29, 24),
- new ECB(19, 25)),
- new ECBlocks(30, new ECB(11, 15),
- new ECB(46, 16))),
- new Version(34, new int[]{6, 34, 62, 90, 118, 146},
- new ECBlocks(30, new ECB(13, 115),
- new ECB(6, 116)),
- new ECBlocks(28, new ECB(14, 46),
- new ECB(23, 47)),
- new ECBlocks(30, new ECB(44, 24),
- new ECB(7, 25)),
- new ECBlocks(30, new ECB(59, 16),
- new ECB(1, 17))),
- new Version(35, new int[]{6, 30, 54, 78, 102, 126, 150},
- new ECBlocks(30, new ECB(12, 121),
- new ECB(7, 122)),
- new ECBlocks(28, new ECB(12, 47),
- new ECB(26, 48)),
- new ECBlocks(30, new ECB(39, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(22, 15),
- new ECB(41, 16))),
- new Version(36, new int[]{6, 24, 50, 76, 102, 128, 154},
- new ECBlocks(30, new ECB(6, 121),
- new ECB(14, 122)),
- new ECBlocks(28, new ECB(6, 47),
- new ECB(34, 48)),
- new ECBlocks(30, new ECB(46, 24),
- new ECB(10, 25)),
- new ECBlocks(30, new ECB(2, 15),
- new ECB(64, 16))),
- new Version(37, new int[]{6, 28, 54, 80, 106, 132, 158},
- new ECBlocks(30, new ECB(17, 122),
- new ECB(4, 123)),
- new ECBlocks(28, new ECB(29, 46),
- new ECB(14, 47)),
- new ECBlocks(30, new ECB(49, 24),
- new ECB(10, 25)),
- new ECBlocks(30, new ECB(24, 15),
- new ECB(46, 16))),
- new Version(38, new int[]{6, 32, 58, 84, 110, 136, 162},
- new ECBlocks(30, new ECB(4, 122),
- new ECB(18, 123)),
- new ECBlocks(28, new ECB(13, 46),
- new ECB(32, 47)),
- new ECBlocks(30, new ECB(48, 24),
- new ECB(14, 25)),
- new ECBlocks(30, new ECB(42, 15),
- new ECB(32, 16))),
- new Version(39, new int[]{6, 26, 54, 82, 110, 138, 166},
- new ECBlocks(30, new ECB(20, 117),
- new ECB(4, 118)),
- new ECBlocks(28, new ECB(40, 47),
- new ECB(7, 48)),
- new ECBlocks(30, new ECB(43, 24),
- new ECB(22, 25)),
- new ECBlocks(30, new ECB(10, 15),
- new ECB(67, 16))),
- new Version(40, new int[]{6, 30, 58, 86, 114, 142, 170},
- new ECBlocks(30, new ECB(19, 118),
- new ECB(6, 119)),
- new ECBlocks(28, new ECB(18, 47),
- new ECB(31, 48)),
- new ECBlocks(30, new ECB(34, 24),
- new ECB(34, 25)),
- new ECBlocks(30, new ECB(20, 15),
- new ECB(61, 16)))
- };
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPattern.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPattern.java
deleted file mode 100644
index 6fc1a2c88..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPattern.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-import com.google.zxing.ResultPoint;
-
-/**
- * <p>Encapsulates an alignment pattern, which are the smaller square patterns found in
- * all but the simplest QR Codes.</p>
- *
- * @author Sean Owen
- */
-public final class AlignmentPattern extends ResultPoint {
-
- private final float estimatedModuleSize;
-
- AlignmentPattern(float posX, float posY, float estimatedModuleSize) {
- super(posX, posY);
- this.estimatedModuleSize = estimatedModuleSize;
- }
-
- /**
- * <p>Determines if this alignment pattern "about equals" an alignment pattern at the stated
- * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
- */
- boolean aboutEquals(float moduleSize, float i, float j) {
- if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
- float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
- return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
- }
- return false;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java
deleted file mode 100644
index 3aadf284f..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/AlignmentPatternFinder.java
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.ResultPointCallback;
-import com.google.zxing.common.BitMatrix;
-
-import java.util.Vector;
-
-/**
- * <p>This class attempts to find alignment patterns in a QR Code. Alignment patterns look like finder
- * patterns but are smaller and appear at regular intervals throughout the image.</p>
- *
- * <p>At the moment this only looks for the bottom-right alignment pattern.</p>
- *
- * <p>This is mostly a simplified copy of {@link FinderPatternFinder}. It is copied,
- * pasted and stripped down here for maximum performance but does unfortunately duplicate
- * some code.</p>
- *
- * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.
- *
- * @author Sean Owen
- */
-final class AlignmentPatternFinder {
-
- private final BitMatrix image;
- private final Vector possibleCenters;
- private final int startX;
- private final int startY;
- private final int width;
- private final int height;
- private final float moduleSize;
- private final int[] crossCheckStateCount;
- private final ResultPointCallback resultPointCallback;
-
- /**
- * <p>Creates a finder that will look in a portion of the whole image.</p>
- *
- * @param image image to search
- * @param startX left column from which to start searching
- * @param startY top row from which to start searching
- * @param width width of region to search
- * @param height height of region to search
- * @param moduleSize estimated module size so far
- */
- AlignmentPatternFinder(BitMatrix image,
- int startX,
- int startY,
- int width,
- int height,
- float moduleSize,
- ResultPointCallback resultPointCallback) {
- this.image = image;
- this.possibleCenters = new Vector(5);
- this.startX = startX;
- this.startY = startY;
- this.width = width;
- this.height = height;
- this.moduleSize = moduleSize;
- this.crossCheckStateCount = new int[3];
- this.resultPointCallback = resultPointCallback;
- }
-
- /**
- * <p>This method attempts to find the bottom-right alignment pattern in the image. It is a bit messy since
- * it's pretty performance-critical and so is written to be fast foremost.</p>
- *
- * @return {@link AlignmentPattern} if found
- * @throws NotFoundException if not found
- */
- AlignmentPattern find() throws NotFoundException {
- int startX = this.startX;
- int height = this.height;
- int maxJ = startX + width;
- int middleI = startY + (height >> 1);
- // We are looking for black/white/black modules in 1:1:1 ratio;
- // this tracks the number of black/white/black modules seen so far
- int[] stateCount = new int[3];
- for (int iGen = 0; iGen < height; iGen++) {
- // Search from middle outwards
- int i = middleI + ((iGen & 0x01) == 0 ? (iGen + 1) >> 1 : -((iGen + 1) >> 1));
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
- int j = startX;
- // Burn off leading white pixels before anything else; if we start in the middle of
- // a white run, it doesn't make sense to count its length, since we don't know if the
- // white run continued to the left of the start point
- while (j < maxJ && !image.get(j, i)) {
- j++;
- }
- int currentState = 0;
- while (j < maxJ) {
- if (image.get(j, i)) {
- // Black pixel
- if (currentState == 1) { // Counting black pixels
- stateCount[currentState]++;
- } else { // Counting white pixels
- if (currentState == 2) { // A winner?
- if (foundPatternCross(stateCount)) { // Yes
- AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, j);
- if (confirmed != null) {
- return confirmed;
- }
- }
- stateCount[0] = stateCount[2];
- stateCount[1] = 1;
- stateCount[2] = 0;
- currentState = 1;
- } else {
- stateCount[++currentState]++;
- }
- }
- } else { // White pixel
- if (currentState == 1) { // Counting black pixels
- currentState++;
- }
- stateCount[currentState]++;
- }
- j++;
- }
- if (foundPatternCross(stateCount)) {
- AlignmentPattern confirmed = handlePossibleCenter(stateCount, i, maxJ);
- if (confirmed != null) {
- return confirmed;
- }
- }
-
- }
-
- // Hmm, nothing we saw was observed and confirmed twice. If we had
- // any guess at all, return it.
- if (!possibleCenters.isEmpty()) {
- return (AlignmentPattern) possibleCenters.elementAt(0);
- }
-
- throw NotFoundException.getNotFoundInstance();
- }
-
- /**
- * Given a count of black/white/black pixels just seen and an end position,
- * figures the location of the center of this black/white/black run.
- */
- private static float centerFromEnd(int[] stateCount, int end) {
- return (float) (end - stateCount[2]) - stateCount[1] / 2.0f;
- }
-
- /**
- * @param stateCount count of black/white/black pixels just read
- * @return true iff the proportions of the counts is close enough to the 1/1/1 ratios
- * used by alignment patterns to be considered a match
- */
- private boolean foundPatternCross(int[] stateCount) {
- float moduleSize = this.moduleSize;
- float maxVariance = moduleSize / 2.0f;
- for (int i = 0; i < 3; i++) {
- if (Math.abs(moduleSize - stateCount[i]) >= maxVariance) {
- return false;
- }
- }
- return true;
- }
-
- /**
- * <p>After a horizontal scan finds a potential alignment pattern, this method
- * "cross-checks" by scanning down vertically through the center of the possible
- * alignment pattern to see if the same proportion is detected.</p>
- *
- * @param startI row where an alignment pattern was detected
- * @param centerJ center of the section that appears to cross an alignment pattern
- * @param maxCount maximum reasonable number of modules that should be
- * observed in any reading state, based on the results of the horizontal scan
- * @return vertical center of alignment pattern, or {@link Float#NaN} if not found
- */
- private float crossCheckVertical(int startI, int centerJ, int maxCount,
- int originalStateCountTotal) {
- BitMatrix image = this.image;
-
- int maxI = image.getHeight();
- int[] stateCount = crossCheckStateCount;
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
-
- // Start counting up from center
- int i = startI;
- while (i >= 0 && image.get(centerJ, i) && stateCount[1] <= maxCount) {
- stateCount[1]++;
- i--;
- }
- // If already too many modules in this state or ran off the edge:
- if (i < 0 || stateCount[1] > maxCount) {
- return Float.NaN;
- }
- while (i >= 0 && !image.get(centerJ, i) && stateCount[0] <= maxCount) {
- stateCount[0]++;
- i--;
- }
- if (stateCount[0] > maxCount) {
- return Float.NaN;
- }
-
- // Now also count down from center
- i = startI + 1;
- while (i < maxI && image.get(centerJ, i) && stateCount[1] <= maxCount) {
- stateCount[1]++;
- i++;
- }
- if (i == maxI || stateCount[1] > maxCount) {
- return Float.NaN;
- }
- while (i < maxI && !image.get(centerJ, i) && stateCount[2] <= maxCount) {
- stateCount[2]++;
- i++;
- }
- if (stateCount[2] > maxCount) {
- return Float.NaN;
- }
-
- int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
- if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
- return Float.NaN;
- }
-
- return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN;
- }
-
- /**
- * <p>This is called when a horizontal scan finds a possible alignment pattern. It will
- * cross check with a vertical scan, and if successful, will see if this pattern had been
- * found on a previous horizontal scan. If so, we consider it confirmed and conclude we have
- * found the alignment pattern.</p>
- *
- * @param stateCount reading state module counts from horizontal scan
- * @param i row where alignment pattern may be found
- * @param j end of possible alignment pattern in row
- * @return {@link AlignmentPattern} if we have found the same pattern twice, or null if not
- */
- private AlignmentPattern handlePossibleCenter(int[] stateCount, int i, int j) {
- int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2];
- float centerJ = centerFromEnd(stateCount, j);
- float centerI = crossCheckVertical(i, (int) centerJ, 2 * stateCount[1], stateCountTotal);
- if (!Float.isNaN(centerI)) {
- float estimatedModuleSize = (float) (stateCount[0] + stateCount[1] + stateCount[2]) / 3.0f;
- int max = possibleCenters.size();
- for (int index = 0; index < max; index++) {
- AlignmentPattern center = (AlignmentPattern) possibleCenters.elementAt(index);
- // Look for about the same center and module size:
- if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
- return new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
- }
- }
- // Hadn't found this before; save it
- ResultPoint point = new AlignmentPattern(centerJ, centerI, estimatedModuleSize);
- possibleCenters.addElement(point);
- if (resultPointCallback != null) {
- resultPointCallback.foundPossibleResultPoint(point);
- }
- }
- return null;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/Detector.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/Detector.java
deleted file mode 100644
index 724d39d59..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/Detector.java
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-import com.google.zxing.DecodeHintType;
-import com.google.zxing.FormatException;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.ResultPointCallback;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.DetectorResult;
-import com.google.zxing.common.GridSampler;
-import com.google.zxing.common.PerspectiveTransform;
-import com.google.zxing.qrcode.decoder.Version;
-
-import java.util.Hashtable;
-
-/**
- * <p>Encapsulates logic that can detect a QR Code in an image, even if the QR Code
- * is rotated or skewed, or partially obscured.</p>
- *
- * @author Sean Owen
- */
-public class Detector {
-
- private final BitMatrix image;
- private ResultPointCallback resultPointCallback;
-
- public Detector(BitMatrix image) {
- this.image = image;
- }
-
- protected BitMatrix getImage() {
- return image;
- }
-
- protected ResultPointCallback getResultPointCallback() {
- return resultPointCallback;
- }
-
- /**
- * <p>Detects a QR Code in an image, simply.</p>
- *
- * @return {@link DetectorResult} encapsulating results of detecting a QR Code
- * @throws NotFoundException if no QR Code can be found
- */
- public DetectorResult detect() throws NotFoundException, FormatException {
- return detect(null);
- }
-
- /**
- * <p>Detects a QR Code in an image, simply.</p>
- *
- * @param hints optional hints to detector
- * @return {@link NotFoundException} encapsulating results of detecting a QR Code
- * @throws NotFoundException if QR Code cannot be found
- * @throws FormatException if a QR Code cannot be decoded
- */
- public DetectorResult detect(Hashtable hints) throws NotFoundException, FormatException {
-
- resultPointCallback = hints == null ? null :
- (ResultPointCallback) hints.get(DecodeHintType.NEED_RESULT_POINT_CALLBACK);
-
- FinderPatternFinder finder = new FinderPatternFinder(image, resultPointCallback);
- FinderPatternInfo info = finder.find(hints);
-
- return processFinderPatternInfo(info);
- }
-
- protected DetectorResult processFinderPatternInfo(FinderPatternInfo info)
- throws NotFoundException, FormatException {
-
- FinderPattern topLeft = info.getTopLeft();
- FinderPattern topRight = info.getTopRight();
- FinderPattern bottomLeft = info.getBottomLeft();
-
- float moduleSize = calculateModuleSize(topLeft, topRight, bottomLeft);
- if (moduleSize < 1.0f) {
- throw NotFoundException.getNotFoundInstance();
- }
- int dimension = computeDimension(topLeft, topRight, bottomLeft, moduleSize);
- Version provisionalVersion = Version.getProvisionalVersionForDimension(dimension);
- int modulesBetweenFPCenters = provisionalVersion.getDimensionForVersion() - 7;
-
- AlignmentPattern alignmentPattern = null;
- // Anything above version 1 has an alignment pattern
- if (provisionalVersion.getAlignmentPatternCenters().length > 0) {
-
- // Guess where a "bottom right" finder pattern would have been
- float bottomRightX = topRight.getX() - topLeft.getX() + bottomLeft.getX();
- float bottomRightY = topRight.getY() - topLeft.getY() + bottomLeft.getY();
-
- // Estimate that alignment pattern is closer by 3 modules
- // from "bottom right" to known top left location
- float correctionToTopLeft = 1.0f - 3.0f / (float) modulesBetweenFPCenters;
- int estAlignmentX = (int) (topLeft.getX() + correctionToTopLeft * (bottomRightX - topLeft.getX()));
- int estAlignmentY = (int) (topLeft.getY() + correctionToTopLeft * (bottomRightY - topLeft.getY()));
-
- // Kind of arbitrary -- expand search radius before giving up
- for (int i = 4; i <= 16; i <<= 1) {
- try {
- alignmentPattern = findAlignmentInRegion(moduleSize,
- estAlignmentX,
- estAlignmentY,
- (float) i);
- break;
- } catch (NotFoundException re) {
- // try next round
- }
- }
- // If we didn't find alignment pattern... well try anyway without it
- }
-
- PerspectiveTransform transform =
- createTransform(topLeft, topRight, bottomLeft, alignmentPattern, dimension);
-
- BitMatrix bits = sampleGrid(image, transform, dimension);
-
- ResultPoint[] points;
- if (alignmentPattern == null) {
- points = new ResultPoint[]{bottomLeft, topLeft, topRight};
- } else {
- points = new ResultPoint[]{bottomLeft, topLeft, topRight, alignmentPattern};
- }
- return new DetectorResult(bits, points);
- }
-
- public static PerspectiveTransform createTransform(ResultPoint topLeft,
- ResultPoint topRight,
- ResultPoint bottomLeft,
- ResultPoint alignmentPattern,
- int dimension) {
- float dimMinusThree = (float) dimension - 3.5f;
- float bottomRightX;
- float bottomRightY;
- float sourceBottomRightX;
- float sourceBottomRightY;
- if (alignmentPattern != null) {
- bottomRightX = alignmentPattern.getX();
- bottomRightY = alignmentPattern.getY();
- sourceBottomRightX = sourceBottomRightY = dimMinusThree - 3.0f;
- } else {
- // Don't have an alignment pattern, just make up the bottom-right point
- bottomRightX = (topRight.getX() - topLeft.getX()) + bottomLeft.getX();
- bottomRightY = (topRight.getY() - topLeft.getY()) + bottomLeft.getY();
- sourceBottomRightX = sourceBottomRightY = dimMinusThree;
- }
-
- return PerspectiveTransform.quadrilateralToQuadrilateral(
- 3.5f,
- 3.5f,
- dimMinusThree,
- 3.5f,
- sourceBottomRightX,
- sourceBottomRightY,
- 3.5f,
- dimMinusThree,
- topLeft.getX(),
- topLeft.getY(),
- topRight.getX(),
- topRight.getY(),
- bottomRightX,
- bottomRightY,
- bottomLeft.getX(),
- bottomLeft.getY());
- }
-
- private static BitMatrix sampleGrid(BitMatrix image,
- PerspectiveTransform transform,
- int dimension) throws NotFoundException {
-
- GridSampler sampler = GridSampler.getInstance();
- return sampler.sampleGrid(image, dimension, dimension, transform);
- }
-
- /**
- * <p>Computes the dimension (number of modules on a size) of the QR Code based on the position
- * of the finder patterns and estimated module size.</p>
- */
- protected static int computeDimension(ResultPoint topLeft,
- ResultPoint topRight,
- ResultPoint bottomLeft,
- float moduleSize) throws NotFoundException {
- int tltrCentersDimension = round(ResultPoint.distance(topLeft, topRight) / moduleSize);
- int tlblCentersDimension = round(ResultPoint.distance(topLeft, bottomLeft) / moduleSize);
- int dimension = ((tltrCentersDimension + tlblCentersDimension) >> 1) + 7;
- switch (dimension & 0x03) { // mod 4
- case 0:
- dimension++;
- break;
- // 1? do nothing
- case 2:
- dimension--;
- break;
- case 3:
- throw NotFoundException.getNotFoundInstance();
- }
- return dimension;
- }
-
- /**
- * <p>Computes an average estimated module size based on estimated derived from the positions
- * of the three finder patterns.</p>
- */
- protected float calculateModuleSize(ResultPoint topLeft,
- ResultPoint topRight,
- ResultPoint bottomLeft) {
- // Take the average
- return (calculateModuleSizeOneWay(topLeft, topRight) +
- calculateModuleSizeOneWay(topLeft, bottomLeft)) / 2.0f;
- }
-
- /**
- * <p>Estimates module size based on two finder patterns -- it uses
- * {@link #sizeOfBlackWhiteBlackRunBothWays(int, int, int, int)} to figure the
- * width of each, measuring along the axis between their centers.</p>
- */
- private float calculateModuleSizeOneWay(ResultPoint pattern, ResultPoint otherPattern) {
- float moduleSizeEst1 = sizeOfBlackWhiteBlackRunBothWays((int) pattern.getX(),
- (int) pattern.getY(),
- (int) otherPattern.getX(),
- (int) otherPattern.getY());
- float moduleSizeEst2 = sizeOfBlackWhiteBlackRunBothWays((int) otherPattern.getX(),
- (int) otherPattern.getY(),
- (int) pattern.getX(),
- (int) pattern.getY());
- if (Float.isNaN(moduleSizeEst1)) {
- return moduleSizeEst2 / 7.0f;
- }
- if (Float.isNaN(moduleSizeEst2)) {
- return moduleSizeEst1 / 7.0f;
- }
- // Average them, and divide by 7 since we've counted the width of 3 black modules,
- // and 1 white and 1 black module on either side. Ergo, divide sum by 14.
- return (moduleSizeEst1 + moduleSizeEst2) / 14.0f;
- }
-
- /**
- * See {@link #sizeOfBlackWhiteBlackRun(int, int, int, int)}; computes the total width of
- * a finder pattern by looking for a black-white-black run from the center in the direction
- * of another point (another finder pattern center), and in the opposite direction too.</p>
- */
- private float sizeOfBlackWhiteBlackRunBothWays(int fromX, int fromY, int toX, int toY) {
-
- float result = sizeOfBlackWhiteBlackRun(fromX, fromY, toX, toY);
-
- // Now count other way -- don't run off image though of course
- float scale = 1.0f;
- int otherToX = fromX - (toX - fromX);
- if (otherToX < 0) {
- scale = (float) fromX / (float) (fromX - otherToX);
- otherToX = 0;
- } else if (otherToX > image.getWidth()) {
- scale = (float) (image.getWidth() - fromX) / (float) (otherToX - fromX);
- otherToX = image.getWidth();
- }
- int otherToY = (int) (fromY - (toY - fromY) * scale);
-
- scale = 1.0f;
- if (otherToY < 0) {
- scale = (float) fromY / (float) (fromY - otherToY);
- otherToY = 0;
- } else if (otherToY > image.getHeight()) {
- scale = (float) (image.getHeight() - fromY) / (float) (otherToY - fromY);
- otherToY = image.getHeight();
- }
- otherToX = (int) (fromX + (otherToX - fromX) * scale);
-
- result += sizeOfBlackWhiteBlackRun(fromX, fromY, otherToX, otherToY);
- return result;
- }
-
- /**
- * <p>This method traces a line from a point in the image, in the direction towards another point.
- * It begins in a black region, and keeps going until it finds white, then black, then white again.
- * It reports the distance from the start to this point.</p>
- *
- * <p>This is used when figuring out how wide a finder pattern is, when the finder pattern
- * may be skewed or rotated.</p>
- */
- private float sizeOfBlackWhiteBlackRun(int fromX, int fromY, int toX, int toY) {
- // Mild variant of Bresenham's algorithm;
- // see http://en.wikipedia.org/wiki/Bresenham's_line_algorithm
- boolean steep = Math.abs(toY - fromY) > Math.abs(toX - fromX);
- if (steep) {
- int temp = fromX;
- fromX = fromY;
- fromY = temp;
- temp = toX;
- toX = toY;
- toY = temp;
- }
-
- int dx = Math.abs(toX - fromX);
- int dy = Math.abs(toY - fromY);
- int error = -dx >> 1;
- int xstep = fromX < toX ? 1 : -1;
- int ystep = fromY < toY ? 1 : -1;
-
- // In black pixels, looking for white, first or second time.
- int state = 0;
- for (int x = fromX, y = fromY; x != toX; x += xstep) {
- int realX = steep ? y : x;
- int realY = steep ? x : y;
-
- // In white pixels, looking for black.
- // FIXME(dswitkin): This method seems to assume square images, which can cause these calls to
- // BitMatrix.get() to throw ArrayIndexOutOfBoundsException.
- if (state == 1) {
- if (image.get(realX, realY)) {
- state++;
- }
- } else {
- if (!image.get(realX, realY)) {
- state++;
- }
- }
-
- // Found black, white, black, and stumbled back onto white, so we're done.
- if (state == 3) {
- int diffX = x - fromX;
- int diffY = y - fromY;
- if (xstep < 0) {
- diffX++;
- }
- return (float) Math.sqrt((double) (diffX * diffX + diffY * diffY));
- }
- error += dy;
- if (error > 0) {
- if (y == toY) {
- break;
- }
- y += ystep;
- error -= dx;
- }
- }
- int diffX = toX - fromX;
- int diffY = toY - fromY;
- return (float) Math.sqrt((double) (diffX * diffX + diffY * diffY));
- }
-
- /**
- * <p>Attempts to locate an alignment pattern in a limited region of the image, which is
- * guessed to contain it. This method uses {@link AlignmentPattern}.</p>
- *
- * @param overallEstModuleSize estimated module size so far
- * @param estAlignmentX x coordinate of center of area probably containing alignment pattern
- * @param estAlignmentY y coordinate of above
- * @param allowanceFactor number of pixels in all directions to search from the center
- * @return {@link AlignmentPattern} if found, or null otherwise
- * @throws NotFoundException if an unexpected error occurs during detection
- */
- protected AlignmentPattern findAlignmentInRegion(float overallEstModuleSize,
- int estAlignmentX,
- int estAlignmentY,
- float allowanceFactor)
- throws NotFoundException {
- // Look for an alignment pattern (3 modules in size) around where it
- // should be
- int allowance = (int) (allowanceFactor * overallEstModuleSize);
- int alignmentAreaLeftX = Math.max(0, estAlignmentX - allowance);
- int alignmentAreaRightX = Math.min(image.getWidth() - 1, estAlignmentX + allowance);
- if (alignmentAreaRightX - alignmentAreaLeftX < overallEstModuleSize * 3) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- int alignmentAreaTopY = Math.max(0, estAlignmentY - allowance);
- int alignmentAreaBottomY = Math.min(image.getHeight() - 1, estAlignmentY + allowance);
- if (alignmentAreaBottomY - alignmentAreaTopY < overallEstModuleSize * 3) {
- throw NotFoundException.getNotFoundInstance();
- }
-
- AlignmentPatternFinder alignmentFinder =
- new AlignmentPatternFinder(
- image,
- alignmentAreaLeftX,
- alignmentAreaTopY,
- alignmentAreaRightX - alignmentAreaLeftX,
- alignmentAreaBottomY - alignmentAreaTopY,
- overallEstModuleSize,
- resultPointCallback);
- return alignmentFinder.find();
- }
-
- /**
- * Ends up being a bit faster than Math.round(). This merely rounds its argument to the nearest int,
- * where x.5 rounds up.
- */
- private static int round(float d) {
- return (int) (d + 0.5f);
- }
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPattern.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPattern.java
deleted file mode 100644
index 7a9914d76..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPattern.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-import com.google.zxing.ResultPoint;
-
-/**
- * <p>Encapsulates a finder pattern, which are the three square patterns found in
- * the corners of QR Codes. It also encapsulates a count of similar finder patterns,
- * as a convenience to the finder's bookkeeping.</p>
- *
- * @author Sean Owen
- */
-public final class FinderPattern extends ResultPoint {
-
- private final float estimatedModuleSize;
- private int count;
-
- FinderPattern(float posX, float posY, float estimatedModuleSize) {
- super(posX, posY);
- this.estimatedModuleSize = estimatedModuleSize;
- this.count = 1;
- }
-
- public float getEstimatedModuleSize() {
- return estimatedModuleSize;
- }
-
- int getCount() {
- return count;
- }
-
- void incrementCount() {
- this.count++;
- }
-
- /**
- * <p>Determines if this finder pattern "about equals" a finder pattern at the stated
- * position and size -- meaning, it is at nearly the same center with nearly the same size.</p>
- */
- boolean aboutEquals(float moduleSize, float i, float j) {
- if (Math.abs(i - getY()) <= moduleSize && Math.abs(j - getX()) <= moduleSize) {
- float moduleSizeDiff = Math.abs(moduleSize - estimatedModuleSize);
- return moduleSizeDiff <= 1.0f || moduleSizeDiff / estimatedModuleSize <= 1.0f;
- }
- return false;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java
deleted file mode 100644
index 01b3bde2a..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternFinder.java
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-import com.google.zxing.DecodeHintType;
-import com.google.zxing.NotFoundException;
-import com.google.zxing.ResultPoint;
-import com.google.zxing.ResultPointCallback;
-import com.google.zxing.common.BitMatrix;
-import com.google.zxing.common.Collections;
-import com.google.zxing.common.Comparator;
-
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * <p>This class attempts to find finder patterns in a QR Code. Finder patterns are the square
- * markers at three corners of a QR Code.</p>
- *
- * <p>This class is thread-safe but not reentrant. Each thread must allocate its own object.
- *
- * @author Sean Owen
- */
-public class FinderPatternFinder {
-
- private static final int CENTER_QUORUM = 2;
- protected static final int MIN_SKIP = 3; // 1 pixel/module times 3 modules/center
- protected static final int MAX_MODULES = 57; // support up to version 10 for mobile clients
- private static final int INTEGER_MATH_SHIFT = 8;
-
- private final BitMatrix image;
- private final Vector possibleCenters;
- private boolean hasSkipped;
- private final int[] crossCheckStateCount;
- private final ResultPointCallback resultPointCallback;
-
- /**
- * <p>Creates a finder that will search the image for three finder patterns.</p>
- *
- * @param image image to search
- */
- public FinderPatternFinder(BitMatrix image) {
- this(image, null);
- }
-
- public FinderPatternFinder(BitMatrix image, ResultPointCallback resultPointCallback) {
- this.image = image;
- this.possibleCenters = new Vector();
- this.crossCheckStateCount = new int[5];
- this.resultPointCallback = resultPointCallback;
- }
-
- protected BitMatrix getImage() {
- return image;
- }
-
- protected Vector getPossibleCenters() {
- return possibleCenters;
- }
-
- FinderPatternInfo find(Hashtable hints) throws NotFoundException {
- boolean tryHarder = hints != null && hints.containsKey(DecodeHintType.TRY_HARDER);
- int maxI = image.getHeight();
- int maxJ = image.getWidth();
- // We are looking for black/white/black/white/black modules in
- // 1:1:3:1:1 ratio; this tracks the number of such modules seen so far
-
- // Let's assume that the maximum version QR Code we support takes up 1/4 the height of the
- // image, and then account for the center being 3 modules in size. This gives the smallest
- // number of pixels the center could be, so skip this often. When trying harder, look for all
- // QR versions regardless of how dense they are.
- int iSkip = (3 * maxI) / (4 * MAX_MODULES);
- if (iSkip < MIN_SKIP || tryHarder) {
- iSkip = MIN_SKIP;
- }
-
- boolean done = false;
- int[] stateCount = new int[5];
- for (int i = iSkip - 1; i < maxI && !done; i += iSkip) {
- // Get a row of black/white values
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
- stateCount[3] = 0;
- stateCount[4] = 0;
- int currentState = 0;
- for (int j = 0; j < maxJ; j++) {
- if (image.get(j, i)) {
- // Black pixel
- if ((currentState & 1) == 1) { // Counting white pixels
- currentState++;
- }
- stateCount[currentState]++;
- } else { // White pixel
- if ((currentState & 1) == 0) { // Counting black pixels
- if (currentState == 4) { // A winner?
- if (foundPatternCross(stateCount)) { // Yes
- boolean confirmed = handlePossibleCenter(stateCount, i, j);
- if (confirmed) {
- // Start examining every other line. Checking each line turned out to be too
- // expensive and didn't improve performance.
- iSkip = 2;
- if (hasSkipped) {
- done = haveMultiplyConfirmedCenters();
- } else {
- int rowSkip = findRowSkip();
- if (rowSkip > stateCount[2]) {
- // Skip rows between row of lower confirmed center
- // and top of presumed third confirmed center
- // but back up a bit to get a full chance of detecting
- // it, entire width of center of finder pattern
-
- // Skip by rowSkip, but back off by stateCount[2] (size of last center
- // of pattern we saw) to be conservative, and also back off by iSkip which
- // is about to be re-added
- i += rowSkip - stateCount[2] - iSkip;
- j = maxJ - 1;
- }
- }
- } else {
- stateCount[0] = stateCount[2];
- stateCount[1] = stateCount[3];
- stateCount[2] = stateCount[4];
- stateCount[3] = 1;
- stateCount[4] = 0;
- currentState = 3;
- continue;
- }
- // Clear state to start looking again
- currentState = 0;
- stateCount[0] = 0;
- stateCount[1] = 0;
- stateCount[2] = 0;
- stateCount[3] = 0;
- stateCount[4] = 0;
- } else { // No, shift counts back by two
- stateCount[0] = stateCount[2];
- stateCount[1] = stateCount[3];
- stateCount[2] = stateCount[4];
- stateCount[3] = 1;
- stateCount[4] = 0;
- currentState = 3;
- }
- } else {
- stateCount[++currentState]++;
- }
- } else { // Counting white pixels
- stateCount[currentState]++;
- }
- }
- }
- if (foundPatternCross(stateCount)) {
- boolean confirmed = handlePossibleCenter(stateCount, i, maxJ);
- if (confirmed) {
- iSkip = stateCount[0];
- if (hasSkipped) {
- // Found a third one
- done = haveMultiplyConfirmedCenters();
- }
- }
- }
- }
-
- FinderPattern[] patternInfo = selectBestPatterns();
- ResultPoint.orderBestPatterns(patternInfo);
-
- return new FinderPatternInfo(patternInfo);
- }
-
- /**
- * Given a count of black/white/black/white/black pixels just seen and an end position,
- * figures the location of the center of this run.
- */
- private static float centerFromEnd(int[] stateCount, int end) {
- return (float) (end - stateCount[4] - stateCount[3]) - stateCount[2] / 2.0f;
- }
-
- /**
- * @param stateCount count of black/white/black/white/black pixels just read
- * @return true iff the proportions of the counts is close enough to the 1/1/3/1/1 ratios
- * used by finder patterns to be considered a match
- */
- protected static boolean foundPatternCross(int[] stateCount) {
- int totalModuleSize = 0;
- for (int i = 0; i < 5; i++) {
- int count = stateCount[i];
- if (count == 0) {
- return false;
- }
- totalModuleSize += count;
- }
- if (totalModuleSize < 7) {
- return false;
- }
- int moduleSize = (totalModuleSize << INTEGER_MATH_SHIFT) / 7;
- int maxVariance = moduleSize / 2;
- // Allow less than 50% variance from 1-1-3-1-1 proportions
- return Math.abs(moduleSize - (stateCount[0] << INTEGER_MATH_SHIFT)) < maxVariance &&
- Math.abs(moduleSize - (stateCount[1] << INTEGER_MATH_SHIFT)) < maxVariance &&
- Math.abs(3 * moduleSize - (stateCount[2] << INTEGER_MATH_SHIFT)) < 3 * maxVariance &&
- Math.abs(moduleSize - (stateCount[3] << INTEGER_MATH_SHIFT)) < maxVariance &&
- Math.abs(moduleSize - (stateCount[4] << INTEGER_MATH_SHIFT)) < maxVariance;
- }
-
- private int[] getCrossCheckStateCount() {
- crossCheckStateCount[0] = 0;
- crossCheckStateCount[1] = 0;
- crossCheckStateCount[2] = 0;
- crossCheckStateCount[3] = 0;
- crossCheckStateCount[4] = 0;
- return crossCheckStateCount;
- }
-
- /**
- * <p>After a horizontal scan finds a potential finder pattern, this method
- * "cross-checks" by scanning down vertically through the center of the possible
- * finder pattern to see if the same proportion is detected.</p>
- *
- * @param startI row where a finder pattern was detected
- * @param centerJ center of the section that appears to cross a finder pattern
- * @param maxCount maximum reasonable number of modules that should be
- * observed in any reading state, based on the results of the horizontal scan
- * @return vertical center of finder pattern, or {@link Float#NaN} if not found
- */
- private float crossCheckVertical(int startI, int centerJ, int maxCount,
- int originalStateCountTotal) {
- BitMatrix image = this.image;
-
- int maxI = image.getHeight();
- int[] stateCount = getCrossCheckStateCount();
-
- // Start counting up from center
- int i = startI;
- while (i >= 0 && image.get(centerJ, i)) {
- stateCount[2]++;
- i--;
- }
- if (i < 0) {
- return Float.NaN;
- }
- while (i >= 0 && !image.get(centerJ, i) && stateCount[1] <= maxCount) {
- stateCount[1]++;
- i--;
- }
- // If already too many modules in this state or ran off the edge:
- if (i < 0 || stateCount[1] > maxCount) {
- return Float.NaN;
- }
- while (i >= 0 && image.get(centerJ, i) && stateCount[0] <= maxCount) {
- stateCount[0]++;
- i--;
- }
- if (stateCount[0] > maxCount) {
- return Float.NaN;
- }
-
- // Now also count down from center
- i = startI + 1;
- while (i < maxI && image.get(centerJ, i)) {
- stateCount[2]++;
- i++;
- }
- if (i == maxI) {
- return Float.NaN;
- }
- while (i < maxI && !image.get(centerJ, i) && stateCount[3] < maxCount) {
- stateCount[3]++;
- i++;
- }
- if (i == maxI || stateCount[3] >= maxCount) {
- return Float.NaN;
- }
- while (i < maxI && image.get(centerJ, i) && stateCount[4] < maxCount) {
- stateCount[4]++;
- i++;
- }
- if (stateCount[4] >= maxCount) {
- return Float.NaN;
- }
-
- // If we found a finder-pattern-like section, but its size is more than 40% different than
- // the original, assume it's a false positive
- int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +
- stateCount[4];
- if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= 2 * originalStateCountTotal) {
- return Float.NaN;
- }
-
- return foundPatternCross(stateCount) ? centerFromEnd(stateCount, i) : Float.NaN;
- }
-
- /**
- * <p>Like {@link #crossCheckVertical(int, int, int, int)}, and in fact is basically identical,
- * except it reads horizontally instead of vertically. This is used to cross-cross
- * check a vertical cross check and locate the real center of the alignment pattern.</p>
- */
- private float crossCheckHorizontal(int startJ, int centerI, int maxCount,
- int originalStateCountTotal) {
- BitMatrix image = this.image;
-
- int maxJ = image.getWidth();
- int[] stateCount = getCrossCheckStateCount();
-
- int j = startJ;
- while (j >= 0 && image.get(j, centerI)) {
- stateCount[2]++;
- j--;
- }
- if (j < 0) {
- return Float.NaN;
- }
- while (j >= 0 && !image.get(j, centerI) && stateCount[1] <= maxCount) {
- stateCount[1]++;
- j--;
- }
- if (j < 0 || stateCount[1] > maxCount) {
- return Float.NaN;
- }
- while (j >= 0 && image.get(j, centerI) && stateCount[0] <= maxCount) {
- stateCount[0]++;
- j--;
- }
- if (stateCount[0] > maxCount) {
- return Float.NaN;
- }
-
- j = startJ + 1;
- while (j < maxJ && image.get(j, centerI)) {
- stateCount[2]++;
- j++;
- }
- if (j == maxJ) {
- return Float.NaN;
- }
- while (j < maxJ && !image.get(j, centerI) && stateCount[3] < maxCount) {
- stateCount[3]++;
- j++;
- }
- if (j == maxJ || stateCount[3] >= maxCount) {
- return Float.NaN;
- }
- while (j < maxJ && image.get(j, centerI) && stateCount[4] < maxCount) {
- stateCount[4]++;
- j++;
- }
- if (stateCount[4] >= maxCount) {
- return Float.NaN;
- }
-
- // If we found a finder-pattern-like section, but its size is significantly different than
- // the original, assume it's a false positive
- int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +
- stateCount[4];
- if (5 * Math.abs(stateCountTotal - originalStateCountTotal) >= originalStateCountTotal) {
- return Float.NaN;
- }
-
- return foundPatternCross(stateCount) ? centerFromEnd(stateCount, j) : Float.NaN;
- }
-
- /**
- * <p>This is called when a horizontal scan finds a possible alignment pattern. It will
- * cross check with a vertical scan, and if successful, will, ah, cross-cross-check
- * with another horizontal scan. This is needed primarily to locate the real horizontal
- * center of the pattern in cases of extreme skew.</p>
- *
- * <p>If that succeeds the finder pattern location is added to a list that tracks
- * the number of times each location has been nearly-matched as a finder pattern.
- * Each additional find is more evidence that the location is in fact a finder
- * pattern center
- *
- * @param stateCount reading state module counts from horizontal scan
- * @param i row where finder pattern may be found
- * @param j end of possible finder pattern in row
- * @return true if a finder pattern candidate was found this time
- */
- protected boolean handlePossibleCenter(int[] stateCount, int i, int j) {
- int stateCountTotal = stateCount[0] + stateCount[1] + stateCount[2] + stateCount[3] +
- stateCount[4];
- float centerJ = centerFromEnd(stateCount, j);
- float centerI = crossCheckVertical(i, (int) centerJ, stateCount[2], stateCountTotal);
- if (!Float.isNaN(centerI)) {
- // Re-cross check
- centerJ = crossCheckHorizontal((int) centerJ, (int) centerI, stateCount[2], stateCountTotal);
- if (!Float.isNaN(centerJ)) {
- float estimatedModuleSize = (float) stateCountTotal / 7.0f;
- boolean found = false;
- int max = possibleCenters.size();
- for (int index = 0; index < max; index++) {
- FinderPattern center = (FinderPattern) possibleCenters.elementAt(index);
- // Look for about the same center and module size:
- if (center.aboutEquals(estimatedModuleSize, centerI, centerJ)) {
- center.incrementCount();
- found = true;
- break;
- }
- }
- if (!found) {
- ResultPoint point = new FinderPattern(centerJ, centerI, estimatedModuleSize);
- possibleCenters.addElement(point);
- if (resultPointCallback != null) {
- resultPointCallback.foundPossibleResultPoint(point);
- }
- }
- return true;
- }
- }
- return false;
- }
-
- /**
- * @return number of rows we could safely skip during scanning, based on the first
- * two finder patterns that have been located. In some cases their position will
- * allow us to infer that the third pattern must lie below a certain point farther
- * down in the image.
- */
- private int findRowSkip() {
- int max = possibleCenters.size();
- if (max <= 1) {
- return 0;
- }
- FinderPattern firstConfirmedCenter = null;
- for (int i = 0; i < max; i++) {
- FinderPattern center = (FinderPattern) possibleCenters.elementAt(i);
- if (center.getCount() >= CENTER_QUORUM) {
- if (firstConfirmedCenter == null) {
- firstConfirmedCenter = center;
- } else {
- // We have two confirmed centers
- // How far down can we skip before resuming looking for the next
- // pattern? In the worst case, only the difference between the
- // difference in the x / y coordinates of the two centers.
- // This is the case where you find top left last.
- hasSkipped = true;
- return (int) (Math.abs(firstConfirmedCenter.getX() - center.getX()) -
- Math.abs(firstConfirmedCenter.getY() - center.getY())) / 2;
- }
- }
- }
- return 0;
- }
-
- /**
- * @return true iff we have found at least 3 finder patterns that have been detected
- * at least {@link #CENTER_QUORUM} times each, and, the estimated module size of the
- * candidates is "pretty similar"
- */
- private boolean haveMultiplyConfirmedCenters() {
- int confirmedCount = 0;
- float totalModuleSize = 0.0f;
- int max = possibleCenters.size();
- for (int i = 0; i < max; i++) {
- FinderPattern pattern = (FinderPattern) possibleCenters.elementAt(i);
- if (pattern.getCount() >= CENTER_QUORUM) {
- confirmedCount++;
- totalModuleSize += pattern.getEstimatedModuleSize();
- }
- }
- if (confirmedCount < 3) {
- return false;
- }
- // OK, we have at least 3 confirmed centers, but, it's possible that one is a "false positive"
- // and that we need to keep looking. We detect this by asking if the estimated module sizes
- // vary too much. We arbitrarily say that when the total deviation from average exceeds
- // 5% of the total module size estimates, it's too much.
- float average = totalModuleSize / (float) max;
- float totalDeviation = 0.0f;
- for (int i = 0; i < max; i++) {
- FinderPattern pattern = (FinderPattern) possibleCenters.elementAt(i);
- totalDeviation += Math.abs(pattern.getEstimatedModuleSize() - average);
- }
- return totalDeviation <= 0.05f * totalModuleSize;
- }
-
- /**
- * @return the 3 best {@link FinderPattern}s from our list of candidates. The "best" are
- * those that have been detected at least {@link #CENTER_QUORUM} times, and whose module
- * size differs from the average among those patterns the least
- * @throws NotFoundException if 3 such finder patterns do not exist
- */
- private FinderPattern[] selectBestPatterns() throws NotFoundException {
-
- int startSize = possibleCenters.size();
- if (startSize < 3) {
- // Couldn't find enough finder patterns
- throw NotFoundException.getNotFoundInstance();
- }
-
- // Filter outlier possibilities whose module size is too different
- if (startSize > 3) {
- // But we can only afford to do so if we have at least 4 possibilities to choose from
- float totalModuleSize = 0.0f;
- float square = 0.0f;
- for (int i = 0; i < startSize; i++) {
- float size = ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize();
- totalModuleSize += size;
- square += size * size;
- }
- float average = totalModuleSize / (float) startSize;
- float stdDev = (float) Math.sqrt(square / startSize - average * average);
-
- Collections.insertionSort(possibleCenters, new FurthestFromAverageComparator(average));
-
- float limit = Math.max(0.2f * average, stdDev);
-
- for (int i = 0; i < possibleCenters.size() && possibleCenters.size() > 3; i++) {
- FinderPattern pattern = (FinderPattern) possibleCenters.elementAt(i);
- if (Math.abs(pattern.getEstimatedModuleSize() - average) > limit) {
- possibleCenters.removeElementAt(i);
- i--;
- }
- }
- }
-
- if (possibleCenters.size() > 3) {
- // Throw away all but those first size candidate points we found.
-
- float totalModuleSize = 0.0f;
- for (int i = 0; i < possibleCenters.size(); i++) {
- totalModuleSize += ((FinderPattern) possibleCenters.elementAt(i)).getEstimatedModuleSize();
- }
-
- float average = totalModuleSize / (float) possibleCenters.size();
-
- Collections.insertionSort(possibleCenters, new CenterComparator(average));
-
- possibleCenters.setSize(3);
- }
-
- return new FinderPattern[]{
- (FinderPattern) possibleCenters.elementAt(0),
- (FinderPattern) possibleCenters.elementAt(1),
- (FinderPattern) possibleCenters.elementAt(2)
- };
- }
-
- /**
- * <p>Orders by furthest from average</p>
- */
- private static class FurthestFromAverageComparator implements Comparator {
- private final float average;
- private FurthestFromAverageComparator(float f) {
- average = f;
- }
- public int compare(Object center1, Object center2) {
- float dA = Math.abs(((FinderPattern) center2).getEstimatedModuleSize() - average);
- float dB = Math.abs(((FinderPattern) center1).getEstimatedModuleSize() - average);
- return dA < dB ? -1 : dA == dB ? 0 : 1;
- }
- }
-
- /**
- * <p>Orders by {@link FinderPattern#getCount()}, descending.</p>
- */
- private static class CenterComparator implements Comparator {
- private final float average;
- private CenterComparator(float f) {
- average = f;
- }
- public int compare(Object center1, Object center2) {
- if (((FinderPattern) center2).getCount() == ((FinderPattern) center1).getCount()) {
- float dA = Math.abs(((FinderPattern) center2).getEstimatedModuleSize() - average);
- float dB = Math.abs(((FinderPattern) center1).getEstimatedModuleSize() - average);
- return dA < dB ? 1 : dA == dB ? 0 : -1;
- } else {
- return ((FinderPattern) center2).getCount() - ((FinderPattern) center1).getCount();
- }
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternInfo.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternInfo.java
deleted file mode 100644
index 3c3401085..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/detector/FinderPatternInfo.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2007 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.detector;
-
-/**
- * <p>Encapsulates information about finder patterns in an image, including the location of
- * the three finder patterns, and their estimated module size.</p>
- *
- * @author Sean Owen
- */
-public final class FinderPatternInfo {
-
- private final FinderPattern bottomLeft;
- private final FinderPattern topLeft;
- private final FinderPattern topRight;
-
- public FinderPatternInfo(FinderPattern[] patternCenters) {
- this.bottomLeft = patternCenters[0];
- this.topLeft = patternCenters[1];
- this.topRight = patternCenters[2];
- }
-
- public FinderPattern getBottomLeft() {
- return bottomLeft;
- }
-
- public FinderPattern getTopLeft() {
- return topLeft;
- }
-
- public FinderPattern getTopRight() {
- return topRight;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/BlockPair.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/BlockPair.java
deleted file mode 100644
index 5714d9c3a..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/BlockPair.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-final class BlockPair {
-
- private final byte[] dataBytes;
- private final byte[] errorCorrectionBytes;
-
- BlockPair(byte[] data, byte[] errorCorrection) {
- dataBytes = data;
- errorCorrectionBytes = errorCorrection;
- }
-
- public byte[] getDataBytes() {
- return dataBytes;
- }
-
- public byte[] getErrorCorrectionBytes() {
- return errorCorrectionBytes;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/ByteMatrix.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/ByteMatrix.java
deleted file mode 100644
index eb248a26c..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/ByteMatrix.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-/**
- * A class which wraps a 2D array of bytes. The default usage is signed. If you want to use it as a
- * unsigned container, it's up to you to do byteValue & 0xff at each location.
- *
- * JAVAPORT: The original code was a 2D array of ints, but since it only ever gets assigned
- * -1, 0, and 1, I'm going to use less memory and go with bytes.
- *
- * @author dswitkin@google.com (Daniel Switkin)
- */
-public final class ByteMatrix {
-
- private final byte[][] bytes;
- private final int width;
- private final int height;
-
- public ByteMatrix(int width, int height) {
- bytes = new byte[height][width];
- this.width = width;
- this.height = height;
- }
-
- public int getHeight() {
- return height;
- }
-
- public int getWidth() {
- return width;
- }
-
- public byte get(int x, int y) {
- return bytes[y][x];
- }
-
- public byte[][] getArray() {
- return bytes;
- }
-
- public void set(int x, int y, byte value) {
- bytes[y][x] = value;
- }
-
- public void set(int x, int y, int value) {
- bytes[y][x] = (byte) value;
- }
-
- public void set(int x, int y, boolean value) {
- bytes[y][x] = (byte) (value ? 1 : 0);
- }
-
- public void clear(byte value) {
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- bytes[y][x] = value;
- }
- }
- }
-
- public String toString() {
- StringBuffer result = new StringBuffer(2 * width * height + 2);
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- switch (bytes[y][x]) {
- case 0:
- result.append(" 0");
- break;
- case 1:
- result.append(" 1");
- break;
- default:
- result.append(" ");
- break;
- }
- }
- result.append('\n');
- }
- return result.toString();
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/Encoder.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/Encoder.java
deleted file mode 100644
index 8796511ab..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/Encoder.java
+++ /dev/null
@@ -1,557 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-import com.google.zxing.EncodeHintType;
-import com.google.zxing.WriterException;
-import com.google.zxing.common.BitArray;
-import com.google.zxing.common.CharacterSetECI;
-import com.google.zxing.common.ECI;
-import com.google.zxing.common.reedsolomon.GenericGF;
-import com.google.zxing.common.reedsolomon.ReedSolomonEncoder;
-import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-import com.google.zxing.qrcode.decoder.Mode;
-import com.google.zxing.qrcode.decoder.Version;
-
-import java.io.UnsupportedEncodingException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-/**
- * @author satorux@google.com (Satoru Takabayashi) - creator
- * @author dswitkin@google.com (Daniel Switkin) - ported from C++
- */
-public final class Encoder {
-
- // The original table is defined in the table 5 of JISX0510:2004 (p.19).
- private static final int[] ALPHANUMERIC_TABLE = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x00-0x0f
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, // 0x10-0x1f
- 36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43, // 0x20-0x2f
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1, // 0x30-0x3f
- -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, // 0x40-0x4f
- 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1, // 0x50-0x5f
- };
-
- static final String DEFAULT_BYTE_MODE_ENCODING = "ISO-8859-1";
-
- private Encoder() {
- }
-
- // The mask penalty calculation is complicated. See Table 21 of JISX0510:2004 (p.45) for details.
- // Basically it applies four rules and summate all penalties.
- private static int calculateMaskPenalty(ByteMatrix matrix) {
- int penalty = 0;
- penalty += MaskUtil.applyMaskPenaltyRule1(matrix);
- penalty += MaskUtil.applyMaskPenaltyRule2(matrix);
- penalty += MaskUtil.applyMaskPenaltyRule3(matrix);
- penalty += MaskUtil.applyMaskPenaltyRule4(matrix);
- return penalty;
- }
-
- /**
- * Encode "bytes" with the error correction level "ecLevel". The encoding mode will be chosen
- * internally by chooseMode(). On success, store the result in "qrCode".
- *
- * We recommend you to use QRCode.EC_LEVEL_L (the lowest level) for
- * "getECLevel" since our primary use is to show QR code on desktop screens. We don't need very
- * strong error correction for this purpose.
- *
- * Note that there is no way to encode bytes in MODE_KANJI. We might want to add EncodeWithMode()
- * with which clients can specify the encoding mode. For now, we don't need the functionality.
- */
- public static void encode(String content, ErrorCorrectionLevel ecLevel, QRCode qrCode)
- throws WriterException {
- encode(content, ecLevel, null, qrCode);
- }
-
- public static void encode(String content, ErrorCorrectionLevel ecLevel, Hashtable hints,
- QRCode qrCode) throws WriterException {
-
- String encoding = hints == null ? null : (String) hints.get(EncodeHintType.CHARACTER_SET);
- if (encoding == null) {
- encoding = DEFAULT_BYTE_MODE_ENCODING;
- }
-
- // Step 1: Choose the mode (encoding).
- Mode mode = chooseMode(content, encoding);
-
- // Step 2: Append "bytes" into "dataBits" in appropriate encoding.
- BitArray dataBits = new BitArray();
- appendBytes(content, mode, dataBits, encoding);
- // Step 3: Initialize QR code that can contain "dataBits".
- int numInputBytes = dataBits.getSizeInBytes();
- initQRCode(numInputBytes, ecLevel, mode, qrCode);
-
- // Step 4: Build another bit vector that contains header and data.
- BitArray headerAndDataBits = new BitArray();
-
- // Step 4.5: Append ECI message if applicable
- if (mode == Mode.BYTE && !DEFAULT_BYTE_MODE_ENCODING.equals(encoding)) {
- CharacterSetECI eci = CharacterSetECI.getCharacterSetECIByName(encoding);
- if (eci != null) {
- appendECI(eci, headerAndDataBits);
- }
- }
-
- appendModeInfo(mode, headerAndDataBits);
-
- int numLetters = mode.equals(Mode.BYTE) ? dataBits.getSizeInBytes() : content.length();
- appendLengthInfo(numLetters, qrCode.getVersion(), mode, headerAndDataBits);
- headerAndDataBits.appendBitArray(dataBits);
-
- // Step 5: Terminate the bits properly.
- terminateBits(qrCode.getNumDataBytes(), headerAndDataBits);
-
- // Step 6: Interleave data bits with error correction code.
- BitArray finalBits = new BitArray();
- interleaveWithECBytes(headerAndDataBits, qrCode.getNumTotalBytes(), qrCode.getNumDataBytes(),
- qrCode.getNumRSBlocks(), finalBits);
-
- // Step 7: Choose the mask pattern and set to "qrCode".
- ByteMatrix matrix = new ByteMatrix(qrCode.getMatrixWidth(), qrCode.getMatrixWidth());
- qrCode.setMaskPattern(chooseMaskPattern(finalBits, qrCode.getECLevel(), qrCode.getVersion(),
- matrix));
-
- // Step 8. Build the matrix and set it to "qrCode".
- MatrixUtil.buildMatrix(finalBits, qrCode.getECLevel(), qrCode.getVersion(),
- qrCode.getMaskPattern(), matrix);
- qrCode.setMatrix(matrix);
- // Step 9. Make sure we have a valid QR Code.
- if (!qrCode.isValid()) {
- throw new WriterException("Invalid QR code: " + qrCode.toString());
- }
- }
-
- /**
- * @return the code point of the table used in alphanumeric mode or
- * -1 if there is no corresponding code in the table.
- */
- static int getAlphanumericCode(int code) {
- if (code < ALPHANUMERIC_TABLE.length) {
- return ALPHANUMERIC_TABLE[code];
- }
- return -1;
- }
-
- public static Mode chooseMode(String content) {
- return chooseMode(content, null);
- }
-
- /**
- * Choose the best mode by examining the content. Note that 'encoding' is used as a hint;
- * if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.
- */
- public static Mode chooseMode(String content, String encoding) {
- if ("Shift_JIS".equals(encoding)) {
- // Choose Kanji mode if all input are double-byte characters
- return isOnlyDoubleByteKanji(content) ? Mode.KANJI : Mode.BYTE;
- }
- boolean hasNumeric = false;
- boolean hasAlphanumeric = false;
- for (int i = 0; i < content.length(); ++i) {
- char c = content.charAt(i);
- if (c >= '0' && c <= '9') {
- hasNumeric = true;
- } else if (getAlphanumericCode(c) != -1) {
- hasAlphanumeric = true;
- } else {
- return Mode.BYTE;
- }
- }
- if (hasAlphanumeric) {
- return Mode.ALPHANUMERIC;
- } else if (hasNumeric) {
- return Mode.NUMERIC;
- }
- return Mode.BYTE;
- }
-
- private static boolean isOnlyDoubleByteKanji(String content) {
- byte[] bytes;
- try {
- bytes = content.getBytes("Shift_JIS");
- } catch (UnsupportedEncodingException uee) {
- return false;
- }
- int length = bytes.length;
- if (length % 2 != 0) {
- return false;
- }
- for (int i = 0; i < length; i += 2) {
- int byte1 = bytes[i] & 0xFF;
- if ((byte1 < 0x81 || byte1 > 0x9F) && (byte1 < 0xE0 || byte1 > 0xEB)) {
- return false;
- }
- }
- return true;
- }
-
- private static int chooseMaskPattern(BitArray bits, ErrorCorrectionLevel ecLevel, int version,
- ByteMatrix matrix) throws WriterException {
-
- int minPenalty = Integer.MAX_VALUE; // Lower penalty is better.
- int bestMaskPattern = -1;
- // We try all mask patterns to choose the best one.
- for (int maskPattern = 0; maskPattern < QRCode.NUM_MASK_PATTERNS; maskPattern++) {
- MatrixUtil.buildMatrix(bits, ecLevel, version, maskPattern, matrix);
- int penalty = calculateMaskPenalty(matrix);
- if (penalty < minPenalty) {
- minPenalty = penalty;
- bestMaskPattern = maskPattern;
- }
- }
- return bestMaskPattern;
- }
-
- /**
- * Initialize "qrCode" according to "numInputBytes", "ecLevel", and "mode". On success,
- * modify "qrCode".
- */
- private static void initQRCode(int numInputBytes, ErrorCorrectionLevel ecLevel, Mode mode,
- QRCode qrCode) throws WriterException {
- qrCode.setECLevel(ecLevel);
- qrCode.setMode(mode);
-
- // In the following comments, we use numbers of Version 7-H.
- for (int versionNum = 1; versionNum <= 40; versionNum++) {
- Version version = Version.getVersionForNumber(versionNum);
- // numBytes = 196
- int numBytes = version.getTotalCodewords();
- // getNumECBytes = 130
- Version.ECBlocks ecBlocks = version.getECBlocksForLevel(ecLevel);
- int numEcBytes = ecBlocks.getTotalECCodewords();
- // getNumRSBlocks = 5
- int numRSBlocks = ecBlocks.getNumBlocks();
- // getNumDataBytes = 196 - 130 = 66
- int numDataBytes = numBytes - numEcBytes;
- // We want to choose the smallest version which can contain data of "numInputBytes" + some
- // extra bits for the header (mode info and length info). The header can be three bytes
- // (precisely 4 + 16 bits) at most. Hence we do +3 here.
- if (numDataBytes >= numInputBytes + 3) {
- // Yay, we found the proper rs block info!
- qrCode.setVersion(versionNum);
- qrCode.setNumTotalBytes(numBytes);
- qrCode.setNumDataBytes(numDataBytes);
- qrCode.setNumRSBlocks(numRSBlocks);
- // getNumECBytes = 196 - 66 = 130
- qrCode.setNumECBytes(numEcBytes);
- // matrix width = 21 + 6 * 4 = 45
- qrCode.setMatrixWidth(version.getDimensionForVersion());
- return;
- }
- }
- throw new WriterException("Cannot find proper rs block info (input data too big?)");
- }
-
- /**
- * Terminate bits as described in 8.4.8 and 8.4.9 of JISX0510:2004 (p.24).
- */
- static void terminateBits(int numDataBytes, BitArray bits) throws WriterException {
- int capacity = numDataBytes << 3;
- if (bits.getSize() > capacity) {
- throw new WriterException("data bits cannot fit in the QR Code" + bits.getSize() + " > " +
- capacity);
- }
- for (int i = 0; i < 4 && bits.getSize() < capacity; ++i) {
- bits.appendBit(false);
- }
- // Append termination bits. See 8.4.8 of JISX0510:2004 (p.24) for details.
- // If the last byte isn't 8-bit aligned, we'll add padding bits.
- int numBitsInLastByte = bits.getSize() & 0x07;
- if (numBitsInLastByte > 0) {
- for (int i = numBitsInLastByte; i < 8; i++) {
- bits.appendBit(false);
- }
- }
- // If we have more space, we'll fill the space with padding patterns defined in 8.4.9 (p.24).
- int numPaddingBytes = numDataBytes - bits.getSizeInBytes();
- for (int i = 0; i < numPaddingBytes; ++i) {
- bits.appendBits((i & 0x01) == 0 ? 0xEC : 0x11, 8);
- }
- if (bits.getSize() != capacity) {
- throw new WriterException("Bits size does not equal capacity");
- }
- }
-
- /**
- * Get number of data bytes and number of error correction bytes for block id "blockID". Store
- * the result in "numDataBytesInBlock", and "numECBytesInBlock". See table 12 in 8.5.1 of
- * JISX0510:2004 (p.30)
- */
- static void getNumDataBytesAndNumECBytesForBlockID(int numTotalBytes, int numDataBytes,
- int numRSBlocks, int blockID, int[] numDataBytesInBlock,
- int[] numECBytesInBlock) throws WriterException {
- if (blockID >= numRSBlocks) {
- throw new WriterException("Block ID too large");
- }
- // numRsBlocksInGroup2 = 196 % 5 = 1
- int numRsBlocksInGroup2 = numTotalBytes % numRSBlocks;
- // numRsBlocksInGroup1 = 5 - 1 = 4
- int numRsBlocksInGroup1 = numRSBlocks - numRsBlocksInGroup2;
- // numTotalBytesInGroup1 = 196 / 5 = 39
- int numTotalBytesInGroup1 = numTotalBytes / numRSBlocks;
- // numTotalBytesInGroup2 = 39 + 1 = 40
- int numTotalBytesInGroup2 = numTotalBytesInGroup1 + 1;
- // numDataBytesInGroup1 = 66 / 5 = 13
- int numDataBytesInGroup1 = numDataBytes / numRSBlocks;
- // numDataBytesInGroup2 = 13 + 1 = 14
- int numDataBytesInGroup2 = numDataBytesInGroup1 + 1;
- // numEcBytesInGroup1 = 39 - 13 = 26
- int numEcBytesInGroup1 = numTotalBytesInGroup1 - numDataBytesInGroup1;
- // numEcBytesInGroup2 = 40 - 14 = 26
- int numEcBytesInGroup2 = numTotalBytesInGroup2 - numDataBytesInGroup2;
- // Sanity checks.
- // 26 = 26
- if (numEcBytesInGroup1 != numEcBytesInGroup2) {
- throw new WriterException("EC bytes mismatch");
- }
- // 5 = 4 + 1.
- if (numRSBlocks != numRsBlocksInGroup1 + numRsBlocksInGroup2) {
- throw new WriterException("RS blocks mismatch");
- }
- // 196 = (13 + 26) * 4 + (14 + 26) * 1
- if (numTotalBytes !=
- ((numDataBytesInGroup1 + numEcBytesInGroup1) *
- numRsBlocksInGroup1) +
- ((numDataBytesInGroup2 + numEcBytesInGroup2) *
- numRsBlocksInGroup2)) {
- throw new WriterException("Total bytes mismatch");
- }
-
- if (blockID < numRsBlocksInGroup1) {
- numDataBytesInBlock[0] = numDataBytesInGroup1;
- numECBytesInBlock[0] = numEcBytesInGroup1;
- } else {
- numDataBytesInBlock[0] = numDataBytesInGroup2;
- numECBytesInBlock[0] = numEcBytesInGroup2;
- }
- }
-
- /**
- * Interleave "bits" with corresponding error correction bytes. On success, store the result in
- * "result". The interleave rule is complicated. See 8.6 of JISX0510:2004 (p.37) for details.
- */
- static void interleaveWithECBytes(BitArray bits, int numTotalBytes,
- int numDataBytes, int numRSBlocks, BitArray result) throws WriterException {
-
- // "bits" must have "getNumDataBytes" bytes of data.
- if (bits.getSizeInBytes() != numDataBytes) {
- throw new WriterException("Number of bits and data bytes does not match");
- }
-
- // Step 1. Divide data bytes into blocks and generate error correction bytes for them. We'll
- // store the divided data bytes blocks and error correction bytes blocks into "blocks".
- int dataBytesOffset = 0;
- int maxNumDataBytes = 0;
- int maxNumEcBytes = 0;
-
- // Since, we know the number of reedsolmon blocks, we can initialize the vector with the number.
- Vector blocks = new Vector(numRSBlocks);
-
- for (int i = 0; i < numRSBlocks; ++i) {
- int[] numDataBytesInBlock = new int[1];
- int[] numEcBytesInBlock = new int[1];
- getNumDataBytesAndNumECBytesForBlockID(
- numTotalBytes, numDataBytes, numRSBlocks, i,
- numDataBytesInBlock, numEcBytesInBlock);
-
- int size = numDataBytesInBlock[0];
- byte[] dataBytes = new byte[size];
- bits.toBytes(8*dataBytesOffset, dataBytes, 0, size);
- byte[] ecBytes = generateECBytes(dataBytes, numEcBytesInBlock[0]);
- blocks.addElement(new BlockPair(dataBytes, ecBytes));
-
- maxNumDataBytes = Math.max(maxNumDataBytes, size);
- maxNumEcBytes = Math.max(maxNumEcBytes, ecBytes.length);
- dataBytesOffset += numDataBytesInBlock[0];
- }
- if (numDataBytes != dataBytesOffset) {
- throw new WriterException("Data bytes does not match offset");
- }
-
- // First, place data blocks.
- for (int i = 0; i < maxNumDataBytes; ++i) {
- for (int j = 0; j < blocks.size(); ++j) {
- byte[] dataBytes = ((BlockPair) blocks.elementAt(j)).getDataBytes();
- if (i < dataBytes.length) {
- result.appendBits(dataBytes[i], 8);
- }
- }
- }
- // Then, place error correction blocks.
- for (int i = 0; i < maxNumEcBytes; ++i) {
- for (int j = 0; j < blocks.size(); ++j) {
- byte[] ecBytes = ((BlockPair) blocks.elementAt(j)).getErrorCorrectionBytes();
- if (i < ecBytes.length) {
- result.appendBits(ecBytes[i], 8);
- }
- }
- }
- if (numTotalBytes != result.getSizeInBytes()) { // Should be same.
- throw new WriterException("Interleaving error: " + numTotalBytes + " and " +
- result.getSizeInBytes() + " differ.");
- }
- }
-
- static byte[] generateECBytes(byte[] dataBytes, int numEcBytesInBlock) {
- int numDataBytes = dataBytes.length;
- int[] toEncode = new int[numDataBytes + numEcBytesInBlock];
- for (int i = 0; i < numDataBytes; i++) {
- toEncode[i] = dataBytes[i] & 0xFF;
- }
- new ReedSolomonEncoder(GenericGF.QR_CODE_FIELD_256).encode(toEncode, numEcBytesInBlock);
-
- byte[] ecBytes = new byte[numEcBytesInBlock];
- for (int i = 0; i < numEcBytesInBlock; i++) {
- ecBytes[i] = (byte) toEncode[numDataBytes + i];
- }
- return ecBytes;
- }
-
- /**
- * Append mode info. On success, store the result in "bits".
- */
- static void appendModeInfo(Mode mode, BitArray bits) {
- bits.appendBits(mode.getBits(), 4);
- }
-
-
- /**
- * Append length info. On success, store the result in "bits".
- */
- static void appendLengthInfo(int numLetters, int version, Mode mode, BitArray bits)
- throws WriterException {
- int numBits = mode.getCharacterCountBits(Version.getVersionForNumber(version));
- if (numLetters > ((1 << numBits) - 1)) {
- throw new WriterException(numLetters + "is bigger than" + ((1 << numBits) - 1));
- }
- bits.appendBits(numLetters, numBits);
- }
-
- /**
- * Append "bytes" in "mode" mode (encoding) into "bits". On success, store the result in "bits".
- */
- static void appendBytes(String content, Mode mode, BitArray bits, String encoding)
- throws WriterException {
- if (mode.equals(Mode.NUMERIC)) {
- appendNumericBytes(content, bits);
- } else if (mode.equals(Mode.ALPHANUMERIC)) {
- appendAlphanumericBytes(content, bits);
- } else if (mode.equals(Mode.BYTE)) {
- append8BitBytes(content, bits, encoding);
- } else if (mode.equals(Mode.KANJI)) {
- appendKanjiBytes(content, bits);
- } else {
- throw new WriterException("Invalid mode: " + mode);
- }
- }
-
- static void appendNumericBytes(String content, BitArray bits) {
- int length = content.length();
- int i = 0;
- while (i < length) {
- int num1 = content.charAt(i) - '0';
- if (i + 2 < length) {
- // Encode three numeric letters in ten bits.
- int num2 = content.charAt(i + 1) - '0';
- int num3 = content.charAt(i + 2) - '0';
- bits.appendBits(num1 * 100 + num2 * 10 + num3, 10);
- i += 3;
- } else if (i + 1 < length) {
- // Encode two numeric letters in seven bits.
- int num2 = content.charAt(i + 1) - '0';
- bits.appendBits(num1 * 10 + num2, 7);
- i += 2;
- } else {
- // Encode one numeric letter in four bits.
- bits.appendBits(num1, 4);
- i++;
- }
- }
- }
-
- static void appendAlphanumericBytes(String content, BitArray bits) throws WriterException {
- int length = content.length();
- int i = 0;
- while (i < length) {
- int code1 = getAlphanumericCode(content.charAt(i));
- if (code1 == -1) {
- throw new WriterException();
- }
- if (i + 1 < length) {
- int code2 = getAlphanumericCode(content.charAt(i + 1));
- if (code2 == -1) {
- throw new WriterException();
- }
- // Encode two alphanumeric letters in 11 bits.
- bits.appendBits(code1 * 45 + code2, 11);
- i += 2;
- } else {
- // Encode one alphanumeric letter in six bits.
- bits.appendBits(code1, 6);
- i++;
- }
- }
- }
-
- static void append8BitBytes(String content, BitArray bits, String encoding)
- throws WriterException {
- byte[] bytes;
- try {
- bytes = content.getBytes(encoding);
- } catch (UnsupportedEncodingException uee) {
- throw new WriterException(uee.toString());
- }
- for (int i = 0; i < bytes.length; ++i) {
- bits.appendBits(bytes[i], 8);
- }
- }
-
- static void appendKanjiBytes(String content, BitArray bits) throws WriterException {
- byte[] bytes;
- try {
- bytes = content.getBytes("Shift_JIS");
- } catch (UnsupportedEncodingException uee) {
- throw new WriterException(uee.toString());
- }
- int length = bytes.length;
- for (int i = 0; i < length; i += 2) {
- int byte1 = bytes[i] & 0xFF;
- int byte2 = bytes[i + 1] & 0xFF;
- int code = (byte1 << 8) | byte2;
- int subtracted = -1;
- if (code >= 0x8140 && code <= 0x9ffc) {
- subtracted = code - 0x8140;
- } else if (code >= 0xe040 && code <= 0xebbf) {
- subtracted = code - 0xc140;
- }
- if (subtracted == -1) {
- throw new WriterException("Invalid byte sequence");
- }
- int encoded = ((subtracted >> 8) * 0xc0) + (subtracted & 0xff);
- bits.appendBits(encoded, 13);
- }
- }
-
- private static void appendECI(ECI eci, BitArray bits) {
- bits.appendBits(Mode.ECI.getBits(), 4);
- // This is correct for values up to 127, which is all we need now.
- bits.appendBits(eci.getValue(), 8);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MaskUtil.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MaskUtil.java
deleted file mode 100644
index 61ccf48c1..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MaskUtil.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-/**
- * @author satorux@google.com (Satoru Takabayashi) - creator
- * @author dswitkin@google.com (Daniel Switkin) - ported from C++
- */
-public final class MaskUtil {
-
- private MaskUtil() {
- // do nothing
- }
-
- // Apply mask penalty rule 1 and return the penalty. Find repetitive cells with the same color and
- // give penalty to them. Example: 00000 or 11111.
- public static int applyMaskPenaltyRule1(ByteMatrix matrix) {
- return applyMaskPenaltyRule1Internal(matrix, true) + applyMaskPenaltyRule1Internal(matrix, false);
- }
-
- // Apply mask penalty rule 2 and return the penalty. Find 2x2 blocks with the same color and give
- // penalty to them.
- public static int applyMaskPenaltyRule2(ByteMatrix matrix) {
- int penalty = 0;
- byte[][] array = matrix.getArray();
- int width = matrix.getWidth();
- int height = matrix.getHeight();
- for (int y = 0; y < height - 1; ++y) {
- for (int x = 0; x < width - 1; ++x) {
- int value = array[y][x];
- if (value == array[y][x + 1] && value == array[y + 1][x] && value == array[y + 1][x + 1]) {
- penalty += 3;
- }
- }
- }
- return penalty;
- }
-
- // Apply mask penalty rule 3 and return the penalty. Find consecutive cells of 00001011101 or
- // 10111010000, and give penalty to them. If we find patterns like 000010111010000, we give
- // penalties twice (i.e. 40 * 2).
- public static int applyMaskPenaltyRule3(ByteMatrix matrix) {
- int penalty = 0;
- byte[][] array = matrix.getArray();
- int width = matrix.getWidth();
- int height = matrix.getHeight();
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- // Tried to simplify following conditions but failed.
- if (x + 6 < width &&
- array[y][x] == 1 &&
- array[y][x + 1] == 0 &&
- array[y][x + 2] == 1 &&
- array[y][x + 3] == 1 &&
- array[y][x + 4] == 1 &&
- array[y][x + 5] == 0 &&
- array[y][x + 6] == 1 &&
- ((x + 10 < width &&
- array[y][x + 7] == 0 &&
- array[y][x + 8] == 0 &&
- array[y][x + 9] == 0 &&
- array[y][x + 10] == 0) ||
- (x - 4 >= 0 &&
- array[y][x - 1] == 0 &&
- array[y][x - 2] == 0 &&
- array[y][x - 3] == 0 &&
- array[y][x - 4] == 0))) {
- penalty += 40;
- }
- if (y + 6 < height &&
- array[y][x] == 1 &&
- array[y + 1][x] == 0 &&
- array[y + 2][x] == 1 &&
- array[y + 3][x] == 1 &&
- array[y + 4][x] == 1 &&
- array[y + 5][x] == 0 &&
- array[y + 6][x] == 1 &&
- ((y + 10 < height &&
- array[y + 7][x] == 0 &&
- array[y + 8][x] == 0 &&
- array[y + 9][x] == 0 &&
- array[y + 10][x] == 0) ||
- (y - 4 >= 0 &&
- array[y - 1][x] == 0 &&
- array[y - 2][x] == 0 &&
- array[y - 3][x] == 0 &&
- array[y - 4][x] == 0))) {
- penalty += 40;
- }
- }
- }
- return penalty;
- }
-
- // Apply mask penalty rule 4 and return the penalty. Calculate the ratio of dark cells and give
- // penalty if the ratio is far from 50%. It gives 10 penalty for 5% distance. Examples:
- // - 0% => 100
- // - 40% => 20
- // - 45% => 10
- // - 50% => 0
- // - 55% => 10
- // - 55% => 20
- // - 100% => 100
- public static int applyMaskPenaltyRule4(ByteMatrix matrix) {
- int numDarkCells = 0;
- byte[][] array = matrix.getArray();
- int width = matrix.getWidth();
- int height = matrix.getHeight();
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- if (array[y][x] == 1) {
- numDarkCells += 1;
- }
- }
- }
- int numTotalCells = matrix.getHeight() * matrix.getWidth();
- double darkRatio = (double) numDarkCells / numTotalCells;
- return Math.abs((int) (darkRatio * 100 - 50)) / 5 * 10;
- }
-
- // Return the mask bit for "getMaskPattern" at "x" and "y". See 8.8 of JISX0510:2004 for mask
- // pattern conditions.
- public static boolean getDataMaskBit(int maskPattern, int x, int y) {
- if (!QRCode.isValidMaskPattern(maskPattern)) {
- throw new IllegalArgumentException("Invalid mask pattern");
- }
- int intermediate;
- int temp;
- switch (maskPattern) {
- case 0:
- intermediate = (y + x) & 0x1;
- break;
- case 1:
- intermediate = y & 0x1;
- break;
- case 2:
- intermediate = x % 3;
- break;
- case 3:
- intermediate = (y + x) % 3;
- break;
- case 4:
- intermediate = ((y >>> 1) + (x / 3)) & 0x1;
- break;
- case 5:
- temp = y * x;
- intermediate = (temp & 0x1) + (temp % 3);
- break;
- case 6:
- temp = y * x;
- intermediate = ((temp & 0x1) + (temp % 3)) & 0x1;
- break;
- case 7:
- temp = y * x;
- intermediate = ((temp % 3) + ((y + x) & 0x1)) & 0x1;
- break;
- default:
- throw new IllegalArgumentException("Invalid mask pattern: " + maskPattern);
- }
- return intermediate == 0;
- }
-
- // Helper function for applyMaskPenaltyRule1. We need this for doing this calculation in both
- // vertical and horizontal orders respectively.
- private static int applyMaskPenaltyRule1Internal(ByteMatrix matrix, boolean isHorizontal) {
- int penalty = 0;
- int numSameBitCells = 0;
- int prevBit = -1;
- // Horizontal mode:
- // for (int i = 0; i < matrix.height(); ++i) {
- // for (int j = 0; j < matrix.width(); ++j) {
- // int bit = matrix.get(i, j);
- // Vertical mode:
- // for (int i = 0; i < matrix.width(); ++i) {
- // for (int j = 0; j < matrix.height(); ++j) {
- // int bit = matrix.get(j, i);
- int iLimit = isHorizontal ? matrix.getHeight() : matrix.getWidth();
- int jLimit = isHorizontal ? matrix.getWidth() : matrix.getHeight();
- byte[][] array = matrix.getArray();
- for (int i = 0; i < iLimit; ++i) {
- for (int j = 0; j < jLimit; ++j) {
- int bit = isHorizontal ? array[i][j] : array[j][i];
- if (bit == prevBit) {
- numSameBitCells += 1;
- // Found five repetitive cells with the same color (bit).
- // We'll give penalty of 3.
- if (numSameBitCells == 5) {
- penalty += 3;
- } else if (numSameBitCells > 5) {
- // After five repetitive cells, we'll add the penalty one
- // by one.
- penalty += 1;
- }
- } else {
- numSameBitCells = 1; // Include the cell itself.
- prevBit = bit;
- }
- }
- numSameBitCells = 0; // Clear at each row/column.
- }
- return penalty;
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MatrixUtil.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MatrixUtil.java
deleted file mode 100644
index 3d434e675..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/MatrixUtil.java
+++ /dev/null
@@ -1,524 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-import com.google.zxing.WriterException;
-import com.google.zxing.common.BitArray;
-import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-
-/**
- * @author satorux@google.com (Satoru Takabayashi) - creator
- * @author dswitkin@google.com (Daniel Switkin) - ported from C++
- */
-public final class MatrixUtil {
-
- private MatrixUtil() {
- // do nothing
- }
-
- private static final int[][] POSITION_DETECTION_PATTERN = {
- {1, 1, 1, 1, 1, 1, 1},
- {1, 0, 0, 0, 0, 0, 1},
- {1, 0, 1, 1, 1, 0, 1},
- {1, 0, 1, 1, 1, 0, 1},
- {1, 0, 1, 1, 1, 0, 1},
- {1, 0, 0, 0, 0, 0, 1},
- {1, 1, 1, 1, 1, 1, 1},
- };
-
- private static final int[][] HORIZONTAL_SEPARATION_PATTERN = {
- {0, 0, 0, 0, 0, 0, 0, 0},
- };
-
- private static final int[][] VERTICAL_SEPARATION_PATTERN = {
- {0}, {0}, {0}, {0}, {0}, {0}, {0},
- };
-
- private static final int[][] POSITION_ADJUSTMENT_PATTERN = {
- {1, 1, 1, 1, 1},
- {1, 0, 0, 0, 1},
- {1, 0, 1, 0, 1},
- {1, 0, 0, 0, 1},
- {1, 1, 1, 1, 1},
- };
-
- // From Appendix E. Table 1, JIS0510X:2004 (p 71). The table was double-checked by komatsu.
- private static final int[][] POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE = {
- {-1, -1, -1, -1, -1, -1, -1}, // Version 1
- { 6, 18, -1, -1, -1, -1, -1}, // Version 2
- { 6, 22, -1, -1, -1, -1, -1}, // Version 3
- { 6, 26, -1, -1, -1, -1, -1}, // Version 4
- { 6, 30, -1, -1, -1, -1, -1}, // Version 5
- { 6, 34, -1, -1, -1, -1, -1}, // Version 6
- { 6, 22, 38, -1, -1, -1, -1}, // Version 7
- { 6, 24, 42, -1, -1, -1, -1}, // Version 8
- { 6, 26, 46, -1, -1, -1, -1}, // Version 9
- { 6, 28, 50, -1, -1, -1, -1}, // Version 10
- { 6, 30, 54, -1, -1, -1, -1}, // Version 11
- { 6, 32, 58, -1, -1, -1, -1}, // Version 12
- { 6, 34, 62, -1, -1, -1, -1}, // Version 13
- { 6, 26, 46, 66, -1, -1, -1}, // Version 14
- { 6, 26, 48, 70, -1, -1, -1}, // Version 15
- { 6, 26, 50, 74, -1, -1, -1}, // Version 16
- { 6, 30, 54, 78, -1, -1, -1}, // Version 17
- { 6, 30, 56, 82, -1, -1, -1}, // Version 18
- { 6, 30, 58, 86, -1, -1, -1}, // Version 19
- { 6, 34, 62, 90, -1, -1, -1}, // Version 20
- { 6, 28, 50, 72, 94, -1, -1}, // Version 21
- { 6, 26, 50, 74, 98, -1, -1}, // Version 22
- { 6, 30, 54, 78, 102, -1, -1}, // Version 23
- { 6, 28, 54, 80, 106, -1, -1}, // Version 24
- { 6, 32, 58, 84, 110, -1, -1}, // Version 25
- { 6, 30, 58, 86, 114, -1, -1}, // Version 26
- { 6, 34, 62, 90, 118, -1, -1}, // Version 27
- { 6, 26, 50, 74, 98, 122, -1}, // Version 28
- { 6, 30, 54, 78, 102, 126, -1}, // Version 29
- { 6, 26, 52, 78, 104, 130, -1}, // Version 30
- { 6, 30, 56, 82, 108, 134, -1}, // Version 31
- { 6, 34, 60, 86, 112, 138, -1}, // Version 32
- { 6, 30, 58, 86, 114, 142, -1}, // Version 33
- { 6, 34, 62, 90, 118, 146, -1}, // Version 34
- { 6, 30, 54, 78, 102, 126, 150}, // Version 35
- { 6, 24, 50, 76, 102, 128, 154}, // Version 36
- { 6, 28, 54, 80, 106, 132, 158}, // Version 37
- { 6, 32, 58, 84, 110, 136, 162}, // Version 38
- { 6, 26, 54, 82, 110, 138, 166}, // Version 39
- { 6, 30, 58, 86, 114, 142, 170}, // Version 40
- };
-
- // Type info cells at the left top corner.
- private static final int[][] TYPE_INFO_COORDINATES = {
- {8, 0},
- {8, 1},
- {8, 2},
- {8, 3},
- {8, 4},
- {8, 5},
- {8, 7},
- {8, 8},
- {7, 8},
- {5, 8},
- {4, 8},
- {3, 8},
- {2, 8},
- {1, 8},
- {0, 8},
- };
-
- // From Appendix D in JISX0510:2004 (p. 67)
- private static final int VERSION_INFO_POLY = 0x1f25; // 1 1111 0010 0101
-
- // From Appendix C in JISX0510:2004 (p.65).
- private static final int TYPE_INFO_POLY = 0x537;
- private static final int TYPE_INFO_MASK_PATTERN = 0x5412;
-
- // Set all cells to -1. -1 means that the cell is empty (not set yet).
- //
- // JAVAPORT: We shouldn't need to do this at all. The code should be rewritten to begin encoding
- // with the ByteMatrix initialized all to zero.
- public static void clearMatrix(ByteMatrix matrix) {
- matrix.clear((byte) -1);
- }
-
- // Build 2D matrix of QR Code from "dataBits" with "ecLevel", "version" and "getMaskPattern". On
- // success, store the result in "matrix" and return true.
- public static void buildMatrix(BitArray dataBits, ErrorCorrectionLevel ecLevel, int version,
- int maskPattern, ByteMatrix matrix) throws WriterException {
- clearMatrix(matrix);
- embedBasicPatterns(version, matrix);
- // Type information appear with any version.
- embedTypeInfo(ecLevel, maskPattern, matrix);
- // Version info appear if version >= 7.
- maybeEmbedVersionInfo(version, matrix);
- // Data should be embedded at end.
- embedDataBits(dataBits, maskPattern, matrix);
- }
-
- // Embed basic patterns. On success, modify the matrix and return true.
- // The basic patterns are:
- // - Position detection patterns
- // - Timing patterns
- // - Dark dot at the left bottom corner
- // - Position adjustment patterns, if need be
- public static void embedBasicPatterns(int version, ByteMatrix matrix) throws WriterException {
- // Let's get started with embedding big squares at corners.
- embedPositionDetectionPatternsAndSeparators(matrix);
- // Then, embed the dark dot at the left bottom corner.
- embedDarkDotAtLeftBottomCorner(matrix);
-
- // Position adjustment patterns appear if version >= 2.
- maybeEmbedPositionAdjustmentPatterns(version, matrix);
- // Timing patterns should be embedded after position adj. patterns.
- embedTimingPatterns(matrix);
- }
-
- // Embed type information. On success, modify the matrix.
- public static void embedTypeInfo(ErrorCorrectionLevel ecLevel, int maskPattern, ByteMatrix matrix)
- throws WriterException {
- BitArray typeInfoBits = new BitArray();
- makeTypeInfoBits(ecLevel, maskPattern, typeInfoBits);
-
- for (int i = 0; i < typeInfoBits.getSize(); ++i) {
- // Place bits in LSB to MSB order. LSB (least significant bit) is the last value in
- // "typeInfoBits".
- boolean bit = typeInfoBits.get(typeInfoBits.getSize() - 1 - i);
-
- // Type info bits at the left top corner. See 8.9 of JISX0510:2004 (p.46).
- int x1 = TYPE_INFO_COORDINATES[i][0];
- int y1 = TYPE_INFO_COORDINATES[i][1];
- matrix.set(x1, y1, bit);
-
- if (i < 8) {
- // Right top corner.
- int x2 = matrix.getWidth() - i - 1;
- int y2 = 8;
- matrix.set(x2, y2, bit);
- } else {
- // Left bottom corner.
- int x2 = 8;
- int y2 = matrix.getHeight() - 7 + (i - 8);
- matrix.set(x2, y2, bit);
- }
- }
- }
-
- // Embed version information if need be. On success, modify the matrix and return true.
- // See 8.10 of JISX0510:2004 (p.47) for how to embed version information.
- public static void maybeEmbedVersionInfo(int version, ByteMatrix matrix) throws WriterException {
- if (version < 7) { // Version info is necessary if version >= 7.
- return; // Don't need version info.
- }
- BitArray versionInfoBits = new BitArray();
- makeVersionInfoBits(version, versionInfoBits);
-
- int bitIndex = 6 * 3 - 1; // It will decrease from 17 to 0.
- for (int i = 0; i < 6; ++i) {
- for (int j = 0; j < 3; ++j) {
- // Place bits in LSB (least significant bit) to MSB order.
- boolean bit = versionInfoBits.get(bitIndex);
- bitIndex--;
- // Left bottom corner.
- matrix.set(i, matrix.getHeight() - 11 + j, bit);
- // Right bottom corner.
- matrix.set(matrix.getHeight() - 11 + j, i, bit);
- }
- }
- }
-
- // Embed "dataBits" using "getMaskPattern". On success, modify the matrix and return true.
- // For debugging purposes, it skips masking process if "getMaskPattern" is -1.
- // See 8.7 of JISX0510:2004 (p.38) for how to embed data bits.
- public static void embedDataBits(BitArray dataBits, int maskPattern, ByteMatrix matrix)
- throws WriterException {
- int bitIndex = 0;
- int direction = -1;
- // Start from the right bottom cell.
- int x = matrix.getWidth() - 1;
- int y = matrix.getHeight() - 1;
- while (x > 0) {
- // Skip the vertical timing pattern.
- if (x == 6) {
- x -= 1;
- }
- while (y >= 0 && y < matrix.getHeight()) {
- for (int i = 0; i < 2; ++i) {
- int xx = x - i;
- // Skip the cell if it's not empty.
- if (!isEmpty(matrix.get(xx, y))) {
- continue;
- }
- boolean bit;
- if (bitIndex < dataBits.getSize()) {
- bit = dataBits.get(bitIndex);
- ++bitIndex;
- } else {
- // Padding bit. If there is no bit left, we'll fill the left cells with 0, as described
- // in 8.4.9 of JISX0510:2004 (p. 24).
- bit = false;
- }
-
- // Skip masking if mask_pattern is -1.
- if (maskPattern != -1) {
- if (MaskUtil.getDataMaskBit(maskPattern, xx, y)) {
- bit = !bit;
- }
- }
- matrix.set(xx, y, bit);
- }
- y += direction;
- }
- direction = -direction; // Reverse the direction.
- y += direction;
- x -= 2; // Move to the left.
- }
- // All bits should be consumed.
- if (bitIndex != dataBits.getSize()) {
- throw new WriterException("Not all bits consumed: " + bitIndex + '/' + dataBits.getSize());
- }
- }
-
- // Return the position of the most significant bit set (to one) in the "value". The most
- // significant bit is position 32. If there is no bit set, return 0. Examples:
- // - findMSBSet(0) => 0
- // - findMSBSet(1) => 1
- // - findMSBSet(255) => 8
- public static int findMSBSet(int value) {
- int numDigits = 0;
- while (value != 0) {
- value >>>= 1;
- ++numDigits;
- }
- return numDigits;
- }
-
- // Calculate BCH (Bose-Chaudhuri-Hocquenghem) code for "value" using polynomial "poly". The BCH
- // code is used for encoding type information and version information.
- // Example: Calculation of version information of 7.
- // f(x) is created from 7.
- // - 7 = 000111 in 6 bits
- // - f(x) = x^2 + x^1 + x^0
- // g(x) is given by the standard (p. 67)
- // - g(x) = x^12 + x^11 + x^10 + x^9 + x^8 + x^5 + x^2 + 1
- // Multiply f(x) by x^(18 - 6)
- // - f'(x) = f(x) * x^(18 - 6)
- // - f'(x) = x^14 + x^13 + x^12
- // Calculate the remainder of f'(x) / g(x)
- // x^2
- // __________________________________________________
- // g(x) )x^14 + x^13 + x^12
- // x^14 + x^13 + x^12 + x^11 + x^10 + x^7 + x^4 + x^2
- // --------------------------------------------------
- // x^11 + x^10 + x^7 + x^4 + x^2
- //
- // The remainder is x^11 + x^10 + x^7 + x^4 + x^2
- // Encode it in binary: 110010010100
- // The return value is 0xc94 (1100 1001 0100)
- //
- // Since all coefficients in the polynomials are 1 or 0, we can do the calculation by bit
- // operations. We don't care if cofficients are positive or negative.
- public static int calculateBCHCode(int value, int poly) {
- // If poly is "1 1111 0010 0101" (version info poly), msbSetInPoly is 13. We'll subtract 1
- // from 13 to make it 12.
- int msbSetInPoly = findMSBSet(poly);
- value <<= msbSetInPoly - 1;
- // Do the division business using exclusive-or operations.
- while (findMSBSet(value) >= msbSetInPoly) {
- value ^= poly << (findMSBSet(value) - msbSetInPoly);
- }
- // Now the "value" is the remainder (i.e. the BCH code)
- return value;
- }
-
- // Make bit vector of type information. On success, store the result in "bits" and return true.
- // Encode error correction level and mask pattern. See 8.9 of
- // JISX0510:2004 (p.45) for details.
- public static void makeTypeInfoBits(ErrorCorrectionLevel ecLevel, int maskPattern, BitArray bits)
- throws WriterException {
- if (!QRCode.isValidMaskPattern(maskPattern)) {
- throw new WriterException("Invalid mask pattern");
- }
- int typeInfo = (ecLevel.getBits() << 3) | maskPattern;
- bits.appendBits(typeInfo, 5);
-
- int bchCode = calculateBCHCode(typeInfo, TYPE_INFO_POLY);
- bits.appendBits(bchCode, 10);
-
- BitArray maskBits = new BitArray();
- maskBits.appendBits(TYPE_INFO_MASK_PATTERN, 15);
- bits.xor(maskBits);
-
- if (bits.getSize() != 15) { // Just in case.
- throw new WriterException("should not happen but we got: " + bits.getSize());
- }
- }
-
- // Make bit vector of version information. On success, store the result in "bits" and return true.
- // See 8.10 of JISX0510:2004 (p.45) for details.
- public static void makeVersionInfoBits(int version, BitArray bits) throws WriterException {
- bits.appendBits(version, 6);
- int bchCode = calculateBCHCode(version, VERSION_INFO_POLY);
- bits.appendBits(bchCode, 12);
-
- if (bits.getSize() != 18) { // Just in case.
- throw new WriterException("should not happen but we got: " + bits.getSize());
- }
- }
-
- // Check if "value" is empty.
- private static boolean isEmpty(int value) {
- return value == -1;
- }
-
- // Check if "value" is valid.
- private static boolean isValidValue(int value) {
- return value == -1 || // Empty.
- value == 0 || // Light (white).
- value == 1; // Dark (black).
- }
-
- private static void embedTimingPatterns(ByteMatrix matrix) throws WriterException {
- // -8 is for skipping position detection patterns (size 7), and two horizontal/vertical
- // separation patterns (size 1). Thus, 8 = 7 + 1.
- for (int i = 8; i < matrix.getWidth() - 8; ++i) {
- int bit = (i + 1) % 2;
- // Horizontal line.
- if (!isValidValue(matrix.get(i, 6))) {
- throw new WriterException();
- }
- if (isEmpty(matrix.get(i, 6))) {
- matrix.set(i, 6, bit);
- }
- // Vertical line.
- if (!isValidValue(matrix.get(6, i))) {
- throw new WriterException();
- }
- if (isEmpty(matrix.get(6, i))) {
- matrix.set(6, i, bit);
- }
- }
- }
-
- // Embed the lonely dark dot at left bottom corner. JISX0510:2004 (p.46)
- private static void embedDarkDotAtLeftBottomCorner(ByteMatrix matrix) throws WriterException {
- if (matrix.get(8, matrix.getHeight() - 8) == 0) {
- throw new WriterException();
- }
- matrix.set(8, matrix.getHeight() - 8, 1);
- }
-
- private static void embedHorizontalSeparationPattern(int xStart, int yStart,
- ByteMatrix matrix) throws WriterException {
- // We know the width and height.
- if (HORIZONTAL_SEPARATION_PATTERN[0].length != 8 || HORIZONTAL_SEPARATION_PATTERN.length != 1) {
- throw new WriterException("Bad horizontal separation pattern");
- }
- for (int x = 0; x < 8; ++x) {
- if (!isEmpty(matrix.get(xStart + x, yStart))) {
- throw new WriterException();
- }
- matrix.set(xStart + x, yStart, HORIZONTAL_SEPARATION_PATTERN[0][x]);
- }
- }
-
- private static void embedVerticalSeparationPattern(int xStart, int yStart,
- ByteMatrix matrix) throws WriterException {
- // We know the width and height.
- if (VERTICAL_SEPARATION_PATTERN[0].length != 1 || VERTICAL_SEPARATION_PATTERN.length != 7) {
- throw new WriterException("Bad vertical separation pattern");
- }
- for (int y = 0; y < 7; ++y) {
- if (!isEmpty(matrix.get(xStart, yStart + y))) {
- throw new WriterException();
- }
- matrix.set(xStart, yStart + y, VERTICAL_SEPARATION_PATTERN[y][0]);
- }
- }
-
- // Note that we cannot unify the function with embedPositionDetectionPattern() despite they are
- // almost identical, since we cannot write a function that takes 2D arrays in different sizes in
- // C/C++. We should live with the fact.
- private static void embedPositionAdjustmentPattern(int xStart, int yStart,
- ByteMatrix matrix) throws WriterException {
- // We know the width and height.
- if (POSITION_ADJUSTMENT_PATTERN[0].length != 5 || POSITION_ADJUSTMENT_PATTERN.length != 5) {
- throw new WriterException("Bad position adjustment");
- }
- for (int y = 0; y < 5; ++y) {
- for (int x = 0; x < 5; ++x) {
- if (!isEmpty(matrix.get(xStart + x, yStart + y))) {
- throw new WriterException();
- }
- matrix.set(xStart + x, yStart + y, POSITION_ADJUSTMENT_PATTERN[y][x]);
- }
- }
- }
-
- private static void embedPositionDetectionPattern(int xStart, int yStart,
- ByteMatrix matrix) throws WriterException {
- // We know the width and height.
- if (POSITION_DETECTION_PATTERN[0].length != 7 || POSITION_DETECTION_PATTERN.length != 7) {
- throw new WriterException("Bad position detection pattern");
- }
- for (int y = 0; y < 7; ++y) {
- for (int x = 0; x < 7; ++x) {
- if (!isEmpty(matrix.get(xStart + x, yStart + y))) {
- throw new WriterException();
- }
- matrix.set(xStart + x, yStart + y, POSITION_DETECTION_PATTERN[y][x]);
- }
- }
- }
-
- // Embed position detection patterns and surrounding vertical/horizontal separators.
- private static void embedPositionDetectionPatternsAndSeparators(ByteMatrix matrix) throws WriterException {
- // Embed three big squares at corners.
- int pdpWidth = POSITION_DETECTION_PATTERN[0].length;
- // Left top corner.
- embedPositionDetectionPattern(0, 0, matrix);
- // Right top corner.
- embedPositionDetectionPattern(matrix.getWidth() - pdpWidth, 0, matrix);
- // Left bottom corner.
- embedPositionDetectionPattern(0, matrix.getWidth() - pdpWidth, matrix);
-
- // Embed horizontal separation patterns around the squares.
- int hspWidth = HORIZONTAL_SEPARATION_PATTERN[0].length;
- // Left top corner.
- embedHorizontalSeparationPattern(0, hspWidth - 1, matrix);
- // Right top corner.
- embedHorizontalSeparationPattern(matrix.getWidth() - hspWidth,
- hspWidth - 1, matrix);
- // Left bottom corner.
- embedHorizontalSeparationPattern(0, matrix.getWidth() - hspWidth, matrix);
-
- // Embed vertical separation patterns around the squares.
- int vspSize = VERTICAL_SEPARATION_PATTERN.length;
- // Left top corner.
- embedVerticalSeparationPattern(vspSize, 0, matrix);
- // Right top corner.
- embedVerticalSeparationPattern(matrix.getHeight() - vspSize - 1, 0, matrix);
- // Left bottom corner.
- embedVerticalSeparationPattern(vspSize, matrix.getHeight() - vspSize,
- matrix);
- }
-
- // Embed position adjustment patterns if need be.
- private static void maybeEmbedPositionAdjustmentPatterns(int version, ByteMatrix matrix)
- throws WriterException {
- if (version < 2) { // The patterns appear if version >= 2
- return;
- }
- int index = version - 1;
- int[] coordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index];
- int numCoordinates = POSITION_ADJUSTMENT_PATTERN_COORDINATE_TABLE[index].length;
- for (int i = 0; i < numCoordinates; ++i) {
- for (int j = 0; j < numCoordinates; ++j) {
- int y = coordinates[i];
- int x = coordinates[j];
- if (x == -1 || y == -1) {
- continue;
- }
- // If the cell is unset, we embed the position adjustment pattern here.
- if (isEmpty(matrix.get(x, y))) {
- // -2 is necessary since the x/y coordinates point to the center of the pattern, not the
- // left top corner.
- embedPositionAdjustmentPattern(x - 2, y - 2, matrix);
- }
- }
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/QRCode.java b/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/QRCode.java
deleted file mode 100644
index 05c818513..000000000
--- a/OpenPGP-Keychain/src/com/google/zxing/qrcode/encoder/QRCode.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * Copyright 2008 ZXing authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.google.zxing.qrcode.encoder;
-
-import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
-import com.google.zxing.qrcode.decoder.Mode;
-
-/**
- * @author satorux@google.com (Satoru Takabayashi) - creator
- * @author dswitkin@google.com (Daniel Switkin) - ported from C++
- */
-public final class QRCode {
-
- public static final int NUM_MASK_PATTERNS = 8;
-
- private Mode mode;
- private ErrorCorrectionLevel ecLevel;
- private int version;
- private int matrixWidth;
- private int maskPattern;
- private int numTotalBytes;
- private int numDataBytes;
- private int numECBytes;
- private int numRSBlocks;
- private ByteMatrix matrix;
-
- public QRCode() {
- mode = null;
- ecLevel = null;
- version = -1;
- matrixWidth = -1;
- maskPattern = -1;
- numTotalBytes = -1;
- numDataBytes = -1;
- numECBytes = -1;
- numRSBlocks = -1;
- matrix = null;
- }
-
- // Mode of the QR Code.
- public Mode getMode() {
- return mode;
- }
-
- // Error correction level of the QR Code.
- public ErrorCorrectionLevel getECLevel() {
- return ecLevel;
- }
-
- // Version of the QR Code. The bigger size, the bigger version.
- public int getVersion() {
- return version;
- }
-
- // ByteMatrix width of the QR Code.
- public int getMatrixWidth() {
- return matrixWidth;
- }
-
- // Mask pattern of the QR Code.
- public int getMaskPattern() {
- return maskPattern;
- }
-
- // Number of total bytes in the QR Code.
- public int getNumTotalBytes() {
- return numTotalBytes;
- }
-
- // Number of data bytes in the QR Code.
- public int getNumDataBytes() {
- return numDataBytes;
- }
-
- // Number of error correction bytes in the QR Code.
- public int getNumECBytes() {
- return numECBytes;
- }
-
- // Number of Reedsolomon blocks in the QR Code.
- public int getNumRSBlocks() {
- return numRSBlocks;
- }
-
- // ByteMatrix data of the QR Code.
- public ByteMatrix getMatrix() {
- return matrix;
- }
-
-
- // Return the value of the module (cell) pointed by "x" and "y" in the matrix of the QR Code. They
- // call cells in the matrix "modules". 1 represents a black cell, and 0 represents a white cell.
- public int at(int x, int y) {
- // The value must be zero or one.
- int value = matrix.get(x, y);
- if (!(value == 0 || value == 1)) {
- // this is really like an assert... not sure what better exception to use?
- throw new RuntimeException("Bad value");
- }
- return value;
- }
-
- // Checks all the member variables are set properly. Returns true on success. Otherwise, returns
- // false.
- public boolean isValid() {
- return
- // First check if all version are not uninitialized.
- mode != null &&
- ecLevel != null &&
- version != -1 &&
- matrixWidth != -1 &&
- maskPattern != -1 &&
- numTotalBytes != -1 &&
- numDataBytes != -1 &&
- numECBytes != -1 &&
- numRSBlocks != -1 &&
- // Then check them in other ways..
- isValidMaskPattern(maskPattern) &&
- numTotalBytes == numDataBytes + numECBytes &&
- // ByteMatrix stuff.
- matrix != null &&
- matrixWidth == matrix.getWidth() &&
- // See 7.3.1 of JISX0510:2004 (p.5).
- matrix.getWidth() == matrix.getHeight(); // Must be square.
- }
-
- // Return debug String.
- public String toString() {
- StringBuffer result = new StringBuffer(200);
- result.append("<<\n");
- result.append(" mode: ");
- result.append(mode);
- result.append("\n ecLevel: ");
- result.append(ecLevel);
- result.append("\n version: ");
- result.append(version);
- result.append("\n matrixWidth: ");
- result.append(matrixWidth);
- result.append("\n maskPattern: ");
- result.append(maskPattern);
- result.append("\n numTotalBytes: ");
- result.append(numTotalBytes);
- result.append("\n numDataBytes: ");
- result.append(numDataBytes);
- result.append("\n numECBytes: ");
- result.append(numECBytes);
- result.append("\n numRSBlocks: ");
- result.append(numRSBlocks);
- if (matrix == null) {
- result.append("\n matrix: null\n");
- } else {
- result.append("\n matrix:\n");
- result.append(matrix.toString());
- }
- result.append(">>\n");
- return result.toString();
- }
-
- public void setMode(Mode value) {
- mode = value;
- }
-
- public void setECLevel(ErrorCorrectionLevel value) {
- ecLevel = value;
- }
-
- public void setVersion(int value) {
- version = value;
- }
-
- public void setMatrixWidth(int value) {
- matrixWidth = value;
- }
-
- public void setMaskPattern(int value) {
- maskPattern = value;
- }
-
- public void setNumTotalBytes(int value) {
- numTotalBytes = value;
- }
-
- public void setNumDataBytes(int value) {
- numDataBytes = value;
- }
-
- public void setNumECBytes(int value) {
- numECBytes = value;
- }
-
- public void setNumRSBlocks(int value) {
- numRSBlocks = value;
- }
-
- // This takes ownership of the 2D array.
- public void setMatrix(ByteMatrix value) {
- matrix = value;
- }
-
- // Check if "mask_pattern" is valid.
- public static boolean isValidMaskPattern(int maskPattern) {
- return maskPattern >= 0 && maskPattern < NUM_MASK_PATTERNS;
- }
-
- // Return true if the all values in the matrix are binary numbers.
- //
- // JAVAPORT: This is going to be super expensive and unnecessary, we should not call this in
- // production. I'm leaving it because it may be useful for testing. It should be removed entirely
- // if ByteMatrix is changed never to contain a -1.
- /*
- private static boolean EverythingIsBinary(final ByteMatrix matrix) {
- for (int y = 0; y < matrix.height(); ++y) {
- for (int x = 0; x < matrix.width(); ++x) {
- int value = matrix.get(y, x);
- if (!(value == 0 || value == 1)) {
- // Found non zero/one value.
- return false;
- }
- }
- }
- return true;
- }
- */
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java
index e9b0b67d4..fb7851774 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/Id.java
@@ -27,18 +27,7 @@ import org.spongycastle.bcpg.CompressionAlgorithmTags;
*/
public final class Id {
- public static final String TAG = "APG";
-
public static final class menu {
- public static final int export = 0x21070001;
- public static final int delete = 0x21070002;
- public static final int edit = 0x21070003;
- public static final int update = 0x21070004;
- public static final int exportToServer = 0x21070005;
- public static final int share = 0x21070006;
- public static final int share_qr_code = 0x21070007;
- public static final int share_nfc = 0x21070008;
- public static final int signKey = 0x21070009;
public static final class option {
public static final int new_pass_phrase = 0x21070001;
@@ -82,20 +71,6 @@ public final class Id {
public static final int unknown_signature_key = 0x00006011;
}
- // public static final class message {
- // public static final int progress_update = 0x21070001;
- // public static final int done = 0x21070002;
- // public static final int import_keys = 0x21070003;
- // public static final int export_keys = 0x21070004;
- // public static final int import_done = 0x21070005;
- // public static final int export_done = 0x21070006;
- // public static final int create_key = 0x21070007;
- // public static final int edit_key = 0x21070008;
- // public static final int delete_done = 0x21070009;
- // public static final int query_done = 0x21070010;
- // public static final int unknown_signature_key = 0x21070011;
- // }
-
// use only lower 16 bits due to compatibility lib
public static final class request {
public static final int public_keys = 0x00007001;
@@ -109,18 +84,6 @@ public final class Id {
public static final int sign_key = 0x00007009;
}
- // public static final class request {
- // public static final int public_keys = 0x21070001;
- // public static final int secret_keys = 0x21070002;
- // public static final int filename = 0x21070003;
- // public static final int output_filename = 0x21070004;
- // public static final int key_server_preference = 0x21070005;
- // public static final int look_up_key_id = 0x21070006;
- // public static final int export_to_server = 0x21070007;
- // public static final int import_from_qr_code = 0x21070008;
- // public static final int sign_key = 0x21070009;
- // }
-
public static final class dialog {
public static final int pass_phrase = 0x21070001;
public static final int encrypting = 0x21070002;
@@ -136,7 +99,6 @@ public final class Id {
public static final int export_keys = 0x2107000c;
public static final int exporting = 0x2107000d;
public static final int new_account = 0x2107000e;
- // public static final int about = 0x2107000f;
public static final int change_log = 0x21070010;
public static final int output_filename = 0x21070011;
public static final int delete_file = 0x21070012;
@@ -152,11 +114,6 @@ public final class Id {
public static final int export_keys = 0x21070002;
}
- // public static final class database {
- // public static final int type_public = 0;
- // public static final int type_secret = 1;
- // }
-
public static final class type {
public static final int public_key = 0x21070001;
public static final int secret_key = 0x21070002;
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ExportHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ExportHelper.java
new file mode 100644
index 000000000..261e26be6
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/ExportHelper.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.helper;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.service.KeychainIntentService;
+import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.os.Messenger;
+import android.widget.Toast;
+
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+
+public class ExportHelper {
+ protected FileDialogFragment mFileDialog;
+ protected String mExportFilename;
+
+ SherlockFragmentActivity activity;
+
+ public ExportHelper(SherlockFragmentActivity activity) {
+ super();
+ this.activity = activity;
+ }
+
+ public void deleteKey(Uri dataUri, final int keyType, Handler deleteHandler) {
+ long keyRingRowId = Long.valueOf(dataUri.getLastPathSegment());
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(deleteHandler);
+
+ DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
+ new long[] { keyRingRowId }, keyType);
+
+ deleteKeyDialog.show(activity.getSupportFragmentManager(), "deleteKeyDialog");
+ }
+
+ /**
+ * Show dialog where to export keys
+ *
+ * @param keyRingMasterKeyId
+ * if -1 export all keys
+ */
+ public void showExportKeysDialog(final Uri dataUri, final int keyType,
+ final String exportFilename) {
+ mExportFilename = exportFilename;
+
+ // Message is received after file is selected
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == FileDialogFragment.MESSAGE_OKAY) {
+ Bundle data = message.getData();
+ mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
+
+ long keyRingRowId = Long.valueOf(dataUri.getLastPathSegment());
+
+ // TODO?
+ long keyRingMasterKeyId = ProviderHelper.getSecretMasterKeyId(activity,
+ keyRingRowId);
+
+ exportKeys(keyRingMasterKeyId, keyType);
+ }
+ }
+ };
+
+ // Create a new Messenger for the communication back
+ final Messenger messenger = new Messenger(returnHandler);
+
+ DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
+ public void run() {
+ String title = null;
+ if (dataUri != null) {
+ // single key export
+ title = activity.getString(R.string.title_export_key);
+ } else {
+ title = activity.getString(R.string.title_export_keys);
+ }
+
+ String message = null;
+ if (keyType == Id.type.public_key) {
+ message = activity.getString(R.string.specify_file_to_export_to);
+ } else {
+ message = activity.getString(R.string.specify_file_to_export_secret_keys_to);
+ }
+
+ mFileDialog = FileDialogFragment.newInstance(messenger, title, message,
+ exportFilename, null, Id.request.filename);
+
+ mFileDialog.show(activity.getSupportFragmentManager(), "fileDialog");
+ }
+ });
+ }
+
+ /**
+ * Export keys
+ *
+ * @param keyRingMasterKeyId
+ * if -1 export all keys
+ */
+ public void exportKeys(long keyRingMasterKeyId, int keyType) {
+ Log.d(Constants.TAG, "exportKeys started");
+
+ // Send all information needed to service to export key in other thread
+ Intent intent = new Intent(activity, KeychainIntentService.class);
+
+ intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING);
+
+ // fill values for this action
+ Bundle data = new Bundle();
+
+ data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFilename);
+ data.putInt(KeychainIntentService.EXPORT_KEY_TYPE, keyType);
+
+ if (keyRingMasterKeyId == -1) {
+ data.putBoolean(KeychainIntentService.EXPORT_ALL, true);
+ } else {
+ data.putLong(KeychainIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, keyRingMasterKeyId);
+ }
+
+ intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
+
+ // Message is received after exporting is done in ApgService
+ KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(activity,
+ R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) {
+ public void handleMessage(Message message) {
+ // handle messages by standard ApgHandler first
+ super.handleMessage(message);
+
+ if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
+ // get returned data bundle
+ Bundle returnData = message.getData();
+
+ int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT);
+ String toastMessage;
+ if (exported == 1) {
+ toastMessage = activity.getString(R.string.key_exported);
+ } else if (exported > 0) {
+ toastMessage = activity.getString(R.string.keys_exported, exported);
+ } else {
+ toastMessage = activity.getString(R.string.no_keys_exported);
+ }
+ Toast.makeText(activity, toastMessage, Toast.LENGTH_SHORT).show();
+
+ }
+ };
+ };
+
+ // Create a new Messenger for the communication back
+ Messenger messenger = new Messenger(exportHandler);
+ intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
+
+ // show progress dialog
+ exportHandler.showProgressDialog(activity);
+
+ // start service with intent
+ activity.startService(intent);
+ }
+
+ public boolean handleActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == Id.request.filename) {
+ if (resultCode == Activity.RESULT_OK && data != null) {
+ try {
+ String path = data.getData().getPath();
+ Log.d(Constants.TAG, "path=" + path);
+
+ // set filename used in export/import dialogs
+ mFileDialog.setFilename(path);
+ } catch (NullPointerException e) {
+ Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
+ }
+ }
+ return true;
+ }
+
+ return false;
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java
index 8fa2df1f5..9f3cd8e88 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/helper/OtherHelper.java
@@ -79,23 +79,4 @@ public class OtherHelper {
}
}
- /**
- * Splits userId string into naming part and email part
- *
- * @param userId
- * @return array with naming (0) and email (1)
- */
- public static String[] splitUserId(String userId) {
- String[] output = new String[2];
-
- String chunks[] = userId.split(" <", 2);
- userId = chunks[0];
- if (chunks.length > 1) {
- output[1] = "<" + chunks[1];
- }
- output[0] = userId;
-
- return output;
- }
-
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
index e2d89bfab..edb30496a 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/pgp/PgpKeyHelper.java
@@ -22,6 +22,8 @@ import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Vector;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.spongycastle.bcpg.sig.KeyFlags;
import org.spongycastle.openpgp.PGPPublicKey;
@@ -40,6 +42,17 @@ import android.content.Context;
public class PgpKeyHelper {
+ /**
+ * Returns the last 9 chars of a fingerprint
+ *
+ * @param fingerprint
+ * String containing short or long fingerprint
+ * @return
+ */
+ public static String shortifyFingerprint(String fingerprint) {
+ return fingerprint.substring(41);
+ }
+
public static Date getCreationDate(PGPPublicKey key) {
return key.getCreationTime();
}
@@ -513,4 +526,32 @@ public class PgpKeyHelper {
return (Long.parseLong(s1, 16) << 32) | Long.parseLong(s2, 16);
}
+ /**
+ * Splits userId string into naming part, email part, and comment part
+ *
+ * @param userId
+ * @return array with naming (0), email (1), comment (2)
+ */
+ public static String[] splitUserId(String userId) {
+ String[] result = new String[] { "", "", "" };
+
+ Pattern withComment = Pattern.compile("^(.*) \\((.*)\\) <(.*)>$");
+ Matcher matcher = withComment.matcher(userId);
+ if (matcher.matches()) {
+ result[0] = matcher.group(1);
+ result[1] = matcher.group(3);
+ result[2] = matcher.group(2);
+ return result;
+ }
+
+ Pattern withoutComment = Pattern.compile("^(.*) <(.*)>$");
+ matcher = withoutComment.matcher(userId);
+ if (matcher.matches()) {
+ result[0] = matcher.group(1);
+ result[1] = matcher.group(2);
+ return result;
+ }
+ return result;
+ }
+
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
index 82bb473f6..d2381f6f0 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/KeychainContract.java
@@ -69,8 +69,8 @@ public class KeychainContract {
public static final String CONTENT_AUTHORITY = Constants.PACKAGE_NAME + ".provider";
- private static final Uri BASE_CONTENT_URI_INTERNAL = Uri.parse("content://"
- + CONTENT_AUTHORITY);
+ private static final Uri BASE_CONTENT_URI_INTERNAL = Uri
+ .parse("content://" + CONTENT_AUTHORITY);
public static final String BASE_KEY_RINGS = "key_rings";
public static final String BASE_DATA = "data";
@@ -185,6 +185,14 @@ public class KeychainContract {
return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId)
.appendPath(PATH_KEYS).appendPath(keyRowId).build();
}
+
+ public static Uri buildKeysUri(Uri keyRingUri) {
+ return keyRingUri.buildUpon().appendPath(PATH_KEYS).build();
+ }
+
+ public static Uri buildKeysUri(Uri keyRingUri, String keyRowId) {
+ return keyRingUri.buildUpon().appendPath(PATH_KEYS).appendPath(keyRowId).build();
+ }
}
public static class UserIds implements UserIdsColumns, BaseColumns {
@@ -216,6 +224,14 @@ public class KeychainContract {
return CONTENT_URI.buildUpon().appendPath(PATH_SECRET).appendPath(keyRingRowId)
.appendPath(PATH_USER_IDS).appendPath(userIdRowId).build();
}
+
+ public static Uri buildUserIdsUri(Uri keyRingUri) {
+ return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).build();
+ }
+
+ public static Uri buildUserIdsUri(Uri keyRingUri, String userIdRowId) {
+ return keyRingUri.buildUpon().appendPath(PATH_USER_IDS).appendPath(userIdRowId).build();
+ }
}
public static class ApiApps implements ApiAppsColumns, BaseColumns {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
index f12048277..1683c7c0e 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/provider/ProviderHelper.java
@@ -60,7 +60,7 @@ public class ProviderHelper {
* @param queryUri
* @return
*/
- private static PGPKeyRing getPGPKeyRing(Context context, Uri queryUri) {
+ public static PGPKeyRing getPGPKeyRing(Context context, Uri queryUri) {
Cursor cursor = context.getContentResolver().query(queryUri,
new String[] { KeyRings._ID, KeyRings.KEY_RING_DATA }, null, null, null);
@@ -493,7 +493,7 @@ public class ProviderHelper {
*/
public static long getPublicMasterKeyId(Context context, long keyRingRowId) {
Uri queryUri = KeyRings.buildPublicKeyRingsUri(String.valueOf(keyRingRowId));
- return getMasterKeyId(context, queryUri, keyRingRowId);
+ return getMasterKeyId(context, queryUri);
}
/**
@@ -551,7 +551,7 @@ public class ProviderHelper {
*/
public static long getSecretMasterKeyId(Context context, long keyRingRowId) {
Uri queryUri = KeyRings.buildSecretKeyRingsUri(String.valueOf(keyRingRowId));
- return getMasterKeyId(context, queryUri, keyRingRowId);
+ return getMasterKeyId(context, queryUri);
}
/**
@@ -562,7 +562,7 @@ public class ProviderHelper {
* @param keyRingRowId
* @return
*/
- private static long getMasterKeyId(Context context, Uri queryUri, long keyRingRowId) {
+ public static long getMasterKeyId(Context context, Uri queryUri) {
String[] projection = new String[] { KeyRings.MASTER_KEY_ID };
ContentResolver cr = context.getContentResolver();
@@ -592,7 +592,7 @@ public class ProviderHelper {
return getKeyRingsAsArmoredString(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds);
}
- private static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri,
+ public static ArrayList<String> getKeyRingsAsArmoredString(Context context, Uri uri,
long[] masterKeyIds) {
ArrayList<String> output = new ArrayList<String>();
@@ -661,7 +661,7 @@ public class ProviderHelper {
return getKeyRingsAsByteArray(context, KeyRings.buildSecretKeyRingsUri(), masterKeyIds);
}
- private static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) {
+ public static byte[] getKeyRingsAsByteArray(Context context, Uri uri, long[] masterKeyIds) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
if (masterKeyIds != null && masterKeyIds.length > 0) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
index e592f5d57..bb6e427a4 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/AppSettingsFragment.java
@@ -49,12 +49,13 @@ import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
public class AppSettingsFragment extends Fragment {
// model
@@ -62,12 +63,12 @@ public class AppSettingsFragment extends Fragment {
// view
private LinearLayout mAdvancedSettingsContainer;
- private Button mAdvancedSettingsButton;
+ private BootstrapButton mAdvancedSettingsButton;
private TextView mAppNameView;
private ImageView mAppIconView;
private TextView mKeyUserId;
private TextView mKeyUserIdRest;
- private Button mSelectKeyButton;
+ private BootstrapButton mSelectKeyButton;
private Spinner mEncryptionAlgorithm;
private Spinner mHashAlgorithm;
private Spinner mCompression;
@@ -116,7 +117,8 @@ public class AppSettingsFragment extends Fragment {
}
private void initView(View view) {
- mAdvancedSettingsButton = (Button) view.findViewById(R.id.api_app_settings_advanced_button);
+ mAdvancedSettingsButton = (BootstrapButton) view
+ .findViewById(R.id.api_app_settings_advanced_button);
mAdvancedSettingsContainer = (LinearLayout) view
.findViewById(R.id.api_app_settings_advanced);
@@ -124,7 +126,8 @@ public class AppSettingsFragment extends Fragment {
mAppIconView = (ImageView) view.findViewById(R.id.api_app_settings_app_icon);
mKeyUserId = (TextView) view.findViewById(R.id.api_app_settings_user_id);
mKeyUserIdRest = (TextView) view.findViewById(R.id.api_app_settings_user_id_rest);
- mSelectKeyButton = (Button) view.findViewById(R.id.api_app_settings_select_key_button);
+ mSelectKeyButton = (BootstrapButton) view
+ .findViewById(R.id.api_app_settings_select_key_button);
mEncryptionAlgorithm = (Spinner) view
.findViewById(R.id.api_app_settings_encryption_algorithm);
mHashAlgorithm = (Spinner) view.findViewById(R.id.api_app_settings_hash_algorithm);
@@ -204,11 +207,13 @@ public class AppSettingsFragment extends Fragment {
if (mAdvancedSettingsContainer.getVisibility() == View.VISIBLE) {
mAdvancedSettingsContainer.startAnimation(invisibleAnimation);
mAdvancedSettingsContainer.setVisibility(View.GONE);
- mAdvancedSettingsButton.setText(R.string.api_settings_show_advanced);
+ mAdvancedSettingsButton.setText(getString(R.string.api_settings_show_advanced));
+ mAdvancedSettingsButton.setLeftIcon("fa-caret-up");
} else {
mAdvancedSettingsContainer.startAnimation(visibleAnimation);
mAdvancedSettingsContainer.setVisibility(View.VISIBLE);
- mAdvancedSettingsButton.setText(R.string.api_settings_hide_advanced);
+ mAdvancedSettingsButton.setText(getString(R.string.api_settings_hide_advanced));
+ mAdvancedSettingsButton.setLeftIcon("fa-caret-down");
}
}
});
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
index 4530ac2fc..3c553fff5 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListActivity.java
@@ -18,44 +18,19 @@
package org.sufficientlysecure.keychain.service.remote;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.ui.MainActivity;
+import org.sufficientlysecure.keychain.ui.DrawerActivity;
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.MenuItem;
-
-import android.content.Intent;
import android.os.Bundle;
-public class RegisteredAppsListActivity extends SherlockFragmentActivity {
- private ActionBar mActionBar;
+public class RegisteredAppsListActivity extends DrawerActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mActionBar = getSupportActionBar();
-
setContentView(R.layout.api_apps_list_activity);
- mActionBar.setDisplayShowTitleEnabled(true);
- mActionBar.setDisplayHomeAsUpEnabled(true);
+ setupDrawerNavigation(savedInstanceState);
}
- /**
- * Menu Options
- */
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
index 1b504a374..4c9d553ad 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/service/remote/RegisteredAppsListFragment.java
@@ -41,9 +41,6 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements
// This is the Adapter being used to display the list's data.
RegisteredAppsAdapter mAdapter;
- // If non-null, this is the current filter the user has provided.
- String mCurFilter;
-
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -75,8 +72,7 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements
}
// These are the Contacts rows that we will retrieve.
- static final String[] CONSUMERS_SUMMARY_PROJECTION = new String[] { ApiApps._ID,
- ApiApps.PACKAGE_NAME };
+ static final String[] PROJECTION = new String[] { ApiApps._ID, ApiApps.PACKAGE_NAME };
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
@@ -87,7 +83,7 @@ public class RegisteredAppsListFragment extends SherlockListFragment implements
// Now create and return a CursorLoader that will take care of
// creating a Cursor for the data being displayed.
- return new CursorLoader(getActivity(), baseUri, CONSUMERS_SUMMARY_PROJECTION, null, null,
+ return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null,
ApiApps.PACKAGE_NAME + " COLLATE LOCALIZED ASC");
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
index 78ad4c9be..6cc0b3b5a 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DecryptActivity.java
@@ -60,19 +60,18 @@ import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox;
import android.widget.EditText;
-import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.BootstrapButton;
@SuppressLint("NewApi")
-public class DecryptActivity extends SherlockFragmentActivity {
+public class DecryptActivity extends DrawerActivity {
/* Intents */
// without permission
@@ -107,7 +106,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
private EditText mFilename = null;
private CheckBox mDeleteAfter = null;
- private ImageButton mBrowse = null;
+ private BootstrapButton mBrowse = null;
private String mInputFilename = null;
private String mOutputFilename = null;
@@ -144,13 +143,6 @@ public class DecryptActivity extends SherlockFragmentActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
case Id.menu.option.decrypt: {
decryptClicked();
@@ -216,7 +208,7 @@ public class DecryptActivity extends SherlockFragmentActivity {
mMessage.setMinimumHeight(height);
mFilename = (EditText) findViewById(R.id.filename);
- mBrowse = (ImageButton) findViewById(R.id.btn_browse);
+ mBrowse = (BootstrapButton) findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FileHelper.openFile(DecryptActivity.this, mFilename.getText().toString(), "*/*",
@@ -238,13 +230,15 @@ public class DecryptActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.decrypt);
+ setContentView(R.layout.decrypt_activity);
// set actionbar without home button if called from another app
ActionBarHelper.setBackButton(this);
initView();
+ setupDrawerNavigation(savedInstanceState);
+
// Handle intent actions
handleActions(getIntent());
@@ -262,7 +256,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
if (matcher.matches()) {
data = matcher.group(1);
mMessage.setText(data);
- Toast.makeText(this, R.string.using_clipboard_content, Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, R.string.using_clipboard_content, Toast.LENGTH_SHORT)
+ .show();
}
}
}
@@ -472,8 +467,9 @@ public class DecryptActivity extends SherlockFragmentActivity {
if (!file.exists() || !file.isFile()) {
Toast.makeText(
this,
- getString(R.string.error_message, getString(R.string.error_file_not_found)),
- Toast.LENGTH_SHORT).show();
+ getString(R.string.error_message,
+ getString(R.string.error_file_not_found)), Toast.LENGTH_SHORT)
+ .show();
return;
}
}
@@ -592,7 +588,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
}
mSecretKeyId = Id.key.symmetric;
if (!PgpOperation.hasSymmetricEncryption(this, inStream)) {
- throw new PgpGeneralException(getString(R.string.error_no_known_encryption_found));
+ throw new PgpGeneralException(
+ getString(R.string.error_no_known_encryption_found));
}
mAssumeSymmetricEncryption = true;
}
@@ -790,8 +787,8 @@ public class DecryptActivity extends SherlockFragmentActivity {
.getBoolean(KeychainIntentService.RESULT_SIGNATURE_UNKNOWN)) {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
Toast.makeText(DecryptActivity.this,
- R.string.unknown_signature_key_touch_to_look_up, Toast.LENGTH_LONG)
- .show();
+ R.string.unknown_signature_key_touch_to_look_up,
+ Toast.LENGTH_LONG).show();
} else {
mSignatureStatusImage.setImageResource(R.drawable.overlay_error);
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DrawerActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DrawerActivity.java
new file mode 100644
index 000000000..ee8a01432
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/DrawerActivity.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.Configuration;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.support.v4.app.ActionBarDrawerToggle;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.view.ActionProvider;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.SubMenu;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.FontAwesomeText;
+
+/**
+ * some fundamental ideas from https://github.com/tobykurien/SherlockNavigationDrawer
+ *
+ *
+ */
+public class DrawerActivity extends SherlockFragmentActivity {
+ private DrawerLayout mDrawerLayout;
+ private ListView mDrawerList;
+ private ActionBarDrawerToggle mDrawerToggle;
+
+ private CharSequence mDrawerTitle;
+ private CharSequence mTitle;
+
+ private static Class[] mItemsClass = new Class[] { KeyListPublicActivity.class,
+ EncryptActivity.class, DecryptActivity.class, ImportKeysActivity.class,
+ KeyListSecretActivity.class, RegisteredAppsListActivity.class };
+
+ private static final int MENU_ID_PREFERENCE = 222;
+ private static final int MENU_ID_HELP = 223;
+
+ protected void setupDrawerNavigation(Bundle savedInstanceState) {
+ mDrawerTitle = getString(R.string.app_name);
+ mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+ mDrawerList = (ListView) findViewById(R.id.left_drawer);
+
+ // set a custom shadow that overlays the main content when the drawer
+ // opens
+ mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
+
+ NavItem mItemIconTexts[] = new NavItem[] {
+ new NavItem("fa-user", getString(R.string.nav_contacts)),
+ new NavItem("fa-lock", getString(R.string.nav_encrypt)),
+ new NavItem("fa-unlock", getString(R.string.nav_decrypt)),
+ new NavItem("fa-download", getString(R.string.nav_import)),
+ new NavItem("fa-key", getString(R.string.nav_secret_keys)),
+ new NavItem("fa-android", getString(R.string.nav_apps)) };
+
+ mDrawerList.setAdapter(new NavigationDrawerAdapter(this, R.layout.drawer_list_item,
+ mItemIconTexts));
+
+ mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
+
+ // enable ActionBar app icon to behave as action to toggle nav drawer
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setHomeButtonEnabled(true);
+
+ // ActionBarDrawerToggle ties together the the proper interactions
+ // between the sliding drawer and the action bar app icon
+ mDrawerToggle = new ActionBarDrawerToggle(this, /* host Activity */
+ mDrawerLayout, /* DrawerLayout object */
+ R.drawable.ic_drawer, /* nav drawer image to replace 'Up' caret */
+ R.string.drawer_open, /* "open drawer" description for accessibility */
+ R.string.drawer_close /* "close drawer" description for accessibility */
+ ) {
+ public void onDrawerClosed(View view) {
+ getSupportActionBar().setTitle(mTitle);
+ // creates call to onPrepareOptionsMenu()
+ supportInvalidateOptionsMenu();
+ }
+
+ public void onDrawerOpened(View drawerView) {
+ mTitle = getSupportActionBar().getTitle();
+ getSupportActionBar().setTitle(mDrawerTitle);
+ // creates call to onPrepareOptionsMenu()
+ supportInvalidateOptionsMenu();
+ }
+ };
+ mDrawerLayout.setDrawerListener(mDrawerToggle);
+
+ // if (savedInstanceState == null) {
+ // selectItem(0);
+ // }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ menu.add(42, MENU_ID_PREFERENCE, 100, R.string.menu_preferences);
+ menu.add(42, MENU_ID_HELP, 101, R.string.menu_help);
+
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ /* Called whenever we call invalidateOptionsMenu() */
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ // If the nav drawer is open, hide action items related to the content
+ // view
+ boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
+ // menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
+ return super.onPrepareOptionsMenu(menu);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ // The action bar home/up action should open or close the drawer.
+ // ActionBarDrawerToggle will take care of this.
+ if (mDrawerToggle.onOptionsItemSelected(getMenuItem(item))) {
+ return true;
+ }
+
+ switch (item.getItemId()) {
+ case MENU_ID_PREFERENCE: {
+ Intent intent = new Intent(this, PreferencesActivity.class);
+ startActivity(intent);
+ return true;
+ }
+ case MENU_ID_HELP: {
+ Intent intent = new Intent(this, HelpActivity.class);
+ startActivity(intent);
+ return true;
+ }
+ default:
+ return super.onOptionsItemSelected(item);
+ }
+
+ // Handle action buttons
+ // switch (item.getItemId()) {
+ // case R.id.action_websearch:
+ // // create intent to perform web search for this planet
+ // Intent intent = new Intent(Intent.ACTION_WEB_SEARCH);
+ // intent.putExtra(SearchManager.QUERY, getSupportActionBar().getTitle());
+ // // catch event that there's no activity to handle intent
+ // if (intent.resolveActivity(getPackageManager()) != null) {
+ // startActivity(intent);
+ // } else {
+ // Toast.makeText(this, R.string.app_not_available, Toast.LENGTH_LONG).show();
+ // }
+ // return true;
+ // default:
+ // return super.onOptionsItemSelected(item);
+ // }
+ }
+
+ private android.view.MenuItem getMenuItem(final MenuItem item) {
+ return new android.view.MenuItem() {
+ @Override
+ public int getItemId() {
+ return item.getItemId();
+ }
+
+ public boolean isEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean collapseActionView() {
+ return false;
+ }
+
+ @Override
+ public boolean expandActionView() {
+ return false;
+ }
+
+ @Override
+ public ActionProvider getActionProvider() {
+ return null;
+ }
+
+ @Override
+ public View getActionView() {
+ return null;
+ }
+
+ @Override
+ public char getAlphabeticShortcut() {
+ return 0;
+ }
+
+ @Override
+ public int getGroupId() {
+ return 0;
+ }
+
+ @Override
+ public Drawable getIcon() {
+ return null;
+ }
+
+ @Override
+ public Intent getIntent() {
+ return null;
+ }
+
+ @Override
+ public ContextMenuInfo getMenuInfo() {
+ return null;
+ }
+
+ @Override
+ public char getNumericShortcut() {
+ return 0;
+ }
+
+ @Override
+ public int getOrder() {
+ return 0;
+ }
+
+ @Override
+ public SubMenu getSubMenu() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTitle() {
+ return null;
+ }
+
+ @Override
+ public CharSequence getTitleCondensed() {
+ return null;
+ }
+
+ @Override
+ public boolean hasSubMenu() {
+ return false;
+ }
+
+ @Override
+ public boolean isActionViewExpanded() {
+ return false;
+ }
+
+ @Override
+ public boolean isCheckable() {
+ return false;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return false;
+ }
+
+ @Override
+ public boolean isVisible() {
+ return false;
+ }
+
+ @Override
+ public android.view.MenuItem setActionProvider(ActionProvider actionProvider) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setActionView(View view) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setActionView(int resId) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setAlphabeticShortcut(char alphaChar) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setCheckable(boolean checkable) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setChecked(boolean checked) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setEnabled(boolean enabled) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setIcon(Drawable icon) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setIcon(int iconRes) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setIntent(Intent intent) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setNumericShortcut(char numericChar) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setOnActionExpandListener(OnActionExpandListener listener) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setOnMenuItemClickListener(
+ OnMenuItemClickListener menuItemClickListener) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setShortcut(char numericChar, char alphaChar) {
+ return null;
+ }
+
+ @Override
+ public void setShowAsAction(int actionEnum) {
+ }
+
+ @Override
+ public android.view.MenuItem setShowAsActionFlags(int actionEnum) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setTitle(CharSequence title) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setTitle(int title) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setTitleCondensed(CharSequence title) {
+ return null;
+ }
+
+ @Override
+ public android.view.MenuItem setVisible(boolean visible) {
+ return null;
+ }
+ };
+ }
+
+ /* The click listener for ListView in the navigation drawer */
+ private class DrawerItemClickListener implements ListView.OnItemClickListener {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ selectItem(position);
+ }
+ }
+
+ private void selectItem(int position) {
+ // update selected item and title, then close the drawer
+ mDrawerList.setItemChecked(position, true);
+ // setTitle(mDrawerTitles[position]);
+ mDrawerLayout.closeDrawer(mDrawerList);
+
+ finish();
+ overridePendingTransition(0, 0);
+
+ Intent intent = new Intent(this, mItemsClass[position]);
+ startActivity(intent);
+ // disable animation of activity start
+ overridePendingTransition(0, 0);
+ }
+
+ /**
+ * When using the ActionBarDrawerToggle, you must call it during onPostCreate() and
+ * onConfigurationChanged()...
+ */
+ @Override
+ protected void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+ // Sync the toggle state after onRestoreInstanceState has occurred.
+ mDrawerToggle.syncState();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+ // Pass any configuration change to the drawer toggles
+ mDrawerToggle.onConfigurationChanged(newConfig);
+ }
+
+ private class NavItem {
+ public String icon;
+ public String title;
+
+ public NavItem(String icon, String title) {
+ super();
+ this.icon = icon;
+ this.title = title;
+ }
+ }
+
+ private class NavigationDrawerAdapter extends ArrayAdapter<NavItem> {
+ Context context;
+ int layoutResourceId;
+ NavItem data[] = null;
+
+ public NavigationDrawerAdapter(Context context, int layoutResourceId, NavItem[] data) {
+ super(context, layoutResourceId, data);
+ this.layoutResourceId = layoutResourceId;
+ this.context = context;
+ this.data = data;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ View row = convertView;
+ NavItemHolder holder = null;
+
+ if (row == null) {
+ LayoutInflater inflater = ((Activity) context).getLayoutInflater();
+ row = inflater.inflate(layoutResourceId, parent, false);
+
+ holder = new NavItemHolder();
+ holder.img = (FontAwesomeText) row.findViewById(R.id.drawer_item_icon);
+ holder.txtTitle = (TextView) row.findViewById(R.id.drawer_item_text);
+
+ row.setTag(holder);
+ } else {
+ holder = (NavItemHolder) row.getTag();
+ }
+
+ NavItem item = data[position];
+ holder.txtTitle.setText(item.title);
+ holder.img.setIcon(item.icon);
+
+ return row;
+ }
+
+ }
+
+ static class NavItemHolder {
+ FontAwesomeText img;
+ TextView txtTitle;
+ }
+
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
index 7abee78f3..be2e4115b 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EditKeyActivity.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
* Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -27,6 +27,7 @@ import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.ActionBarHelper;
+import org.sufficientlysecure.keychain.helper.ExportHelper;
import org.sufficientlysecure.keychain.pgp.PgpConversionHelper;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.pgp.exception.PgpGeneralException;
@@ -34,6 +35,7 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.PassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
import org.sufficientlysecure.keychain.ui.widget.KeyEditor;
@@ -45,6 +47,7 @@ import org.sufficientlysecure.keychain.util.Log;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
+import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -53,7 +56,6 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
@@ -61,6 +63,9 @@ import android.widget.LinearLayout;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class EditKeyActivity extends SherlockFragmentActivity {
@@ -72,13 +77,14 @@ public class EditKeyActivity extends SherlockFragmentActivity {
public static final String EXTRA_USER_IDS = "user_ids";
public static final String EXTRA_NO_PASSPHRASE = "no_passphrase";
public static final String EXTRA_GENERATE_DEFAULT_KEYS = "generate_default_keys";
- public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
- public static final String EXTRA_MASTER_CAN_SIGN = "master_can_sign";
// results when saving key
public static final String RESULT_EXTRA_MASTER_KEY_ID = "master_key_id";
public static final String RESULT_EXTRA_USER_ID = "user_id";
+ // EDIT
+ private Uri mDataUri;
+
private PGPSecretKeyRing mKeyRing = null;
private SectionView mUserIdsView;
@@ -87,7 +93,7 @@ public class EditKeyActivity extends SherlockFragmentActivity {
private String mCurrentPassPhrase = null;
private String mNewPassPhrase = null;
- private Button mChangePassPhrase;
+ private BootstrapButton mChangePassPhrase;
private CheckBox mNoPassphrase;
@@ -96,34 +102,13 @@ public class EditKeyActivity extends SherlockFragmentActivity {
Vector<Integer> mKeysUsages;
boolean masterCanSign = true;
- // will be set to false to build layout later in handler
- private boolean mBuildLayout = true;
+ ExportHelper mExportHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Inflate a "Done"/"Cancel" custom action bar
- ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_save,
- new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // save
- saveClicked();
- }
- }, R.string.btn_do_not_save, new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- // cancel
- cancelClicked();
- }
- });
-
- setContentView(R.layout.edit_key);
-
- // find views
- mChangePassPhrase = (Button) findViewById(R.id.edit_key_btn_change_pass_phrase);
- mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
+ mExportHelper = new ExportHelper(this);
mUserIds = new Vector<String>();
mKeys = new Vector<PGPSecretKey>();
@@ -137,32 +122,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
} else if (ACTION_EDIT_KEY.equals(action)) {
handleActionEditKey(intent);
}
-
- mChangePassPhrase.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- showSetPassphraseDialog();
- }
- });
-
- // disable passphrase when no passphrase checkobox is checked!
- mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() {
-
- @Override
- public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (isChecked) {
- // remove passphrase
- mNewPassPhrase = null;
-
- mChangePassPhrase.setVisibility(View.GONE);
- } else {
- mChangePassPhrase.setVisibility(View.VISIBLE);
- }
- }
- });
-
- if (mBuildLayout) {
- buildLayout();
- }
}
/**
@@ -171,6 +130,20 @@ public class EditKeyActivity extends SherlockFragmentActivity {
* @param intent
*/
private void handleActionCreateKey(Intent intent) {
+ // Inflate a "Done"/"Cancel" custom action bar
+ ActionBarHelper.setDoneCancelView(getSupportActionBar(), R.string.btn_save,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ saveClicked();
+ }
+ }, R.string.btn_do_not_save, new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ cancelClicked();
+ }
+ });
+
Bundle extras = intent.getExtras();
mCurrentPassPhrase = "";
@@ -197,9 +170,6 @@ public class EditKeyActivity extends SherlockFragmentActivity {
boolean generateDefaultKeys = extras.getBoolean(EXTRA_GENERATE_DEFAULT_KEYS);
if (generateDefaultKeys) {
- // build layout in handler after generating keys not directly in onCreate
- mBuildLayout = false;
-
// Send all information needed to service generate keys in other thread
Intent serviceIntent = new Intent(this, KeychainIntentService.class);
serviceIntent.setAction(KeychainIntentService.ACTION_GENERATE_DEFAULT_RSA_KEYS);
@@ -256,12 +226,55 @@ public class EditKeyActivity extends SherlockFragmentActivity {
startService(serviceIntent);
}
}
+ } else {
+ buildLayout();
+ }
+ }
+
+ /**
+ * Handle intent action to edit existing key
+ *
+ * @param intent
+ */
+ private void handleActionEditKey(Intent intent) {
+ // Inflate a "Done"/"Cancel" custom action bar
+ ActionBarHelper.setDoneView(getSupportActionBar(), R.string.btn_save,
+ new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ saveClicked();
+ }
+ });
+
+ mDataUri = intent.getData();
+ if (mDataUri == null) {
+ Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!");
+ finish();
+ return;
+ } else {
+ Log.d(Constants.TAG, "uri: " + mDataUri);
+
+ long keyRingRowId = Long.valueOf(mDataUri.getLastPathSegment());
+
+ // get master key id using row id
+ long masterKeyId = ProviderHelper.getSecretMasterKeyId(this, keyRingRowId);
+
+ boolean masterCanSign = ProviderHelper.getSecretMasterKeyCanSign(this, keyRingRowId);
+
+ String passphrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
+ if (passphrase == null) {
+ showPassphraseDialog(masterKeyId, masterCanSign);
+ } else {
+ // PgpMain.setEditPassPhrase(passPhrase);
+ mCurrentPassPhrase = passphrase;
+
+ finallyEdit(masterKeyId, masterCanSign);
+ }
}
}
private void showPassphraseDialog(final long masterKeyId, final boolean masterCanSign) {
// Message is received after passphrase is cached
- final boolean mCanSign = masterCanSign;
Handler returnHandler = new Handler() {
@Override
public void handleMessage(Message message) {
@@ -291,51 +304,54 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
}
- /**
- * Handle intent action to edit existing key
- *
- * @param intent
- */
- @SuppressWarnings("unchecked")
- private void handleActionEditKey(Intent intent) {
- Bundle extras = intent.getExtras();
-
- if (extras != null) {
- if (extras.containsKey(EXTRA_MASTER_CAN_SIGN)) {
- masterCanSign = extras.getBoolean(EXTRA_MASTER_CAN_SIGN);
- }
- if (extras.containsKey(EXTRA_MASTER_KEY_ID)) {
- long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
-
- // build layout in edit()
- mBuildLayout = false;
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ // show menu only on edit
+ if (mDataUri != null) {
+ return super.onPrepareOptionsMenu(menu);
+ } else {
+ return false;
+ }
+ }
- String passPhrase = PassphraseCacheService.getCachedPassphrase(this, masterKeyId);
- if (passPhrase == null) {
- showPassphraseDialog(masterKeyId, masterCanSign);
- } else {
- // PgpMain.setEditPassPhrase(passPhrase);
- mCurrentPassPhrase = passPhrase;
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getSupportMenuInflater().inflate(R.menu.key_edit, menu);
+ return true;
+ }
- finallyEdit(masterKeyId, masterCanSign);
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case R.id.menu_key_edit_cancel:
+ cancelClicked();
+ return true;
+ case R.id.menu_key_edit_export_file:
+ mExportHelper.showExportKeysDialog(mDataUri, Id.type.secret_key, Constants.path.APP_DIR
+ + "/secexport.asc");
+ return true;
+ case R.id.menu_key_edit_delete: {
+ // Message is received after key is deleted
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
}
+ };
- }
+ mExportHelper.deleteKey(mDataUri, Id.type.secret_key, returnHandler);
+ return true;
}
+ }
+ return super.onOptionsItemSelected(item);
}
+ @SuppressWarnings("unchecked")
private void finallyEdit(final long masterKeyId, final boolean masterCanSign) {
- // TODO: ???
- if (mCurrentPassPhrase == null) {
- mCurrentPassPhrase = "";
- }
-
- if (mCurrentPassPhrase.equals("")) {
- // check "no passphrase" checkbox and remove button
- mNoPassphrase.setChecked(true);
- mChangePassPhrase.setVisibility(View.GONE);
- }
-
if (masterKeyId != 0) {
PGPSecretKey masterKey = null;
mKeyRing = ProviderHelper.getPGPSecretKeyRingByMasterKeyId(this, masterKeyId);
@@ -357,7 +373,18 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
}
+ // TODO: ???
+ if (mCurrentPassPhrase == null) {
+ mCurrentPassPhrase = "";
+ }
+
buildLayout();
+
+ if (mCurrentPassPhrase.equals("")) {
+ // check "no passphrase" checkbox and remove button
+ mNoPassphrase.setChecked(true);
+ mChangePassPhrase.setVisibility(View.GONE);
+ }
}
/**
@@ -402,6 +429,12 @@ public class EditKeyActivity extends SherlockFragmentActivity {
* id and key.
*/
private void buildLayout() {
+ setContentView(R.layout.edit_key_activity);
+
+ // find views
+ mChangePassPhrase = (BootstrapButton) findViewById(R.id.edit_key_btn_change_pass_phrase);
+ mNoPassphrase = (CheckBox) findViewById(R.id.edit_key_no_passphrase);
+
// Build layout based on given userIds and keys
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
@@ -418,6 +451,28 @@ public class EditKeyActivity extends SherlockFragmentActivity {
container.addView(mKeysView);
updatePassPhraseButtonText();
+
+ mChangePassPhrase.setOnClickListener(new OnClickListener() {
+ public void onClick(View v) {
+ showSetPassphraseDialog();
+ }
+ });
+
+ // disable passphrase when no passphrase checkobox is checked!
+ mNoPassphrase.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+
+ @Override
+ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
+ if (isChecked) {
+ // remove passphrase
+ mNewPassPhrase = null;
+
+ mChangePassPhrase.setVisibility(View.GONE);
+ } else {
+ mChangePassPhrase.setVisibility(View.VISIBLE);
+ }
+ }
+ });
}
private long getMasterKeyId() {
@@ -604,7 +659,14 @@ public class EditKeyActivity extends SherlockFragmentActivity {
}
private void updatePassPhraseButtonText() {
- mChangePassPhrase.setText(isPassphraseSet() ? R.string.btn_change_passphrase
- : R.string.btn_set_passphrase);
+ mChangePassPhrase.setText(isPassphraseSet() ? getString(R.string.btn_change_passphrase)
+ : getString(R.string.btn_set_passphrase));
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (!mExportHelper.handleActivityResult(requestCode, resultCode, data)) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
}
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
index 2dfdf254e..c974dfd46 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/EncryptActivity.java
@@ -55,21 +55,19 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
-import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
-import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ViewFlipper;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.BootstrapButton;
-public class EncryptActivity extends SherlockFragmentActivity {
+public class EncryptActivity extends DrawerActivity {
/* Intents */
public static final String ACTION_ENCRYPT = Constants.INTENT_PREFIX + "ENCRYPT";
@@ -87,7 +85,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
private long mEncryptionKeyIds[] = null;
private EditText mMessage = null;
- private Button mSelectKeysButton = null;
+ private BootstrapButton mSelectKeysButton = null;
private boolean mEncryptEnabled = false;
private String mEncryptString = "";
@@ -117,7 +115,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
private EditText mFilename = null;
private CheckBox mDeleteAfter = null;
- private ImageButton mBrowse = null;
+ private BootstrapButton mBrowse = null;
private String mInputFilename = null;
private String mOutputFilename = null;
@@ -154,13 +152,6 @@ public class EncryptActivity extends SherlockFragmentActivity {
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
case Id.menu.option.encrypt_to_clipboard:
encryptToClipboardClicked();
@@ -181,13 +172,15 @@ public class EncryptActivity extends SherlockFragmentActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.encrypt);
+ setContentView(R.layout.encrypt_activity);
// set actionbar without home button if called from another app
ActionBarHelper.setBackButton(this);
initView();
+ setupDrawerNavigation(savedInstanceState);
+
// Handle intent actions
handleActions(getIntent());
@@ -492,8 +485,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
if (!file.exists() || !file.isFile()) {
Toast.makeText(
this,
- getString(R.string.error_message, getString(R.string.error_file_not_found)),
- Toast.LENGTH_SHORT).show();
+ getString(R.string.error_message,
+ getString(R.string.error_file_not_found)), Toast.LENGTH_SHORT)
+ .show();
return;
}
}
@@ -511,7 +505,8 @@ public class EncryptActivity extends SherlockFragmentActivity {
gotPassPhrase = (passPhrase.length() != 0);
if (!gotPassPhrase) {
- Toast.makeText(this, R.string.passphrase_must_not_be_empty, Toast.LENGTH_SHORT).show();
+ Toast.makeText(this, R.string.passphrase_must_not_be_empty, Toast.LENGTH_SHORT)
+ .show();
return;
}
} else {
@@ -523,8 +518,8 @@ public class EncryptActivity extends SherlockFragmentActivity {
}
if (!encryptIt && mSecretKeyId == 0) {
- Toast.makeText(this, R.string.select_encryption_or_signature_key, Toast.LENGTH_SHORT)
- .show();
+ Toast.makeText(this, R.string.select_encryption_or_signature_key,
+ Toast.LENGTH_SHORT).show();
return;
}
@@ -825,7 +820,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
mModeLabel.setOnClickListener(nextModeClickListener);
mMessage = (EditText) findViewById(R.id.message);
- mSelectKeysButton = (Button) findViewById(R.id.btn_selectEncryptKeys);
+ mSelectKeysButton = (BootstrapButton) findViewById(R.id.btn_selectEncryptKeys);
mSign = (CheckBox) findViewById(R.id.sign);
mMainUserId = (TextView) findViewById(R.id.mainUserId);
mMainUserIdRest = (TextView) findViewById(R.id.mainUserIdRest);
@@ -841,7 +836,7 @@ public class EncryptActivity extends SherlockFragmentActivity {
mMessage.setMinimumHeight(height);
mFilename = (EditText) findViewById(R.id.filename);
- mBrowse = (ImageButton) findViewById(R.id.btn_browse);
+ mBrowse = (BootstrapButton) findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
FileHelper.openFile(EncryptActivity.this, mFilename.getText().toString(), "*/*",
@@ -853,10 +848,12 @@ public class EncryptActivity extends SherlockFragmentActivity {
Choice[] choices = new Choice[] {
new Choice(Id.choice.compression.none, getString(R.string.choice_none) + " ("
+ getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.zip, "ZIP (" + getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.zlib, "ZLIB (" + getString(R.string.compression_fast) + ")"),
- new Choice(Id.choice.compression.bzip2, "BZIP2 (" + getString(R.string.compression_very_slow)
- + ")"), };
+ new Choice(Id.choice.compression.zip, "ZIP ("
+ + getString(R.string.compression_fast) + ")"),
+ new Choice(Id.choice.compression.zlib, "ZLIB ("
+ + getString(R.string.compression_fast) + ")"),
+ new Choice(Id.choice.compression.bzip2, "BZIP2 ("
+ + getString(R.string.compression_very_slow) + ")"), };
ArrayAdapter<Choice> adapter = new ArrayAdapter<Choice>(this,
android.R.layout.simple_spinner_item, choices);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
@@ -896,9 +893,9 @@ public class EncryptActivity extends SherlockFragmentActivity {
private void updateView() {
if (mEncryptionKeyIds == null || mEncryptionKeyIds.length == 0) {
- mSelectKeysButton.setText(R.string.no_keys_selected);
+ mSelectKeysButton.setText(getString(R.string.no_keys_selected));
} else if (mEncryptionKeyIds.length == 1) {
- mSelectKeysButton.setText(R.string.one_key_selected);
+ mSelectKeysButton.setText(getString(R.string.one_key_selected));
} else {
mSelectKeysButton.setText("" + mEncryptionKeyIds.length + " "
+ getResources().getString(R.string.n_keys_selected));
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpActivity.java
index 13350b6c6..d604c1c86 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpActivity.java
@@ -17,24 +17,21 @@
package org.sufficientlysecure.keychain.ui;
+import java.util.ArrayList;
+
import org.sufficientlysecure.keychain.R;
+import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.app.FragmentTransaction;
+import android.support.v4.view.ViewPager;
import android.widget.TextView;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
-import com.actionbarsherlock.view.MenuItem;
-
-import java.util.ArrayList;
-
-import android.content.Context;
-import android.support.v4.app.Fragment;
-import android.support.v4.app.FragmentPagerAdapter;
-import android.support.v4.view.ViewPager;
-
import com.actionbarsherlock.app.SherlockFragmentActivity;
public class HelpActivity extends SherlockFragmentActivity {
@@ -45,37 +42,19 @@ public class HelpActivity extends SherlockFragmentActivity {
TextView tabCenter;
TextView tabText;
- /**
- * Menu Items
- */
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
setContentView(R.layout.help_activity);
- mViewPager = new ViewPager(this);
- mViewPager.setId(R.id.pager);
+ mViewPager = (ViewPager) findViewById(R.id.pager);
- setContentView(mViewPager);
- ActionBar bar = getSupportActionBar();
- bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
- bar.setDisplayShowTitleEnabled(true);
- bar.setDisplayHomeAsUpEnabled(true);
+ final ActionBar actionBar = getSupportActionBar();
+ actionBar.setDisplayShowTitleEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+ actionBar.setHomeButtonEnabled(false);
+ actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mTabsAdapter = new TabsAdapter(this, mViewPager);
@@ -87,20 +66,20 @@ public class HelpActivity extends SherlockFragmentActivity {
Bundle startBundle = new Bundle();
startBundle.putInt(HelpFragmentHtml.ARG_HTML_FILE, R.raw.help_start);
- mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.help_tab_start)),
+ mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_start)),
HelpFragmentHtml.class, startBundle, (selectedTab == 0 ? true : false));
Bundle nfcBundle = new Bundle();
nfcBundle.putInt(HelpFragmentHtml.ARG_HTML_FILE, R.raw.help_nfc_beam);
- mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.help_tab_nfc_beam)),
+ mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_nfc_beam)),
HelpFragmentHtml.class, nfcBundle, (selectedTab == 1 ? true : false));
Bundle changelogBundle = new Bundle();
changelogBundle.putInt(HelpFragmentHtml.ARG_HTML_FILE, R.raw.help_changelog);
- mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.help_tab_changelog)),
+ mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_changelog)),
HelpFragmentHtml.class, changelogBundle, (selectedTab == 2 ? true : false));
- mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.help_tab_about)),
+ mTabsAdapter.addTab(actionBar.newTab().setText(getString(R.string.help_tab_about)),
HelpFragmentAbout.class, null, (selectedTab == 3 ? true : false));
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpFragmentAbout.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpFragmentAbout.java
index e7a977707..840ebb650 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpFragmentAbout.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/HelpFragmentAbout.java
@@ -48,7 +48,7 @@ public class HelpFragmentAbout extends SherlockFragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.help_fragment_about, container, false);
+ View view = inflater.inflate(R.layout.help_about_fragment, container, false);
TextView versionText = (TextView) view.findViewById(R.id.help_about_version);
versionText.setText(getString(R.string.help_about_version) + " " + getVersion());
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
index 37edc8f49..7d8f4154f 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysActivity.java
@@ -22,7 +22,6 @@ import java.util.List;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.ActionBarHelper;
import org.sufficientlysecure.keychain.service.KeychainIntentService;
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
import org.sufficientlysecure.keychain.ui.adapter.ImportKeysListEntry;
@@ -30,26 +29,30 @@ import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
import org.sufficientlysecure.keychain.util.Log;
+import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.nfc.NdefMessage;
+import android.nfc.NfcAdapter;
import android.os.Bundle;
import android.os.Message;
import android.os.Messenger;
+import android.os.Parcelable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.View;
+import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.OnNavigationListener;
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.BootstrapButton;
-public class ImportKeysActivity extends SherlockFragmentActivity implements OnNavigationListener {
+public class ImportKeysActivity extends DrawerActivity implements OnNavigationListener {
public static final String ACTION_IMPORT_KEY = Constants.INTENT_PREFIX + "IMPORT_KEY";
public static final String ACTION_IMPORT_KEY_FROM_QR_CODE = Constants.INTENT_PREFIX
+ "IMPORT_KEY_FROM_QR_CODE";
@@ -73,14 +76,36 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
OnNavigationListener mOnNavigationListener;
String[] mNavigationStrings;
+ BootstrapButton mImportButton;
+ BootstrapButton mImportSignUploadButton;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.import_keys);
+ setContentView(R.layout.import_keys_activity);
+
+ mImportButton = (BootstrapButton) findViewById(R.id.import_import);
+ mImportButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ importKeys();
+ }
+ });
+ mImportSignUploadButton = (BootstrapButton) findViewById(R.id.import_sign_and_upload);
+ mImportSignUploadButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ signAndUploadOnClick();
+ }
+ });
+
+ getSupportActionBar().setDisplayShowTitleEnabled(false);
+
+ setupDrawerNavigation(savedInstanceState);
// set actionbar without home button if called from another app
- ActionBarHelper.setBackButton(this);
+ // ActionBarHelper.setBackButton(this);
// set drop down navigation
mNavigationStrings = getResources().getStringArray(R.array.import_action_list);
@@ -90,7 +115,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
list.setDropDownViewResource(R.layout.sherlock_spinner_dropdown_item);
getSupportActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
getSupportActionBar().setListNavigationCallbacks(list, this);
- getSupportActionBar().setDisplayShowTitleEnabled(false);
handleActions(savedInstanceState, getIntent());
}
@@ -216,23 +240,6 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
mListFragment.loadNew(importData, importFilename);
}
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
-
- }
- }
-
// private void importAndSignOld(final long keyId, final String expectedFingerprint) {
// if (expectedFingerprint != null && expectedFingerprint.length() > 0) {
//
@@ -345,7 +352,8 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
int bad = returnData.getInt(KeychainIntentService.RESULT_IMPORT_BAD);
String toastMessage;
if (added > 0 && updated > 0) {
- toastMessage = getString(R.string.keys_added_and_updated, added, updated);
+ toastMessage = getString(R.string.keys_added_and_updated, added,
+ updated);
} else if (added > 0) {
toastMessage = getString(R.string.keys_added, added);
} else if (updated > 0) {
@@ -396,11 +404,11 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
}
}
- public void importOnClick(View view) {
+ public void importOnClick() {
importKeys();
}
- public void signAndUploadOnClick(View view) {
+ public void signAndUploadOnClick() {
// first, import!
// importOnClick(view);
@@ -409,4 +417,43 @@ public class ImportKeysActivity extends SherlockFragmentActivity implements OnNa
.show();
}
+ /**
+ * NFC
+ */
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Check to see that the Activity started due to an Android Beam
+ if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
+ handleActionNdefDiscovered(getIntent());
+ }
+ }
+
+ /**
+ * NFC
+ */
+ @Override
+ public void onNewIntent(Intent intent) {
+ // onResume gets called after this to handle the intent
+ setIntent(intent);
+ }
+
+ /**
+ * NFC: Parses the NDEF Message from the intent and prints to the TextView
+ */
+ @SuppressLint("NewApi")
+ void handleActionNdefDiscovered(Intent intent) {
+ Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
+ // only one message sent during the beam
+ NdefMessage msg = (NdefMessage) rawMsgs[0];
+ // record 0 contains the MIME type, record 1 is the AAR, if present
+ byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
+
+ Intent importIntent = new Intent(this, ImportKeysActivity.class);
+ importIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY);
+ importIntent.putExtra(ImportKeysActivity.EXTRA_KEY_BYTES, receivedKeyringBytes);
+
+ handleActions(null, importIntent);
+ }
+
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java
index dcb7dbcc6..31f758395 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysClipboardFragment.java
@@ -26,12 +26,13 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.Button;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class ImportKeysClipboardFragment extends Fragment {
private ImportKeysActivity mImportActivity;
- private Button mButton;
+ private BootstrapButton mButton;
/**
* Creates new instance of this fragment
@@ -52,7 +53,7 @@ public class ImportKeysClipboardFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_clipboard_fragment, container, false);
- mButton = (Button) view.findViewById(R.id.import_clipboard_button);
+ mButton = (BootstrapButton) view.findViewById(R.id.import_clipboard_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
index fbca9013b..ea76d2898 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysFileFragment.java
@@ -31,14 +31,15 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
-import android.widget.ImageButton;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class ImportKeysFileFragment extends Fragment {
public static final String ARG_PATH = "path";
private ImportKeysActivity mImportActivity;
private EditText mFilename;
- private ImageButton mBrowse;
+ private BootstrapButton mBrowse;
/**
* Creates new instance of this fragment
@@ -61,7 +62,7 @@ public class ImportKeysFileFragment extends Fragment {
View view = inflater.inflate(R.layout.import_keys_file_fragment, container, false);
mFilename = (EditText) view.findViewById(R.id.import_keys_file_input);
- mBrowse = (ImageButton) view.findViewById(R.id.import_keys_file_browse);
+ mBrowse = (BootstrapButton) view.findViewById(R.id.import_keys_file_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java
index 2d756dde6..83af8cf48 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysNFCFragment.java
@@ -26,11 +26,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.Button;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class ImportKeysNFCFragment extends Fragment {
- private Button mButton;
+ private BootstrapButton mButton;
/**
* Creates new instance of this fragment
@@ -51,7 +52,7 @@ public class ImportKeysNFCFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_nfc_fragment, container, false);
- mButton = (Button) view.findViewById(R.id.import_nfc_button);
+ mButton = (BootstrapButton) view.findViewById(R.id.import_nfc_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
index 62b59b4f7..f9ead3a94 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysQrCodeFragment.java
@@ -30,18 +30,18 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
+import com.beardedhen.androidbootstrap.BootstrapButton;
import com.google.zxing.integration.android.IntentIntegratorSupportV4;
import com.google.zxing.integration.android.IntentResult;
public class ImportKeysQrCodeFragment extends Fragment {
private ImportKeysActivity mImportActivity;
- private Button mButton;
+ private BootstrapButton mButton;
private TextView mText;
private ProgressBar mProgress;
@@ -66,7 +66,7 @@ public class ImportKeysQrCodeFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_qr_code_fragment, container, false);
- mButton = (Button) view.findViewById(R.id.import_qrcode_button);
+ mButton = (BootstrapButton) view.findViewById(R.id.import_qrcode_button);
mText = (TextView) view.findViewById(R.id.import_qrcode_text);
mProgress = (ProgressBar) view.findViewById(R.id.import_qrcode_progress);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
index 106c8ebef..c985f1f60 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ImportKeysServerFragment.java
@@ -24,12 +24,13 @@ import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
-import android.view.ViewGroup;
import android.view.View.OnClickListener;
-import android.widget.Button;
+import android.view.ViewGroup;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class ImportKeysServerFragment extends Fragment {
- private Button mButton;
+ private BootstrapButton mButton;
/**
* Creates new instance of this fragment
@@ -50,7 +51,7 @@ public class ImportKeysServerFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.import_keys_keyserver_fragment, container, false);
- mButton = (Button) view.findViewById(R.id.import_keyserver_button);
+ mButton = (BootstrapButton) view.findViewById(R.id.import_keyserver_button);
mButton.setOnClickListener(new OnClickListener() {
@Override
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListActivity.java
deleted file mode 100644
index 7b844fe08..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListActivity.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
-import org.sufficientlysecure.keychain.service.KeychainIntentService;
-import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
-import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
-import org.sufficientlysecure.keychain.ui.dialog.FileDialogFragment;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.R;
-
-import android.app.ProgressDialog;
-import android.app.SearchManager;
-import android.content.Intent;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Messenger;
-import android.widget.Toast;
-
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-
-public class KeyListActivity extends SherlockFragmentActivity {
-
- protected String mExportFilename = Constants.path.APP_DIR + "/";
-
- protected String mImportData;
- protected boolean mDeleteAfterImport = false;
-
- protected int mKeyType;
-
- FileDialogFragment mFileDialog;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- getSupportActionBar().setDisplayHomeAsUpEnabled(true);
- getSupportActionBar().setHomeButtonEnabled(true);
-
- handleActions(getIntent());
- }
-
- // TODO: needed?
- // @Override
- // protected void onNewIntent(Intent intent) {
- // super.onNewIntent(intent);
- // handleActions(intent);
- // }
-
- protected void handleActions(Intent intent) {
- String action = intent.getAction();
- Bundle extras = intent.getExtras();
-
- if (extras == null) {
- extras = new Bundle();
- }
-
- /**
- * Android Standard Actions
- */
- String searchString = null;
- if (Intent.ACTION_SEARCH.equals(action)) {
- searchString = extras.getString(SearchManager.QUERY);
- if (searchString != null && searchString.trim().length() == 0) {
- searchString = null;
- }
- }
-
- // if (searchString == null) {
- // mFilterLayout.setVisibility(View.GONE);
- // } else {
- // mFilterLayout.setVisibility(View.VISIBLE);
- // mFilterInfo.setText(getString(R.string.filterInfo, searchString));
- // }
- //
- // if (mListAdapter != null) {
- // mListAdapter.cleanup();
- // }
- // mListAdapter = new KeyListAdapter(this, searchString);
- // mList.setAdapter(mListAdapter);
-
- }
-
- @Override
- protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- switch (requestCode) {
- case Id.request.filename: {
- if (resultCode == RESULT_OK && data != null) {
- try {
- String path = data.getData().getPath();
- Log.d(Constants.TAG, "path=" + path);
-
- // set filename used in export/import dialogs
- mFileDialog.setFilename(path);
- } catch (NullPointerException e) {
- Log.e(Constants.TAG, "Nullpointer while retrieving path!", e);
- }
- }
- return;
- }
-
- default: {
- break;
- }
- }
- super.onActivityResult(requestCode, resultCode, data);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- super.onCreateOptionsMenu(menu);
- // TODO: reimplement!
- // menu.add(3, Id.menu.option.search, 0, R.string.menu_search)
- // .setIcon(R.drawable.ic_menu_search).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS);
- menu.add(0, Id.menu.option.import_from_file, 5, R.string.menu_import_from_file)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- menu.add(0, Id.menu.option.export_keys, 6, R.string.menu_export_keys).setShowAsAction(
- MenuItem.SHOW_AS_ACTION_NEVER | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
- case Id.menu.option.import_from_file: {
- Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
- intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE);
- startActivityForResult(intentImportFromFile, 0);
- return true;
- }
-
- case Id.menu.option.export_keys: {
- showExportKeysDialog(-1);
- return true;
- }
-
- // case Id.menu.option.search:
- // startSearch("", false, null, false);
- // return true;
-
- default: {
- return super.onOptionsItemSelected(item);
- }
- }
- }
-
- /**
- * Show dialog where to export keys
- *
- * @param keyRingMasterKeyId
- * if -1 export all keys
- */
- public void showExportKeysDialog(final long keyRingMasterKeyId) {
- // Message is received after file is selected
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == FileDialogFragment.MESSAGE_OKAY) {
- Bundle data = message.getData();
- mExportFilename = data.getString(FileDialogFragment.MESSAGE_DATA_FILENAME);
-
- exportKeys(keyRingMasterKeyId);
- }
- }
- };
-
- // Create a new Messenger for the communication back
- final Messenger messenger = new Messenger(returnHandler);
-
- DialogFragmentWorkaround.INTERFACE.runnableRunDelayed(new Runnable() {
- public void run() {
- String title = null;
- if (keyRingMasterKeyId != -1) {
- // single key export
- title = getString(R.string.title_export_key);
- } else {
- title = getString(R.string.title_export_keys);
- }
-
- String message = null;
- if (mKeyType == Id.type.public_key) {
- message = getString(R.string.specify_file_to_export_to);
- } else {
- message = getString(R.string.specify_file_to_export_secret_keys_to);
- }
-
- mFileDialog = FileDialogFragment.newInstance(messenger, title, message,
- mExportFilename, null, Id.request.filename);
-
- mFileDialog.show(getSupportFragmentManager(), "fileDialog");
- }
- });
- }
-
- /**
- * Show dialog to delete key
- *
- * @param keyRingId
- */
- public void showDeleteKeyDialog(long keyRingId) {
- // Message is received after key is deleted
- Handler returnHandler = new Handler() {
- @Override
- public void handleMessage(Message message) {
- if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
- // no further actions needed
- }
- }
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(returnHandler);
-
- DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
- keyRingId, mKeyType);
-
- deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
- }
-
- /**
- * Export keys
- *
- * @param keyRingMasterKeyId
- * if -1 export all keys
- */
- public void exportKeys(long keyRingMasterKeyId) {
- Log.d(Constants.TAG, "exportKeys started");
-
- // Send all information needed to service to export key in other thread
- Intent intent = new Intent(this, KeychainIntentService.class);
-
- intent.setAction(KeychainIntentService.ACTION_EXPORT_KEYRING);
-
- // fill values for this action
- Bundle data = new Bundle();
-
- data.putString(KeychainIntentService.EXPORT_FILENAME, mExportFilename);
- data.putInt(KeychainIntentService.EXPORT_KEY_TYPE, mKeyType);
-
- if (keyRingMasterKeyId == -1) {
- data.putBoolean(KeychainIntentService.EXPORT_ALL, true);
- } else {
- data.putLong(KeychainIntentService.EXPORT_KEY_RING_MASTER_KEY_ID, keyRingMasterKeyId);
- }
-
- intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
-
- // Message is received after exporting is done in ApgService
- KeychainIntentServiceHandler exportHandler = new KeychainIntentServiceHandler(this,
- R.string.progress_exporting, ProgressDialog.STYLE_HORIZONTAL) {
- public void handleMessage(Message message) {
- // handle messages by standard ApgHandler first
- super.handleMessage(message);
-
- if (message.arg1 == KeychainIntentServiceHandler.MESSAGE_OKAY) {
- // get returned data bundle
- Bundle returnData = message.getData();
-
- int exported = returnData.getInt(KeychainIntentService.RESULT_EXPORT);
- String toastMessage;
- if (exported == 1) {
- toastMessage = getString(R.string.key_exported);
- } else if (exported > 0) {
- toastMessage = getString(R.string.keys_exported, exported);
- } else {
- toastMessage = getString(R.string.no_keys_exported);
- }
- Toast.makeText(KeyListActivity.this, toastMessage, Toast.LENGTH_SHORT).show();
-
- }
- };
- };
-
- // Create a new Messenger for the communication back
- Messenger messenger = new Messenger(exportHandler);
- intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger);
-
- // show progress dialog
- exportHandler.showProgressDialog(this);
-
- // start service with intent
- startService(intent);
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListFragment.java
deleted file mode 100644
index 0d61b1108..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListFragment.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.widget.ExpandableListFragment;
-import org.sufficientlysecure.keychain.R;
-
-import android.os.Bundle;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.view.View;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
-
-public class KeyListFragment extends ExpandableListFragment {
- protected KeyListActivity mKeyListActivity;
-
- @Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- mKeyListActivity = (KeyListActivity) getActivity();
-
- // register long press context menu
- registerForContextMenu(getListView());
-
- // Give some text to display if there is no data. In a real
- // application this would come from a resource.
- setEmptyText(getString(R.string.list_empty));
- }
-
- /**
- * Context Menu on Long Click
- */
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- menu.add(0, Id.menu.export, 5, R.string.menu_export_key);
- menu.add(0, Id.menu.delete, 111, R.string.menu_delete_key);
- }
-
- @Override
- public boolean onContextItemSelected(android.view.MenuItem item) {
- ExpandableListContextMenuInfo expInfo = (ExpandableListContextMenuInfo) item.getMenuInfo();
-
- // expInfo.id would also return row id of childs, but we always want to get the row id of
- // the group item, thus we are using the following way
- int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition);
- long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition);
-
- switch (item.getItemId()) {
- case Id.menu.export:
- long masterKeyId = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId);
- if (masterKeyId == -1) {
- masterKeyId = ProviderHelper.getSecretMasterKeyId(mKeyListActivity, keyRingRowId);
- }
-
- mKeyListActivity.showExportKeysDialog(masterKeyId);
- return true;
-
- case Id.menu.delete:
- mKeyListActivity.showDeleteKeyDialog(keyRingRowId);
- return true;
-
- default:
- return super.onContextItemSelected(item);
-
- }
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
index 95a3dd3b1..204939610 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicActivity.java
@@ -20,102 +20,79 @@ package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.ExportHelper;
+
+import android.content.Intent;
+import android.os.Bundle;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
-import android.content.Intent;
-import android.os.Bundle;
+public class KeyListPublicActivity extends DrawerActivity {
-public class KeyListPublicActivity extends KeyListActivity {
+ ExportHelper mExportHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mKeyType = Id.type.public_key;
+ mExportHelper = new ExportHelper(this);
setContentView(R.layout.key_list_public_activity);
- mExportFilename = Constants.path.APP_DIR + "/pubexport.asc";
+ // now setup navigation drawer in DrawerActivity...
+ setupDrawerNavigation(savedInstanceState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- menu.add(1, Id.menu.option.key_server, 1, R.string.menu_key_server)
- .setIcon(R.drawable.ic_menu_search_list)
- .setShowAsAction(
- MenuItem.SHOW_AS_ACTION_ALWAYS);
- menu.add(1, Id.menu.option.import_from_qr_code, 2, R.string.menu_import_from_qr_code)
- .setShowAsAction(
- MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- menu.add(1, Id.menu.option.import_from_nfc, 3, R.string.menu_import_from_nfc)
- .setShowAsAction(
- MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
-
+ getSupportMenuInflater().inflate(R.menu.key_list_public, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case Id.menu.option.key_server: {
- startActivityForResult(new Intent(this, KeyServerQueryActivity.class), 0);
+ case R.id.menu_key_list_public_import:
+ Intent intentImport = new Intent(this, ImportKeysActivity.class);
+ startActivityForResult(intentImport, Id.request.import_from_qr_code);
return true;
- }
- case Id.menu.option.import_from_file: {
- Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
- intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE);
- startActivityForResult(intentImportFromFile, 0);
-
- return true;
- }
-
- case Id.menu.option.import_from_qr_code: {
- Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
- intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_QR_CODE);
- startActivityForResult(intentImportFromFile, Id.request.import_from_qr_code);
+ case R.id.menu_key_list_public_export:
+ mExportHelper.showExportKeysDialog(null, Id.type.public_key, Constants.path.APP_DIR
+ + "/pubexport.asc");
return true;
- }
-
- case Id.menu.option.import_from_nfc: {
- Intent intentImportFromFile = new Intent(this, ImportKeysActivity.class);
- intentImportFromFile.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_NFC);
- startActivityForResult(intentImportFromFile, 0);
-
- return true;
- }
-
- default: {
+ default:
return super.onOptionsItemSelected(item);
}
- }
}
- // @Override
- // protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- // switch (requestCode) {
- // case Id.request.look_up_key_id: {
- // if (resultCode == RESULT_CANCELED || data == null
- // || data.getStringExtra(KeyServerQueryActivity.RESULT_EXTRA_TEXT) == null) {
- // return;
- // }
- //
- // Intent intent = new Intent(this, KeyListPublicActivity.class);
- // intent.setAction(KeyListPublicActivity.ACTION_IMPORT);
- // intent.putExtra(KeyListPublicActivity.EXTRA_TEXT,
- // data.getStringExtra(KeyListActivity.EXTRA_TEXT));
- // handleActions(intent);
- // break;
- // }
- //
- // default: {
- // super.onActivityResult(requestCode, resultCode, data);
- // break;
- // }
- // }
- // }
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (!mExportHelper.handleActivityResult(requestCode, resultCode, data)) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ // switch (requestCode) {
+ // case Id.request.look_up_key_id: {
+ // if (resultCode == RESULT_CANCELED || data == null
+ // || data.getStringExtra(KeyServerQueryActivity.RESULT_EXTRA_TEXT) == null) {
+ // return;
+ // }
+ //
+ // Intent intent = new Intent(this, KeyListPublicActivity.class);
+ // intent.setAction(KeyListPublicActivity.ACTION_IMPORT);
+ // intent.putExtra(KeyListPublicActivity.EXTRA_TEXT,
+ // data.getStringExtra(KeyListActivity.EXTRA_TEXT));
+ // handleActions(intent);
+ // break;
+ // }
+ //
+ // default: {
+ // super.onActivityResult(requestCode, resultCode, data);
+ // break;
+ // }
+ // }
+ }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
index 0fdcea809..ea088efca 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListPublicFragment.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -17,171 +17,205 @@
package org.sufficientlysecure.keychain.ui;
-import org.spongycastle.openpgp.PGPPublicKeyRing;
+import java.util.Set;
+
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
-import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.adapter.KeyListPublicAdapter;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
+import se.emilsjolander.stickylistheaders.ApiLevelTooLowException;
+import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.support.v4.app.LoaderManager;
-import android.view.ContextMenu;
+import android.view.ActionMode;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
-import android.view.ContextMenu.ContextMenuInfo;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.AdapterView;
+import android.widget.ListView;
-public class KeyListPublicFragment extends KeyListFragment implements
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
+/**
+ * Public key list with sticky list headers. It does _not_ extend ListFragment because it uses
+ * StickyListHeaders library which does not extend upon ListView.
+ */
+public class KeyListPublicFragment extends Fragment implements AdapterView.OnItemClickListener,
LoaderManager.LoaderCallbacks<Cursor> {
- private KeyListPublicActivity mKeyListPublicActivity;
+ private KeyListPublicAdapter mAdapter;
+ private StickyListHeadersListView mStickyList;
- private KeyListAdapter mAdapter;
+ // empty layout
+ private BootstrapButton mButtonEmptyCreate;
+ private BootstrapButton mButtonEmptyImport;
/**
- * Define Adapter and Loader on create of Activity
+ * Load custom layout with StickyListView from library
*/
@Override
- public void onActivityCreated(Bundle savedInstanceState) {
- super.onActivityCreated(savedInstanceState);
-
- mKeyListPublicActivity = (KeyListPublicActivity) getActivity();
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.key_list_public_fragment, container, false);
+
+ mButtonEmptyCreate = (BootstrapButton) view.findViewById(R.id.key_list_empty_button_create);
+ mButtonEmptyCreate.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(getActivity(), EditKeyActivity.class);
+ intent.setAction(EditKeyActivity.ACTION_CREATE_KEY);
+ intent.putExtra(EditKeyActivity.EXTRA_GENERATE_DEFAULT_KEYS, true);
+ intent.putExtra(EditKeyActivity.EXTRA_USER_IDS, ""); // show user id view
+ startActivityForResult(intent, 0);
+ }
+ });
- mAdapter = new KeyListAdapter(mKeyListPublicActivity, null, Id.type.public_key);
- setListAdapter(mAdapter);
+ mButtonEmptyImport = (BootstrapButton) view.findViewById(R.id.key_list_empty_button_import);
+ mButtonEmptyImport.setOnClickListener(new OnClickListener() {
- // Start out with a progress indicator.
- setListShown(false);
+ @Override
+ public void onClick(View v) {
+ Intent intentImportFromFile = new Intent(getActivity(), ImportKeysActivity.class);
+ startActivityForResult(intentImportFromFile, Id.request.import_from_qr_code);
+ }
+ });
- // Prepare the loader. Either re-connect with an existing one,
- // or start a new one.
- // id is -1 as the child cursors are numbered 0,...,n
- getLoaderManager().initLoader(-1, null, this);
+ return view;
}
/**
- * Context Menu on Long Click
+ * Define Adapter and Loader on create of Activity
*/
+ @SuppressLint("NewApi")
@Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- menu.add(0, Id.menu.update, 1, R.string.menu_update_key);
- menu.add(0, Id.menu.signKey, 2, R.string.menu_sign_key);
- menu.add(0, Id.menu.exportToServer, 3, R.string.menu_export_key_to_server);
- menu.add(0, Id.menu.share, 6, R.string.menu_share);
- menu.add(0, Id.menu.share_qr_code, 7, R.string.menu_share_qr_code);
- menu.add(0, Id.menu.share_nfc, 8, R.string.menu_share_nfc);
-
- }
-
- @Override
- public boolean onContextItemSelected(android.view.MenuItem item) {
- ExpandableListContextMenuInfo expInfo = (ExpandableListContextMenuInfo) item.getMenuInfo();
-
- // expInfo.id would also return row id of childs, but we always want to get the row id of
- // the group item, thus we are using the following way
- int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition);
- long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition);
-
- switch (item.getItemId()) {
- case Id.menu.update:
- long updateKeyId = 0;
- PGPPublicKeyRing updateKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(
- mKeyListActivity, keyRingRowId);
- if (updateKeyRing != null) {
- updateKeyId = PgpKeyHelper.getMasterKey(updateKeyRing).getKeyID();
- }
- if (updateKeyId == 0) {
- // this shouldn't happen
- return true;
- }
-
- Intent queryIntent = new Intent(mKeyListActivity, KeyServerQueryActivity.class);
- queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID_AND_RETURN);
- queryIntent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, updateKeyId);
-
- // TODO: lookup??
- startActivityForResult(queryIntent, Id.request.look_up_key_id);
-
- return true;
-
- case Id.menu.exportToServer:
- Intent uploadIntent = new Intent(mKeyListActivity, KeyServerUploadActivity.class);
- uploadIntent.setAction(KeyServerUploadActivity.ACTION_EXPORT_KEY_TO_SERVER);
- uploadIntent.putExtra(KeyServerUploadActivity.EXTRA_KEYRING_ROW_ID, (int)keyRingRowId);
- startActivityForResult(uploadIntent, Id.request.export_to_server);
-
- return true;
-
- case Id.menu.signKey:
- long keyId = 0;
- PGPPublicKeyRing signKeyRing = ProviderHelper.getPGPPublicKeyRingByRowId(
- mKeyListActivity, keyRingRowId);
- if (signKeyRing != null) {
- keyId = PgpKeyHelper.getMasterKey(signKeyRing).getKeyID();
- }
- if (keyId == 0) {
- // this shouldn't happen
- return true;
- }
-
- Intent signIntent = new Intent(mKeyListActivity, SignKeyActivity.class);
- signIntent.putExtra(SignKeyActivity.EXTRA_KEY_ID, keyId);
- startActivity(signIntent);
-
- return true;
-
- case Id.menu.share_qr_code:
- // get master key id using row id
- long masterKeyId = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId);
-
- Intent qrCodeIntent = new Intent(mKeyListActivity, ShareActivity.class);
- qrCodeIntent.setAction(ShareActivity.ACTION_SHARE_KEYRING_WITH_QR_CODE);
- qrCodeIntent.putExtra(ShareActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
- startActivityForResult(qrCodeIntent, 0);
-
- return true;
-
- case Id.menu.share_nfc:
- // get master key id using row id
- long masterKeyId2 = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId);
-
- Intent nfcIntent = new Intent(mKeyListActivity, ShareNfcBeamActivity.class);
- nfcIntent.setAction(ShareNfcBeamActivity.ACTION_SHARE_KEYRING_WITH_NFC);
- nfcIntent.putExtra(ShareNfcBeamActivity.EXTRA_MASTER_KEY_ID, masterKeyId2);
- startActivityForResult(nfcIntent, 0);
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
- return true;
+ // mKeyListPublicActivity = (KeyListPublicActivity) getActivity();
+ mStickyList = (StickyListHeadersListView) getActivity().findViewById(R.id.list);
- case Id.menu.share:
- // get master key id using row id
- long masterKeyId3 = ProviderHelper.getPublicMasterKeyId(mKeyListActivity, keyRingRowId);
+ mStickyList.setOnItemClickListener(this);
+ mStickyList.setAreHeadersSticky(true);
+ mStickyList.setDrawingListUnderStickyHeader(false);
+ mStickyList.setFastScrollEnabled(true);
+ try {
+ mStickyList.setFastScrollAlwaysVisible(true);
+ } catch (ApiLevelTooLowException e) {
+ }
- Intent shareIntent = new Intent(mKeyListActivity, ShareActivity.class);
- shareIntent.setAction(ShareActivity.ACTION_SHARE_KEYRING);
- shareIntent.putExtra(ShareActivity.EXTRA_MASTER_KEY_ID, masterKeyId3);
- startActivityForResult(shareIntent, 0);
+ // this view is made visible if no data is available
+ mStickyList.setEmptyView(getActivity().findViewById(R.id.empty));
+
+ /*
+ * ActionBarSherlock does not support MultiChoiceModeListener. Thus multi-selection is only
+ * available for Android >= 3.0
+ */
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ mStickyList.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+ mStickyList.getWrappedList().setMultiChoiceModeListener(new MultiChoiceModeListener() {
+
+ private int count = 0;
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ android.view.MenuInflater inflater = getActivity().getMenuInflater();
+ inflater.inflate(R.menu.key_list_public_multi, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ Set<Integer> positions = mAdapter.getCurrentCheckedPosition();
+
+ // get IDs for checked positions as long array
+ long[] ids = new long[positions.size()];
+ int i = 0;
+ for (int pos : positions) {
+ ids[i] = mAdapter.getItemId(pos);
+ i++;
+ }
+
+ switch (item.getItemId()) {
+ case R.id.menu_key_list_public_multi_encrypt: {
+ encrypt(ids);
+
+ break;
+ }
+ case R.id.menu_key_list_public_multi_delete: {
+ showDeleteKeyDialog(ids);
+
+ break;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ count = 0;
+ mAdapter.clearSelection();
+ }
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ if (checked) {
+ count++;
+ mAdapter.setNewSelection(position, checked);
+ } else {
+ count--;
+ mAdapter.removeSelection(position);
+ }
+
+ String keysSelected = getResources().getQuantityString(
+ R.plurals.key_list_selected_keys, count, count);
+ mode.setTitle(keysSelected);
+ }
+
+ });
+ }
- return true;
+ // NOTE: Not supported by StickyListHeader, thus no indicator is shown while loading
+ // Start out with a progress indicator.
+ // setListShown(false);
- default:
- return super.onContextItemSelected(item);
+ // Create an empty adapter we will use to display the loaded data.
+ mAdapter = new KeyListPublicAdapter(getActivity(), null, Id.type.public_key, USER_ID_INDEX);
+ mStickyList.setAdapter(mAdapter);
- }
+ // Prepare the loader. Either re-connect with an existing one,
+ // or start a new one.
+ getLoaderManager().initLoader(0, null, this);
}
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID,
UserIds.USER_ID };
+ static final int USER_ID_INDEX = 2;
+
static final String SORT_ORDER = UserIds.USER_ID + " ASC";
@Override
@@ -199,14 +233,17 @@ public class KeyListPublicFragment extends KeyListFragment implements
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
- mAdapter.setGroupCursor(data);
+ mAdapter.swapCursor(data);
+ mStickyList.setAdapter(mAdapter);
+
+ // NOTE: Not supported by StickyListHeader, thus no indicator is shown while loading
// The list should now be shown.
- if (isResumed()) {
- setListShown(true);
- } else {
- setListShownNoAnimation(true);
- }
+ // if (isResumed()) {
+ // setListShown(true);
+ // } else {
+ // setListShownNoAnimation(true);
+ // }
}
@Override
@@ -214,7 +251,43 @@ public class KeyListPublicFragment extends KeyListFragment implements
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
- mAdapter.setGroupCursor(null);
+ mAdapter.swapCursor(null);
+ }
+
+ /**
+ * On click on item, start key view activity
+ */
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+ Intent detailsIntent = new Intent(getActivity(), ViewKeyActivity.class);
+ detailsIntent.setData(KeychainContract.KeyRings.buildPublicKeyRingsUri(Long.toString(id)));
+ startActivity(detailsIntent);
+ }
+
+ public void encrypt(long[] keyRingRowIds) {
+ // get master key ids from row ids
+ long[] keyRingIds = new long[keyRingRowIds.length];
+ for (int i = 0; i < keyRingRowIds.length; i++) {
+ keyRingIds[i] = ProviderHelper.getPublicMasterKeyId(getActivity(), keyRingRowIds[i]);
+ }
+
+ Intent intent = new Intent(getActivity(), EncryptActivity.class);
+ intent.setAction(EncryptActivity.ACTION_ENCRYPT);
+ intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, keyRingIds);
+ // used instead of startActivity set actionbar based on callingPackage
+ startActivityForResult(intent, 0);
+ }
+
+ /**
+ * Show dialog to delete key
+ *
+ * @param keyRingRowIds
+ */
+ public void showDeleteKeyDialog(long[] keyRingRowIds) {
+ DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(null,
+ keyRingRowIds, Id.type.public_key);
+
+ deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
}
-}
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
index 822c73872..34a053d25 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretActivity.java
@@ -1,18 +1,18 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
@@ -20,6 +20,7 @@ package org.sufficientlysecure.keychain.ui;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.helper.ExportHelper;
import android.content.Intent;
import android.os.Bundle;
@@ -27,47 +28,53 @@ import android.os.Bundle;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
-public class KeyListSecretActivity extends KeyListActivity {
+public class KeyListSecretActivity extends DrawerActivity {
+
+ ExportHelper mExportHelper;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- mKeyType = Id.type.secret_key;
+ mExportHelper = new ExportHelper(this);
setContentView(R.layout.key_list_secret_activity);
- mExportFilename = Constants.path.APP_DIR + "/secexport.asc";
+ // now setup navigation drawer in DrawerActivity...
+ setupDrawerNavigation(savedInstanceState);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
super.onCreateOptionsMenu(menu);
- menu.add(1, Id.menu.option.create, 1, R.string.menu_create_key).setShowAsAction(
- MenuItem.SHOW_AS_ACTION_IF_ROOM | MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- menu.add(1, Id.menu.option.createExpert, 2, R.string.menu_create_key_expert).setShowAsAction(
- MenuItem.SHOW_AS_ACTION_NEVER);
-
+ getSupportMenuInflater().inflate(R.menu.key_list_secret, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case Id.menu.option.create: {
+ case R.id.menu_key_list_secret_create:
createKey();
- return true;
- }
- case Id.menu.option.createExpert: {
+ return true;
+ case R.id.menu_key_list_secret_create_expert:
createKeyExpert();
+
return true;
- }
+ case R.id.menu_key_list_secret_export:
+ mExportHelper.showExportKeysDialog(null, Id.type.secret_key, Constants.path.APP_DIR
+ + "/secexport.asc");
- default: {
+ return true;
+ case R.id.menu_key_list_secret_import:
+ Intent intentImport = new Intent(this, ImportKeysActivity.class);
+ startActivityForResult(intentImport, Id.request.import_from_qr_code);
+
+ return true;
+ default:
return super.onOptionsItemSelected(item);
}
- }
}
private void createKey() {
@@ -84,12 +91,11 @@ public class KeyListSecretActivity extends KeyListActivity {
startActivityForResult(intent, 0);
}
- void editKey(long masterKeyId, boolean masterCanSign) {
- Intent intent = new Intent(this, EditKeyActivity.class);
- intent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
- intent.putExtra(EditKeyActivity.EXTRA_MASTER_KEY_ID, masterKeyId);
- intent.putExtra(EditKeyActivity.EXTRA_MASTER_CAN_SIGN, masterCanSign);
- startActivityForResult(intent, 0);
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (!mExportHelper.handleActivityResult(requestCode, resultCode, data)) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
}
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
index 4bbf3d6ef..0e2d22e1e 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyListSecretFragment.java
@@ -1,116 +1,168 @@
/*
- * Copyright (C) 2012 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2010 Thialfihar <thi@thialfihar.org>
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
*
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
*
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.sufficientlysecure.keychain.ui;
+import java.util.Set;
+
import org.sufficientlysecure.keychain.Id;
import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.adapter.KeyListAdapter;
+import org.sufficientlysecure.keychain.ui.adapter.KeyListSecretAdapter;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
+import android.annotation.SuppressLint;
+import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
-import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
+import android.view.ActionMode;
+import android.view.Menu;
+import android.view.MenuItem;
import android.view.View;
-import android.widget.ExpandableListView;
-import android.widget.ExpandableListView.ExpandableListContextMenuInfo;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.AdapterView.OnItemClickListener;
-public class KeyListSecretFragment extends KeyListFragment implements
- LoaderManager.LoaderCallbacks<Cursor> {
+import com.actionbarsherlock.app.SherlockListFragment;
- private KeyListSecretActivity mKeyListSecretActivity;
+public class KeyListSecretFragment extends SherlockListFragment implements
+ LoaderManager.LoaderCallbacks<Cursor>, OnItemClickListener {
- private KeyListAdapter mAdapter;
+ private KeyListSecretActivity mKeyListSecretActivity;
+ private KeyListSecretAdapter mAdapter;
/**
* Define Adapter and Loader on create of Activity
*/
+ @SuppressLint("NewApi")
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mKeyListSecretActivity = (KeyListSecretActivity) getActivity();
- mAdapter = new KeyListAdapter(mKeyListSecretActivity, null, Id.type.secret_key);
- setListAdapter(mAdapter);
+ getListView().setOnItemClickListener(this);
+
+ // Give some text to display if there is no data. In a real
+ // application this would come from a resource.
+ setEmptyText(getString(R.string.list_empty));
+
+ /*
+ * ActionBarSherlock does not support MultiChoiceModeListener. Thus multi-selection is only
+ * available for Android >= 3.0
+ */
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
+ getListView().setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
+ getListView().setMultiChoiceModeListener(new MultiChoiceModeListener() {
+
+ private int count = 0;
+
+ @Override
+ public boolean onCreateActionMode(ActionMode mode, Menu menu) {
+ android.view.MenuInflater inflater = getActivity().getMenuInflater();
+ inflater.inflate(R.menu.key_list_secret_multi, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
+ return false;
+ }
+
+ @Override
+ public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
+ Set<Integer> positions = mAdapter.getCurrentCheckedPosition();
+
+ // get IDs for checked positions as long array
+ long[] ids = new long[positions.size()];
+ int i = 0;
+ for (int pos : positions) {
+ ids[i] = mAdapter.getItemId(pos);
+ i++;
+ }
+
+ switch (item.getItemId()) {
+ case R.id.menu_key_list_public_multi_delete: {
+ showDeleteKeyDialog(ids);
+
+ break;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onDestroyActionMode(ActionMode mode) {
+ count = 0;
+ mAdapter.clearSelection();
+ }
+
+ @Override
+ public void onItemCheckedStateChanged(ActionMode mode, int position, long id,
+ boolean checked) {
+ if (checked) {
+ count++;
+ mAdapter.setNewSelection(position, checked);
+ } else {
+ count--;
+ mAdapter.removeSelection(position);
+ }
+
+ String keysSelected = getResources().getQuantityString(
+ R.plurals.key_list_selected_keys, count, count);
+ mode.setTitle(keysSelected);
+ }
+
+ });
+ }
+
+ // We have a menu item to show in action bar.
+ setHasOptionsMenu(true);
// Start out with a progress indicator.
setListShown(false);
+ // Create an empty adapter we will use to display the loaded data.
+ mAdapter = new KeyListSecretAdapter(mKeyListSecretActivity, null, 0);
+ setListAdapter(mAdapter);
+
// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
- // id is -1 as the child cursors are numbered 0,...,n
- getLoaderManager().initLoader(-1, null, this);
- }
-
- /**
- * Context Menu on Long Click
- */
- @Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- super.onCreateContextMenu(menu, v, menuInfo);
- menu.add(0, Id.menu.edit, 0, R.string.menu_edit_key);
- }
-
- @Override
- public boolean onContextItemSelected(android.view.MenuItem item) {
- ExpandableListContextMenuInfo expInfo = (ExpandableListContextMenuInfo) item.getMenuInfo();
-
- // expInfo.id would also return row id of childs, but we always want to get the row id of
- // the group item, thus we are using the following way
- int groupPosition = ExpandableListView.getPackedPositionGroup(expInfo.packedPosition);
- long keyRingRowId = getExpandableListAdapter().getGroupId(groupPosition);
-
- // get master key id using row id
- long masterKeyId = ProviderHelper
- .getSecretMasterKeyId(mKeyListSecretActivity, keyRingRowId);
-
- boolean masterCanSign = ProviderHelper.getSecretMasterKeyCanSign(mKeyListSecretActivity,
- keyRingRowId);
-
- switch (item.getItemId()) {
- case Id.menu.edit:
- mKeyListSecretActivity.editKey(masterKeyId, masterCanSign);
-
- return true;
-
- default:
- return super.onContextItemSelected(item);
-
- }
+ getLoaderManager().initLoader(0, null, this);
}
// These are the rows that we will retrieve.
static final String[] PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID,
UserIds.USER_ID };
+ static final String SORT_ORDER = UserIds.USER_ID + " COLLATE LOCALIZED ASC";
- static final String SORT_ORDER = UserIds.USER_ID + " ASC";
-
- @Override
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
// This is called when a new Loader needs to be created. This
// sample only has one Loader, so we don't care about the ID.
+ // First, pick the base URI to use depending on whether we are
+ // currently filtering.
Uri baseUri = KeyRings.buildSecretKeyRingsUri();
// Now create and return a CursorLoader that will take care of
@@ -118,11 +170,10 @@ public class KeyListSecretFragment extends KeyListFragment implements
return new CursorLoader(getActivity(), baseUri, PROJECTION, null, null, SORT_ORDER);
}
- @Override
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
- mAdapter.setGroupCursor(data);
+ mAdapter.swapCursor(data);
// The list should now be shown.
if (isResumed()) {
@@ -132,12 +183,33 @@ public class KeyListSecretFragment extends KeyListFragment implements
}
}
- @Override
public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
- mAdapter.setGroupCursor(null);
+ mAdapter.swapCursor(null);
}
+ /**
+ * On click on item, start key view activity
+ */
+ @Override
+ public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
+ Intent editIntent = new Intent(mKeyListSecretActivity, EditKeyActivity.class);
+ editIntent.setData(KeychainContract.KeyRings.buildSecretKeyRingsUri(Long.toString(id)));
+ editIntent.setAction(EditKeyActivity.ACTION_EDIT_KEY);
+ startActivityForResult(editIntent, 0);
+ }
+
+ /**
+ * Show dialog to delete key
+ *
+ * @param keyRingRowIds
+ */
+ public void showDeleteKeyDialog(long[] keyRingRowIds) {
+ DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(null,
+ keyRingRowIds, Id.type.secret_key);
+
+ deleteKeyDialog.show(getActivity().getSupportFragmentManager(), "deleteKeyDialog");
+ }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
index b4679f9d5..6073e6b80 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerQueryActivity.java
@@ -111,7 +111,7 @@ public class KeyServerQueryActivity extends SherlockFragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.key_server_query_layout);
+ setContentView(R.layout.key_server_query);
mQuery = (EditText)findViewById(R.id.query);
mSearch = (Button)findViewById(R.id.btn_search);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerUploadActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerUploadActivity.java
index 996637c7a..8a32ea513 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerUploadActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/KeyServerUploadActivity.java
@@ -76,7 +76,7 @@ public class KeyServerUploadActivity extends SherlockFragmentActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.key_server_export_layout);
+ setContentView(R.layout.key_server_export);
export = (Button) findViewById(R.id.btn_export_to_server);
keyServer = (Spinner) findViewById(R.id.keyServer);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java
deleted file mode 100644
index 9a270e60b..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/MainActivity.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.service.remote.RegisteredAppsListActivity;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.app.SherlockActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuItem;
-
-import android.content.Intent;
-import android.os.Bundle;
-import android.view.View;
-
-public class MainActivity extends SherlockActivity {
-
- public void manageKeysOnClick(View view) {
- // used instead of startActivity set actionbar based on callingPackage
- startActivityForResult(new Intent(this, KeyListPublicActivity.class), 0);
- }
-
- public void myKeysOnClick(View view) {
- // used instead of startActivity set actionbar based on callingPackage
- startActivityForResult(new Intent(this, KeyListSecretActivity.class), 0);
- }
-
- public void encryptOnClick(View view) {
- Intent intent = new Intent(MainActivity.this, EncryptActivity.class);
- intent.setAction(EncryptActivity.ACTION_ENCRYPT);
- // used instead of startActivity set actionbar based on callingPackage
- startActivityForResult(intent, 0);
- }
-
- public void decryptOnClick(View view) {
- Intent intent = new Intent(MainActivity.this, DecryptActivity.class);
- intent.setAction(DecryptActivity.ACTION_DECRYPT);
- // used instead of startActivity set actionbar based on callingPackage
- startActivityForResult(intent, 0);
- }
-
- public void scanQrcodeOnClick(View view) {
- Intent intent = new Intent(this, ImportKeysActivity.class);
- startActivityForResult(intent, 0);
- }
-
- public void helpOnClick(View view) {
- startActivity(new Intent(this, HelpActivity.class));
- }
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
-
- final ActionBar actionBar = getSupportActionBar();
- actionBar.setDisplayShowTitleEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(false);
- actionBar.setHomeButtonEnabled(false);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- menu.add(0, Id.menu.option.preferences, 0, R.string.menu_preferences)
- .setIcon(R.drawable.ic_menu_settings)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
- menu.add(0, Id.menu.option.crypto_consumers, 0, R.string.menu_api_app_settings)
- .setIcon(R.drawable.ic_menu_settings)
- .setShowAsAction(MenuItem.SHOW_AS_ACTION_WITH_TEXT);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case Id.menu.option.preferences:
- startActivity(new Intent(this, PreferencesActivity.class));
- return true;
-
- case Id.menu.option.crypto_consumers:
- startActivity(new Intent(this, RegisteredAppsListActivity.class));
- return true;
-
- default:
- break;
-
- }
- return false;
- }
-
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/PreferencesActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/PreferencesActivity.java
index 6607ab4d5..46bbd05c9 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/PreferencesActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/PreferencesActivity.java
@@ -20,13 +20,9 @@ import org.spongycastle.bcpg.HashAlgorithmTags;
import org.spongycastle.openpgp.PGPEncryptedData;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.Preferences;
import org.sufficientlysecure.keychain.ui.widget.IntegerListPreference;
-import org.sufficientlysecure.keychain.R;
-
-import com.actionbarsherlock.app.ActionBar;
-import com.actionbarsherlock.app.SherlockPreferenceActivity;
-import com.actionbarsherlock.view.MenuItem;
import android.content.Intent;
import android.os.Bundle;
@@ -34,6 +30,9 @@ import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceScreen;
+import com.actionbarsherlock.app.ActionBar;
+import com.actionbarsherlock.app.SherlockPreferenceActivity;
+
public class PreferencesActivity extends SherlockPreferenceActivity {
private IntegerListPreference mPassPhraseCacheTtl = null;
private IntegerListPreference mEncryptionAlgorithm = null;
@@ -52,8 +51,8 @@ public class PreferencesActivity extends SherlockPreferenceActivity {
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(true);
- actionBar.setDisplayHomeAsUpEnabled(true);
- actionBar.setHomeButtonEnabled(true);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+ actionBar.setHomeButtonEnabled(false);
addPreferencesFromResource(R.xml.preferences);
@@ -219,22 +218,4 @@ public class PreferencesActivity extends SherlockPreferenceActivity {
}
}
}
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
- default:
- break;
-
- }
- return false;
- }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
index b0711ed31..83669a523 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SelectSecretKeyActivity.java
@@ -137,21 +137,4 @@ public class SelectSecretKeyActivity extends SherlockFragmentActivity {
return true;
}
- /**
- * Menu Options
- */
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
- case android.R.id.home:
- // app icon in Action Bar clicked; go home
- Intent intent = new Intent(this, MainActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareActivity.java
deleted file mode 100644
index 159b2b63a..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareActivity.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import java.util.ArrayList;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-
-public class ShareActivity extends SherlockFragmentActivity {
- // Actions for internal use only:
- public static final String ACTION_SHARE_KEYRING = Constants.INTENT_PREFIX + "SHARE_KEYRING";
- public static final String ACTION_SHARE_KEYRING_WITH_QR_CODE = Constants.INTENT_PREFIX
- + "SHARE_KEYRING_WITH_QR_CODE";
-
- public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- handleActions(getIntent());
- }
-
- protected void handleActions(Intent intent) {
- String action = intent.getAction();
- Bundle extras = intent.getExtras();
-
- if (extras == null) {
- extras = new Bundle();
- }
-
- long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
-
- // get public keyring as ascii armored string
- ArrayList<String> keyringArmored = ProviderHelper.getPublicKeyRingsAsArmoredString(this,
- new long[] { masterKeyId });
-
- if (ACTION_SHARE_KEYRING.equals(action)) {
- // let user choose application
- Intent sendIntent = new Intent(Intent.ACTION_SEND);
- sendIntent.putExtra(Intent.EXTRA_TEXT, keyringArmored.get(0));
- sendIntent.setType("text/plain");
- startActivity(Intent.createChooser(sendIntent,
- getResources().getText(R.string.action_share_key_with)));
- } else if (ACTION_SHARE_KEYRING_WITH_QR_CODE.equals(action)) {
- ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(keyringArmored
- .get(0));
- dialog.show(getSupportFragmentManager(), "qrCodeShareDialog");
- }
-
- // close this activity
- // TODO: finish() would also close dialog...
- // integrate this into new KeyViewActivity when ready
- // finish();
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareNfcBeamActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareNfcBeamActivity.java
deleted file mode 100644
index db6a156c7..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ShareNfcBeamActivity.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui;
-
-import org.sufficientlysecure.htmltextview.HtmlTextView;
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.R;
-import org.sufficientlysecure.keychain.helper.ActionBarHelper;
-import org.sufficientlysecure.keychain.provider.ProviderHelper;
-
-import android.annotation.TargetApi;
-import android.content.Intent;
-import android.nfc.NdefMessage;
-import android.nfc.NdefRecord;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcAdapter.CreateNdefMessageCallback;
-import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
-import android.nfc.NfcEvent;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
-import android.os.Parcelable;
-import android.provider.Settings;
-import android.widget.Toast;
-
-import com.actionbarsherlock.app.SherlockFragmentActivity;
-import com.actionbarsherlock.view.Menu;
-import com.actionbarsherlock.view.MenuInflater;
-import com.actionbarsherlock.view.MenuItem;
-
-@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
-public class ShareNfcBeamActivity extends SherlockFragmentActivity implements
- CreateNdefMessageCallback, OnNdefPushCompleteCallback {
- public static final String ACTION_SHARE_KEYRING_WITH_NFC = Constants.INTENT_PREFIX
- + "SHARE_KEYRING_WITH_NFC";
-
- public static final String EXTRA_MASTER_KEY_ID = "master_key_id";
-
- NfcAdapter mNfcAdapter;
-
- byte[] mSharedKeyringBytes;
-
- private static final int MESSAGE_SENT = 1;
-
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
- Toast.makeText(this,
- getString(R.string.error) + ": " + getString(R.string.error_jelly_bean_needed),
- Toast.LENGTH_LONG).show();
- finish();
- } else {
- // Check for available NFC Adapter
- mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
- if (mNfcAdapter == null) {
- Toast.makeText(this,
- getString(R.string.error) + ": " + getString(R.string.error_nfc_needed),
- Toast.LENGTH_LONG).show();
- finish();
- } else {
- // handle actions after verifying that nfc works...
- handleActions(getIntent());
- }
- }
- }
-
- protected void handleActions(Intent intent) {
- String action = intent.getAction();
- Bundle extras = intent.getExtras();
-
- if (extras == null) {
- extras = new Bundle();
- }
-
- if (ACTION_SHARE_KEYRING_WITH_NFC.equals(action)) {
- long masterKeyId = extras.getLong(EXTRA_MASTER_KEY_ID);
-
- // get public keyring as byte array
- mSharedKeyringBytes = ProviderHelper.getPublicKeyRingsAsByteArray(this,
- new long[] { masterKeyId });
-
- // Register callback to set NDEF message
- mNfcAdapter.setNdefPushMessageCallback(this, this);
- // Register callback to listen for message-sent success
- mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
- }
- }
-
- /**
- * Parses the NDEF Message from the intent and prints to the TextView
- */
- void handleActionNdefDiscovered(Intent intent) {
- Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
- // only one message sent during the beam
- NdefMessage msg = (NdefMessage) rawMsgs[0];
- // record 0 contains the MIME type, record 1 is the AAR, if present
- byte[] receivedKeyringBytes = msg.getRecords()[0].getPayload();
-
- Intent importIntent = new Intent(this, ImportKeysActivity.class);
- importIntent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY);
- importIntent.putExtra(ImportKeysActivity.EXTRA_KEY_BYTES, receivedKeyringBytes);
-
- finish();
-
- startActivity(importIntent);
- }
-
- private void buildView() {
- setContentView(R.layout.share_nfc_beam);
-
- HtmlTextView aboutTextView = (HtmlTextView) findViewById(R.id.nfc_beam_text);
-
- // load html from raw resource (Parsing handled by HtmlTextView library)
- aboutTextView.setHtmlFromRawResource(this, R.raw.nfc_beam_share);
-
- // no flickering when clicking textview for Android < 4
- aboutTextView.setTextColor(getResources().getColor(android.R.color.black));
-
- // set actionbar without home button if called from another app
- ActionBarHelper.setBackButton(this);
- }
-
- /**
- * Implementation for the CreateNdefMessageCallback interface
- */
- @Override
- public NdefMessage createNdefMessage(NfcEvent event) {
- /**
- * When a device receives a push with an AAR in it, the application specified in the AAR is
- * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
- * guarantee that this activity starts when receiving a beamed message. For now, this code
- * uses the tag dispatch system.
- */
- NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
- mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
- return msg;
- }
-
- /**
- * Implementation for the OnNdefPushCompleteCallback interface
- */
- @Override
- public void onNdefPushComplete(NfcEvent arg0) {
- // A handler is needed to send messages to the activity when this
- // callback occurs, because it happens from a binder thread
- mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();
- }
-
- /** This handler receives a message from onNdefPushComplete */
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_SENT:
- Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG)
- .show();
- break;
- }
- }
- };
-
- @Override
- public void onResume() {
- super.onResume();
- // Check to see that the Activity started due to an Android Beam
- if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
- handleActionNdefDiscovered(getIntent());
- } else {
- // build view only when sending nfc, not when receiving, as it gets directly into Import
- // activity on receiving
- buildView();
- }
- }
-
- @Override
- public void onNewIntent(Intent intent) {
- // onResume gets called after this to handle the intent
- setIntent(intent);
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- MenuInflater inflater = getSupportMenuInflater();
- inflater.inflate(R.menu.nfc_beam, menu);
- return true;
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- switch (item.getItemId()) {
-
- case android.R.id.home:
- // app icon in Action Bar clicked; go to KeyListPublicActivity
- Intent intent = new Intent(this, KeyListPublicActivity.class);
- intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- startActivity(intent);
- return true;
-
- case R.id.menu_settings:
- Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
- startActivity(intentSettings);
- return true;
-
- default:
- return super.onOptionsItemSelected(item);
- }
- }
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
index c2fe1315b..6abdddee6 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/SignKeyActivity.java
@@ -68,7 +68,7 @@ public class SignKeyActivity extends SherlockFragmentActivity {
super.onCreate(savedInstanceState);
// check we havent already signed it
- setContentView(R.layout.sign_key_layout);
+ setContentView(R.layout.sign_key_activity);
final ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowTitleEnabled(true);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
new file mode 100644
index 000000000..e2f90e87c
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/ViewKeyActivity.java
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2013-2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2013 Bahtiar 'kalkin' Gadimov
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui;
+
+import java.util.ArrayList;
+import java.util.Date;
+
+import org.spongycastle.openpgp.PGPPublicKey;
+import org.spongycastle.openpgp.PGPPublicKeyRing;
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.compatibility.ClipboardReflection;
+import org.sufficientlysecure.keychain.helper.ExportHelper;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.provider.ProviderHelper;
+import org.sufficientlysecure.keychain.ui.adapter.ViewKeyKeysAdapter;
+import org.sufficientlysecure.keychain.ui.adapter.ViewKeyUserIdsAdapter;
+import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.ShareNfcDialogFragment;
+import org.sufficientlysecure.keychain.ui.dialog.ShareQrCodeDialogFragment;
+import org.sufficientlysecure.keychain.util.Log;
+
+import android.annotation.SuppressLint;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.nfc.NdefMessage;
+import android.nfc.NdefRecord;
+import android.nfc.NfcAdapter;
+import android.nfc.NfcAdapter.CreateNdefMessageCallback;
+import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;
+import android.nfc.NfcEvent;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.CursorLoader;
+import android.support.v4.content.Loader;
+import android.text.format.DateFormat;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.actionbarsherlock.view.Menu;
+import com.actionbarsherlock.view.MenuItem;
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
+@SuppressLint("NewApi")
+public class ViewKeyActivity extends SherlockFragmentActivity implements CreateNdefMessageCallback,
+ OnNdefPushCompleteCallback, LoaderManager.LoaderCallbacks<Cursor> {
+
+ ExportHelper mExportHelper;
+
+ private Uri mDataUri;
+
+ private PGPPublicKey mPublicKey;
+
+ private TextView mName;
+ private TextView mEmail;
+ private TextView mComment;
+ private TextView mAlgorithm;
+ private TextView mKeyId;
+ private TextView mExpiry;
+ private TextView mCreation;
+ private TextView mFingerprint;
+ private BootstrapButton mActionEncrypt;
+
+ private ListView mUserIds;
+ private ListView mKeys;
+
+ // NFC
+ private NfcAdapter mNfcAdapter;
+ private byte[] mSharedKeyringBytes;
+ private static final int NFC_SENT = 1;
+
+ private static final int LOADER_ID_KEYRING = 0;
+ private static final int LOADER_ID_USER_IDS = 1;
+ private static final int LOADER_ID_KEYS = 2;
+ private ViewKeyUserIdsAdapter mUserIdsAdapter;
+ private ViewKeyKeysAdapter mKeysAdapter;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mExportHelper = new ExportHelper(this);
+
+ getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+ getSupportActionBar().setIcon(android.R.color.transparent);
+ getSupportActionBar().setHomeButtonEnabled(true);
+
+ setContentView(R.layout.view_key_activity);
+
+ mName = (TextView) findViewById(R.id.name);
+ mEmail = (TextView) findViewById(R.id.email);
+ mComment = (TextView) findViewById(R.id.comment);
+ mKeyId = (TextView) findViewById(R.id.key_id);
+ mAlgorithm = (TextView) findViewById(R.id.algorithm);
+ mCreation = (TextView) findViewById(R.id.creation);
+ mExpiry = (TextView) findViewById(R.id.expiry);
+ mFingerprint = (TextView) findViewById(R.id.fingerprint);
+ mActionEncrypt = (BootstrapButton) findViewById(R.id.action_encrypt);
+ mUserIds = (ListView) findViewById(R.id.user_ids);
+ mKeys = (ListView) findViewById(R.id.keys);
+
+ Intent intent = getIntent();
+ mDataUri = intent.getData();
+ if (mDataUri == null) {
+ Log.e(Constants.TAG, "Intent data missing. Should be Uri of key!");
+ finish();
+ return;
+ } else {
+ Log.d(Constants.TAG, "uri: " + mDataUri);
+ loadData(mDataUri);
+ initNfc(mDataUri);
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ getSupportMenuInflater().inflate(R.menu.key_view, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ Intent homeIntent = new Intent(this, KeyListPublicActivity.class);
+ homeIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+ startActivity(homeIntent);
+ return true;
+ case R.id.menu_key_view_update:
+ updateFromKeyserver(mDataUri);
+ return true;
+ case R.id.menu_key_view_sign:
+ signKey(mDataUri);
+ return true;
+ case R.id.menu_key_view_export_keyserver:
+ uploadToKeyserver(mDataUri);
+ return true;
+ case R.id.menu_key_view_export_file:
+ mExportHelper.showExportKeysDialog(mDataUri, Id.type.public_key, Constants.path.APP_DIR
+ + "/pubexport.asc");
+ return true;
+ case R.id.menu_key_view_share_default:
+ shareKey(mDataUri);
+ return true;
+ case R.id.menu_key_view_share_qr_code:
+ shareKeyQrCode(mDataUri);
+ return true;
+ case R.id.menu_key_view_share_nfc:
+ shareNfc();
+ return true;
+ case R.id.menu_key_view_share_clipboard:
+ copyToClipboard(mDataUri);
+ return true;
+ case R.id.menu_key_view_delete: {
+ // Message is received after key is deleted
+ Handler returnHandler = new Handler() {
+ @Override
+ public void handleMessage(Message message) {
+ if (message.what == DeleteKeyDialogFragment.MESSAGE_OKAY) {
+ setResult(RESULT_CANCELED);
+ finish();
+ }
+ }
+ };
+
+ mExportHelper.deleteKey(mDataUri, Id.type.public_key, returnHandler);
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void loadData(Uri dataUri) {
+ // TODO: don't use pubkey object, use database!!!
+
+ PGPPublicKeyRing ring = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, dataUri);
+ mPublicKey = ring.getPublicKey();
+
+ mKeyId.setText(PgpKeyHelper.shortifyFingerprint(PgpKeyHelper
+ .convertFingerprintToHex(mPublicKey.getFingerprint())));
+
+ String fingerprint = PgpKeyHelper.convertFingerprintToHex(mPublicKey.getFingerprint());
+ fingerprint = fingerprint.replace(" ", "\n");
+ mFingerprint.setText(fingerprint);
+
+ // TODO: get image with getUserAttributes() on key and then PGPUserAttributeSubpacketVector
+
+ Date expiryDate = PgpKeyHelper.getExpiryDate(mPublicKey);
+ if (expiryDate == null) {
+ mExpiry.setText(R.string.none);
+ } else {
+ mExpiry.setText(DateFormat.getDateFormat(getApplicationContext()).format(expiryDate));
+ }
+
+ mCreation.setText(DateFormat.getDateFormat(getApplicationContext()).format(
+ PgpKeyHelper.getCreationDate(mPublicKey)));
+ mAlgorithm.setText(PgpKeyHelper.getAlgorithmInfo(mPublicKey));
+
+ mActionEncrypt.setOnClickListener(new OnClickListener() {
+
+ @Override
+ public void onClick(View v) {
+ long[] encryptionKeyIds = new long[] { mPublicKey.getKeyID() };
+ Intent intent = new Intent(ViewKeyActivity.this, EncryptActivity.class);
+ intent.setAction(EncryptActivity.ACTION_ENCRYPT);
+ intent.putExtra(EncryptActivity.EXTRA_ENCRYPTION_KEY_IDS, encryptionKeyIds);
+ // used instead of startActivity set actionbar based on callingPackage
+ startActivityForResult(intent, 0);
+ }
+ });
+
+ mUserIdsAdapter = new ViewKeyUserIdsAdapter(this, null, 0);
+
+ mUserIds.setAdapter(mUserIdsAdapter);
+ // mUserIds.setEmptyView(findViewById(android.R.id.empty));
+ // mUserIds.setClickable(true);
+ // mUserIds.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ // @Override
+ // public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
+ // }
+ // });
+
+ mKeysAdapter = new ViewKeyKeysAdapter(this, null, 0);
+
+ mKeys.setAdapter(mKeysAdapter);
+
+ // Prepare the loader. Either re-connect with an existing one,
+ // or start a new one.
+ getSupportLoaderManager().initLoader(LOADER_ID_KEYRING, null, this);
+ getSupportLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
+ getSupportLoaderManager().initLoader(LOADER_ID_KEYS, null, this);
+ }
+
+ static final String[] KEYRING_PROJECTION = new String[] { KeyRings._ID, KeyRings.MASTER_KEY_ID,
+ UserIds.USER_ID };
+
+ static final String[] USER_IDS_PROJECTION = new String[] { UserIds._ID, UserIds.USER_ID,
+ UserIds.RANK, };
+ // not the main user id
+ static final String USER_IDS_SELECTION = UserIds.RANK + " > 0 ";
+ static final String USER_IDS_SORT_ORDER = UserIds.USER_ID + " COLLATE LOCALIZED ASC";
+
+ static final String[] KEYS_PROJECTION = new String[] { Keys._ID, Keys.KEY_ID,
+ Keys.IS_MASTER_KEY, Keys.ALGORITHM, Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN,
+ Keys.CAN_ENCRYPT, };
+ static final String KEYS_SORT_ORDER = Keys.RANK + " ASC";
+
+ public Loader<Cursor> onCreateLoader(int id, Bundle args) {
+ switch (id) {
+ case LOADER_ID_KEYRING: {
+ Uri baseUri = mDataUri;
+
+ // Now create and return a CursorLoader that will take care of
+ // creating a Cursor for the data being displayed.
+ return new CursorLoader(this, baseUri, KEYRING_PROJECTION, null, null, null);
+ }
+ case LOADER_ID_USER_IDS: {
+ Uri baseUri = UserIds.buildUserIdsUri(mDataUri);
+
+ // Now create and return a CursorLoader that will take care of
+ // creating a Cursor for the data being displayed.
+ return new CursorLoader(this, baseUri, USER_IDS_PROJECTION, USER_IDS_SELECTION, null,
+ USER_IDS_SORT_ORDER);
+ }
+ case LOADER_ID_KEYS: {
+ Uri baseUri = Keys.buildKeysUri(mDataUri);
+
+ // Now create and return a CursorLoader that will take care of
+ // creating a Cursor for the data being displayed.
+ return new CursorLoader(this, baseUri, KEYS_PROJECTION, null, null, KEYS_SORT_ORDER);
+ }
+
+ default:
+ return null;
+ }
+ }
+
+ public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
+ // Swap the new cursor in. (The framework will take care of closing the
+ // old cursor once we return.)
+ switch (loader.getId()) {
+ case LOADER_ID_KEYRING:
+ if (data.moveToFirst()) {
+ String[] mainUserId = PgpKeyHelper.splitUserId(data.getString(2));
+ setTitle(mainUserId[0]);
+ mName.setText(mainUserId[0]);
+ mEmail.setText(mainUserId[1]);
+ mComment.setText(mainUserId[2]);
+ }
+
+ break;
+ case LOADER_ID_USER_IDS:
+ mUserIdsAdapter.swapCursor(data);
+ break;
+ case LOADER_ID_KEYS:
+ mKeysAdapter.swapCursor(data);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * This is called when the last Cursor provided to onLoadFinished() above is about to be closed.
+ * We need to make sure we are no longer using it.
+ */
+ public void onLoaderReset(Loader<Cursor> loader) {
+ switch (loader.getId()) {
+ case LOADER_ID_KEYRING:
+ // TODO?
+ break;
+ case LOADER_ID_USER_IDS:
+ mUserIdsAdapter.swapCursor(null);
+ break;
+ case LOADER_ID_KEYS:
+ mKeysAdapter.swapCursor(null);
+ break;
+ default:
+ break;
+ }
+ }
+
+ private void uploadToKeyserver(Uri dataUri) {
+ long keyRingRowId = Long.valueOf(dataUri.getLastPathSegment());
+
+ Intent uploadIntent = new Intent(this, KeyServerUploadActivity.class);
+ uploadIntent.setAction(KeyServerUploadActivity.ACTION_EXPORT_KEY_TO_SERVER);
+ uploadIntent.putExtra(KeyServerUploadActivity.EXTRA_KEYRING_ROW_ID, (int) keyRingRowId);
+ startActivityForResult(uploadIntent, Id.request.export_to_server);
+ }
+
+ private void updateFromKeyserver(Uri dataUri) {
+ long updateKeyId = 0;
+ PGPPublicKeyRing updateRing = (PGPPublicKeyRing) ProviderHelper
+ .getPGPKeyRing(this, dataUri);
+
+ if (updateRing != null) {
+ updateKeyId = PgpKeyHelper.getMasterKey(updateRing).getKeyID();
+ }
+ if (updateKeyId == 0) {
+ Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!");
+ return;
+ }
+
+ Intent signIntent = new Intent(this, SignKeyActivity.class);
+ signIntent.putExtra(SignKeyActivity.EXTRA_KEY_ID, updateKeyId);
+ startActivity(signIntent);
+
+ Intent queryIntent = new Intent(this, KeyServerQueryActivity.class);
+ queryIntent.setAction(KeyServerQueryActivity.ACTION_LOOK_UP_KEY_ID_AND_RETURN);
+ queryIntent.putExtra(KeyServerQueryActivity.EXTRA_KEY_ID, updateKeyId);
+
+ // TODO: lookup??
+ startActivityForResult(queryIntent, Id.request.look_up_key_id);
+ }
+
+ private void signKey(Uri dataUri) {
+ long keyId = 0;
+ PGPPublicKeyRing signKey = (PGPPublicKeyRing) ProviderHelper.getPGPKeyRing(this, dataUri);
+
+ if (signKey != null) {
+ keyId = PgpKeyHelper.getMasterKey(signKey).getKeyID();
+ }
+ if (keyId == 0) {
+ Log.e(Constants.TAG, "this shouldn't happen. KeyId == 0!");
+ return;
+ }
+
+ Intent signIntent = new Intent(this, SignKeyActivity.class);
+ signIntent.putExtra(SignKeyActivity.EXTRA_KEY_ID, keyId);
+ startActivity(signIntent);
+ }
+
+ private void shareKey(Uri dataUri) {
+ // get public keyring as ascii armored string
+ long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
+ ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri,
+ new long[] { masterKeyId });
+
+ // let user choose application
+ Intent sendIntent = new Intent(Intent.ACTION_SEND);
+ sendIntent.putExtra(Intent.EXTRA_TEXT, keyringArmored.get(0));
+ sendIntent.setType("text/plain");
+ startActivity(Intent.createChooser(sendIntent,
+ getResources().getText(R.string.action_share_key_with)));
+ }
+
+ private void shareKeyQrCode(Uri dataUri) {
+ // get public keyring as ascii armored string
+ long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
+ ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri,
+ new long[] { masterKeyId });
+
+ ShareQrCodeDialogFragment dialog = ShareQrCodeDialogFragment.newInstance(keyringArmored
+ .get(0));
+ dialog.show(getSupportFragmentManager(), "shareQrCodeDialog");
+ }
+
+ private void copyToClipboard(Uri dataUri) {
+ // get public keyring as ascii armored string
+ long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
+ ArrayList<String> keyringArmored = ProviderHelper.getKeyRingsAsArmoredString(this, dataUri,
+ new long[] { masterKeyId });
+
+ ClipboardReflection.copyToClipboard(this, keyringArmored.get(0));
+ }
+
+ private void shareNfc() {
+ ShareNfcDialogFragment dialog = ShareNfcDialogFragment.newInstance();
+ dialog.show(getSupportFragmentManager(), "shareNfcDialog");
+ }
+
+ /**
+ * NFC: Initialize NFC sharing if OS and device supports it
+ */
+ private void initNfc(Uri dataUri) {
+ // check if NFC Beam is supported (>= Android 4.1)
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ // Check for available NFC Adapter
+ mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
+ if (mNfcAdapter != null) {
+ // init nfc
+
+ // get public keyring as byte array
+ long masterKeyId = ProviderHelper.getMasterKeyId(this, dataUri);
+ mSharedKeyringBytes = ProviderHelper.getKeyRingsAsByteArray(this, dataUri,
+ new long[] { masterKeyId });
+
+ // Register callback to set NDEF message
+ mNfcAdapter.setNdefPushMessageCallback(this, this);
+ // Register callback to listen for message-sent success
+ mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
+ }
+ }
+ }
+
+ /**
+ * NFC: Implementation for the CreateNdefMessageCallback interface
+ */
+ @Override
+ public NdefMessage createNdefMessage(NfcEvent event) {
+ /**
+ * When a device receives a push with an AAR in it, the application specified in the AAR is
+ * guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
+ * guarantee that this activity starts when receiving a beamed message. For now, this code
+ * uses the tag dispatch system.
+ */
+ NdefMessage msg = new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
+ mSharedKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
+ return msg;
+ }
+
+ /**
+ * NFC: Implementation for the OnNdefPushCompleteCallback interface
+ */
+ @Override
+ public void onNdefPushComplete(NfcEvent arg0) {
+ // A handler is needed to send messages to the activity when this
+ // callback occurs, because it happens from a binder thread
+ mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
+ }
+
+ /**
+ * NFC: This handler receives a message from onNdefPushComplete
+ */
+ private final Handler mNfcHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case NFC_SENT:
+ Toast.makeText(getApplicationContext(), R.string.nfc_successfull, Toast.LENGTH_LONG)
+ .show();
+ break;
+ }
+ }
+ };
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (!mExportHelper.handleActivityResult(requestCode, resultCode, data)) {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListAdapter.java
deleted file mode 100644
index e94934008..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListAdapter.java
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (C) 2012-2013 Dominik Schürmann <dominik@dominikschuermann.de>
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui.adapter;
-
-import org.sufficientlysecure.keychain.Constants;
-import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.helper.OtherHelper;
-import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
-import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
-import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.R;
-
-import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.MergeCursor;
-import android.net.Uri;
-import android.provider.BaseColumns;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.CursorTreeAdapter;
-import android.widget.ImageView;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class KeyListAdapter extends CursorTreeAdapter {
- private Context mContext;
- private LayoutInflater mInflater;
-
- protected int mKeyType;
-
- private static final int CHILD_KEY = 0;
- private static final int CHILD_USER_ID = 1;
- private static final int CHILD_FINGERPRINT = 2;
-
- public KeyListAdapter(Context context, Cursor groupCursor, int keyType) {
- super(groupCursor, context);
- mContext = context;
- mInflater = LayoutInflater.from(context);
- mKeyType = keyType;
- }
-
- /**
- * Inflate new view for group items
- */
- @Override
- public View newGroupView(Context context, Cursor cursor, boolean isExpanded, ViewGroup parent) {
- return mInflater.inflate(R.layout.key_list_group_item, null);
- }
-
- /**
- * Binds TextViews from group view to results from database group cursor.
- */
- @Override
- protected void bindGroupView(View view, Context context, Cursor cursor, boolean isExpanded) {
- int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
-
- TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
- mainUserId.setText(R.string.unknown_user_id);
- TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
- mainUserIdRest.setText("");
-
- String userId = cursor.getString(userIdIndex);
- if (userId != null) {
- String[] userIdSplit = OtherHelper.splitUserId(userId);
-
- if (userIdSplit[1] != null) {
- mainUserIdRest.setText(userIdSplit[1]);
- }
- mainUserId.setText(userIdSplit[0]);
- }
-
- if (mainUserId.getText().length() == 0) {
- mainUserId.setText(R.string.unknown_user_id);
- }
-
- if (mainUserIdRest.getText().length() == 0) {
- mainUserIdRest.setVisibility(View.GONE);
- } else {
- mainUserIdRest.setVisibility(View.VISIBLE);
- }
- }
-
- /**
- * Inflate new view for child items
- */
- @Override
- public View newChildView(Context context, Cursor cursor, boolean isLastChild, ViewGroup parent) {
- return mInflater.inflate(R.layout.key_list_child_item, null);
- }
-
- /**
- * Bind TextViews from view of childs based on query results
- */
- @Override
- protected void bindChildView(View view, Context context, Cursor cursor, boolean isLastChild) {
- LinearLayout keyLayout = (LinearLayout) view.findViewById(R.id.keyLayout);
- LinearLayout userIdLayout = (LinearLayout) view.findViewById(R.id.userIdLayout);
-
- // first entry is fingerprint
- if (cursor.getPosition() == 0) {
- // show only userId layout
- keyLayout.setVisibility(View.GONE);
- userIdLayout.setVisibility(View.VISIBLE);
-
- String fingerprint = PgpKeyHelper.getFingerPrint(context,
- cursor.getLong(cursor.getColumnIndex(Keys.KEY_ID)));
- fingerprint = fingerprint.replace(" ", "\n");
-
- TextView userId = (TextView) view.findViewById(R.id.userId);
- if (userId == null) {
- Log.d(Constants.TAG, "userId is null!");
- }
- userId.setText(context.getString(R.string.fingerprint) + "\n" + fingerprint);
- } else {
- // differentiate between keys and userIds in MergeCursor
- if (cursor.getColumnIndex(Keys.KEY_ID) != -1) {
- keyLayout.setVisibility(View.VISIBLE);
- userIdLayout.setVisibility(View.GONE);
-
- String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(cursor
- .getColumnIndex(Keys.KEY_ID)));
- String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
- cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
- cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
-
- TextView keyId = (TextView) view.findViewById(R.id.keyId);
- keyId.setText(keyIdStr);
-
- TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
- keyDetails.setText("(" + algorithmStr + ")");
-
- ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
- if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
- masterKeyIcon.setVisibility(View.INVISIBLE);
- } else {
- masterKeyIcon.setVisibility(View.VISIBLE);
- }
-
- ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
- if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
- certifyIcon.setVisibility(View.GONE);
- } else {
- certifyIcon.setVisibility(View.VISIBLE);
- }
-
- ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
- if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
- encryptIcon.setVisibility(View.GONE);
- } else {
- encryptIcon.setVisibility(View.VISIBLE);
- }
-
- ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
- if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
- signIcon.setVisibility(View.GONE);
- } else {
- signIcon.setVisibility(View.VISIBLE);
- }
- } else {
- keyLayout.setVisibility(View.GONE);
- userIdLayout.setVisibility(View.VISIBLE);
-
- String userIdStr = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
-
- TextView userId = (TextView) view.findViewById(R.id.userId);
- userId.setText(userIdStr);
- }
- }
- }
-
- /**
- * Given the group cursor, we start cursors for a fingerprint, keys, and userIds, which are
- * merged together and build the child cursor
- */
- @Override
- protected Cursor getChildrenCursor(Cursor groupCursor) {
- final long keyRingRowId = groupCursor.getLong(groupCursor.getColumnIndex(BaseColumns._ID));
-
- Cursor fingerprintCursor = getChildCursor(keyRingRowId, CHILD_FINGERPRINT);
- Cursor keyCursor = getChildCursor(keyRingRowId, CHILD_KEY);
- Cursor userIdCursor = getChildCursor(keyRingRowId, CHILD_USER_ID);
-
- MergeCursor mergeCursor = new MergeCursor(new Cursor[] { fingerprintCursor, keyCursor,
- userIdCursor });
- Log.d(Constants.TAG, "mergeCursor:" + DatabaseUtils.dumpCursorToString(mergeCursor));
-
- return mergeCursor;
- }
-
- /**
- * This builds a cursor for a specific type of children
- *
- * @param keyRingRowId
- * foreign row id of the keyRing
- * @param type
- * @return
- */
- private Cursor getChildCursor(long keyRingRowId, int type) {
- Uri uri = null;
- String[] projection = null;
- String sortOrder = null;
- String selection = null;
-
- switch (type) {
- case CHILD_FINGERPRINT:
- projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
- Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
- sortOrder = Keys.RANK + " ASC";
-
- // use only master key for fingerprint
- selection = Keys.IS_MASTER_KEY + " = 1 ";
-
- if (mKeyType == Id.type.public_key) {
- uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
- } else {
- uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
- }
- break;
-
- case CHILD_KEY:
- projection = new String[] { Keys._ID, Keys.KEY_ID, Keys.IS_MASTER_KEY, Keys.ALGORITHM,
- Keys.KEY_SIZE, Keys.CAN_CERTIFY, Keys.CAN_SIGN, Keys.CAN_ENCRYPT, };
- sortOrder = Keys.RANK + " ASC";
-
- if (mKeyType == Id.type.public_key) {
- uri = Keys.buildPublicKeysUri(String.valueOf(keyRingRowId));
- } else {
- uri = Keys.buildSecretKeysUri(String.valueOf(keyRingRowId));
- }
-
- break;
-
- case CHILD_USER_ID:
- projection = new String[] { UserIds._ID, UserIds.USER_ID, UserIds.RANK, };
- sortOrder = UserIds.RANK + " ASC";
-
- // not the main user id
- selection = UserIds.RANK + " > 0 ";
-
- if (mKeyType == Id.type.public_key) {
- uri = UserIds.buildPublicUserIdsUri(String.valueOf(keyRingRowId));
- } else {
- uri = UserIds.buildSecretUserIdsUri(String.valueOf(keyRingRowId));
- }
-
- break;
-
- default:
- return null;
-
- }
-
- return mContext.getContentResolver().query(uri, projection, selection, null, sortOrder);
- }
-
-}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
new file mode 100644
index 000000000..f1e58a5d3
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListPublicAdapter.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+import org.sufficientlysecure.keychain.util.Log;
+
+import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Implements StickyListHeadersAdapter from library
+ */
+public class KeyListPublicAdapter extends CursorAdapter implements StickyListHeadersAdapter {
+ private LayoutInflater mInflater;
+ private int mSectionColumnIndex;
+
+ @SuppressLint("UseSparseArrays")
+ private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+
+ public KeyListPublicAdapter(Context context, Cursor c, int flags, int sectionColumnIndex) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ mSectionColumnIndex = sectionColumnIndex;
+ }
+
+ /**
+ * Bind cursor data to the item list view
+ *
+ * NOTE: CursorAdapter already implements the ViewHolder pattern in its getView() method. Thus
+ * no ViewHolder is required here.
+ */
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
+
+ TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
+ mainUserId.setText(R.string.unknown_user_id);
+ TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
+ mainUserIdRest.setText("");
+
+ String userId = cursor.getString(userIdIndex);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[1] != null) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ }
+ mainUserId.setText(userIdSplit[0]);
+ }
+
+ if (mainUserId.getText().length() == 0) {
+ mainUserId.setText(R.string.unknown_user_id);
+ }
+
+ if (mainUserIdRest.getText().length() == 0) {
+ mainUserIdRest.setVisibility(View.GONE);
+ } else {
+ mainUserIdRest.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.key_list_item, null);
+ }
+
+ /**
+ * Creates a new header view and binds the section headers to it. It uses the ViewHolder
+ * pattern. Most functionality is similar to getView() from Android's CursorAdapter.
+ *
+ * NOTE: The variables mDataValid and mCursor are available due to the super class
+ * CursorAdapter.
+ */
+ @Override
+ public View getHeaderView(int position, View convertView, ViewGroup parent) {
+ HeaderViewHolder holder;
+ if (convertView == null) {
+ holder = new HeaderViewHolder();
+ convertView = mInflater.inflate(R.layout.key_list_public_header, parent, false);
+ holder.text = (TextView) convertView.findViewById(R.id.stickylist_header_text);
+ convertView.setTag(holder);
+ } else {
+ holder = (HeaderViewHolder) convertView.getTag();
+ }
+
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return convertView;
+ }
+
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // set header text as first char in user id
+ String headerText = "" + mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
+ holder.text.setText(headerText);
+ return convertView;
+ }
+
+ /**
+ * Header IDs should be static, position=1 should always return the same Id that is.
+ */
+ @Override
+ public long getHeaderId(int position) {
+ if (!mDataValid) {
+ // no data available at this point
+ Log.d(Constants.TAG, "getHeaderView: No data available at this point!");
+ return -1;
+ }
+
+ if (!mCursor.moveToPosition(position)) {
+ throw new IllegalStateException("couldn't move cursor to position " + position);
+ }
+
+ // return the first character of the name as ID because this is what
+ // headers private HashMap<Integer, Boolean> mSelection = new HashMap<Integer,
+ // Boolean>();are based upon
+ return mCursor.getString(mSectionColumnIndex).subSequence(0, 1).charAt(0);
+ }
+
+ class HeaderViewHolder {
+ TextView text;
+ }
+
+ /** -------------------------- MULTI-SELECTION METHODS -------------- */
+ public void setNewSelection(int position, boolean value) {
+ mSelection.put(position, value);
+ notifyDataSetChanged();
+ }
+
+ public boolean isPositionChecked(int position) {
+ Boolean result = mSelection.get(position);
+ return result == null ? false : result;
+ }
+
+ public Set<Integer> getCurrentCheckedPosition() {
+ return mSelection.keySet();
+ }
+
+ public void removeSelection(int position) {
+ mSelection.remove(position);
+ notifyDataSetChanged();
+ }
+
+ public void clearSelection() {
+ mSelection.clear();
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // let the adapter handle setting up the row views
+ View v = super.getView(position, convertView, parent);
+
+ /**
+ * Change color for multi-selection
+ */
+ // default color
+ v.setBackgroundColor(Color.TRANSPARENT);
+ if (mSelection.get(position) != null) {
+ // this is a selected position, change color!
+ v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
+ }
+ return v;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
new file mode 100644
index 000000000..d06c0287c
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/KeyListSecretAdapter.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import java.util.HashMap;
+import java.util.Set;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class KeyListSecretAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ @SuppressLint("UseSparseArrays")
+ private HashMap<Integer, Boolean> mSelection = new HashMap<Integer, Boolean>();
+
+ public KeyListSecretAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
+
+ TextView mainUserId = (TextView) view.findViewById(R.id.mainUserId);
+ mainUserId.setText(R.string.unknown_user_id);
+ TextView mainUserIdRest = (TextView) view.findViewById(R.id.mainUserIdRest);
+ mainUserIdRest.setText("");
+
+ String userId = cursor.getString(userIdIndex);
+ if (userId != null) {
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
+
+ if (userIdSplit[1] != null) {
+ mainUserIdRest.setText(userIdSplit[1]);
+ }
+ mainUserId.setText(userIdSplit[0]);
+ }
+
+ if (mainUserId.getText().length() == 0) {
+ mainUserId.setText(R.string.unknown_user_id);
+ }
+
+ if (mainUserIdRest.getText().length() == 0) {
+ mainUserIdRest.setVisibility(View.GONE);
+ } else {
+ mainUserIdRest.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.key_list_item, null);
+ }
+
+ /** -------------------------- MULTI-SELECTION METHODS -------------- */
+ public void setNewSelection(int position, boolean value) {
+ mSelection.put(position, value);
+ notifyDataSetChanged();
+ }
+
+ public boolean isPositionChecked(int position) {
+ Boolean result = mSelection.get(position);
+ return result == null ? false : result;
+ }
+
+ public Set<Integer> getCurrentCheckedPosition() {
+ return mSelection.keySet();
+ }
+
+ public void removeSelection(int position) {
+ mSelection.remove(position);
+ notifyDataSetChanged();
+ }
+
+ public void clearSelection() {
+ mSelection.clear();
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // let the adapter handle setting up the row views
+ View v = super.getView(position, convertView, parent);
+
+ /**
+ * Change color for multi-selection
+ */
+ // default color
+ v.setBackgroundColor(Color.TRANSPARENT);
+ if (mSelection.get(position) != null) {
+ // this is a selected position, change color!
+ v.setBackgroundColor(parent.getResources().getColor(R.color.emphasis));
+ }
+ return v;
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
index ebb7261be..c6eca0296 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java
@@ -18,11 +18,10 @@
package org.sufficientlysecure.keychain.ui.adapter;
import org.sufficientlysecure.keychain.Id;
-import org.sufficientlysecure.keychain.helper.OtherHelper;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
-import org.sufficientlysecure.keychain.R;
import android.content.Context;
import android.database.Cursor;
@@ -78,7 +77,7 @@ public class SelectKeyCursorAdapter extends CursorAdapter {
String userId = cursor.getString(cursor.getColumnIndex(UserIds.USER_ID));
if (userId != null) {
- String[] userIdSplit = OtherHelper.splitUserId(userId);
+ String[] userIdSplit = PgpKeyHelper.splitUserId(userId);
if (userIdSplit[1] != null) {
mainUserIdRest.setText(userIdSplit[1]);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java
new file mode 100644
index 000000000..51286af66
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyKeysAdapter.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
+import org.sufficientlysecure.keychain.provider.KeychainContract.Keys;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+public class ViewKeyKeysAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ public ViewKeyKeysAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ String keyIdStr = PgpKeyHelper.convertKeyIdToHex(cursor.getLong(cursor
+ .getColumnIndex(Keys.KEY_ID)));
+ String algorithmStr = PgpKeyHelper.getAlgorithmInfo(
+ cursor.getInt(cursor.getColumnIndex(Keys.ALGORITHM)),
+ cursor.getInt(cursor.getColumnIndex(Keys.KEY_SIZE)));
+
+ TextView keyId = (TextView) view.findViewById(R.id.keyId);
+ keyId.setText(keyIdStr);
+
+ TextView keyDetails = (TextView) view.findViewById(R.id.keyDetails);
+ keyDetails.setText("(" + algorithmStr + ")");
+
+ ImageView masterKeyIcon = (ImageView) view.findViewById(R.id.ic_masterKey);
+ if (cursor.getInt(cursor.getColumnIndex(Keys.IS_MASTER_KEY)) != 1) {
+ masterKeyIcon.setVisibility(View.INVISIBLE);
+ } else {
+ masterKeyIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView certifyIcon = (ImageView) view.findViewById(R.id.ic_certifyKey);
+ if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_CERTIFY)) != 1) {
+ certifyIcon.setVisibility(View.GONE);
+ } else {
+ certifyIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView encryptIcon = (ImageView) view.findViewById(R.id.ic_encryptKey);
+ if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_ENCRYPT)) != 1) {
+ encryptIcon.setVisibility(View.GONE);
+ } else {
+ encryptIcon.setVisibility(View.VISIBLE);
+ }
+
+ ImageView signIcon = (ImageView) view.findViewById(R.id.ic_signKey);
+ if (cursor.getInt(cursor.getColumnIndex(Keys.CAN_SIGN)) != 1) {
+ signIcon.setVisibility(View.GONE);
+ } else {
+ signIcon.setVisibility(View.VISIBLE);
+ }
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.view_key_keys_item, null);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java
new file mode 100644
index 000000000..2e2606fd0
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/adapter/ViewKeyUserIdsAdapter.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.adapter;
+
+import org.sufficientlysecure.keychain.R;
+import org.sufficientlysecure.keychain.provider.KeychainContract.UserIds;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.v4.widget.CursorAdapter;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+public class ViewKeyUserIdsAdapter extends CursorAdapter {
+ private LayoutInflater mInflater;
+
+ public ViewKeyUserIdsAdapter(Context context, Cursor c, int flags) {
+ super(context, c, flags);
+
+ mInflater = LayoutInflater.from(context);
+ }
+
+ @Override
+ public void bindView(View view, Context context, Cursor cursor) {
+ int userIdIndex = cursor.getColumnIndex(UserIds.USER_ID);
+
+ String userIdStr = cursor.getString(userIdIndex);
+
+ TextView userId = (TextView) view.findViewById(R.id.userId);
+ userId.setText(userIdStr);
+ }
+
+ @Override
+ public View newView(Context context, Cursor cursor, ViewGroup parent) {
+ return mInflater.inflate(R.layout.view_key_userids_item, null);
+ }
+
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
index 638702b57..101167777 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/DeleteKeyDialogFragment.java
@@ -38,7 +38,7 @@ import android.support.v4.app.FragmentActivity;
public class DeleteKeyDialogFragment extends DialogFragment {
private static final String ARG_MESSENGER = "messenger";
- private static final String ARG_DELETE_KEY_RING_ROW_ID = "delete_file";
+ private static final String ARG_DELETE_KEY_RING_ROW_IDS = "delete_file";
private static final String ARG_KEY_TYPE = "key_type";
public static final int MESSAGE_OKAY = 1;
@@ -48,13 +48,13 @@ public class DeleteKeyDialogFragment extends DialogFragment {
/**
* Creates new instance of this delete file dialog fragment
*/
- public static DeleteKeyDialogFragment newInstance(Messenger messenger, long deleteKeyRingRowId,
+ public static DeleteKeyDialogFragment newInstance(Messenger messenger, long[] keyRingRowIds,
int keyType) {
DeleteKeyDialogFragment frag = new DeleteKeyDialogFragment();
Bundle args = new Bundle();
args.putParcelable(ARG_MESSENGER, messenger);
- args.putLong(ARG_DELETE_KEY_RING_ROW_ID, deleteKeyRingRowId);
+ args.putLongArray(ARG_DELETE_KEY_RING_ROW_IDS, keyRingRowIds);
args.putInt(ARG_KEY_TYPE, keyType);
frag.setArguments(args);
@@ -70,36 +70,48 @@ public class DeleteKeyDialogFragment extends DialogFragment {
final FragmentActivity activity = getActivity();
mMessenger = getArguments().getParcelable(ARG_MESSENGER);
- final long deleteKeyRingRowId = getArguments().getLong(ARG_DELETE_KEY_RING_ROW_ID);
+ final long[] keyRingRowIds = getArguments().getLongArray(ARG_DELETE_KEY_RING_ROW_IDS);
final int keyType = getArguments().getInt(ARG_KEY_TYPE);
- // TODO: better way to do this?
- String userId = activity.getString(R.string.unknown_user_id);
+ AlertDialog.Builder builder = new AlertDialog.Builder(activity);
+ builder.setTitle(R.string.warning);
+
+ if (keyRingRowIds.length == 1) {
+ // TODO: better way to do this?
+ String userId = activity.getString(R.string.unknown_user_id);
+
+ if (keyType == Id.type.public_key) {
+ PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByRowId(activity,
+ keyRingRowIds[0]);
+ userId = PgpKeyHelper.getMainUserIdSafe(activity,
+ PgpKeyHelper.getMasterKey(keyRing));
+ } else {
+ PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByRowId(activity,
+ keyRingRowIds[0]);
+ userId = PgpKeyHelper.getMainUserIdSafe(activity,
+ PgpKeyHelper.getMasterKey(keyRing));
+ }
- if (keyType == Id.type.public_key) {
- PGPPublicKeyRing keyRing = ProviderHelper.getPGPPublicKeyRingByRowId(activity,
- deleteKeyRingRowId);
- userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
+ builder.setMessage(getString(
+ keyType == Id.type.public_key ? R.string.key_deletion_confirmation
+ : R.string.secret_key_deletion_confirmation, userId));
} else {
- PGPSecretKeyRing keyRing = ProviderHelper.getPGPSecretKeyRingByRowId(activity,
- deleteKeyRingRowId);
- userId = PgpKeyHelper.getMainUserIdSafe(activity, PgpKeyHelper.getMasterKey(keyRing));
+ builder.setMessage(R.string.key_deletion_confirmation_multi);
}
- AlertDialog.Builder builder = new AlertDialog.Builder(activity);
- builder.setTitle(R.string.warning);
- builder.setMessage(getString(
- keyType == Id.type.public_key ? R.string.key_deletion_confirmation
- : R.string.secret_key_deletion_confirmation, userId));
builder.setIcon(android.R.drawable.ic_dialog_alert);
builder.setPositiveButton(R.string.btn_delete, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
if (keyType == Id.type.public_key) {
- ProviderHelper.deletePublicKeyRing(activity, deleteKeyRingRowId);
+ for (long keyRowId : keyRingRowIds) {
+ ProviderHelper.deletePublicKeyRing(activity, keyRowId);
+ }
} else {
- ProviderHelper.deleteSecretKeyRing(activity, deleteKeyRingRowId);
+ for (long keyRowId : keyRingRowIds) {
+ ProviderHelper.deleteSecretKeyRing(activity, keyRowId);
+ }
}
dismiss();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
index 730fcc520..e65da2aa8 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/FileDialogFragment.java
@@ -18,9 +18,9 @@
package org.sufficientlysecure.keychain.ui.dialog;
import org.sufficientlysecure.keychain.Constants;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.helper.FileHelper;
import org.sufficientlysecure.keychain.util.Log;
-import org.sufficientlysecure.keychain.R;
import android.app.Activity;
import android.app.AlertDialog;
@@ -36,7 +36,8 @@ import android.view.LayoutInflater;
import android.view.View;
import android.widget.CheckBox;
import android.widget.EditText;
-import android.widget.ImageButton;
+
+import com.beardedhen.androidbootstrap.BootstrapButton;
// TODO: return result from file manager activity to this dialog! not the activity!
// do it like in ImportFileFragment!
@@ -55,6 +56,10 @@ public class FileDialogFragment extends DialogFragment {
private Messenger mMessenger;
+ private EditText mFilename;
+ private BootstrapButton mBrowse;
+ private CheckBox mCheckBox;
+
/**
* Creates new instance of this file dialog fragment
*/
@@ -90,10 +95,6 @@ public class FileDialogFragment extends DialogFragment {
String checkboxText = getArguments().getString(ARG_CHECKBOX_TEXT);
final int requestCode = getArguments().getInt(ARG_REQUEST_CODE);
- final EditText mFilename;
- final ImageButton mBrowse;
- final CheckBox mCheckBox;
-
LayoutInflater inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
AlertDialog.Builder alert = new AlertDialog.Builder(activity);
@@ -105,13 +106,13 @@ public class FileDialogFragment extends DialogFragment {
mFilename = (EditText) view.findViewById(R.id.input);
mFilename.setText(defaultFile);
- mBrowse = (ImageButton) view.findViewById(R.id.btn_browse);
+ mBrowse = (BootstrapButton) view.findViewById(R.id.btn_browse);
mBrowse.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// only .asc or .gpg files
- // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc or gpg types!
- FileHelper.openFile(activity, mFilename.getText().toString(), "*/*",
- requestCode);
+ // setting it to text/plain prevents Cynaogenmod's file manager from selecting asc
+ // or gpg types!
+ FileHelper.openFile(activity, mFilename.getText().toString(), "*/*", requestCode);
}
});
@@ -196,4 +197,3 @@ public class FileDialogFragment extends DialogFragment {
}
}
}
-
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
index aba7e974e..e88271240 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/PassphraseDialogFragment.java
@@ -141,7 +141,7 @@ public class PassphraseDialogFragment extends DialogFragment implements OnEditor
}
LayoutInflater inflater = activity.getLayoutInflater();
- View view = inflater.inflate(R.layout.passphrase, null);
+ View view = inflater.inflate(R.layout.passphrase_dialog, null);
alert.setView(view);
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
index 797b28829..d5c366bed 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
@@ -90,7 +90,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
alert.setMessage(R.string.enter_passphrase_twice);
LayoutInflater inflater = activity.getLayoutInflater();
- View view = inflater.inflate(R.layout.passphrase_repeat, null);
+ View view = inflater.inflate(R.layout.passphrase_repeat_dialog, null);
alert.setView(view);
mPassphraseEditText = (EditText) view.findViewById(R.id.passphrase_passphrase);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java
new file mode 100644
index 000000000..03e09cdcb
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/dialog/ShareNfcDialogFragment.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.sufficientlysecure.keychain.ui.dialog;
+
+import org.sufficientlysecure.htmltextview.HtmlTextView;
+import org.sufficientlysecure.keychain.R;
+
+import android.annotation.TargetApi;
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.nfc.NfcAdapter;
+import android.os.Build;
+import android.os.Bundle;
+import android.provider.Settings;
+import android.support.v4.app.DialogFragment;
+import android.support.v4.app.FragmentActivity;
+
+@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
+public class ShareNfcDialogFragment extends DialogFragment {
+
+ /**
+ * Creates new instance of this fragment
+ */
+ public static ShareNfcDialogFragment newInstance() {
+ ShareNfcDialogFragment frag = new ShareNfcDialogFragment();
+
+ return frag;
+ }
+
+ /**
+ * Creates dialog
+ */
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final FragmentActivity activity = getActivity();
+
+ AlertDialog.Builder alert = new AlertDialog.Builder(activity);
+
+ alert.setIcon(android.R.drawable.ic_dialog_info);
+ alert.setTitle(R.string.share_nfc_dialog);
+ alert.setCancelable(true);
+
+ alert.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ dismiss();
+ }
+ });
+
+ HtmlTextView textView = new HtmlTextView(getActivity());
+ textView.setPadding(8, 8, 8, 8);
+ alert.setView(textView);
+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
+ textView.setText(getString(R.string.error) + ": "
+ + getString(R.string.error_jelly_bean_needed));
+ } else {
+ // check if NFC Adapter is available
+ NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity());
+ if (nfcAdapter == null) {
+ textView.setText(getString(R.string.error) + ": "
+ + getString(R.string.error_nfc_needed));
+ } else {
+ // nfc works...
+ textView.setHtmlFromRawResource(getActivity(), R.raw.nfc_beam_share);
+
+ alert.setNegativeButton(R.string.menu_beam_preferences,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ Intent intentSettings = new Intent(
+ Settings.ACTION_NFCSHARING_SETTINGS);
+ startActivity(intentSettings);
+ }
+ });
+ }
+ }
+
+ // no flickering when clicking textview for Android < 4
+ // aboutTextView.setTextColor(getResources().getColor(android.R.color.black));
+
+ return alert.create();
+ }
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/DashboardLayout.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/DashboardLayout.java
deleted file mode 100644
index 158a271bc..000000000
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/DashboardLayout.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.sufficientlysecure.keychain.ui.widget;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-/**
- * Custom layout that arranges children in a grid-like manner, optimizing for even horizontal and
- * vertical whitespace.
- */
-public class DashboardLayout extends ViewGroup {
- private static final int UNEVEN_GRID_PENALTY_MULTIPLIER = 10;
-
- private int mMaxChildWidth = 0;
- private int mMaxChildHeight = 0;
-
- public DashboardLayout(Context context) {
- super(context, null);
- }
-
- public DashboardLayout(Context context, AttributeSet attrs) {
- super(context, attrs, 0);
- }
-
- public DashboardLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- mMaxChildWidth = 0;
- mMaxChildHeight = 0;
-
- // Measure once to find the maximum child size.
-
- int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.AT_MOST);
- int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
- MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.AT_MOST);
-
- final int count = getChildCount();
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
-
- mMaxChildWidth = Math.max(mMaxChildWidth, child.getMeasuredWidth());
- mMaxChildHeight = Math.max(mMaxChildHeight, child.getMeasuredHeight());
- }
-
- // Measure again for each child to be exactly the same size.
-
- childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildWidth, MeasureSpec.EXACTLY);
- childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(mMaxChildHeight, MeasureSpec.EXACTLY);
-
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
-
- child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
- }
-
- setMeasuredDimension(resolveSize(mMaxChildWidth, widthMeasureSpec),
- resolveSize(mMaxChildHeight, heightMeasureSpec));
- }
-
- @Override
- protected void onLayout(boolean changed, int l, int t, int r, int b) {
- int width = r - l;
- int height = b - t;
-
- final int count = getChildCount();
-
- // Calculate the number of visible children.
- int visibleCount = 0;
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
- ++visibleCount;
- }
-
- if (visibleCount == 0) {
- return;
- }
-
- // Calculate what number of rows and columns will optimize for even horizontal and
- // vertical whitespace between items. Start with a 1 x N grid, then try 2 x N, and so on.
- int bestSpaceDifference = Integer.MAX_VALUE;
- int spaceDifference;
-
- // Horizontal and vertical space between items
- int hSpace = 0;
- int vSpace = 0;
-
- int cols = 1;
- int rows;
-
- while (true) {
- rows = (visibleCount - 1) / cols + 1;
-
- hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));
- vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));
-
- spaceDifference = Math.abs(vSpace - hSpace);
- if (rows * cols != visibleCount) {
- spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER;
- } else if (rows * mMaxChildHeight > height || cols * mMaxChildWidth > width) {
- spaceDifference *= UNEVEN_GRID_PENALTY_MULTIPLIER;
- }
-
- if (spaceDifference < bestSpaceDifference) {
- // Found a better whitespace squareness/ratio
- bestSpaceDifference = spaceDifference;
-
- // If we found a better whitespace squareness and there's only 1 row, this is
- // the best we can do.
- if (rows == 1) {
- break;
- }
- } else {
- // This is a worse whitespace ratio, use the previous value of cols and exit.
- --cols;
- rows = (visibleCount - 1) / cols + 1;
- hSpace = ((width - mMaxChildWidth * cols) / (cols + 1));
- vSpace = ((height - mMaxChildHeight * rows) / (rows + 1));
- break;
- }
-
- ++cols;
- }
-
- // Lay out children based on calculated best-fit number of rows and cols.
-
- // If we chose a layout that has negative horizontal or vertical space, force it to zero.
- hSpace = Math.max(0, hSpace);
- vSpace = Math.max(0, vSpace);
-
- // Re-use width/height variables to be child width/height.
- width = (width - hSpace * (cols + 1)) / cols;
- height = (height - vSpace * (rows + 1)) / rows;
-
- int left, top;
- int col, row;
- int visibleIndex = 0;
- for (int i = 0; i < count; i++) {
- final View child = getChildAt(i);
- if (child.getVisibility() == GONE) {
- continue;
- }
-
- row = visibleIndex / cols;
- col = visibleIndex % cols;
-
- left = hSpace * (col + 1) + width * col;
- top = vSpace * (row + 1) + height * row;
-
- child.layout(left, top, (hSpace == 0 && col == cols - 1) ? r : (left + width),
- (vSpace == 0 && row == rows - 1) ? b : (top + height));
- ++visibleIndex;
- }
- }
-} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/FixedListView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/FixedListView.java
new file mode 100644
index 000000000..277f14b6f
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/FixedListView.java
@@ -0,0 +1,55 @@
+package org.sufficientlysecure.keychain.ui.widget;
+
+/*
+ * Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.ListView;
+
+/**
+ * Automatically calculate height of listview based on contained items. This enables to put this
+ * ListView into a ScrollView without messing up.
+ *
+ * from
+ * http://stackoverflow.com/questions/2419246/how-do-i-create-a-listview-thats-not-in-a-scrollview-
+ * or-has-the-scrollview-dis
+ */
+public class FixedListView extends ListView {
+
+ public FixedListView(Context context) {
+ super(context);
+ }
+
+ public FixedListView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public FixedListView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ // Calculate height of the entire list by providing a very large
+ // height hint. But do not use the highest 2 bits of this integer;
+ // those are reserved for the MeasureSpec mode.
+ int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
+ super.onMeasure(widthMeasureSpec, expandSpec);
+ }
+
+} \ No newline at end of file
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
index 5748839bc..0f5d26644 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyEditor.java
@@ -16,12 +16,18 @@
package org.sufficientlysecure.keychain.ui.widget;
+import java.text.DateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Vector;
+
import org.spongycastle.openpgp.PGPPublicKey;
import org.spongycastle.openpgp.PGPSecretKey;
import org.sufficientlysecure.keychain.Id;
+import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.pgp.PgpKeyHelper;
import org.sufficientlysecure.keychain.util.Choice;
-import org.sufficientlysecure.keychain.R;
import android.app.DatePickerDialog;
import android.app.Dialog;
@@ -32,18 +38,12 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
-import android.widget.Button;
import android.widget.DatePicker;
-import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
-import java.text.DateFormat;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.GregorianCalendar;
-import java.util.Vector;
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private PGPSecretKey mKey;
@@ -51,12 +51,12 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
private boolean mIsMasterKey;
- ImageButton mDeleteButton;
+ BootstrapButton mDeleteButton;
TextView mAlgorithm;
TextView mKeyId;
Spinner mUsage;
TextView mCreationDate;
- Button mExpiryDateButton;
+ BootstrapButton mExpiryDateButton;
GregorianCalendar mExpiryDate;
private int mDatePickerResultCount = 0;
@@ -87,7 +87,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
mAlgorithm = (TextView) findViewById(R.id.algorithm);
mKeyId = (TextView) findViewById(R.id.keyId);
mCreationDate = (TextView) findViewById(R.id.creation);
- mExpiryDateButton = (Button) findViewById(R.id.expiry);
+ mExpiryDateButton = (BootstrapButton) findViewById(R.id.expiry);
mUsage = (Spinner) findViewById(R.id.usage);
Choice choices[] = {
new Choice(Id.choice.usage.sign_only, getResources().getString(
@@ -101,7 +101,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mUsage.setAdapter(adapter);
- mDeleteButton = (ImageButton) findViewById(R.id.delete);
+ mDeleteButton = (BootstrapButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
setExpiryDate(null);
@@ -118,16 +118,18 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
date.get(Calendar.DAY_OF_MONTH));
mDatePickerResultCount = 0;
dialog.setCancelable(true);
- dialog.setButton(Dialog.BUTTON_NEGATIVE, getContext()
- .getString(R.string.btn_no_date), new DialogInterface.OnClickListener() {
- public void onClick(DialogInterface dialog, int which) {
- if (mDatePickerResultCount++ == 0) // Note: Ignore results after the first
- // one - android sends multiples.
- {
- setExpiryDate(null);
- }
- }
- });
+ dialog.setButton(Dialog.BUTTON_NEGATIVE,
+ getContext().getString(R.string.btn_no_date),
+ new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if (mDatePickerResultCount++ == 0) // Note: Ignore results after the
+ // first
+ // one - android sends multiples.
+ {
+ setExpiryDate(null);
+ }
+ }
+ });
dialog.show();
}
});
@@ -237,7 +239,7 @@ public class KeyEditor extends LinearLayout implements Editor, OnClickListener {
private void setExpiryDate(GregorianCalendar date) {
mExpiryDate = date;
if (date == null) {
- mExpiryDateButton.setText(R.string.none);
+ mExpiryDateButton.setText(getContext().getString(R.string.none));
} else {
mExpiryDateButton.setText(DateFormat.getDateInstance().format(date.getTime()));
}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java
index 5fdb2c9c8..01259ccd1 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/KeyServerEditor.java
@@ -23,14 +23,15 @@ import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
public class KeyServerEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
- ImageButton mDeleteButton;
+ BootstrapButton mDeleteButton;
TextView mServer;
public KeyServerEditor(Context context) {
@@ -48,7 +49,7 @@ public class KeyServerEditor extends LinearLayout implements Editor, OnClickList
mServer = (TextView) findViewById(R.id.server);
- mDeleteButton = (ImageButton) findViewById(R.id.delete);
+ mDeleteButton = (BootstrapButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
super.onFinishInflate();
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
index 99190e9c7..b33dbe4c5 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/SectionView.java
@@ -45,17 +45,16 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
-import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.Spinner;
import android.widget.TextView;
import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.beardedhen.androidbootstrap.BootstrapButton;
public class SectionView extends LinearLayout implements OnClickListener, EditorListener {
private LayoutInflater mInflater;
- private View mAdd;
- private ImageView mPlusButton;
+ private BootstrapButton mPlusButton;
private ViewGroup mEditors;
private TextView mTitle;
private int mType = 0;
@@ -103,7 +102,6 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
public void setCanEdit(boolean bCanEdit) {
canEdit = bCanEdit;
- mPlusButton = (ImageView) findViewById(R.id.plusbutton);
if (!canEdit) {
mPlusButton.setVisibility(View.INVISIBLE);
}
@@ -117,8 +115,8 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
- mAdd = findViewById(R.id.header);
- mAdd.setOnClickListener(this);
+ mPlusButton = (BootstrapButton) findViewById(R.id.plusbutton);
+ mPlusButton.setOnClickListener(this);
mEditors = (ViewGroup) findViewById(R.id.editors);
mTitle = (TextView) findViewById(R.id.title);
@@ -155,7 +153,7 @@ public class SectionView extends LinearLayout implements OnClickListener, Editor
case Id.type.key: {
AlertDialog.Builder dialog = new AlertDialog.Builder(getContext());
- View view = mInflater.inflate(R.layout.create_key, null);
+ View view = mInflater.inflate(R.layout.create_key_dialog, null);
dialog.setView(view);
dialog.setTitle(R.string.title_create_key);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UnderlineTextView.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UnderlineTextView.java
new file mode 100644
index 000000000..752d44f89
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UnderlineTextView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2013 Eric Frohnhoefer
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.ui.widget;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.util.TypedValue;
+import android.widget.TextView;
+
+/**
+ * Copied from StickyListHeaders lib example
+ *
+ * @author Eric Frohnhoefer
+ */
+public class UnderlineTextView extends TextView {
+ private final Paint mPaint = new Paint();
+ private int mUnderlineHeight = 0;
+
+ public UnderlineTextView(Context context) {
+ this(context, null);
+ }
+
+ public UnderlineTextView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public UnderlineTextView(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ init(context, attrs);
+ }
+
+ private void init(Context context, AttributeSet attrs) {
+ Resources r = getResources();
+ mUnderlineHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2,
+ r.getDisplayMetrics());
+ }
+
+ @Override
+ public void setPadding(int left, int top, int right, int bottom) {
+ super.setPadding(left, top, right, bottom + mUnderlineHeight);
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ // Draw the underline the same color as the text
+ mPaint.setColor(getTextColors().getDefaultColor());
+ canvas.drawRect(0, getHeight() - mUnderlineHeight, getWidth(), getHeight(), mPaint);
+ }
+}
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
index 6c65e840c..5428b626e 100644
--- a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/ui/widget/UserIdEditor.java
@@ -27,14 +27,15 @@ import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.EditText;
-import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;
+import com.beardedhen.androidbootstrap.BootstrapButton;
+
public class UserIdEditor extends LinearLayout implements Editor, OnClickListener {
private EditorListener mEditorListener = null;
- private ImageButton mDeleteButton;
+ private BootstrapButton mDeleteButton;
private RadioButton mIsMainUserId;
private EditText mName;
private EditText mEmail;
@@ -95,7 +96,7 @@ public class UserIdEditor extends LinearLayout implements Editor, OnClickListene
setDrawingCacheEnabled(true);
setAlwaysDrawnWithCacheEnabled(true);
- mDeleteButton = (ImageButton) findViewById(R.id.delete);
+ mDeleteButton = (BootstrapButton) findViewById(R.id.delete);
mDeleteButton.setOnClickListener(this);
mIsMainUserId = (RadioButton) findViewById(R.id.isMainUserId);
mIsMainUserId.setOnClickListener(this);
diff --git a/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/SectionCursorAdapter.java b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/SectionCursorAdapter.java
new file mode 100644
index 000000000..0d4092d9e
--- /dev/null
+++ b/OpenPGP-Keychain/src/org/sufficientlysecure/keychain/util/SectionCursorAdapter.java
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2013 Dominik Schürmann <dominik@dominikschuermann.de>
+ * Copyright (C) 2011 Gonçalo Ferreira
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.sufficientlysecure.keychain.util;
+
+import java.util.LinkedHashMap;
+
+import android.content.Context;
+import android.database.Cursor;
+import android.database.DataSetObserver;
+import android.support.v4.widget.CursorAdapter;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+/**
+ * Originally from https://github.com/monxalo/android-section-adapter
+ *
+ * getCustomGroup() has been modified
+ */
+public abstract class SectionCursorAdapter extends CursorAdapter {
+
+ private static final String TAG = "SectionCursorAdapter";
+ private static final boolean LOGV = false;
+
+ private static final int TYPE_NORMAL = 1;
+ private static final int TYPE_HEADER = 0;
+ private static final int TYPE_COUNT = 2;
+
+ private final int mHeaderRes;
+ private final int mGroupColumn;
+ private final LayoutInflater mLayoutInflater;
+
+ private LinkedHashMap<Integer, String> sectionsIndexer;
+
+ public static class ViewHolder {
+ public TextView textView;
+ }
+
+ public SectionCursorAdapter(Context context, Cursor c, int headerLayout, int groupColumn) {
+ super(context, c, 0);
+
+ sectionsIndexer = new LinkedHashMap<Integer, String>();
+
+ mHeaderRes = headerLayout;
+ mGroupColumn = groupColumn;
+ mLayoutInflater = LayoutInflater.from(context);
+
+ if (c != null) {
+ calculateSectionHeaders();
+ c.registerDataSetObserver(mDataSetObserver);
+ }
+ }
+
+ private DataSetObserver mDataSetObserver = new DataSetObserver() {
+ public void onChanged() {
+ calculateSectionHeaders();
+ };
+
+ public void onInvalidated() {
+ sectionsIndexer.clear();
+ };
+ };
+
+ /**
+ * <p>
+ * This method serve as an intercepter before the sections are calculated so you can transform
+ * some computer data into human readable, e.g. format a unix timestamp, or a status.
+ * </p>
+ *
+ * <p>
+ * By default this method returns the original data for the group column.
+ * </p>
+ *
+ * @param groupData
+ * @return
+ */
+ protected String getCustomGroup(String groupData) {
+ return groupData.substring(0, 1);
+ }
+
+ private void calculateSectionHeaders() {
+ int i = 0;
+
+ String previous = "";
+ int count = 0;
+
+ final Cursor c = getCursor();
+
+ sectionsIndexer.clear();
+
+ if (c == null) {
+ return;
+ }
+
+ c.moveToPosition(-1);
+
+ while (c.moveToNext()) {
+ final String group = getCustomGroup(c.getString(mGroupColumn));
+
+ if (!previous.equals(group)) {
+ sectionsIndexer.put(i + count, group);
+ previous = group;
+
+ if (LOGV)
+ Log.v(TAG, "Group " + group + "at position: " + (i + count));
+
+ count++;
+ }
+
+ i++;
+ }
+ }
+
+ public String getGroupCustomFormat(Object obj) {
+ return null;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ int viewType = getItemViewType(position);
+
+ if (viewType == TYPE_NORMAL) {
+ Cursor c = (Cursor) getItem(position);
+
+ if (c == null) {
+ if (LOGV)
+ Log.d(TAG, "getItem(" + position + ") = null");
+ return mLayoutInflater.inflate(mHeaderRes, parent, false);
+ }
+
+ final int mapCursorPos = getSectionForPosition(position);
+ c.moveToPosition(mapCursorPos);
+
+ return super.getView(mapCursorPos, convertView, parent);
+ } else {
+ ViewHolder holder = null;
+
+ if (convertView == null) {
+ if (LOGV)
+ Log.v(TAG, "Creating new view for section");
+
+ holder = new ViewHolder();
+ convertView = mLayoutInflater.inflate(mHeaderRes, parent, false);
+ holder.textView = (TextView) convertView;
+
+ convertView.setTag(holder);
+ } else {
+ if (LOGV)
+ Log.v(TAG, "Reusing view for section");
+
+ holder = (ViewHolder) convertView.getTag();
+ }
+
+ TextView sectionText = holder.textView;
+
+ final String group = sectionsIndexer.get(position);
+ final String customFormat = getGroupCustomFormat(group);
+
+ sectionText.setText(customFormat == null ? group : customFormat);
+
+ return sectionText;
+ }
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return TYPE_COUNT;
+ }
+
+ @Override
+ public int getCount() {
+ return super.getCount() + sectionsIndexer.size();
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItemViewType(position) == TYPE_NORMAL;
+ }
+
+ public int getPositionForSection(int section) {
+ if (sectionsIndexer.containsKey(section)) {
+ return section + 1;
+ }
+ return section;
+ }
+
+ public int getSectionForPosition(int position) {
+ int offset = 0;
+ for (Integer key : sectionsIndexer.keySet()) {
+ if (position > key) {
+ offset++;
+ } else {
+ break;
+ }
+ }
+
+ return position - offset;
+ }
+
+ @Override
+ public Object getItem(int position) {
+ if (getItemViewType(position) == TYPE_NORMAL) {
+ return super.getItem(getSectionForPosition(position));
+ }
+ return super.getItem(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ if (getItemViewType(position) == TYPE_NORMAL) {
+ return super.getItemId(getSectionForPosition(position));
+ }
+ return super.getItemId(position);
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ if (position == getPositionForSection(position)) {
+ return TYPE_NORMAL;
+ }
+ return TYPE_HEADER;
+ }
+
+ @Override
+ public void changeCursor(Cursor cursor) {
+ final Cursor old = swapCursor(cursor);
+
+ if (old != null) {
+ old.close();
+ }
+ }
+
+ @Override
+ public Cursor swapCursor(Cursor newCursor) {
+ if (getCursor() != null) {
+ getCursor().unregisterDataSetObserver(mDataSetObserver);
+ }
+
+ final Cursor oldCursor = super.swapCursor(newCursor);
+
+ calculateSectionHeaders();
+
+ if (newCursor != null) {
+ newCursor.registerDataSetObserver(mDataSetObserver);
+ }
+
+ return oldCursor;
+ }
+} \ No newline at end of file